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 }