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

     1  package openflow13
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  
     7  	"github.com/contiv/libOpenflow/util"
     8  )
     9  
    10  // ofp_action_type 1.3
    11  const (
    12  	ActionType_Output     = 0
    13  	ActionType_CopyTtlOut = 11
    14  	ActionType_CopyTtlIn  = 12
    15  	ActionType_SetMplsTtl = 15
    16  	ActionType_DecMplsTtl = 16
    17  	ActionType_PushVlan   = 17
    18  	ActionType_PopVlan    = 18
    19  	ActionType_PushMpls   = 19
    20  	ActionType_PopMpls    = 20
    21  	ActionType_SetQueue   = 21
    22  	ActionType_Group      = 22
    23  	ActionType_SetNwTtl   = 23
    24  	ActionType_DecNwTtl   = 24
    25  	ActionType_SetField   = 25
    26  	ActionType_PushPbb    = 26
    27  	ActionType_PopPbb     = 27
    28  
    29  	ActionType_Experimenter = 0xffff
    30  )
    31  
    32  type Action interface {
    33  	Header() *ActionHeader
    34  	util.Message
    35  }
    36  
    37  type ActionHeader struct {
    38  	Type   uint16
    39  	Length uint16
    40  }
    41  
    42  func (a *ActionHeader) Header() *ActionHeader {
    43  	return a
    44  }
    45  
    46  func (a *ActionHeader) Len() (n uint16) {
    47  	return 4
    48  }
    49  
    50  func (a *ActionHeader) MarshalBinary() (data []byte, err error) {
    51  	data = make([]byte, a.Len())
    52  	binary.BigEndian.PutUint16(data[:2], a.Type)
    53  	binary.BigEndian.PutUint16(data[2:4], a.Length)
    54  	return
    55  }
    56  
    57  func (a *ActionHeader) UnmarshalBinary(data []byte) error {
    58  	if len(data) < int(a.Len()) {
    59  		return errors.New("The []byte the wrong size to unmarshal an " +
    60  			"ActionHeader message.")
    61  	}
    62  	a.Type = binary.BigEndian.Uint16(data[:2])
    63  	a.Length = binary.BigEndian.Uint16(data[2:4])
    64  	return nil
    65  }
    66  
    67  // Decode Action types.
    68  func DecodeAction(data []byte) (Action, error) {
    69  	t := binary.BigEndian.Uint16(data[:2])
    70  	var a Action
    71  	switch t {
    72  	case ActionType_Output:
    73  		a = new(ActionOutput)
    74  	case ActionType_CopyTtlOut:
    75  		a = new(ActionHeader)
    76  	case ActionType_CopyTtlIn:
    77  		a = new(ActionHeader)
    78  	case ActionType_SetMplsTtl:
    79  		a = new(ActionMplsTtl)
    80  	case ActionType_DecMplsTtl:
    81  		a = new(ActionHeader)
    82  	case ActionType_PushVlan:
    83  		a = new(ActionPush)
    84  	case ActionType_PopVlan:
    85  		a = new(ActionHeader)
    86  	case ActionType_PushMpls:
    87  		a = new(ActionPush)
    88  	case ActionType_PopMpls:
    89  		a = new(ActionPopMpls)
    90  	case ActionType_SetQueue:
    91  		a = new(ActionSetqueue)
    92  	case ActionType_Group:
    93  		a = new(ActionGroup)
    94  	case ActionType_SetNwTtl:
    95  		a = new(ActionNwTtl)
    96  	case ActionType_DecNwTtl:
    97  		a = new(ActionDecNwTtl)
    98  	case ActionType_SetField:
    99  		a = new(ActionSetField)
   100  	case ActionType_PushPbb:
   101  		a = new(ActionPush)
   102  	case ActionType_PopPbb:
   103  		a = new(ActionHeader)
   104  	case ActionType_Experimenter:
   105  		// For Experimenter message, the length of action should be at least 10 bytes,
   106  		// including type(2 byte), length(2 byte), vendor(4 byte), and subtype(2 byte)
   107  		if len(data) < NxActionHeaderLength {
   108  			return nil, errors.New("the []byte is too short to decode OpenFlow experimenter message")
   109  		}
   110  		v := binary.BigEndian.Uint32(data[4:8])
   111  		if v == NxExperimenterID {
   112  			a = DecodeNxAction(data)
   113  		}
   114  	}
   115  	err := a.UnmarshalBinary(data)
   116  	if err != nil {
   117  		return a, err
   118  	}
   119  	return a, nil
   120  }
   121  
   122  // Action structure for OFPAT_OUTPUT, which sends packets out ’port’.
   123  // When the ’port’ is the OFPP_CONTROLLER, ’max_len’ indicates the max
   124  // number of bytes to send. A ’max_len’ of zero means no bytes of the
   125  // packet should be sent.
   126  type ActionOutput struct {
   127  	ActionHeader
   128  	Port   uint32
   129  	MaxLen uint16
   130  	pad    []byte // 6 bytes to make it 64bit aligned
   131  }
   132  
   133  // ofp_controller_max_len 1.3
   134  const (
   135  	OFPCML_MAX       = 0xffe5 /* maximum max_len value which can be used to request a specific byte length. */
   136  	OFPCML_NO_BUFFER = 0xffff /* indicates that no buffering should be applied and the whole packet is to be sent to the controller. */
   137  )
   138  
   139  // Returns a new Action Output message which sends packets out
   140  // port number.
   141  func NewActionOutput(portNum uint32) *ActionOutput {
   142  	act := new(ActionOutput)
   143  	act.Type = ActionType_Output
   144  	act.Length = act.Len()
   145  	act.Port = portNum
   146  	act.MaxLen = 256
   147  	act.pad = make([]byte, 6)
   148  	return act
   149  }
   150  
   151  func (a *ActionOutput) Len() (n uint16) {
   152  	return a.ActionHeader.Len() + 12
   153  }
   154  
   155  func (a *ActionOutput) MarshalBinary() (data []byte, err error) {
   156  	data = make([]byte, int(a.Len()))
   157  	b := make([]byte, 0)
   158  	n := 0
   159  
   160  	b, err = a.ActionHeader.MarshalBinary()
   161  	copy(data[n:], b)
   162  	n += len(b)
   163  	binary.BigEndian.PutUint32(data[n:], a.Port)
   164  	n += 4
   165  	binary.BigEndian.PutUint16(data[n:], a.MaxLen)
   166  	n += 2
   167  	copy(data[n:], a.pad)
   168  	n += len(a.pad)
   169  
   170  	return
   171  }
   172  
   173  func (a *ActionOutput) UnmarshalBinary(data []byte) error {
   174  	if len(data) < int(a.Len()) {
   175  		return errors.New("The []byte the wrong size to unmarshal an " +
   176  			"ActionOutput message.")
   177  	}
   178  	n := 0
   179  	err := a.ActionHeader.UnmarshalBinary(data[n:])
   180  	n += int(a.ActionHeader.Len())
   181  	a.Port = binary.BigEndian.Uint32(data[n:])
   182  	n += 4
   183  	a.MaxLen = binary.BigEndian.Uint16(data[n:])
   184  	n += 2
   185  	copy(a.pad, data[n:n+6])
   186  	n += 6
   187  	return err
   188  }
   189  
   190  type ActionSetqueue struct {
   191  	ActionHeader
   192  	QueueId uint32
   193  }
   194  
   195  func NewActionSetQueue(queue uint32) *ActionSetqueue {
   196  	a := new(ActionSetqueue)
   197  	a.Type = ActionType_SetQueue
   198  	a.Length = a.Len()
   199  	a.QueueId = queue
   200  	return a
   201  }
   202  
   203  func (a *ActionSetqueue) Len() (n uint16) {
   204  	return a.ActionHeader.Len() + 4
   205  }
   206  
   207  func (a *ActionSetqueue) MarshalBinary() (data []byte, err error) {
   208  	data, err = a.ActionHeader.MarshalBinary()
   209  
   210  	bytes := make([]byte, 4)
   211  	binary.BigEndian.PutUint32(bytes[0:], a.QueueId)
   212  
   213  	data = append(data, bytes...)
   214  	return
   215  }
   216  
   217  func (a *ActionSetqueue) UnmarshalBinary(data []byte) error {
   218  	if len(data) != int(a.Len()) {
   219  		return errors.New("The []byte the wrong size to unmarshal an " +
   220  			"ActionEnqueue message.")
   221  	}
   222  	a.ActionHeader.UnmarshalBinary(data[:4])
   223  	a.QueueId = binary.BigEndian.Uint32(data[4:8])
   224  	return nil
   225  }
   226  
   227  type ActionGroup struct {
   228  	ActionHeader
   229  	GroupId uint32
   230  }
   231  
   232  func NewActionGroup(group uint32) *ActionGroup {
   233  	a := new(ActionGroup)
   234  	a.Type = ActionType_Group
   235  	a.Length = a.Len()
   236  	a.GroupId = group
   237  	return a
   238  }
   239  
   240  func (a *ActionGroup) Len() (n uint16) {
   241  	return a.ActionHeader.Len() + 4
   242  }
   243  
   244  func (a *ActionGroup) MarshalBinary() (data []byte, err error) {
   245  	data = make([]byte, int(a.Len()))
   246  	b := make([]byte, 0)
   247  	n := 0
   248  
   249  	b, err = a.ActionHeader.MarshalBinary()
   250  	copy(data[n:], b)
   251  	n += len(b)
   252  	binary.BigEndian.PutUint32(data[n:], a.GroupId)
   253  	n += 4
   254  
   255  	return
   256  }
   257  
   258  func (a *ActionGroup) UnmarshalBinary(data []byte) error {
   259  	if len(data) < int(a.Len()) {
   260  		return errors.New("The []byte the wrong size to unmarshal an " +
   261  			"ActionOutput message.")
   262  	}
   263  	n := 0
   264  	err := a.ActionHeader.UnmarshalBinary(data[n:])
   265  	n += int(a.ActionHeader.Len())
   266  	a.GroupId = binary.BigEndian.Uint32(data[n:])
   267  	n += 4
   268  
   269  	return err
   270  }
   271  
   272  type ActionMplsTtl struct {
   273  	ActionHeader
   274  	MplsTtl uint8
   275  	pad     []byte // 3bytes
   276  }
   277  
   278  type ActionDecNwTtl struct {
   279  	ActionHeader
   280  	pad []byte // 4bytes
   281  }
   282  
   283  func NewActionDecNwTtl() *ActionDecNwTtl {
   284  	act := new(ActionDecNwTtl)
   285  	act.Type = ActionType_DecNwTtl
   286  	act.Length = act.Len()
   287  	act.pad = make([]byte, 4)
   288  	return act
   289  }
   290  
   291  func (a *ActionDecNwTtl) Len() (n uint16) {
   292  	return a.ActionHeader.Len() + 4
   293  }
   294  
   295  func (a *ActionDecNwTtl) MarshalBinary() (data []byte, err error) {
   296  	data, err = a.ActionHeader.MarshalBinary()
   297  	if err != nil {
   298  		return
   299  	}
   300  
   301  	// Padding
   302  	bytes := make([]byte, 4)
   303  	data = append(data, bytes...)
   304  	return
   305  }
   306  
   307  func (a *ActionDecNwTtl) UnmarshalBinary(data []byte) error {
   308  	return a.ActionHeader.UnmarshalBinary(data[:4])
   309  }
   310  
   311  type ActionNwTtl struct {
   312  	ActionHeader
   313  	NwTtl uint8
   314  	pad   []byte // 3bytes
   315  }
   316  
   317  type ActionPush struct {
   318  	ActionHeader
   319  	EtherType uint16
   320  	pad       []byte // 2bytes
   321  }
   322  
   323  func NewActionPushVlan(etherType uint16) *ActionPush {
   324  	a := new(ActionPush)
   325  	a.Type = ActionType_PushVlan
   326  	a.Length = a.Len()
   327  	a.EtherType = etherType
   328  	return a
   329  }
   330  
   331  func NewActionPushMpls(etherType uint16) *ActionPush {
   332  	a := new(ActionPush)
   333  	a.Type = ActionType_PushMpls
   334  	a.Length = a.Len()
   335  	a.EtherType = etherType
   336  	return a
   337  }
   338  
   339  func (a *ActionPush) Len() (n uint16) {
   340  	return a.ActionHeader.Len() + 4
   341  }
   342  
   343  func (a *ActionPush) MarshalBinary() (data []byte, err error) {
   344  	data, err = a.ActionHeader.MarshalBinary()
   345  
   346  	bytes := make([]byte, 4)
   347  	binary.BigEndian.PutUint16(bytes[0:], a.EtherType)
   348  
   349  	data = append(data, bytes...)
   350  	return
   351  }
   352  
   353  func (a *ActionPush) UnmarshalBinary(data []byte) error {
   354  	a.ActionHeader.UnmarshalBinary(data[:4])
   355  	a.EtherType = binary.BigEndian.Uint16(data[4:])
   356  	return nil
   357  }
   358  
   359  type ActionPopVlan struct {
   360  	ActionHeader
   361  	pad []byte // 4bytes
   362  }
   363  
   364  func NewActionPopVlan() *ActionPopVlan {
   365  	act := new(ActionPopVlan)
   366  	act.Type = ActionType_PopVlan
   367  	act.Length = act.Len()
   368  
   369  	return act
   370  }
   371  
   372  func (a *ActionPopVlan) Len() (n uint16) {
   373  	return a.ActionHeader.Len() + 4
   374  }
   375  
   376  func (a *ActionPopVlan) MarshalBinary() (data []byte, err error) {
   377  	data, err = a.ActionHeader.MarshalBinary()
   378  
   379  	// Padding
   380  	bytes := make([]byte, 4)
   381  
   382  	data = append(data, bytes...)
   383  	return
   384  }
   385  
   386  func (a *ActionPopVlan) UnmarshalBinary(data []byte) error {
   387  	a.ActionHeader.UnmarshalBinary(data[:4])
   388  	return nil
   389  }
   390  
   391  type ActionPopMpls struct {
   392  	ActionHeader
   393  	EtherType uint16
   394  	pad       []byte // 2bytes
   395  }
   396  
   397  func NewActionPopMpls(etherType uint16) *ActionPopMpls {
   398  	act := new(ActionPopMpls)
   399  	act.Type = ActionType_PopMpls
   400  	act.EtherType = etherType
   401  	act.Length = act.Len()
   402  
   403  	return act
   404  }
   405  
   406  func (a *ActionPopMpls) Len() (n uint16) {
   407  	return a.ActionHeader.Len() + 4
   408  }
   409  
   410  func (a *ActionPopMpls) MarshalBinary() (data []byte, err error) {
   411  	data, err = a.ActionHeader.MarshalBinary()
   412  
   413  	// Padding
   414  	bytes := make([]byte, 4)
   415  	binary.BigEndian.PutUint16(bytes[0:], a.EtherType)
   416  
   417  	data = append(data, bytes...)
   418  	return
   419  }
   420  
   421  func (a *ActionPopMpls) UnmarshalBinary(data []byte) error {
   422  	a.ActionHeader.UnmarshalBinary(data[:4])
   423  	a.EtherType = binary.BigEndian.Uint16(data[4:])
   424  	return nil
   425  }
   426  
   427  type ActionSetField struct {
   428  	ActionHeader
   429  	Field MatchField
   430  }
   431  
   432  func NewActionSetField(field MatchField) *ActionSetField {
   433  	a := new(ActionSetField)
   434  	a.Type = ActionType_SetField
   435  	a.Field = field
   436  	a.Length = a.Len()
   437  	return a
   438  }
   439  
   440  func (a *ActionSetField) Len() (n uint16) {
   441  	n = a.ActionHeader.Len() + a.Field.Len()
   442  	// Round it to closest multiple of 8
   443  	n = ((n + 7) / 8) * 8
   444  
   445  	return
   446  }
   447  
   448  func (a *ActionSetField) MarshalBinary() (data []byte, err error) {
   449  	data = make([]byte, int(a.Len()))
   450  	n := 0
   451  	b, err := a.ActionHeader.MarshalBinary()
   452  	copy(data, b)
   453  	n += int(a.ActionHeader.Len())
   454  
   455  	b, err = a.Field.MarshalBinary()
   456  	copy(data[n:], b)
   457  
   458  	return
   459  }
   460  func (a *ActionSetField) UnmarshalBinary(data []byte) error {
   461  	n := 0
   462  	err := a.ActionHeader.UnmarshalBinary(data[n:])
   463  	n += int(a.ActionHeader.Len())
   464  	err = a.Field.UnmarshalBinary(data[n:])
   465  	n += int(a.Field.Len())
   466  
   467  	return err
   468  }