github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/openflow13/nxt_message.go (about)

     1  package openflow13
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  
     7  	"github.com/contiv/libOpenflow/util"
     8  )
     9  
    10  // Nicira extension messages.
    11  const (
    12  	Type_SetFlowFormat     = 12
    13  	Type_FlowModTableId    = 15
    14  	Type_SetPacketInFormat = 16
    15  	Type_SetControllerId   = 20
    16  	Type_TlvTableMod       = 24
    17  	Type_TlvTableRequest   = 25
    18  	Type_TlvTableReply     = 26
    19  	Type_Resume            = 28
    20  	Type_CtFlushZone       = 29
    21  )
    22  
    23  // ofpet_tlv_table_mod_failed_code 1.3
    24  const (
    25  	OFPERR_NXTTMFC_BAD_COMMAND     = 16
    26  	OFPERR_NXTTMFC_BAD_OPT_LEN     = 17
    27  	ERR_NXTTMFC_BAD_FIELD_IDX      = 18
    28  	OFPERR_NXTTMFC_TABLE_FULL      = 19
    29  	OFPERR_NXTTMFC_ALREADY_MAPPED  = 20
    30  	OFPERR_NXTTMFC_DUP_ENTRY       = 21
    31  	OFPERR_NXTTMFC_INVALID_TLV_DEL = 38
    32  )
    33  
    34  func NewNXTVendorHeader(msgType uint32) *VendorHeader {
    35  	h := NewOfp13Header()
    36  	h.Type = Type_Experimenter
    37  	return &VendorHeader{
    38  		Header:           h,
    39  		Vendor:           NxExperimenterID,
    40  		ExperimenterType: msgType,
    41  	}
    42  }
    43  
    44  type ControllerID struct {
    45  	pad [6]byte
    46  	ID  uint16
    47  }
    48  
    49  func (c *ControllerID) Len() uint16 {
    50  	return uint16(len(c.pad) + 2)
    51  }
    52  
    53  func (c *ControllerID) MarshalBinary() (data []byte, err error) {
    54  	data = make([]byte, int(c.Len()))
    55  	n := 6
    56  	binary.BigEndian.PutUint16(data[n:], c.ID)
    57  	return data, nil
    58  }
    59  
    60  func (c *ControllerID) UnmarshalBinary(data []byte) error {
    61  	if len(data) < int(c.Len()) {
    62  		return errors.New("the []byte is too short to unmarshal a full ControllerID message")
    63  	}
    64  	n := 6
    65  	c.ID = binary.BigEndian.Uint16(data[n:])
    66  	return nil
    67  }
    68  
    69  func NewSetControllerID(id uint16) *VendorHeader {
    70  	msg := NewNXTVendorHeader(Type_SetControllerId)
    71  	msg.VendorData = &ControllerID{
    72  		ID: id,
    73  	}
    74  	return msg
    75  }
    76  
    77  type TLVTableMap struct {
    78  	OptClass  uint16
    79  	OptType   uint8
    80  	OptLength uint8
    81  	Index     uint16
    82  	pad       [2]byte
    83  }
    84  
    85  func (t *TLVTableMap) Len() uint16 {
    86  	return uint16(len(t.pad) + 6)
    87  }
    88  
    89  func (t *TLVTableMap) MarshalBinary() (data []byte, err error) {
    90  	data = make([]byte, int(t.Len()))
    91  	n := 0
    92  	binary.BigEndian.PutUint16(data[n:], t.OptClass)
    93  	n += 2
    94  	data[n] = t.OptType
    95  	n += 1
    96  	data[n] = t.OptLength
    97  	n += 1
    98  	binary.BigEndian.PutUint16(data[n:], t.Index)
    99  	return data, nil
   100  }
   101  
   102  func (t *TLVTableMap) UnmarshalBinary(data []byte) error {
   103  	if len(data) < int(t.Len()) {
   104  		return errors.New("the []byte is too short to unmarshal a full TLVTableMap message")
   105  	}
   106  	n := 0
   107  	t.OptClass = binary.BigEndian.Uint16(data[n:])
   108  	n += 2
   109  	t.OptType = data[n]
   110  	n += 1
   111  	t.OptLength = data[n]
   112  	n += 1
   113  	t.Index = binary.BigEndian.Uint16(data[n:])
   114  	return nil
   115  }
   116  
   117  type TLVTableMod struct {
   118  	Command uint16
   119  	pad     [6]byte
   120  	TlvMaps []*TLVTableMap
   121  }
   122  
   123  func (t *TLVTableMod) Len() uint16 {
   124  	length := uint16(8)
   125  	for _, tlvMap := range t.TlvMaps {
   126  		length += tlvMap.Len()
   127  	}
   128  	return length
   129  }
   130  
   131  func (t *TLVTableMod) MarshalBinary() (data []byte, err error) {
   132  	data = make([]byte, t.Len())
   133  	n := 0
   134  	binary.BigEndian.PutUint16(data[n:], t.Command)
   135  	n += 2
   136  	n += 6
   137  	for _, tlvMap := range t.TlvMaps {
   138  		tlvData, err := tlvMap.MarshalBinary()
   139  		if err != nil {
   140  			return nil, err
   141  		}
   142  		copy(data[n:], tlvData)
   143  		n += len(tlvData)
   144  	}
   145  	return data, nil
   146  }
   147  
   148  func (t *TLVTableMod) UnmarshalBinary(data []byte) error {
   149  	if len(data) < 8 {
   150  		return errors.New("the []byte is too short to unmarshal a full TLVTableMod message")
   151  	}
   152  	n := 0
   153  	t.Command = binary.BigEndian.Uint16(data[n:])
   154  	n += 2
   155  	n += 6
   156  
   157  	for n < len(data) {
   158  		tlvMap := new(TLVTableMap)
   159  		err := tlvMap.UnmarshalBinary(data[n:])
   160  		if err != nil {
   161  			return err
   162  		}
   163  		n += int(tlvMap.Len())
   164  		t.TlvMaps = append(t.TlvMaps, tlvMap)
   165  	}
   166  	return nil
   167  }
   168  
   169  func NewTLVTableMod(command uint16, tlvMaps []*TLVTableMap) *TLVTableMod {
   170  	return &TLVTableMod{
   171  		Command: command,
   172  		TlvMaps: tlvMaps,
   173  	}
   174  }
   175  
   176  func NewTLVTableModMessage(tlvMod *TLVTableMod) *VendorHeader {
   177  	msg := NewNXTVendorHeader(Type_TlvTableMod)
   178  	msg.VendorData = tlvMod
   179  	return msg
   180  }
   181  
   182  type TLVTableReply struct {
   183  	MaxSpace  uint32
   184  	MaxFields uint16
   185  	reserved  [10]byte
   186  	TlvMaps   []*TLVTableMap
   187  }
   188  
   189  func (t *TLVTableReply) Len() uint16 {
   190  	length := uint16(16)
   191  	for _, tlvMap := range t.TlvMaps {
   192  		length += tlvMap.Len()
   193  	}
   194  	return length
   195  }
   196  
   197  func (t *TLVTableReply) MarshalBinary() (data []byte, err error) {
   198  	data = make([]byte, t.Len())
   199  	n := 0
   200  	binary.BigEndian.PutUint32(data[n:], t.MaxSpace)
   201  	n += 4
   202  	binary.BigEndian.PutUint16(data[n:], t.MaxFields)
   203  	n += 2
   204  	n += 10
   205  	for _, tlvMap := range t.TlvMaps {
   206  		tlvData, err := tlvMap.MarshalBinary()
   207  		if err != nil {
   208  			return nil, err
   209  		}
   210  		copy(data[n:], tlvData)
   211  		n += len(tlvData)
   212  	}
   213  	return data, nil
   214  }
   215  
   216  func (t *TLVTableReply) UnmarshalBinary(data []byte) error {
   217  	n := 0
   218  	t.MaxSpace = binary.BigEndian.Uint32(data[n:])
   219  	n += 4
   220  	t.MaxFields = binary.BigEndian.Uint16(data[n:])
   221  	n += 2
   222  	t.reserved = [10]byte{}
   223  	copy(t.reserved[0:], data[n:n+10])
   224  	n += 10
   225  	for n < len(data) {
   226  		tlvMap := new(TLVTableMap)
   227  		err := tlvMap.UnmarshalBinary(data[n:])
   228  		if err != nil {
   229  			return err
   230  		}
   231  		n += int(tlvMap.Len())
   232  		t.TlvMaps = append(t.TlvMaps, tlvMap)
   233  	}
   234  	return nil
   235  }
   236  
   237  func NewTLVTableRequest() *VendorHeader {
   238  	return NewNXTVendorHeader(Type_TlvTableRequest)
   239  }
   240  
   241  func decodeVendorData(experimenterType uint32, data []byte) (msg util.Message, err error) {
   242  	switch experimenterType {
   243  	case Type_SetControllerId:
   244  		msg = new(ControllerID)
   245  	case Type_TlvTableMod:
   246  		msg = new(TLVTableMod)
   247  	case Type_TlvTableReply:
   248  		msg = new(TLVTableReply)
   249  	case Type_BundleCtrl:
   250  		msg = new(BundleControl)
   251  	case Type_BundleAdd:
   252  		msg = new(BundleAdd)
   253  	}
   254  	err = msg.UnmarshalBinary(data)
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  	return msg, err
   259  }