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 }