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

     1  package openflow13
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"net"
     7  )
     8  
     9  // NX Action constants
    10  const (
    11  	NxExperimenterID     = 0x00002320 // Vendor ID for Nicira extension messages
    12  	NxActionHeaderLength = 10         // Length of Nicira extension message header
    13  )
    14  
    15  // NX Action subtypes
    16  const (
    17  	NXAST_RESUBMIT         = 1  // Nicira extended action: resubmit(port)
    18  	NXAST_SET_TUNNEL       = 2  // Nicira extended action: set_tunnel
    19  	NXAST_DROP_SPOOFED_ARP = 3  // Nicira extended action: drop spoofed arp packets
    20  	NXAST_SET_QUEUE        = 4  // Nicira extended action: set_queue
    21  	NXAST_POP_QUEUE        = 5  // Nicira extended action: pop_tunnel
    22  	NXAST_REG_MOVE         = 6  // Nicira extended action: move:srcField[m1..n1]->dstField[m2..n2]
    23  	NXAST_REG_LOAD         = 7  // Nicira extended action: load:data->dstField[m..n]
    24  	NXAST_NOTE             = 8  // Nicira extended action: note
    25  	NXAST_SET_TUNNEL_V6    = 9  // Nicira extended action: set_tunnel64
    26  	NXAST_MULTIPATH        = 10 // Nicira extended action: set_tunnel
    27  	NXAST_AUTOPATH         = 11 // Nicira extended action: multipath
    28  	NXAST_BUNDLE           = 12 // Nicira extended action: bundle
    29  	NXAST_BUNDLE_LOAD      = 13 // Nicira extended action: bundle_load
    30  	NXAST_RESUBMIT_TABLE   = 14 // Nicira extended action: resubmit(port, table)
    31  	NXAST_OUTPUT_REG       = 15 // Nicira extended action: output:field
    32  	NXAST_LEARN            = 16 // Nicira extended action: learn
    33  	NXAST_EXIT             = 17 // Nicira extended action: exit
    34  	NXAST_DEC_TTL          = 18 // Nicira extended action: dec_ttl
    35  	NXAST_FIN_TIMEOUT      = 19 // Nicira extended action: fin_timeout
    36  	NXAST_CONTROLLER       = 20 // Nicira extended action: controller(reason=xx,max_len=xx,id=xx)
    37  	NXAST_DEC_TTL_CNT_IDS  = 21 // Nicira extended action: dec_ttl(id1,[id2]...)
    38  	NXAST_PUSH_MPLS        = 23 // Nicira extended action: push_mpls
    39  	NXAST_POP_MPLS         = 24 // Nicira extended action: pop_mpls
    40  	NXAST_SET_MPLS_TTL     = 25 // Nicira extended action: set_mpls_ttl
    41  	NXAST_DEC_MPLS_TTL     = 26 // Nicira extended action: dec_mpls_ttl
    42  	NXAST_STACK_PUSH       = 27 // Nicira extended action: push:src
    43  	NXAST_STACK_POP        = 28 // Nicira extended action: pop:dst
    44  	NXAST_SAMPLE           = 29 // Nicira extended action: sample
    45  	NXAST_SET_MPLS_LABEL   = 30 // Nicira extended action: set_mpls_label
    46  	NXAST_SET_MPLS_TC      = 31 // Nicira extended action: set_mpls_tc
    47  	NXAST_OUTPUT_REG2      = 32 // Nicira extended action: output(port=port,max_len)
    48  	NXAST_REG_LOAD2        = 33 // Nicira extended action: load
    49  	NXAST_CONJUNCTION      = 34 // Nicira extended action: conjunction
    50  	NXAST_CT               = 35 // Nicira extended action: ct
    51  	NXAST_NAT              = 36 // Nicira extended action: nat, need to be along with ct action
    52  	NXAST_CONTROLLER2      = 37 // Nicira extended action: controller(userdata=xxx,pause)
    53  	NXAST_SAMPLE2          = 38 // Nicira extended action: sample, support for exporting egress tunnel
    54  	NXAST_OUTPUT_TRUNC     = 39 // Nicira extended action: truncate output action
    55  	NXAST_CT_CLEAR         = 43 // Nicira extended action: ct_clear
    56  	NXAST_CT_RESUBMIT      = 44 // Nicira extended action: resubmit to table in ct
    57  	NXAST_RAW_ENCAP        = 46 // Nicira extended action: encap
    58  	NXAST_RAW_DECAP        = 47 // Nicira extended action: decap
    59  	NXAST_DEC_NSH_TTL      = 48 // Nicira extended action: dec_nsh_ttl
    60  )
    61  
    62  type NXActionHeader struct {
    63  	*ActionHeader
    64  	Vendor  uint32
    65  	Subtype uint16
    66  }
    67  
    68  func (a *NXActionHeader) Header() *ActionHeader {
    69  	return a.ActionHeader
    70  }
    71  
    72  func (a *NXActionHeader) NXHeader() *NXActionHeader {
    73  	return a
    74  }
    75  
    76  func (a *NXActionHeader) Len() (n uint16) {
    77  	return NxActionHeaderLength
    78  }
    79  
    80  func (a *NXActionHeader) MarshalBinary() (data []byte, err error) {
    81  	data = make([]byte, a.Len())
    82  	var b []byte
    83  	n := 0
    84  
    85  	b, err = a.ActionHeader.MarshalBinary()
    86  	copy(data[n:], b)
    87  	n += len(b)
    88  	binary.BigEndian.PutUint32(data[n:], a.Vendor)
    89  	n += 4
    90  	binary.BigEndian.PutUint16(data[n:], a.Subtype)
    91  	return
    92  }
    93  
    94  func (a *NXActionHeader) UnmarshalBinary(data []byte) error {
    95  	if len(data) < int(NxActionHeaderLength) {
    96  		return errors.New("the []byte is too short to unmarshal a full NXActionHeader message")
    97  	}
    98  	a.ActionHeader = new(ActionHeader)
    99  	n := 0
   100  	err := a.ActionHeader.UnmarshalBinary(data[:4])
   101  	n += 4
   102  	a.Vendor = binary.BigEndian.Uint32(data[n:])
   103  	n += 4
   104  	a.Subtype = binary.BigEndian.Uint16(data[n:])
   105  	return err
   106  }
   107  
   108  func NewNxActionHeader(subtype uint16) *NXActionHeader {
   109  	actionHeader := &ActionHeader{Type: ActionType_Experimenter, Length: NxActionHeaderLength}
   110  	return &NXActionHeader{ActionHeader: actionHeader, Vendor: NxExperimenterID, Subtype: subtype}
   111  }
   112  
   113  func DecodeNxAction(data []byte) Action {
   114  	var a Action
   115  	// Previous 8 bytes in the data includes type(2 byte), length(2 byte), and vendor(4 byte)
   116  	subtype := binary.BigEndian.Uint16(data[8:])
   117  	switch subtype {
   118  	case NXAST_RESUBMIT:
   119  		a = new(NXActionResubmit)
   120  	case NXAST_SET_TUNNEL:
   121  	case NXAST_DROP_SPOOFED_ARP:
   122  	case NXAST_SET_QUEUE:
   123  	case NXAST_POP_QUEUE:
   124  	case NXAST_REG_MOVE:
   125  		a = new(NXActionRegMove)
   126  	case NXAST_REG_LOAD:
   127  		a = new(NXActionRegLoad)
   128  	case NXAST_NOTE:
   129  		a = new(NXActionNote)
   130  	case NXAST_SET_TUNNEL_V6:
   131  	case NXAST_MULTIPATH:
   132  	case NXAST_AUTOPATH:
   133  	case NXAST_BUNDLE:
   134  	case NXAST_BUNDLE_LOAD:
   135  	case NXAST_RESUBMIT_TABLE:
   136  		a = new(NXActionResubmitTable)
   137  	case NXAST_OUTPUT_REG:
   138  		a = new(NXActionOutputReg)
   139  	case NXAST_LEARN:
   140  		a = new(NXActionLearn)
   141  	case NXAST_EXIT:
   142  	case NXAST_DEC_TTL:
   143  		a = new(NXActionDecTTL)
   144  	case NXAST_FIN_TIMEOUT:
   145  	case NXAST_CONTROLLER:
   146  		a = new(NXActionController)
   147  	case NXAST_DEC_TTL_CNT_IDS:
   148  		a = new(NXActionDecTTLCntIDs)
   149  	case NXAST_PUSH_MPLS:
   150  	case NXAST_POP_MPLS:
   151  	case NXAST_SET_MPLS_TTL:
   152  	case NXAST_DEC_MPLS_TTL:
   153  	case NXAST_STACK_PUSH:
   154  	case NXAST_STACK_POP:
   155  	case NXAST_SAMPLE:
   156  	case NXAST_SET_MPLS_LABEL:
   157  	case NXAST_SET_MPLS_TC:
   158  	case NXAST_OUTPUT_REG2:
   159  		a = new(NXActionOutputReg)
   160  	case NXAST_REG_LOAD2:
   161  		a = new(NXActionRegLoad2)
   162  	case NXAST_CONJUNCTION:
   163  		a = new(NXActionConjunction)
   164  	case NXAST_CT:
   165  		a = new(NXActionConnTrack)
   166  	case NXAST_NAT:
   167  		a = new(NXActionCTNAT)
   168  	case NXAST_CONTROLLER2:
   169  	case NXAST_SAMPLE2:
   170  	case NXAST_OUTPUT_TRUNC:
   171  	case NXAST_CT_CLEAR:
   172  	case NXAST_CT_RESUBMIT:
   173  		a = new(NXActionResubmitTable)
   174  		a.(*NXActionResubmitTable).withCT = true
   175  	case NXAST_RAW_ENCAP:
   176  	case NXAST_RAW_DECAP:
   177  	case NXAST_DEC_NSH_TTL:
   178  	}
   179  	return a
   180  }
   181  
   182  // NXActionConjunction is NX action to configure conjunctive match flows.
   183  type NXActionConjunction struct {
   184  	*NXActionHeader
   185  	Clause  uint8
   186  	NClause uint8
   187  	ID      uint32
   188  }
   189  
   190  // NewNXActionConjunction creates NXActionConjunction, the action in flow entry is like conjunction(ID, Clause/nclause).
   191  func NewNXActionConjunction(clause uint8, nclause uint8, id uint32) *NXActionConjunction {
   192  	a := new(NXActionConjunction)
   193  	a.NXActionHeader = NewNxActionHeader(NXAST_CONJUNCTION)
   194  	a.Length = a.NXActionHeader.Len() + 6
   195  	a.Clause = clause
   196  	a.NClause = nclause
   197  	a.ID = id
   198  	return a
   199  }
   200  
   201  func (a *NXActionConjunction) Len() (n uint16) {
   202  	return a.Length
   203  }
   204  
   205  func (a *NXActionConjunction) MarshalBinary() (data []byte, err error) {
   206  	data = make([]byte, int(a.Len()))
   207  	var b []byte
   208  	n := 0
   209  
   210  	b, err = a.NXActionHeader.MarshalBinary()
   211  	copy(data[n:], b)
   212  	n += len(b)
   213  	data[n] = a.Clause
   214  	n++
   215  	data[n] = a.NClause
   216  	n++
   217  	binary.BigEndian.PutUint32(data[n:], a.ID)
   218  	n += 4
   219  
   220  	return
   221  }
   222  
   223  func (a *NXActionConjunction) UnmarshalBinary(data []byte) error {
   224  	n := 0
   225  	a.NXActionHeader = new(NXActionHeader)
   226  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   227  	n += int(a.NXActionHeader.Len())
   228  	if len(data) < int(a.Len()) {
   229  		return errors.New("the []byte is too short to unmarshal a full NXActionConjunction message")
   230  	}
   231  	a.Clause = uint8(data[n])
   232  	n++
   233  	a.NClause = uint8(data[n])
   234  	n++
   235  	a.ID = binary.BigEndian.Uint32(data[n:])
   236  
   237  	return err
   238  }
   239  
   240  // NXActionConnTrack is NX action for conntrack.
   241  type NXActionConnTrack struct {
   242  	*NXActionHeader
   243  	Flags        uint16
   244  	ZoneSrc      uint32
   245  	ZoneOfsNbits uint16
   246  	RecircTable  uint8
   247  	pad          []byte // 3bytes
   248  	Alg          uint16
   249  	actions      []Action
   250  }
   251  
   252  func (a *NXActionConnTrack) Len() (n uint16) {
   253  	return a.Length
   254  }
   255  
   256  func (a *NXActionConnTrack) MarshalBinary() (data []byte, err error) {
   257  	data = make([]byte, int(a.Length))
   258  	var b []byte
   259  	n := 0
   260  
   261  	b, err = a.NXActionHeader.MarshalBinary()
   262  	copy(data[n:], b)
   263  	n += len(b)
   264  	binary.BigEndian.PutUint16(data[n:], a.Flags)
   265  	n += 2
   266  	binary.BigEndian.PutUint32(data[n:], a.ZoneSrc)
   267  	n += 4
   268  	binary.BigEndian.PutUint16(data[n:], a.ZoneOfsNbits)
   269  	n += 2
   270  	data[n] = a.RecircTable
   271  	n++
   272  	copy(data[n:], a.pad)
   273  	n += 3
   274  	binary.BigEndian.PutUint16(data[n:], a.Alg)
   275  	n += 2
   276  	// Marshal ct actions
   277  	for _, action := range a.actions {
   278  		actionBytes, err := action.MarshalBinary()
   279  		if err != nil {
   280  			return data, errors.New("failed to Marshal ct subActions")
   281  		}
   282  		copy(data[n:], actionBytes)
   283  		n += len(actionBytes)
   284  	}
   285  	return
   286  }
   287  
   288  func (a *NXActionConnTrack) UnmarshalBinary(data []byte) error {
   289  	n := 0
   290  	a.NXActionHeader = new(NXActionHeader)
   291  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   292  	n += int(a.NXActionHeader.Len())
   293  	if len(data) < int(a.Len()) {
   294  		return errors.New("the []byte is too short to unmarshal a full NXActionConnTrack message")
   295  	}
   296  	a.Flags = binary.BigEndian.Uint16(data[n:])
   297  	n += 2
   298  	a.ZoneSrc = binary.BigEndian.Uint32(data[n:])
   299  	n += 4
   300  	a.ZoneOfsNbits = binary.BigEndian.Uint16(data[n:])
   301  	n += 2
   302  	a.RecircTable = data[n]
   303  	n++
   304  	copy(a.pad, data[n:n+3])
   305  	n += 3
   306  	a.Alg = binary.BigEndian.Uint16(data[n:])
   307  	n += 2
   308  
   309  	for n < int(a.Len()) {
   310  		act, err := DecodeAction(data[n:])
   311  		if err != nil {
   312  			return errors.New("failed to decode actions")
   313  		}
   314  		a.actions = append(a.actions, act)
   315  		n += int(act.Len())
   316  	}
   317  	a.Length = uint16(n)
   318  	return err
   319  }
   320  
   321  func (a *NXActionConnTrack) Commit() *NXActionConnTrack {
   322  	a.Flags |= NX_CT_F_COMMIT
   323  	return a
   324  }
   325  
   326  func (a *NXActionConnTrack) Force() *NXActionConnTrack {
   327  	a.Flags |= NX_CT_F_FORCE
   328  	return a
   329  }
   330  
   331  func (a *NXActionConnTrack) Table(tableID uint8) *NXActionConnTrack {
   332  	a.RecircTable = tableID
   333  	return a
   334  }
   335  
   336  func (a *NXActionConnTrack) ZoneImm(zoneID uint16) *NXActionConnTrack {
   337  	a.ZoneSrc = 0
   338  	a.ZoneOfsNbits = zoneID
   339  	return a
   340  }
   341  
   342  func (a *NXActionConnTrack) ZoneRange(field *MatchField, rng *NXRange) *NXActionConnTrack {
   343  	a.ZoneSrc = field.MarshalHeader()
   344  	a.ZoneOfsNbits = rng.ToOfsBits()
   345  	return a
   346  }
   347  
   348  func (a *NXActionConnTrack) AddAction(actions ...Action) *NXActionConnTrack {
   349  	for _, act := range actions {
   350  		a.actions = append(a.actions, act)
   351  		a.Length += act.Len()
   352  	}
   353  	return a
   354  }
   355  
   356  func NewNXActionConnTrack() *NXActionConnTrack {
   357  	a := new(NXActionConnTrack)
   358  	a.NXActionHeader = NewNxActionHeader(NXAST_CT)
   359  	a.Length = a.NXActionHeader.Len() + 14
   360  	a.RecircTable = NX_CT_RECIRC_NONE
   361  	return a
   362  }
   363  
   364  // NXActionRegLoad is NX action to load data to a specified field.
   365  type NXActionRegLoad struct {
   366  	*NXActionHeader
   367  	OfsNbits uint16
   368  	DstReg   *MatchField
   369  	Value    uint64
   370  }
   371  
   372  func NewNXActionRegLoad(ofsNbits uint16, dstField *MatchField, value uint64) *NXActionRegLoad {
   373  	a := new(NXActionRegLoad)
   374  	a.NXActionHeader = NewNxActionHeader(NXAST_REG_LOAD)
   375  	a.Length = a.NXActionHeader.Len() + 14
   376  	a.OfsNbits = ofsNbits
   377  	a.DstReg = dstField
   378  	a.Value = value
   379  	return a
   380  }
   381  
   382  func (a *NXActionRegLoad) Len() (n uint16) {
   383  	return a.Length
   384  }
   385  
   386  func (a *NXActionRegLoad) MarshalBinary() (data []byte, err error) {
   387  	data = make([]byte, int(a.Len()))
   388  	var b []byte
   389  	n := 0
   390  
   391  	b, err = a.NXActionHeader.MarshalBinary()
   392  	copy(data[n:], b)
   393  	n += len(b)
   394  	binary.BigEndian.PutUint16(data[n:], a.OfsNbits)
   395  	n += 2
   396  	fieldHeaderData := a.DstReg.MarshalHeader()
   397  	binary.BigEndian.PutUint32(data[n:], fieldHeaderData)
   398  	n += 4
   399  	binary.BigEndian.PutUint64(data[n:], a.Value)
   400  	n += 8
   401  
   402  	return
   403  }
   404  
   405  func (a *NXActionRegLoad) UnmarshalBinary(data []byte) error {
   406  	n := 0
   407  	a.NXActionHeader = new(NXActionHeader)
   408  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   409  	n += int(a.NXActionHeader.Len())
   410  	if len(data) < int(a.Len()) {
   411  		return errors.New("the []byte is too short to unmarshal a full NXActionRegLoad message")
   412  	}
   413  	a.OfsNbits = binary.BigEndian.Uint16(data[n:])
   414  	n += 2
   415  	a.DstReg = new(MatchField)
   416  	err = a.DstReg.UnmarshalHeader(data[n : n+4])
   417  	n += 4
   418  	a.Value = binary.BigEndian.Uint64(data[n:])
   419  	return err
   420  }
   421  
   422  // NXActionRegMove is NX action to move data from srcField to dstField.
   423  type NXActionRegMove struct {
   424  	*NXActionHeader
   425  	Nbits    uint16
   426  	SrcOfs   uint16
   427  	DstOfs   uint16
   428  	SrcField *MatchField
   429  	DstField *MatchField
   430  }
   431  
   432  func NewNXActionRegMove(nBits uint16, srcOfs uint16, dstOfs uint16, srcField *MatchField, dstField *MatchField) *NXActionRegMove {
   433  	a := new(NXActionRegMove)
   434  	a.NXActionHeader = NewNxActionHeader(NXAST_REG_MOVE)
   435  	a.Length = a.NXActionHeader.Len() + 14
   436  	a.Nbits = nBits
   437  	a.SrcOfs = srcOfs
   438  	a.DstOfs = dstOfs
   439  	a.SrcField = srcField
   440  	a.DstField = dstField
   441  	return a
   442  }
   443  
   444  func (a *NXActionRegMove) Len() (n uint16) {
   445  	return a.Length
   446  }
   447  
   448  func (a *NXActionRegMove) MarshalBinary() (data []byte, err error) {
   449  	data = make([]byte, a.Length)
   450  	var b []byte
   451  	n := 0
   452  
   453  	b, err = a.NXActionHeader.MarshalBinary()
   454  	copy(data[n:], b)
   455  	n += len(b)
   456  	binary.BigEndian.PutUint16(data[n:], a.Nbits)
   457  	n += 2
   458  	binary.BigEndian.PutUint16(data[n:], a.SrcOfs)
   459  	n += 2
   460  	binary.BigEndian.PutUint16(data[n:], a.DstOfs)
   461  	n += 2
   462  
   463  	srcFieldHeaderData := a.SrcField.MarshalHeader()
   464  	binary.BigEndian.PutUint32(data[n:], srcFieldHeaderData)
   465  	n += 4
   466  
   467  	dstFieldHeaderData := a.DstField.MarshalHeader()
   468  	binary.BigEndian.PutUint32(data[n:], dstFieldHeaderData)
   469  	n += 4
   470  	return
   471  }
   472  
   473  func (a *NXActionRegMove) UnmarshalBinary(data []byte) error {
   474  	n := 0
   475  	a.NXActionHeader = new(NXActionHeader)
   476  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   477  	n += int(a.NXActionHeader.Len())
   478  	if len(data) < int(a.Length) {
   479  		return errors.New("the []byte is too short to unmarshal a full NXActionRegMove message")
   480  	}
   481  	a.Nbits = binary.BigEndian.Uint16(data[n:])
   482  	n += 2
   483  	a.SrcOfs = binary.BigEndian.Uint16(data[n:])
   484  	n += 2
   485  	a.DstOfs = binary.BigEndian.Uint16(data[n:])
   486  	n += 2
   487  	a.SrcField = new(MatchField)
   488  	err = a.SrcField.UnmarshalHeader(data[n:])
   489  	n += 4
   490  	a.DstField = new(MatchField)
   491  	err = a.DstField.UnmarshalHeader(data[n:])
   492  	return err
   493  }
   494  
   495  // NXActionResubmit is NX action to resubmit packet to a specified in_port.
   496  type NXActionResubmit struct {
   497  	*NXActionHeader
   498  	InPort  uint16
   499  	TableID uint8
   500  	pad     [3]byte // 3 bytes
   501  }
   502  
   503  func NewNXActionResubmit(inPort uint16) *NXActionResubmit {
   504  	a := new(NXActionResubmit)
   505  	a.NXActionHeader = NewNxActionHeader(NXAST_RESUBMIT)
   506  	a.Type = Type_Experimenter
   507  	a.Length = a.NXActionHeader.Len() + 6
   508  	a.InPort = inPort
   509  	a.pad = [3]byte{}
   510  	return a
   511  }
   512  
   513  func (a *NXActionResubmit) Len() (n uint16) {
   514  	return a.Length
   515  }
   516  
   517  func (a *NXActionResubmit) MarshalBinary() (data []byte, err error) {
   518  	data = make([]byte, int(a.Len()))
   519  	var b []byte
   520  	n := 0
   521  
   522  	b, err = a.NXActionHeader.MarshalBinary()
   523  	copy(data[n:], b)
   524  	n += len(b)
   525  	binary.BigEndian.PutUint16(data[n:], a.InPort)
   526  	n += 2
   527  	a.TableID = OFPTT_ALL
   528  	n++
   529  	// Skip padding copy, move the index.
   530  	n += 3
   531  
   532  	return
   533  }
   534  
   535  func (a *NXActionResubmit) UnmarshalBinary(data []byte) error {
   536  	n := 0
   537  	a.NXActionHeader = new(NXActionHeader)
   538  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   539  	n += int(a.NXActionHeader.Len())
   540  	if len(data) < int(a.Len()) {
   541  		return errors.New("the []byte is too short to unmarshal a full NXActionConjunction message")
   542  	}
   543  	a.InPort = binary.BigEndian.Uint16(data[n:])
   544  
   545  	return err
   546  }
   547  
   548  // NXActionResubmitTable is NX action to resubmit packet to a specified table and in_port.
   549  type NXActionResubmitTable struct {
   550  	*NXActionHeader
   551  	InPort  uint16
   552  	TableID uint8
   553  	pad     [3]byte // 3 bytes
   554  	withCT  bool
   555  }
   556  
   557  func newNXActionResubmitTable() *NXActionResubmitTable {
   558  	a := &NXActionResubmitTable{
   559  		NXActionHeader: NewNxActionHeader(NXAST_RESUBMIT_TABLE),
   560  		withCT:         false,
   561  		pad:            [3]byte{},
   562  	}
   563  	a.Length = 16
   564  	return a
   565  }
   566  
   567  func newNXActionResubmitTableCT() *NXActionResubmitTable {
   568  	a := &NXActionResubmitTable{
   569  		NXActionHeader: NewNxActionHeader(NXAST_CT_RESUBMIT),
   570  		withCT:         true,
   571  		pad:            [3]byte{},
   572  	}
   573  	a.Length = 16
   574  	return a
   575  }
   576  
   577  func NewNXActionResubmitTableAction(inPort uint16, tableID uint8) *NXActionResubmitTable {
   578  	a := newNXActionResubmitTable()
   579  	a.InPort = inPort
   580  	a.TableID = tableID
   581  	return a
   582  }
   583  
   584  func (a *NXActionResubmitTable) IsCT() bool {
   585  	return a.withCT
   586  }
   587  
   588  func (a *NXActionResubmitTable) Len() (n uint16) {
   589  	return a.Length
   590  }
   591  
   592  func (a *NXActionResubmitTable) MarshalBinary() (data []byte, err error) {
   593  	data = make([]byte, int(a.Len()))
   594  	var b []byte
   595  	n := 0
   596  
   597  	b, err = a.NXActionHeader.MarshalBinary()
   598  	copy(data[n:], b)
   599  	n += len(b)
   600  	binary.BigEndian.PutUint16(data[n:], a.InPort)
   601  	n += 2
   602  	data[n] = a.TableID
   603  	n++
   604  	// Skip padding copy, move the index.
   605  	n += 3
   606  
   607  	return
   608  }
   609  
   610  func (a *NXActionResubmitTable) UnmarshalBinary(data []byte) error {
   611  	n := 0
   612  	a.NXActionHeader = new(NXActionHeader)
   613  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   614  	n += int(a.NXActionHeader.Len())
   615  	if len(data) < int(a.Len()) {
   616  		return errors.New("the []byte is too short to unmarshal a full NXActionResubmitTable message")
   617  	}
   618  	a.InPort = binary.BigEndian.Uint16(data[n:])
   619  	n += 2
   620  	a.TableID = data[n]
   621  	n++
   622  	// Skip padding copy, move the index.
   623  	n += 3
   624  
   625  	return err
   626  }
   627  
   628  func NewNXActionResubmitTableCT(inPort uint16, tableID uint8) *NXActionResubmitTable {
   629  	a := newNXActionResubmitTableCT()
   630  	a.InPort = inPort
   631  	a.TableID = tableID
   632  	return a
   633  }
   634  
   635  func NewNXActionResubmitTableCTNoInPort(tableID uint8) *NXActionResubmitTable {
   636  	a := newNXActionResubmitTableCT()
   637  	a.InPort = OFPP_IN_PORT
   638  	a.TableID = tableID
   639  	return a
   640  }
   641  
   642  // NXActionCTNAT is NX action to set NAT in conntrack.
   643  type NXActionCTNAT struct {
   644  	*NXActionHeader
   645  	pad          []byte // 2 bytes
   646  	Flags        uint16 // nat Flags to identify snat/dnat, and nat algorithms: random/protocolHash, connection persistent
   647  	rangePresent uint16 // mark if has set nat range, including ipv4/ipv6 range, port range
   648  
   649  	rangeIPv4Min  net.IP
   650  	rangeIPv4Max  net.IP
   651  	rangeIPv6Min  net.IP
   652  	rangeIPv6Max  net.IP
   653  	rangeProtoMin *uint16
   654  	rangeProtoMax *uint16
   655  }
   656  
   657  func NewNXActionCTNAT() *NXActionCTNAT {
   658  	a := new(NXActionCTNAT)
   659  	a.NXActionHeader = NewNxActionHeader(NXAST_NAT)
   660  	a.Length = 16
   661  	a.pad = make([]byte, 2)
   662  	return a
   663  }
   664  
   665  func (a *NXActionCTNAT) Len() (n uint16) {
   666  	a.Length = ((a.Length + 7) / 8) * 8
   667  	return a.Length
   668  }
   669  
   670  func (a *NXActionCTNAT) MarshalBinary() (data []byte, err error) {
   671  	data = make([]byte, a.Len())
   672  	b := make([]byte, a.NXActionHeader.Len())
   673  	n := 0
   674  
   675  	b, err = a.NXActionHeader.MarshalBinary()
   676  	copy(data[n:], b)
   677  	n += len(b)
   678  	// Skip padding bytes
   679  	n += 2
   680  	binary.BigEndian.PutUint16(data[n:], a.Flags)
   681  	n += 2
   682  	binary.BigEndian.PutUint16(data[n:], a.rangePresent)
   683  	n += 2
   684  
   685  	if a.rangeIPv4Min != nil {
   686  		copy(data[n:], a.rangeIPv4Min.To4())
   687  		n += 4
   688  	}
   689  	if a.rangeIPv4Max != nil {
   690  		copy(data[n:], a.rangeIPv4Max.To4())
   691  		n += 4
   692  	}
   693  	if a.rangeIPv6Min != nil {
   694  		copy(data[n:], a.rangeIPv6Min.To16())
   695  		n += 16
   696  	}
   697  	if a.rangeIPv6Max != nil {
   698  		copy(data[n:], a.rangeIPv6Max.To16())
   699  		n += 16
   700  	}
   701  	if a.rangeProtoMin != nil {
   702  		binary.BigEndian.PutUint16(data[n:], *a.rangeProtoMin)
   703  		n += 2
   704  	}
   705  	if a.rangeProtoMin != nil {
   706  		binary.BigEndian.PutUint16(data[n:], *a.rangeProtoMax)
   707  		n += 2
   708  	}
   709  
   710  	return
   711  }
   712  
   713  func (a *NXActionCTNAT) SetSNAT() error {
   714  	if a.Flags&NX_NAT_F_DST != 0 {
   715  		return errors.New("the SNAT and DNAT actions should be mutually exclusive")
   716  	}
   717  	a.Flags |= NX_NAT_F_SRC
   718  	return nil
   719  }
   720  
   721  func (a *NXActionCTNAT) SetDNAT() error {
   722  	if a.Flags&NX_NAT_F_SRC != 0 {
   723  		return errors.New("the DNAT and SNAT actions should be mutually exclusive")
   724  	}
   725  	a.Flags |= NX_NAT_F_DST
   726  	return nil
   727  }
   728  
   729  func (a *NXActionCTNAT) SetProtoHash() error {
   730  	if a.Flags&NX_NAT_F_PROTO_RANDOM != 0 {
   731  		return errors.New("protocol hash and random should be mutually exclusive")
   732  	}
   733  	a.Flags |= NX_NAT_F_PROTO_HASH
   734  	return nil
   735  }
   736  
   737  func (a *NXActionCTNAT) SetRandom() error {
   738  	if a.Flags&NX_NAT_F_PROTO_HASH != 0 {
   739  		return errors.New("random and protocol hash should be mutually exclusive")
   740  	}
   741  	a.Flags |= NX_NAT_F_PROTO_RANDOM
   742  	return nil
   743  }
   744  
   745  func (a *NXActionCTNAT) SetPersistent() error {
   746  	a.Flags |= NX_NAT_F_PERSISTENT
   747  	return nil
   748  }
   749  
   750  func (a *NXActionCTNAT) SetRangeIPv4Min(ipMin net.IP) {
   751  	a.rangeIPv4Min = ipMin
   752  	a.rangePresent |= NX_NAT_RANGE_IPV4_MIN
   753  	a.Length += 4
   754  }
   755  func (a *NXActionCTNAT) SetRangeIPv4Max(ipMax net.IP) {
   756  	a.rangeIPv4Max = ipMax
   757  	a.rangePresent |= NX_NAT_RANGE_IPV4_MAX
   758  	a.Length += 4
   759  }
   760  func (a *NXActionCTNAT) SetRangeIPv6Min(ipMin net.IP) {
   761  	a.rangeIPv6Min = ipMin
   762  	a.rangePresent |= NX_NAT_RANGE_IPV6_MIN
   763  	a.Length += 16
   764  }
   765  func (a *NXActionCTNAT) SetRangeIPv6Max(ipMax net.IP) {
   766  	a.rangeIPv6Max = ipMax
   767  	a.rangePresent |= NX_NAT_RANGE_IPV6_MAX
   768  	a.Length += 16
   769  }
   770  func (a *NXActionCTNAT) SetRangeProtoMin(protoMin *uint16) {
   771  	a.rangeProtoMin = protoMin
   772  	a.rangePresent |= NX_NAT_RANGE_PROTO_MIN
   773  	a.Length += 2
   774  }
   775  func (a *NXActionCTNAT) SetRangeProtoMax(protoMax *uint16) {
   776  	a.rangeProtoMax = protoMax
   777  	a.rangePresent |= NX_NAT_RANGE_PROTO_MAX
   778  	a.Length += 2
   779  }
   780  
   781  func (a *NXActionCTNAT) UnmarshalBinary(data []byte) error {
   782  	n := 0
   783  	a.NXActionHeader = new(NXActionHeader)
   784  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   785  	n += int(a.NXActionHeader.Len())
   786  	if len(data) < int(a.Len()) {
   787  		return errors.New("the []byte is too short to unmarshal a full NXActionCTNAT message")
   788  	}
   789  	// Skip padding bytes
   790  	n += 2
   791  	a.Flags = binary.BigEndian.Uint16(data[n:])
   792  	n += 2
   793  	a.rangePresent = binary.BigEndian.Uint16(data[n:])
   794  	n += 2
   795  	if a.rangePresent&NX_NAT_RANGE_IPV4_MIN != 0 {
   796  		a.rangeIPv4Min = net.IPv4(data[n], data[n+1], data[n+2], data[n+3])
   797  		n += 4
   798  	}
   799  	if a.rangePresent&NX_NAT_RANGE_IPV4_MAX != 0 {
   800  		a.rangeIPv4Max = net.IPv4(data[n], data[n+1], data[n+2], data[n+3])
   801  		n += 4
   802  	}
   803  	if a.rangePresent&NX_NAT_RANGE_IPV6_MIN != 0 {
   804  		a.rangeIPv6Min = make([]byte, 16)
   805  		copy(a.rangeIPv6Min, data[n:n+16])
   806  		n += 16
   807  	}
   808  	if a.rangePresent&NX_NAT_RANGE_IPV6_MAX != 0 {
   809  		a.rangeIPv6Max = make([]byte, 16)
   810  		copy(a.rangeIPv6Max, data[n:n+16])
   811  		n += 16
   812  	}
   813  	if a.rangePresent&NX_NAT_RANGE_PROTO_MIN != 0 {
   814  		portMin := binary.BigEndian.Uint16(data[n:])
   815  		a.rangeProtoMin = &portMin
   816  		n += 2
   817  	}
   818  	if a.rangePresent&NX_NAT_RANGE_PROTO_MAX != 0 {
   819  		portMax := binary.BigEndian.Uint16(data[n:])
   820  		a.rangeProtoMax = &portMax
   821  		n += 2
   822  	}
   823  
   824  	return err
   825  }
   826  
   827  // NXActionOutputReg is NX action to output to a field with a specified range.
   828  type NXActionOutputReg struct {
   829  	*NXActionHeader
   830  	OfsNbits uint16      // (ofs << 6 | (Nbits -1)
   831  	SrcField *MatchField // source nxm_nx_reg
   832  	MaxLen   uint16      // Max length to send to controller if chosen port is OFPP_CONTROLLER
   833  	zero     [6]uint8    // 6 uint8 with all Value as 0, reserved
   834  }
   835  
   836  func (a *NXActionOutputReg) Len() (n uint16) {
   837  	return a.Length
   838  }
   839  
   840  func (a *NXActionOutputReg) MarshalBinary() (data []byte, err error) {
   841  	data = make([]byte, int(a.Len()))
   842  	var b []byte
   843  	n := 0
   844  
   845  	b, err = a.NXActionHeader.MarshalBinary()
   846  	copy(data[n:], b)
   847  	n += len(b)
   848  	binary.BigEndian.PutUint16(data[n:], a.OfsNbits)
   849  	n += 2
   850  	fieldHeaderData := a.SrcField.MarshalHeader()
   851  	binary.BigEndian.PutUint32(data[n:], fieldHeaderData)
   852  	n += 4
   853  	binary.BigEndian.PutUint16(data[n:], a.MaxLen)
   854  	n += 2
   855  	copy(data[n:], a.zero[0:])
   856  	n += 6
   857  
   858  	return
   859  }
   860  
   861  func (a *NXActionOutputReg) UnmarshalBinary(data []byte) error {
   862  	n := 0
   863  	a.NXActionHeader = new(NXActionHeader)
   864  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   865  	n += int(a.NXActionHeader.Len())
   866  	if len(data) < int(a.Len()) {
   867  		return errors.New("the []byte is too short to unmarshal a full NXActionOutputReg message")
   868  	}
   869  	a.OfsNbits = binary.BigEndian.Uint16(data[n:])
   870  	n += 2
   871  	a.SrcField = new(MatchField)
   872  	err = a.SrcField.UnmarshalHeader(data[n : n+4])
   873  	n += 4
   874  	a.MaxLen = binary.BigEndian.Uint16(data[n:])
   875  	return err
   876  }
   877  
   878  func newNXActionOutputReg() *NXActionOutputReg {
   879  	a := &NXActionOutputReg{
   880  		NXActionHeader: NewNxActionHeader(NXAST_OUTPUT_REG),
   881  		zero:           [6]uint8{},
   882  	}
   883  	a.Length = 24
   884  	return a
   885  }
   886  
   887  func NewOutputFromField(srcField *MatchField, ofsNbits uint16) *NXActionOutputReg {
   888  	a := newNXActionOutputReg()
   889  	a.SrcField = srcField
   890  	a.OfsNbits = ofsNbits
   891  	a.MaxLen = uint16(0xffff)
   892  	return a
   893  }
   894  
   895  func NewOutputFromFieldWithMaxLen(srcField *MatchField, ofsNbits uint16, maxLen uint16) *NXActionOutputReg {
   896  	a := newNXActionOutputReg()
   897  	a.SrcField = srcField
   898  	a.OfsNbits = ofsNbits
   899  	a.MaxLen = maxLen
   900  	return a
   901  }
   902  
   903  type NXActionDecTTL struct {
   904  	*NXActionHeader
   905  	controllers uint16   // number of controller
   906  	zeros       [4]uint8 // 4 byte with zeros
   907  }
   908  
   909  func (a *NXActionDecTTL) Len() (n uint16) {
   910  	return a.Length
   911  }
   912  
   913  func (a *NXActionDecTTL) MarshalBinary() (data []byte, err error) {
   914  	data = make([]byte, int(a.Len()))
   915  	var b []byte
   916  	n := 0
   917  
   918  	b, err = a.NXActionHeader.MarshalBinary()
   919  	copy(data[n:], b)
   920  	n += len(b)
   921  	binary.BigEndian.PutUint16(data[n:], a.controllers)
   922  	n += 2
   923  	copy(data[n:], a.zeros[0:])
   924  	return
   925  }
   926  
   927  func (a *NXActionDecTTL) UnmarshalBinary(data []byte) error {
   928  	n := 0
   929  	a.NXActionHeader = new(NXActionHeader)
   930  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   931  	n += int(a.NXActionHeader.Len())
   932  	if len(data) < int(a.Len()) {
   933  		return errors.New("the []byte is too short to unmarshal a full NXActionDecTTL message")
   934  	}
   935  	a.controllers = binary.BigEndian.Uint16(data[n:])
   936  	n += 2
   937  	a.zeros = [4]uint8{}
   938  	return err
   939  }
   940  
   941  func NewNXActionDecTTL() *NXActionDecTTL {
   942  	a := &NXActionDecTTL{
   943  		NXActionHeader: NewNxActionHeader(NXAST_DEC_TTL),
   944  		zeros:          [4]uint8{},
   945  	}
   946  	a.Length = 16
   947  	return a
   948  }
   949  
   950  type NXActionDecTTLCntIDs struct {
   951  	*NXActionHeader
   952  	controllers uint16   // number of controller
   953  	zeros       [4]uint8 // 4 byte with zeros
   954  	cntIDs      []uint16 // controller IDs
   955  }
   956  
   957  func (a *NXActionDecTTLCntIDs) Len() (n uint16) {
   958  	return a.Length
   959  }
   960  
   961  func (a *NXActionDecTTLCntIDs) MarshalBinary() (data []byte, err error) {
   962  	data = make([]byte, int(a.Len()))
   963  	var b []byte
   964  	n := 0
   965  
   966  	b, err = a.NXActionHeader.MarshalBinary()
   967  	copy(data[n:], b)
   968  	n += len(b)
   969  	binary.BigEndian.PutUint16(data[n:], a.controllers)
   970  	n += 2
   971  	copy(data[n:], a.zeros[0:])
   972  	n += 4
   973  	for _, id := range a.cntIDs {
   974  		binary.BigEndian.PutUint16(data[n:], id)
   975  		n += 2
   976  	}
   977  	return
   978  }
   979  
   980  func (a *NXActionDecTTLCntIDs) UnmarshalBinary(data []byte) error {
   981  	n := 0
   982  	a.NXActionHeader = new(NXActionHeader)
   983  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
   984  	n += int(a.NXActionHeader.Len())
   985  	if len(data) < int(a.Len()) {
   986  		return errors.New("the []byte is too short to unmarshal a full NXActionDecTTLCntIDs message")
   987  	}
   988  	a.controllers = binary.BigEndian.Uint16(data[n:])
   989  	n += 2
   990  	a.zeros = [4]uint8{}
   991  	n += 4
   992  	for i := 0; i < int(a.controllers); i++ {
   993  		id := binary.BigEndian.Uint16(data[n:])
   994  		a.cntIDs = append(a.cntIDs, id)
   995  		n += 2
   996  	}
   997  	return err
   998  }
   999  
  1000  func NewNXActionDecTTLCntIDs(controllers uint16, ids ...uint16) *NXActionDecTTLCntIDs {
  1001  	a := &NXActionDecTTLCntIDs{
  1002  		NXActionHeader: NewNxActionHeader(NXAST_DEC_TTL_CNT_IDS),
  1003  		controllers:    controllers,
  1004  		zeros:          [4]uint8{},
  1005  		cntIDs:         ids,
  1006  	}
  1007  	a.Length = 16 + uint16(2*len(ids))
  1008  	return a
  1009  }
  1010  
  1011  type NXLearnSpecHeader struct {
  1012  	src    bool
  1013  	dst    bool
  1014  	output bool
  1015  	nBits  uint16
  1016  	length uint16
  1017  }
  1018  
  1019  func (h *NXLearnSpecHeader) MarshalBinary() (data []byte, err error) {
  1020  	data = make([]byte, h.length)
  1021  	value := h.nBits
  1022  	if h.src {
  1023  		value |= 1 << LEARN_SPEC_HEADER_MATCH
  1024  	} else {
  1025  		value &^= 1 << LEARN_SPEC_HEADER_MATCH
  1026  	}
  1027  	if h.dst {
  1028  		value |= 1 << LEARN_SPEC_HEADER_LOAD
  1029  	} else {
  1030  		value &^= 1 << LEARN_SPEC_HEADER_LOAD
  1031  	}
  1032  	if h.output {
  1033  		value &^= 1 << LEARN_SPEC_HEADER_MATCH
  1034  		value |= 2 << LEARN_SPEC_HEADER_LOAD
  1035  	}
  1036  	binary.BigEndian.PutUint16(data[0:], value)
  1037  	return
  1038  }
  1039  
  1040  func (h *NXLearnSpecHeader) UnmarshalBinary(data []byte) error {
  1041  	if len(data) < 2 {
  1042  		return errors.New("the []byte is too short to unmarshal a full NXLearnSpecHeader message")
  1043  	}
  1044  	value := binary.BigEndian.Uint16(data)
  1045  	h.length = 2
  1046  	h.nBits = (0xffff >> 5) & value
  1047  	h.src = ((1 << LEARN_SPEC_HEADER_MATCH) & value) != 0
  1048  	h.dst = ((1 << LEARN_SPEC_HEADER_LOAD) & value) != 0
  1049  	h.output = ((2 << LEARN_SPEC_HEADER_LOAD) & value) != 0
  1050  	return nil
  1051  }
  1052  
  1053  func (h *NXLearnSpecHeader) Len() (n uint16) {
  1054  	return h.length
  1055  }
  1056  
  1057  func NewLearnHeaderMatchFromValue(nBits uint16) *NXLearnSpecHeader {
  1058  	return &NXLearnSpecHeader{src: true, dst: false, nBits: nBits, length: 2}
  1059  }
  1060  
  1061  func NewLearnHeaderMatchFromField(nBits uint16) *NXLearnSpecHeader {
  1062  	return &NXLearnSpecHeader{src: false, dst: false, nBits: nBits, length: 2}
  1063  }
  1064  
  1065  func NewLearnHeaderLoadFromValue(nBits uint16) *NXLearnSpecHeader {
  1066  	return &NXLearnSpecHeader{src: true, dst: true, nBits: nBits, length: 2}
  1067  }
  1068  
  1069  func NewLearnHeaderLoadFromField(nBits uint16) *NXLearnSpecHeader {
  1070  	return &NXLearnSpecHeader{src: false, dst: true, nBits: nBits, length: 2}
  1071  }
  1072  
  1073  func NewLearnHeaderOutputFromField(nBits uint16) *NXLearnSpecHeader {
  1074  	return &NXLearnSpecHeader{src: false, dst: false, output: true, nBits: nBits, length: 2}
  1075  }
  1076  
  1077  type NXLearnSpecField struct {
  1078  	Field *MatchField
  1079  	Ofs   uint16
  1080  }
  1081  
  1082  func (f *NXLearnSpecField) Len() uint16 {
  1083  	return uint16(6)
  1084  }
  1085  
  1086  func (f *NXLearnSpecField) MarshalBinary() (data []byte, err error) {
  1087  	data = make([]byte, f.Len())
  1088  	n := 0
  1089  	fieldValue := f.Field.MarshalHeader()
  1090  	binary.BigEndian.PutUint32(data[n:], fieldValue)
  1091  	n += 4
  1092  	binary.BigEndian.PutUint16(data[n:], f.Ofs)
  1093  	return
  1094  }
  1095  
  1096  func (f *NXLearnSpecField) UnmarshalBinary(data []byte) error {
  1097  	if len(data) < int(f.Len()) {
  1098  		return errors.New("the []byte is too short to unmarshal a full NXLearnSpecField message")
  1099  	}
  1100  	f.Field = new(MatchField)
  1101  	n := 0
  1102  	err := f.Field.UnmarshalHeader(data[n:])
  1103  	if err != nil {
  1104  		return err
  1105  	}
  1106  	n += 4
  1107  	f.Ofs = binary.BigEndian.Uint16(data[n:])
  1108  	return nil
  1109  }
  1110  
  1111  type NXLearnSpec struct {
  1112  	Header   *NXLearnSpecHeader
  1113  	SrcField *NXLearnSpecField
  1114  	DstField *NXLearnSpecField
  1115  	SrcValue []byte
  1116  }
  1117  
  1118  func (s *NXLearnSpec) Len() uint16 {
  1119  	length := s.Header.Len()
  1120  	if s.Header.src {
  1121  		length += 2 * ((s.Header.nBits + 15) / 16)
  1122  	} else {
  1123  		length += 6
  1124  	}
  1125  
  1126  	// Add the length of DstField if it is not to "output" to a port.
  1127  	if !s.Header.output {
  1128  		length += 6
  1129  	}
  1130  	return length
  1131  }
  1132  
  1133  func (s *NXLearnSpec) MarshalBinary() (data []byte, err error) {
  1134  	data = make([]byte, s.Len())
  1135  	n := 0
  1136  	b, err := s.Header.MarshalBinary()
  1137  	if err != nil {
  1138  		return data, err
  1139  	}
  1140  	copy(data[n:], b)
  1141  	n += len(b)
  1142  	var srcData []byte
  1143  	var srcDataLength int
  1144  	if s.Header.src {
  1145  		srcDataLength = int(2 * ((s.Header.nBits + 15) / 16))
  1146  		srcData = append(srcData, s.SrcValue[:srcDataLength]...)
  1147  	} else {
  1148  		srcData, err = s.SrcField.MarshalBinary()
  1149  		if err != nil {
  1150  			return data, err
  1151  		}
  1152  		srcDataLength = 6
  1153  	}
  1154  	copy(data[n:], srcData)
  1155  	n += srcDataLength
  1156  	if !s.Header.output {
  1157  		var dstData []byte
  1158  		dstData, err = s.DstField.MarshalBinary()
  1159  		if err != nil {
  1160  			return data, err
  1161  		}
  1162  		copy(data[n:], dstData)
  1163  	}
  1164  	return data, err
  1165  }
  1166  
  1167  func (s *NXLearnSpec) UnmarshalBinary(data []byte) error {
  1168  	var err error
  1169  	s.Header = new(NXLearnSpecHeader)
  1170  	err = s.Header.UnmarshalBinary(data)
  1171  	if err != nil {
  1172  		return err
  1173  	}
  1174  	n := s.Header.Len()
  1175  	if s.Header.src {
  1176  		srcDataLength := 2 * ((s.Header.nBits + 15) / 16)
  1177  		s.SrcValue = data[n : n+srcDataLength]
  1178  		n += srcDataLength
  1179  	} else {
  1180  		s.SrcField = new(NXLearnSpecField)
  1181  		err = s.SrcField.UnmarshalBinary(data[n:])
  1182  		if err != nil {
  1183  			return err
  1184  		}
  1185  		n += s.SrcField.Len()
  1186  	}
  1187  	if !s.Header.output {
  1188  		s.DstField = new(NXLearnSpecField)
  1189  		err = s.DstField.UnmarshalBinary(data[n:])
  1190  		if err != nil {
  1191  			return err
  1192  		}
  1193  		n += s.DstField.Len()
  1194  	}
  1195  
  1196  	return err
  1197  }
  1198  
  1199  type NXActionLearn struct {
  1200  	*NXActionHeader
  1201  	IdleTimeout    uint16
  1202  	HardTimeout    uint16
  1203  	Priority       uint16
  1204  	Cookie         uint64
  1205  	Flags          uint16
  1206  	TableID        uint8
  1207  	pad            uint8
  1208  	FinIdleTimeout uint16
  1209  	FinHardTimeout uint16
  1210  	LearnSpecs     []*NXLearnSpec
  1211  	pad2           []byte
  1212  }
  1213  
  1214  func (a *NXActionLearn) Len() uint16 {
  1215  	length := a.NXActionHeader.Len() + 22
  1216  	for _, s := range a.LearnSpecs {
  1217  		length += s.Len()
  1218  	}
  1219  	return 8 * ((length + 7) / 8)
  1220  }
  1221  
  1222  func (a *NXActionLearn) MarshalBinary() (data []byte, err error) {
  1223  	data = make([]byte, a.Len())
  1224  	var b []byte
  1225  	n := 0
  1226  	a.Length = a.Len()
  1227  	b, err = a.NXActionHeader.MarshalBinary()
  1228  	copy(data[n:], b)
  1229  	n += len(b)
  1230  	binary.BigEndian.PutUint16(data[n:], a.IdleTimeout)
  1231  	n += 2
  1232  	binary.BigEndian.PutUint16(data[n:], a.HardTimeout)
  1233  	n += 2
  1234  	binary.BigEndian.PutUint16(data[n:], a.Priority)
  1235  	n += 2
  1236  	binary.BigEndian.PutUint64(data[n:], a.Cookie)
  1237  	n += 8
  1238  	binary.BigEndian.PutUint16(data[n:], a.Flags)
  1239  	n += 2
  1240  	data[n] = a.TableID
  1241  	n += 2
  1242  	binary.BigEndian.PutUint16(data[n:], a.FinIdleTimeout)
  1243  	n += 2
  1244  	binary.BigEndian.PutUint16(data[n:], a.FinHardTimeout)
  1245  	n += 2
  1246  	for _, s := range a.LearnSpecs {
  1247  		b, err = s.MarshalBinary()
  1248  		if err != nil {
  1249  			return data, err
  1250  		}
  1251  		copy(data[n:], b)
  1252  		n += len(b)
  1253  	}
  1254  	return
  1255  }
  1256  
  1257  func (a *NXActionLearn) UnmarshalBinary(data []byte) error {
  1258  	n := 0
  1259  	a.NXActionHeader = new(NXActionHeader)
  1260  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
  1261  	if err != nil {
  1262  		return err
  1263  	}
  1264  	if len(data) < int(a.Length) {
  1265  		return errors.New("the []byte is too short to unmarshal a full NXActionLearn message")
  1266  	}
  1267  	n += int(a.NXActionHeader.Len())
  1268  	a.IdleTimeout = binary.BigEndian.Uint16(data[n:])
  1269  	n += 2
  1270  	a.HardTimeout = binary.BigEndian.Uint16(data[n:])
  1271  	n += 2
  1272  	a.Priority = binary.BigEndian.Uint16(data[n:])
  1273  	n += 2
  1274  	a.Cookie = binary.BigEndian.Uint64(data[n:])
  1275  	n += 8
  1276  	a.Flags = binary.BigEndian.Uint16(data[n:])
  1277  	n += 2
  1278  	a.TableID = data[n]
  1279  	n += 2
  1280  	a.FinIdleTimeout = binary.BigEndian.Uint16(data[n:])
  1281  	n += 2
  1282  	a.FinHardTimeout = binary.BigEndian.Uint16(data[n:])
  1283  	n += 2
  1284  	for n < int(a.Length) {
  1285  		if int(a.Length)-n < 8 {
  1286  			break
  1287  		}
  1288  		spec := new(NXLearnSpec)
  1289  		err = spec.UnmarshalBinary(data[n:])
  1290  		if err != nil {
  1291  			return err
  1292  		}
  1293  		a.LearnSpecs = append(a.LearnSpecs, spec)
  1294  		n += int(spec.Len())
  1295  	}
  1296  	return nil
  1297  }
  1298  
  1299  func NewNXActionLearn() *NXActionLearn {
  1300  	return &NXActionLearn{
  1301  		NXActionHeader: NewNxActionHeader(NXAST_LEARN),
  1302  	}
  1303  }
  1304  
  1305  type NXActionNote struct {
  1306  	*NXActionHeader
  1307  	Note []byte
  1308  }
  1309  
  1310  func (a *NXActionNote) Len() uint16 {
  1311  	length := a.NXActionHeader.Len() + uint16(len(a.Note))
  1312  	return 8 * ((length + 7) / 8)
  1313  }
  1314  
  1315  func (a *NXActionNote) MarshalBinary() (data []byte, err error) {
  1316  	data = make([]byte, a.Len())
  1317  	n := 0
  1318  	a.Length = a.Len()
  1319  	b, err := a.NXActionHeader.MarshalBinary()
  1320  	if err != nil {
  1321  		return data, err
  1322  	}
  1323  	copy(data[n:], b)
  1324  	n += len(b)
  1325  	copy(data[n:], a.Note)
  1326  	return
  1327  }
  1328  
  1329  func (a *NXActionNote) UnmarshalBinary(data []byte) error {
  1330  	a.NXActionHeader = new(NXActionHeader)
  1331  	err := a.NXActionHeader.UnmarshalBinary(data)
  1332  	if err != nil {
  1333  		return err
  1334  	}
  1335  	if len(data) < int(a.Length) {
  1336  		return errors.New("the []byte is too short to unmarshal a full NXActionNote message")
  1337  	}
  1338  	n := a.NXActionHeader.Len()
  1339  	a.Note = data[n:a.Length]
  1340  	return nil
  1341  }
  1342  
  1343  func NewNXActionNote() *NXActionNote {
  1344  	return &NXActionNote{
  1345  		NXActionHeader: NewNxActionHeader(NXAST_NOTE),
  1346  	}
  1347  }
  1348  
  1349  // NXActionRegLoad2 is NX action to load data to a specified field.
  1350  type NXActionRegLoad2 struct {
  1351  	*NXActionHeader
  1352  	DstField *MatchField
  1353  	pad      []byte
  1354  }
  1355  
  1356  func NewNXActionRegLoad2(dstField *MatchField) *NXActionRegLoad2 {
  1357  	a := new(NXActionRegLoad2)
  1358  	a.NXActionHeader = NewNxActionHeader(NXAST_REG_LOAD2)
  1359  	a.DstField = dstField
  1360  	return a
  1361  }
  1362  
  1363  func (a *NXActionRegLoad2) Len() (n uint16) {
  1364  	return 8 * ((a.NXActionHeader.Len() + a.DstField.Len() + 7) / 8)
  1365  }
  1366  
  1367  func (a *NXActionRegLoad2) MarshalBinary() (data []byte, err error) {
  1368  	data = make([]byte, int(a.Len()))
  1369  	var b []byte
  1370  	n := 0
  1371  	a.Length = a.Len()
  1372  	b, err = a.NXActionHeader.MarshalBinary()
  1373  	copy(data[n:], b)
  1374  	n += len(b)
  1375  	fieldData, err := a.DstField.MarshalBinary()
  1376  	if err != nil {
  1377  		return nil, err
  1378  	}
  1379  	copy(data[n:], fieldData)
  1380  	n += len(fieldData)
  1381  	return
  1382  }
  1383  
  1384  func (a *NXActionRegLoad2) UnmarshalBinary(data []byte) error {
  1385  	n := 0
  1386  	a.NXActionHeader = new(NXActionHeader)
  1387  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
  1388  	n += int(a.NXActionHeader.Len())
  1389  	if len(data) < int(a.Length) {
  1390  		return errors.New("the []byte is too short to unmarshal a full NXActionRegLoad2 message")
  1391  	}
  1392  	a.DstField = new(MatchField)
  1393  	err = a.DstField.UnmarshalBinary(data[n:])
  1394  	if err != nil {
  1395  		return err
  1396  	}
  1397  	return nil
  1398  }
  1399  
  1400  // NXActionController is NX action to output packet to the Controller set with a specified ID.
  1401  type NXActionController struct {
  1402  	*NXActionHeader
  1403  	MaxLen       uint16
  1404  	ControllerID uint16
  1405  	Reason       uint8
  1406  	pad          uint8
  1407  }
  1408  
  1409  func (a *NXActionController) Len() uint16 {
  1410  	return a.NXActionHeader.Len() + 6
  1411  }
  1412  
  1413  func (a *NXActionController) MarshalBinary() (data []byte, err error) {
  1414  	data = make([]byte, a.Len())
  1415  	var b []byte
  1416  	n := 0
  1417  	a.Length = a.Len()
  1418  	b, err = a.NXActionHeader.MarshalBinary()
  1419  	if err != nil {
  1420  		return nil, err
  1421  	}
  1422  	copy(data[n:], b)
  1423  	n += len(b)
  1424  	binary.BigEndian.PutUint16(data[n:], a.MaxLen)
  1425  	n += 2
  1426  	binary.BigEndian.PutUint16(data[n:], a.ControllerID)
  1427  	n += 2
  1428  	data[n] = a.Reason
  1429  	n += 1
  1430  
  1431  	return data, nil
  1432  }
  1433  
  1434  func (a *NXActionController) UnmarshalBinary(data []byte) error {
  1435  	a.NXActionHeader = new(NXActionHeader)
  1436  	n := 0
  1437  	err := a.NXActionHeader.UnmarshalBinary(data[n:])
  1438  	if err != nil {
  1439  		return err
  1440  	}
  1441  	if len(data) < int(a.Length) {
  1442  		return errors.New("the []byte is too short to unmarshal a full NXActionController message")
  1443  	}
  1444  	n += int(a.NXActionHeader.Len())
  1445  	a.MaxLen = binary.BigEndian.Uint16(data[n:])
  1446  	n += 2
  1447  	a.ControllerID = binary.BigEndian.Uint16(data[n:])
  1448  	n += 2
  1449  	a.Reason = data[n]
  1450  	n += 1
  1451  	return nil
  1452  }
  1453  
  1454  func NewNXActionController(controllerID uint16) *NXActionController {
  1455  	a := new(NXActionController)
  1456  	a.NXActionHeader = NewNxActionHeader(NXAST_CONTROLLER)
  1457  	a.ControllerID = controllerID
  1458  	a.Length = a.NXActionHeader.Len() + 6
  1459  	return a
  1460  }