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

     1  package openflow13
     2  
     3  // This file contains OFP 1.3 instruction defenitions
     4  
     5  import (
     6  	"encoding/binary"
     7  	"errors"
     8  
     9  	"github.com/contiv/libOpenflow/util"
    10  )
    11  
    12  // ofp_instruction_type 1.3
    13  const (
    14  	InstrType_GOTO_TABLE     = 1      /* Setup the next table in the lookup pipeline */
    15  	InstrType_WRITE_METADATA = 2      /* Setup the metadata field for use later in pipeline */
    16  	InstrType_WRITE_ACTIONS  = 3      /* Write the action(s) onto the datapath action set */
    17  	InstrType_APPLY_ACTIONS  = 4      /* Applies the action(s) immediately */
    18  	InstrType_CLEAR_ACTIONS  = 5      /* Clears all actions from the datapath action set */
    19  	InstrType_METER          = 6      /* Apply meter (rate limiter) */
    20  	InstrType_EXPERIMENTER   = 0xFFFF /* Experimenter instruction */
    21  )
    22  
    23  // Generic instruction header
    24  type InstrHeader struct {
    25  	Type   uint16
    26  	Length uint16
    27  }
    28  
    29  type Instruction interface {
    30  	util.Message
    31  	AddAction(act Action, prepend bool) error
    32  }
    33  
    34  func (a *InstrHeader) Len() (n uint16) {
    35  	return 4
    36  }
    37  
    38  func (a *InstrHeader) MarshalBinary() (data []byte, err error) {
    39  	data = make([]byte, a.Len())
    40  	binary.BigEndian.PutUint16(data[:2], a.Type)
    41  	binary.BigEndian.PutUint16(data[2:4], a.Length)
    42  	return
    43  }
    44  
    45  func (a *InstrHeader) UnmarshalBinary(data []byte) error {
    46  	if len(data) != 4 {
    47  		return errors.New("Wrong size to unmarshal an InstrHeader message.")
    48  	}
    49  	a.Type = binary.BigEndian.Uint16(data[:2])
    50  	a.Length = binary.BigEndian.Uint16(data[2:4])
    51  	return nil
    52  }
    53  
    54  func DecodeInstr(data []byte) Instruction {
    55  	t := binary.BigEndian.Uint16(data[:2])
    56  	var a Instruction
    57  	switch t {
    58  	case InstrType_GOTO_TABLE:
    59  		a = new(InstrGotoTable)
    60  	case InstrType_WRITE_METADATA:
    61  		a = new(InstrWriteMetadata)
    62  	case InstrType_WRITE_ACTIONS:
    63  		a = new(InstrActions)
    64  	case InstrType_APPLY_ACTIONS:
    65  		a = new(InstrActions)
    66  	case InstrType_CLEAR_ACTIONS:
    67  		a = new(InstrActions)
    68  	case InstrType_METER:
    69  		a = new(InstrMeter)
    70  	case InstrType_EXPERIMENTER:
    71  	}
    72  
    73  	a.UnmarshalBinary(data)
    74  	return a
    75  }
    76  
    77  type InstrGotoTable struct {
    78  	InstrHeader
    79  	TableId uint8
    80  	pad     []byte // 3 bytes
    81  }
    82  
    83  func (instr *InstrGotoTable) Len() (n uint16) {
    84  	return 8
    85  }
    86  
    87  func (instr *InstrGotoTable) MarshalBinary() (data []byte, err error) {
    88  	data, err = instr.InstrHeader.MarshalBinary()
    89  
    90  	b := make([]byte, 4)
    91  	b[0] = instr.TableId
    92  	copy(b[3:], instr.pad)
    93  
    94  	data = append(data, b...)
    95  	return
    96  }
    97  
    98  func (instr *InstrGotoTable) UnmarshalBinary(data []byte) error {
    99  	instr.InstrHeader.UnmarshalBinary(data[:4])
   100  
   101  	instr.TableId = data[4]
   102  	copy(instr.pad, data[5:8])
   103  
   104  	return nil
   105  }
   106  
   107  func NewInstrGotoTable(tableId uint8) *InstrGotoTable {
   108  	instr := new(InstrGotoTable)
   109  	instr.Type = InstrType_GOTO_TABLE
   110  	instr.TableId = tableId
   111  	instr.pad = make([]byte, 3)
   112  	instr.Length = instr.Len()
   113  
   114  	return instr
   115  }
   116  
   117  func (instr *InstrGotoTable) AddAction(act Action, prepend bool) error {
   118  	return errors.New("Not supported on this instrction")
   119  }
   120  
   121  type InstrWriteMetadata struct {
   122  	InstrHeader
   123  	pad          []byte // 4 bytes
   124  	Metadata     uint64 /* Metadata value to write */
   125  	MetadataMask uint64 /* Metadata write bitmask */
   126  }
   127  
   128  // FIXME: we need marshall/unmarshall/len/new functions for write metadata instr
   129  func (instr *InstrWriteMetadata) Len() (n uint16) {
   130  	return 24
   131  }
   132  
   133  func (instr *InstrWriteMetadata) MarshalBinary() (data []byte, err error) {
   134  	data, err = instr.InstrHeader.MarshalBinary()
   135  
   136  	b := make([]byte, 20)
   137  	copy(b, instr.pad)
   138  	binary.BigEndian.PutUint64(b[4:], instr.Metadata)
   139  	binary.BigEndian.PutUint64(b[12:], instr.MetadataMask)
   140  
   141  	data = append(data, b...)
   142  	return
   143  }
   144  
   145  func (instr *InstrWriteMetadata) UnmarshalBinary(data []byte) error {
   146  	instr.InstrHeader.UnmarshalBinary(data[:4])
   147  
   148  	copy(instr.pad, data[4:8])
   149  	instr.Metadata = binary.BigEndian.Uint64(data[8:16])
   150  	instr.MetadataMask = binary.BigEndian.Uint64(data[16:24])
   151  
   152  	return nil
   153  }
   154  
   155  func NewInstrWriteMetadata(metadata, metadataMask uint64) *InstrWriteMetadata {
   156  	instr := new(InstrWriteMetadata)
   157  	instr.Type = InstrType_WRITE_METADATA
   158  	instr.pad = make([]byte, 4)
   159  	instr.Metadata = metadata
   160  	instr.MetadataMask = metadataMask
   161  	instr.Length = instr.Len()
   162  
   163  	return instr
   164  }
   165  
   166  func (instr *InstrWriteMetadata) AddAction(act Action, prepend bool) error {
   167  	return errors.New("Not supported on this instrction")
   168  }
   169  
   170  // *_ACTION instructions
   171  type InstrActions struct {
   172  	InstrHeader
   173  	pad     []byte   // 4 bytes
   174  	Actions []Action /* 0 or more actions associated with OFPIT_WRITE_ACTIONS and OFPIT_APPLY_ACTIONS */
   175  }
   176  
   177  func (instr *InstrActions) Len() (n uint16) {
   178  	n = 8
   179  
   180  	for _, act := range instr.Actions {
   181  		n += act.Len()
   182  	}
   183  
   184  	return
   185  }
   186  
   187  func (instr *InstrActions) MarshalBinary() (data []byte, err error) {
   188  	data, err = instr.InstrHeader.MarshalBinary()
   189  
   190  	b := make([]byte, 4)
   191  	copy(b, instr.pad)
   192  	data = append(data, b...)
   193  
   194  	for _, act := range instr.Actions {
   195  		b, err = act.MarshalBinary()
   196  		data = append(data, b...)
   197  	}
   198  
   199  	return
   200  }
   201  
   202  func (instr *InstrActions) UnmarshalBinary(data []byte) error {
   203  	instr.InstrHeader.UnmarshalBinary(data[:4])
   204  
   205  	n := 8
   206  	for n < int(instr.Length) {
   207  		act, err := DecodeAction(data[n:])
   208  		if err != nil {
   209  			return err
   210  		}
   211  		instr.Actions = append(instr.Actions, act)
   212  		n += int(act.Len())
   213  	}
   214  
   215  	return nil
   216  }
   217  
   218  func (instr *InstrActions) AddAction(act Action, prepend bool) error {
   219  	// Append or prepend to the list
   220  	if prepend {
   221  		instr.Actions = append([]Action{act}, instr.Actions...)
   222  	} else {
   223  		instr.Actions = append(instr.Actions, act)
   224  	}
   225  
   226  	instr.Length = instr.Len()
   227  	return nil
   228  }
   229  
   230  func NewInstrWriteActions() *InstrActions {
   231  	instr := new(InstrActions)
   232  	instr.Type = InstrType_WRITE_ACTIONS
   233  	instr.pad = make([]byte, 4)
   234  	instr.Actions = make([]Action, 0)
   235  	instr.Length = instr.Len()
   236  
   237  	return instr
   238  }
   239  
   240  func NewInstrApplyActions() *InstrActions {
   241  	instr := new(InstrActions)
   242  	instr.Type = InstrType_APPLY_ACTIONS
   243  	instr.pad = make([]byte, 4)
   244  	instr.Actions = make([]Action, 0)
   245  	instr.Length = instr.Len()
   246  
   247  	return instr
   248  }
   249  
   250  type InstrMeter struct {
   251  	InstrHeader
   252  	MeterId uint32
   253  }
   254  
   255  func NewInstrMeter(meterId uint32) *InstrMeter {
   256  	instr := new(InstrMeter)
   257  	instr.Type = InstrType_METER
   258  	instr.MeterId = meterId
   259  	instr.Length = instr.Len()
   260  
   261  	return instr
   262  }
   263  
   264  func (instr *InstrMeter) Len() (n uint16) {
   265  	return 8
   266  }
   267  
   268  func (instr *InstrMeter) MarshalBinary() (data []byte, err error) {
   269  	data, err = instr.InstrHeader.MarshalBinary()
   270  
   271  	b := make([]byte, 4)
   272  	binary.BigEndian.PutUint32(b, instr.MeterId)
   273  
   274  	data = append(data, b...)
   275  
   276  	return
   277  }
   278  
   279  func (instr *InstrMeter) UnmarshalBinary(data []byte) error {
   280  	instr.InstrHeader.UnmarshalBinary(data[:4])
   281  
   282  	instr.MeterId = binary.BigEndian.Uint32(data[4:8])
   283  
   284  	return nil
   285  }
   286  
   287  func (instr *InstrMeter) AddAction(act Action, prepend bool) error {
   288  	return errors.New("Not supported on this instrction")
   289  }