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

     1  package openflow13
     2  
     3  // Package openflow13 provides OpenFlow 1.3 structs along with Read
     4  // and Write methods for each.
     5  // OpenFlow Wire Protocol 0x04
     6  //
     7  // Struct documentation is taken from the OpenFlow Switch
     8  // Specification Version 1.3.3.
     9  // https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.3.3.pdf
    10  
    11  import (
    12  	"encoding/binary"
    13  	"errors"
    14  	"net"
    15  
    16  	"github.com/contiv/libOpenflow/common"
    17  	"github.com/contiv/libOpenflow/protocol"
    18  	"github.com/contiv/libOpenflow/util"
    19  )
    20  
    21  const (
    22  	VERSION = 4
    23  )
    24  
    25  // Returns a new OpenFlow header with version field set to v1.3.
    26  var NewOfp13Header func() common.Header = common.NewHeaderGenerator(VERSION)
    27  
    28  // Echo request/reply messages can be sent from either the
    29  // switch or the controller, and must return an echo reply. They
    30  // can be used to indicate the latency, bandwidth, and/or
    31  // liveness of a controller-switch connection.
    32  func NewEchoRequest() *common.Header {
    33  	h := NewOfp13Header()
    34  	h.Type = Type_EchoRequest
    35  	return &h
    36  }
    37  
    38  // Echo request/reply messages can be sent from either the
    39  // switch or the controller, and must return an echo reply. They
    40  // can be used to indicate the latency, bandwidth, and/or
    41  // liveness of a controller-switch connection.
    42  func NewEchoReply() *common.Header {
    43  	h := NewOfp13Header()
    44  	h.Type = Type_EchoReply
    45  	return &h
    46  }
    47  
    48  // ofp_type 1.3
    49  const (
    50  	/* Immutable messages. */
    51  	Type_Hello        = 0
    52  	Type_Error        = 1
    53  	Type_EchoRequest  = 2
    54  	Type_EchoReply    = 3
    55  	Type_Experimenter = 4
    56  
    57  	/* Switch configuration messages. */
    58  	Type_FeaturesRequest  = 5
    59  	Type_FeaturesReply    = 6
    60  	Type_GetConfigRequest = 7
    61  	Type_GetConfigReply   = 8
    62  	Type_SetConfig        = 9
    63  
    64  	/* Asynchronous messages. */
    65  	Type_PacketIn    = 10
    66  	Type_FlowRemoved = 11
    67  	Type_PortStatus  = 12
    68  
    69  	/* Controller command messages. */
    70  	Type_PacketOut = 13
    71  	Type_FlowMod   = 14
    72  	Type_GroupMod  = 15
    73  	Type_PortMod   = 16
    74  	Type_TableMod  = 17
    75  
    76  	/* Multipart messages. */
    77  	Type_MultiPartRequest = 18
    78  	Type_MultiPartReply   = 19
    79  
    80  	/* Barrier messages. */
    81  	Type_BarrierRequest = 20
    82  	Type_BarrierReply   = 21
    83  
    84  	/* Queue Configuration messages. */
    85  	Type_QueueGetConfigRequest = 22
    86  	Type_QueueGetConfigReply   = 23
    87  
    88  	/* Controller role change request messages. */
    89  	Type_RoleRequest = 24
    90  	Type_RoleReply   = 25
    91  
    92  	/* Asynchronous message configuration. */
    93  	Type_GetAsyncRequest = 26
    94  	Type_GetAsyncReply   = 27
    95  	Type_SetAsync        = 28
    96  
    97  	/* Meters and rate limiters configuration messages. */
    98  	Type_MeterMod = 29
    99  )
   100  
   101  func Parse(b []byte) (message util.Message, err error) {
   102  	switch b[1] {
   103  	case Type_Hello:
   104  		message = new(common.Hello)
   105  		err = message.UnmarshalBinary(b)
   106  	case Type_Error:
   107  		errMsg := new(ErrorMsg)
   108  		err = errMsg.UnmarshalBinary(b)
   109  		if err != nil {
   110  			return
   111  		}
   112  		switch errMsg.Type {
   113  		case ET_EXPERIMENTER:
   114  			message = new(VendorError)
   115  			err = message.UnmarshalBinary(b)
   116  		default:
   117  			message = errMsg
   118  		}
   119  	case Type_EchoRequest:
   120  		message = new(common.Header)
   121  		err = message.UnmarshalBinary(b)
   122  	case Type_EchoReply:
   123  		message = new(common.Header)
   124  		err = message.UnmarshalBinary(b)
   125  	case Type_Experimenter:
   126  		message = new(VendorHeader)
   127  		err = message.UnmarshalBinary(b)
   128  	case Type_FeaturesRequest:
   129  		message = NewFeaturesRequest()
   130  		err = message.UnmarshalBinary(b)
   131  	case Type_FeaturesReply:
   132  		message = NewFeaturesReply()
   133  		err = message.UnmarshalBinary(b)
   134  	case Type_GetConfigRequest:
   135  		message = new(common.Header)
   136  		err = message.UnmarshalBinary(b)
   137  	case Type_GetConfigReply:
   138  		message = new(SwitchConfig)
   139  		err = message.UnmarshalBinary(b)
   140  	case Type_SetConfig:
   141  		message = NewSetConfig()
   142  		err = message.UnmarshalBinary(b)
   143  	case Type_PacketIn:
   144  		message = new(PacketIn)
   145  		err = message.UnmarshalBinary(b)
   146  	case Type_FlowRemoved:
   147  		message = NewFlowRemoved()
   148  		err = message.UnmarshalBinary(b)
   149  	case Type_PortStatus:
   150  		message = new(PortStatus)
   151  		err = message.UnmarshalBinary(b)
   152  	case Type_PacketOut:
   153  		break
   154  	case Type_FlowMod:
   155  		message = NewFlowMod()
   156  		err = message.UnmarshalBinary(b)
   157  	case Type_GroupMod:
   158  		break
   159  	case Type_PortMod:
   160  		break
   161  	case Type_TableMod:
   162  		break
   163  	case Type_BarrierRequest:
   164  		message = new(common.Header)
   165  		err = message.UnmarshalBinary(b)
   166  	case Type_BarrierReply:
   167  		message = new(common.Header)
   168  		err = message.UnmarshalBinary(b)
   169  	case Type_QueueGetConfigRequest:
   170  		break
   171  	case Type_QueueGetConfigReply:
   172  		break
   173  	case Type_MultiPartRequest:
   174  		message = new(MultipartRequest)
   175  		err = message.UnmarshalBinary(b)
   176  	case Type_MultiPartReply:
   177  		message = new(MultipartReply)
   178  		err = message.UnmarshalBinary(b)
   179  	default:
   180  		err = errors.New("An unknown v1.0 packet type was received. Parse function will discard data.")
   181  	}
   182  	return
   183  }
   184  
   185  // When the controller wishes to send a packet out through the
   186  // datapath, it uses the OFPT_PACKET_OUT message: The buffer_id
   187  // is the same given in the ofp_packet_in message. If the
   188  // buffer_id is -1, then the packet data is included in the data
   189  // array. If OFPP_TABLE is specified as the output port of an
   190  // action, the in_port in the packet_out message is used in the
   191  // flow table lookup.
   192  type PacketOut struct {
   193  	common.Header
   194  	BufferId   uint32
   195  	InPort     uint32
   196  	ActionsLen uint16
   197  	pad        []byte
   198  	Actions    []Action
   199  	Data       util.Message
   200  }
   201  
   202  func NewPacketOut() *PacketOut {
   203  	p := new(PacketOut)
   204  	p.Header = NewOfp13Header()
   205  	p.Header.Type = Type_PacketOut
   206  	p.BufferId = 0xffffffff
   207  	p.InPort = P_ANY
   208  	p.ActionsLen = 0
   209  	p.pad = make([]byte, 6)
   210  	p.Actions = make([]Action, 0)
   211  	return p
   212  }
   213  
   214  func (p *PacketOut) AddAction(act Action) {
   215  	p.Actions = append(p.Actions, act)
   216  	p.ActionsLen += act.Len()
   217  }
   218  
   219  func (p *PacketOut) Len() (n uint16) {
   220  	n += p.Header.Len()
   221  	n += 16
   222  	for _, a := range p.Actions {
   223  		n += a.Len()
   224  	}
   225  	n += p.Data.Len()
   226  	//if n < 72 { return 72 }
   227  	return
   228  }
   229  
   230  func (p *PacketOut) MarshalBinary() (data []byte, err error) {
   231  	data = make([]byte, int(p.Len()))
   232  	b := make([]byte, 0)
   233  	n := 0
   234  
   235  	p.Header.Length = p.Len()
   236  	b, err = p.Header.MarshalBinary()
   237  	copy(data[n:], b)
   238  	n += len(b)
   239  
   240  	binary.BigEndian.PutUint32(data[n:], p.BufferId)
   241  	n += 4
   242  	binary.BigEndian.PutUint32(data[n:], p.InPort)
   243  	n += 4
   244  	binary.BigEndian.PutUint16(data[n:], p.ActionsLen)
   245  	n += 2
   246  	n += 6 // for pad
   247  
   248  	for _, a := range p.Actions {
   249  		b, err = a.MarshalBinary()
   250  		copy(data[n:], b)
   251  		n += len(b)
   252  	}
   253  
   254  	b, err = p.Data.MarshalBinary()
   255  	copy(data[n:], b)
   256  	n += len(b)
   257  	return
   258  }
   259  
   260  func (p *PacketOut) UnmarshalBinary(data []byte) error {
   261  	err := p.Header.UnmarshalBinary(data)
   262  	n := p.Header.Len()
   263  
   264  	p.BufferId = binary.BigEndian.Uint32(data[n:])
   265  	n += 4
   266  	p.InPort = binary.BigEndian.Uint32(data[n:])
   267  	n += 4
   268  	p.ActionsLen = binary.BigEndian.Uint16(data[n:])
   269  	n += 2
   270  
   271  	n += 6 // for pad
   272  
   273  	for n < (n + p.ActionsLen) {
   274  		a, err := DecodeAction(data[n:])
   275  		if err != nil {
   276  			return err
   277  		}
   278  		p.Actions = append(p.Actions, a)
   279  		n += a.Len()
   280  	}
   281  
   282  	err = p.Data.UnmarshalBinary(data[n:])
   283  	return err
   284  }
   285  
   286  // ofp_packet_in 1.3
   287  type PacketIn struct {
   288  	common.Header
   289  	BufferId uint32
   290  	TotalLen uint16
   291  	Reason   uint8
   292  	TableId  uint8
   293  	Cookie   uint64
   294  	Match    Match
   295  	pad      []uint8
   296  	Data     protocol.Ethernet
   297  }
   298  
   299  func NewPacketIn() *PacketIn {
   300  	p := new(PacketIn)
   301  	p.Header = NewOfp13Header()
   302  	p.Header.Type = Type_PacketIn
   303  	p.BufferId = 0xffffffff
   304  	p.Reason = 0
   305  	p.TableId = 0
   306  	p.Cookie = 0
   307  	p.Match = *NewMatch()
   308  	return p
   309  }
   310  
   311  func (p *PacketIn) Len() (n uint16) {
   312  	n += p.Header.Len()
   313  	n += 16
   314  	n += p.Match.Len()
   315  	n += 2
   316  	n += p.Data.Len()
   317  	return
   318  }
   319  
   320  func (p *PacketIn) MarshalBinary() (data []byte, err error) {
   321  	data, err = p.Header.MarshalBinary()
   322  
   323  	b := make([]byte, 16)
   324  	n := 0
   325  	binary.BigEndian.PutUint32(b, p.BufferId)
   326  	n += 4
   327  	binary.BigEndian.PutUint16(b[n:], p.TotalLen)
   328  	n += 2
   329  	b[n] = p.Reason
   330  	n += 1
   331  	b[n] = p.TableId
   332  	n += 1
   333  	binary.BigEndian.PutUint64(b, p.Cookie)
   334  	n += 8
   335  	data = append(data, b...)
   336  
   337  	b, err = p.Match.MarshalBinary()
   338  	data = append(data, b...)
   339  
   340  	b = make([]byte, 2)
   341  	copy(b[0:], p.pad)
   342  	data = append(data, b...)
   343  
   344  	b, err = p.Data.MarshalBinary()
   345  	data = append(data, b...)
   346  	return
   347  }
   348  
   349  func (p *PacketIn) UnmarshalBinary(data []byte) error {
   350  	err := p.Header.UnmarshalBinary(data)
   351  	n := p.Header.Len()
   352  
   353  	p.BufferId = binary.BigEndian.Uint32(data[n:])
   354  	n += 4
   355  	p.TotalLen = binary.BigEndian.Uint16(data[n:])
   356  	n += 2
   357  	p.Reason = data[n]
   358  	n += 1
   359  	p.TableId = data[n]
   360  	n += 1
   361  	p.Cookie = binary.BigEndian.Uint64(data[n:])
   362  	n += 8
   363  
   364  	if err := p.Match.UnmarshalBinary(data[n:]); err != nil {
   365  		return err
   366  	}
   367  	n += p.Match.Len()
   368  
   369  	copy(p.pad, data[n:])
   370  	n += 2
   371  
   372  	err = p.Data.UnmarshalBinary(data[n:])
   373  	return err
   374  }
   375  
   376  // ofp_packet_in_reason 1.3
   377  const (
   378  	R_NO_MATCH    = iota /* No matching flow (table-miss flow entry). */
   379  	R_ACTION             /* Action explicitly output to controller. */
   380  	R_INVALID_TTL        /* Packet has invalid TTL */
   381  )
   382  
   383  func NewConfigRequest() *common.Header {
   384  	h := NewOfp13Header()
   385  	h.Type = Type_GetConfigRequest
   386  	return &h
   387  }
   388  
   389  // ofp_config_flags 1.3
   390  const (
   391  	C_FRAG_NORMAL = 0
   392  	C_FRAG_DROP   = 1
   393  	C_FRAG_REASM  = 2
   394  	C_FRAG_MASK   = 3
   395  )
   396  
   397  // ofp_switch_config 1.3
   398  type SwitchConfig struct {
   399  	common.Header
   400  	Flags       uint16 // OFPC_* flags
   401  	MissSendLen uint16
   402  }
   403  
   404  func NewSetConfig() *SwitchConfig {
   405  	c := new(SwitchConfig)
   406  	c.Header = NewOfp13Header()
   407  	c.Header.Type = Type_SetConfig
   408  	c.Flags = 0
   409  	c.MissSendLen = 0
   410  	return c
   411  }
   412  
   413  func (c *SwitchConfig) Len() (n uint16) {
   414  	n = c.Header.Len()
   415  	n += 4
   416  	return
   417  }
   418  
   419  func (c *SwitchConfig) MarshalBinary() (data []byte, err error) {
   420  	data = make([]byte, int(c.Len()))
   421  	bytes := make([]byte, 0)
   422  	next := 0
   423  
   424  	c.Header.Length = c.Len()
   425  	bytes, err = c.Header.MarshalBinary()
   426  	copy(data[next:], bytes)
   427  	next += len(bytes)
   428  	binary.BigEndian.PutUint16(data[next:], c.Flags)
   429  	next += 2
   430  	binary.BigEndian.PutUint16(data[next:], c.MissSendLen)
   431  	next += 2
   432  	return
   433  }
   434  
   435  func (c *SwitchConfig) UnmarshalBinary(data []byte) error {
   436  	var err error
   437  	next := 0
   438  
   439  	err = c.Header.UnmarshalBinary(data[next:])
   440  	next += int(c.Header.Len())
   441  	c.Flags = binary.BigEndian.Uint16(data[next:])
   442  	next += 2
   443  	c.MissSendLen = binary.BigEndian.Uint16(data[next:])
   444  	next += 2
   445  	return err
   446  }
   447  
   448  // BEGIN: ofp13 - 7.4.4
   449  // ofp_error_msg 1.3
   450  type ErrorMsg struct {
   451  	common.Header
   452  	Type uint16
   453  	Code uint16
   454  	Data util.Buffer
   455  }
   456  
   457  func NewErrorMsg() *ErrorMsg {
   458  	e := new(ErrorMsg)
   459  	e.Data = *util.NewBuffer(make([]byte, 0))
   460  	return e
   461  }
   462  
   463  func (e *ErrorMsg) Len() (n uint16) {
   464  	n = e.Header.Len()
   465  	n += 2
   466  	n += 2
   467  	n += e.Data.Len()
   468  	return
   469  }
   470  
   471  func (e *ErrorMsg) MarshalBinary() (data []byte, err error) {
   472  	data = make([]byte, int(e.Len()))
   473  	next := 0
   474  
   475  	bytes, err := e.Header.MarshalBinary()
   476  	copy(data[next:], bytes)
   477  	next += len(bytes)
   478  	binary.BigEndian.PutUint16(data[next:], e.Type)
   479  	next += 2
   480  	binary.BigEndian.PutUint16(data[next:], e.Code)
   481  	next += 2
   482  	bytes, err = e.Data.MarshalBinary()
   483  	copy(data[next:], bytes)
   484  	next += len(bytes)
   485  	return
   486  }
   487  
   488  func (e *ErrorMsg) UnmarshalBinary(data []byte) error {
   489  	next := 0
   490  	e.Header.UnmarshalBinary(data[next:])
   491  	next += int(e.Header.Len())
   492  	e.Type = binary.BigEndian.Uint16(data[next:])
   493  	next += 2
   494  	e.Code = binary.BigEndian.Uint16(data[next:])
   495  	next += 2
   496  	e.Data.UnmarshalBinary(data[next:])
   497  	next += int(e.Data.Len())
   498  	return nil
   499  }
   500  
   501  // ofp_error_type 1.3
   502  const (
   503  	ET_HELLO_FAILED          = 0      /* Hello protocol failed. */
   504  	ET_BAD_REQUEST           = 1      /* Request was not understood. */
   505  	ET_BAD_ACTION            = 2      /* Error in action description. */
   506  	ET_BAD_INSTRUCTION       = 3      /* Error in instruction list. */
   507  	PET_BAD_MATCH            = 4      /* Error in match. */
   508  	ET_FLOW_MOD_FAILED       = 5      /* Problem modifying flow entry. */
   509  	ET_GROUP_MOD_FAILED      = 6      /* Problem modifying group entry. */
   510  	ET_PORT_MOD_FAILED       = 7      /* Port mod request failed. */
   511  	ET_TABLE_MOD_FAILED      = 8      /* Table mod request failed. */
   512  	ET_QUEUE_OP_FAILED       = 9      /* Queue operation failed. */
   513  	ET_ROLE_REQUEST_FAILED   = 11     /* Controller Role request failed. */
   514  	ET_METER_MOD_FAILED      = 12     /* Error in meter. */
   515  	ET_TABLE_FEATURES_FAILED = 13     /* Setting table features failed. */
   516  	ET_EXPERIMENTER          = 0xffff /* Experimenter error messages. */
   517  )
   518  
   519  // ofp_hello_failed_code 1.3
   520  const (
   521  	HFC_INCOMPATIBLE = iota
   522  	HFC_EPERM
   523  )
   524  
   525  // ofp_bad_request_code 1.3
   526  const (
   527  	BRC_BAD_VERSION = iota
   528  	BRC_BAD_TYPE
   529  	BRC_BAD_MULTIPART
   530  	BRC_BAD_EXPERIMENTER
   531  
   532  	BRC_BAD_EXP_TYPE
   533  	BRC_EPERM
   534  	BRC_BAD_LEN
   535  	BRC_BUFFER_EMPTY
   536  	BRC_BUFFER_UNKNOWN
   537  	BRC_BAD_TABLE_ID
   538  	BRC_IS_SLAVE
   539  	BRC_BAD_PORT
   540  	BRC_BAD_PACKET
   541  	BRC_MULTIPART_BUFFER_OVERFLOW
   542  )
   543  
   544  // ofp_bad_action_code 1.3
   545  const (
   546  	BAC_BAD_TYPE = iota
   547  	BAC_BAD_LEN
   548  	BAC_BAD_EXPERIMENTER
   549  	BAC_BAD_EXP_TYPE
   550  	BAC_BAD_OUT_PORT
   551  	BAC_BAD_ARGUMENT
   552  	BAC_EPERM
   553  	BAC_TOO_MANY
   554  	BAC_BAD_QUEUE
   555  	BAC_BAD_OUT_GROUP
   556  	BAC_MATCH_INCONSISTENT
   557  	BAC_UNSUPPORTED_ORDER
   558  	BAC_BAD_TAG
   559  	BAC_BAD_SET_TYPE
   560  	BAC_BAD_SET_LEN
   561  	BAC_BAD_SET_ARGUMENT
   562  )
   563  
   564  // ofp_bad_instruction_code 1.3
   565  const (
   566  	BIC_UNKNOWN_INST        = 0 /* Unknown instruction. */
   567  	BIC_UNSUP_INST          = 1 /* Switch or table does not support the instruction. */
   568  	BIC_BAD_TABLE_ID        = 2 /* Invalid Table-ID specified. */
   569  	BIC_UNSUP_METADATA      = 3 /* Metadata value unsupported by datapath. */
   570  	BIC_UNSUP_METADATA_MASK = 4 /* Metadata mask value unsupported by datapath. */
   571  	BIC_BAD_EXPERIMENTER    = 5 /* Unknown experimenter id specified. */
   572  	BIC_BAD_EXP_TYPE        = 6 /* Unknown instruction for experimenter id. */
   573  	BIC_BAD_LEN             = 7 /* Length problem in instructions. */
   574  	BIC_EPERM               = 8 /* Permissions error. */
   575  )
   576  
   577  // ofp_flow_mod_failed_code 1.3
   578  const (
   579  	FMFC_UNKNOWN      = 0 /* Unspecified error. */
   580  	FMFC_TABLE_FULL   = 1 /* Flow not added because table was full. */
   581  	FMFC_BAD_TABLE_ID = 2 /* Table does not exist */
   582  	FMFC_OVERLAP      = 3 /* Attempted to add overlapping flow with CHECK_OVERLAP flag set. */
   583  	FMFC_EPERM        = 4 /* Permissions error. */
   584  	FMFC_BAD_TIMEOUT  = 5 /* Flow not added because of unsupported idle/hard timeout. */
   585  	FMFC_BAD_COMMAND  = 6 /* Unsupported or unknown command. */
   586  	FMFC_BAD_FLAGS    = 7 /* Unsupported or unknown flags. */
   587  )
   588  
   589  // ofp_bad_match_code 1.3
   590  const (
   591  	BMC_BAD_TYPE         = 0  /* Unsupported match type specified by the match */
   592  	BMC_BAD_LEN          = 1  /* Length problem in match. */
   593  	BMC_BAD_TAG          = 2  /* Match uses an unsupported tag/encap. */
   594  	BMC_BAD_DL_ADDR_MASK = 3  /* Unsupported datalink addr mask - switch does not support arbitrary datalink address mask. */
   595  	BMC_BAD_NW_ADDR_MASK = 4  /* Unsupported network addr mask - switch does not support arbitrary network address mask. */
   596  	BMC_BAD_WILDCARDS    = 5  /* Unsupported combination of fields masked or omitted in the match. */
   597  	BMC_BAD_FIELD        = 6  /* Unsupported field type in the match. */
   598  	BMC_BAD_VALUE        = 7  /* Unsupported value in a match field. */
   599  	BMC_BAD_MASK         = 8  /* Unsupported mask specified in the match, field is not dl-address or nw-address. */
   600  	BMC_BAD_PREREQ       = 9  /* A prerequisite was not met. */
   601  	BMC_DUP_FIELD        = 10 /* A field type was duplicated. */
   602  	BMC_EPERM            = 11 /* Permissions error. */
   603  )
   604  
   605  // ofp_group_mod_failed_code 1.3
   606  const (
   607  	GMFC_GROUP_EXISTS         = 0  /* Group not added because a group ADD attempted to replace an already-present group. */
   608  	GMFC_INVALID_GROUP        = 1  /* Group not added because Group specified is invalid. */
   609  	GMFC_WEIGHT_UNSUPPORTED   = 2  /* Switch does not support unequal load 105 ➞ 2013; The Open Networking Foundation OpenFlow Switch Specification Version 1.3.3 sharing with select groups. */
   610  	GMFC_OUT_OF_GROUPS        = 3  /* The group table is full. */
   611  	GMFC_OUT_OF_BUCKETS       = 4  /* The maximum number of action buckets for a group has been exceeded. */
   612  	GMFC_CHAINING_UNSUPPORTED = 5  /* Switch does not support groups that forward to groups. */
   613  	GMFC_WATCH_UNSUPPORTED    = 6  /* This group cannot watch the watch_port or watch_group specified. */
   614  	GMFC_LOOP                 = 7  /* Group entry would cause a loop. */
   615  	GMFC_UNKNOWN_GROUP        = 8  /* Group not modified because a group MODIFY attempted to modify a non-existent group. */
   616  	GMFC_CHAINED_GROUP        = 9  /* Group not deleted because another group is forwarding to it. */
   617  	GMFC_BAD_TYPE             = 10 /* Unsupported or unknown group type. */
   618  	GMFC_BAD_COMMAND          = 11 /* Unsupported or unknown command. */
   619  	GMFC_BAD_BUCKET           = 12 /* Error in bucket. */
   620  	GMFC_BAD_WATCH            = 13 /* Error in watch port/group. */
   621  	GMFC_EPERM                = 14 /* Permissions error. */
   622  )
   623  
   624  // ofp_port_mod_failed_code 1.0
   625  const (
   626  	PMFC_BAD_PORT = iota
   627  	PMFC_BAD_HW_ADDR
   628  	PMFC_BAD_CONFIG
   629  	PMFC_BAD_ADVERTISE
   630  	PMFC_EPERM
   631  )
   632  
   633  // ofp_table_mod_failed_code
   634  const (
   635  	TMFC_BAD_TABLE  = 0 /* Specified table does not exist. */
   636  	TMFC_BAD_CONFIG = 1 /* Specified config is invalid. */
   637  	TMFC_EPERM      = 2 /* Permissions error. */
   638  )
   639  
   640  // ofp_queue_op_failed_code 1.0
   641  const (
   642  	QOFC_BAD_PORT = iota
   643  	QOFC_BAD_QUEUE
   644  	QOFC_EPERM
   645  )
   646  
   647  // END: ofp13 - 7.4.4
   648  // END: ofp13 - 7.4
   649  
   650  type SwitchFeatures struct {
   651  	common.Header
   652  	DPID         net.HardwareAddr // Size 8
   653  	Buffers      uint32
   654  	NumTables    uint8
   655  	AuxilaryId   uint8
   656  	pad          []uint8 // Size 2
   657  	Capabilities uint32
   658  	Actions      uint32
   659  
   660  	Ports []PhyPort
   661  }
   662  
   663  // FeaturesRequest constructor
   664  func NewFeaturesRequest() *common.Header {
   665  	req := NewOfp13Header()
   666  	req.Type = Type_FeaturesRequest
   667  	return &req
   668  }
   669  
   670  // FeaturesReply constructor
   671  func NewFeaturesReply() *SwitchFeatures {
   672  	res := new(SwitchFeatures)
   673  	res.Header = NewOfp13Header()
   674  	res.Header.Type = Type_FeaturesReply
   675  	res.DPID = make([]byte, 8)
   676  	res.pad = make([]byte, 2)
   677  	res.Ports = make([]PhyPort, 0)
   678  	return res
   679  }
   680  
   681  func (s *SwitchFeatures) Len() (n uint16) {
   682  	n = s.Header.Len()
   683  	n += uint16(len(s.DPID))
   684  	n += 16
   685  	for _, p := range s.Ports {
   686  		n += p.Len()
   687  	}
   688  	return
   689  }
   690  
   691  func (s *SwitchFeatures) MarshalBinary() (data []byte, err error) {
   692  	data = make([]byte, int(s.Len()))
   693  	bytes := make([]byte, 0)
   694  	next := 0
   695  
   696  	s.Header.Length = s.Len()
   697  	bytes, err = s.Header.MarshalBinary()
   698  	copy(data[next:], bytes)
   699  	next += len(bytes)
   700  	binary.BigEndian.PutUint32(data[next:], s.Buffers)
   701  	next += 4
   702  	data[next] = s.NumTables
   703  	next += 1
   704  	data[next] = s.AuxilaryId
   705  	next += 1
   706  	copy(data[next:], s.pad)
   707  	next += len(s.pad)
   708  	binary.BigEndian.PutUint32(data[next:], s.Capabilities)
   709  	next += 4
   710  	binary.BigEndian.PutUint32(data[next:], s.Actions)
   711  	next += 4
   712  
   713  	for _, p := range s.Ports {
   714  		bytes, err = p.MarshalBinary()
   715  		if err != nil {
   716  			return
   717  		}
   718  		copy(data[next:], bytes)
   719  		next += len(bytes)
   720  	}
   721  	return
   722  }
   723  
   724  func (s *SwitchFeatures) UnmarshalBinary(data []byte) error {
   725  	var err error
   726  	next := 0
   727  
   728  	err = s.Header.UnmarshalBinary(data[next:])
   729  	next = int(s.Header.Len())
   730  	copy(s.DPID, data[next:])
   731  	next += len(s.DPID)
   732  	s.Buffers = binary.BigEndian.Uint32(data[next:])
   733  	next += 4
   734  	s.NumTables = data[next]
   735  	next += 1
   736  	s.AuxilaryId = data[next]
   737  	next += 1
   738  	copy(s.pad, data[next:])
   739  	next += len(s.pad)
   740  	s.Capabilities = binary.BigEndian.Uint32(data[next:])
   741  	next += 4
   742  	s.Actions = binary.BigEndian.Uint32(data[next:])
   743  	next += 4
   744  
   745  	for next < len(data) {
   746  		p := NewPhyPort()
   747  		err = p.UnmarshalBinary(data[next:])
   748  		next += int(p.Len())
   749  	}
   750  	return err
   751  }
   752  
   753  // ofp_capabilities 1.3
   754  const (
   755  	C_FLOW_STATS   = 1 << 0
   756  	C_TABLE_STATS  = 1 << 1
   757  	C_PORT_STATS   = 1 << 2
   758  	C_GROUP_STATS  = 1 << 3
   759  	C_RESERVED     = 1 << 4
   760  	C_IP_REASM     = 1 << 5
   761  	C_QUEUE_STATS  = 1 << 6
   762  	C_PORT_BLOCKED = 1 << 8
   763  )
   764  
   765  // ofp_vendor 1.3
   766  type VendorHeader struct {
   767  	Header           common.Header /*Type OFPT_VENDOR*/
   768  	Vendor           uint32
   769  	ExperimenterType uint32
   770  	VendorData       util.Message
   771  }
   772  
   773  func (v *VendorHeader) Len() (n uint16) {
   774  	length := uint16(16)
   775  	if v.VendorData != nil {
   776  		length += v.VendorData.Len()
   777  	}
   778  	return length
   779  }
   780  
   781  func (v *VendorHeader) MarshalBinary() (data []byte, err error) {
   782  	v.Header.Length = v.Len()
   783  	data = make([]byte, v.Len())
   784  	b, err := v.Header.MarshalBinary()
   785  	n := 0
   786  	copy(data[n:], b)
   787  	n += len(b)
   788  	binary.BigEndian.PutUint32(data[n:], v.Vendor)
   789  	n += 4
   790  	binary.BigEndian.PutUint32(data[n:], v.ExperimenterType)
   791  	n += 4
   792  	if v.VendorData != nil {
   793  		vd, err := v.VendorData.MarshalBinary()
   794  		if err != nil {
   795  			return nil, err
   796  		}
   797  		copy(data[n:], vd)
   798  		n += len(vd)
   799  	}
   800  	return
   801  }
   802  
   803  func (v *VendorHeader) UnmarshalBinary(data []byte) error {
   804  	if len(data) < 16 {
   805  		return errors.New("The []byte the wrong size to unmarshal an " +
   806  			"VendorHeader message.")
   807  	}
   808  	v.Header.UnmarshalBinary(data)
   809  	n := int(v.Header.Len())
   810  	v.Vendor = binary.BigEndian.Uint32(data[n:])
   811  	n += 4
   812  	v.ExperimenterType = binary.BigEndian.Uint32(data[n:])
   813  	n += 4
   814  	if n < int(v.Header.Length) {
   815  		var err error
   816  		v.VendorData, err = decodeVendorData(v.ExperimenterType, data[n:v.Header.Length])
   817  		if err != nil {
   818  			return err
   819  		}
   820  	}
   821  	return nil
   822  }