github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/openflow13/openflow13.go (about) 1 package openflow13 2 3 // Package openflow13 provides OpenFlow 1.3 structs along with Read 4 // and Write methods for each. 5 // OpenFlow Wire Protocol 0x04 6 // 7 // Struct documentation is taken from the OpenFlow Switch 8 // Specification Version 1.3.3. 9 // https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.3.3.pdf 10 11 import ( 12 "encoding/binary" 13 "errors" 14 "net" 15 16 "github.com/contiv/libOpenflow/common" 17 "github.com/contiv/libOpenflow/protocol" 18 "github.com/contiv/libOpenflow/util" 19 ) 20 21 const ( 22 VERSION = 4 23 ) 24 25 // Returns a new OpenFlow header with version field set to v1.3. 26 var NewOfp13Header func() common.Header = common.NewHeaderGenerator(VERSION) 27 28 // Echo request/reply messages can be sent from either the 29 // switch or the controller, and must return an echo reply. They 30 // can be used to indicate the latency, bandwidth, and/or 31 // liveness of a controller-switch connection. 32 func NewEchoRequest() *common.Header { 33 h := NewOfp13Header() 34 h.Type = Type_EchoRequest 35 return &h 36 } 37 38 // Echo request/reply messages can be sent from either the 39 // switch or the controller, and must return an echo reply. They 40 // can be used to indicate the latency, bandwidth, and/or 41 // liveness of a controller-switch connection. 42 func NewEchoReply() *common.Header { 43 h := NewOfp13Header() 44 h.Type = Type_EchoReply 45 return &h 46 } 47 48 // ofp_type 1.3 49 const ( 50 /* Immutable messages. */ 51 Type_Hello = 0 52 Type_Error = 1 53 Type_EchoRequest = 2 54 Type_EchoReply = 3 55 Type_Experimenter = 4 56 57 /* Switch configuration messages. */ 58 Type_FeaturesRequest = 5 59 Type_FeaturesReply = 6 60 Type_GetConfigRequest = 7 61 Type_GetConfigReply = 8 62 Type_SetConfig = 9 63 64 /* Asynchronous messages. */ 65 Type_PacketIn = 10 66 Type_FlowRemoved = 11 67 Type_PortStatus = 12 68 69 /* Controller command messages. */ 70 Type_PacketOut = 13 71 Type_FlowMod = 14 72 Type_GroupMod = 15 73 Type_PortMod = 16 74 Type_TableMod = 17 75 76 /* Multipart messages. */ 77 Type_MultiPartRequest = 18 78 Type_MultiPartReply = 19 79 80 /* Barrier messages. */ 81 Type_BarrierRequest = 20 82 Type_BarrierReply = 21 83 84 /* Queue Configuration messages. */ 85 Type_QueueGetConfigRequest = 22 86 Type_QueueGetConfigReply = 23 87 88 /* Controller role change request messages. */ 89 Type_RoleRequest = 24 90 Type_RoleReply = 25 91 92 /* Asynchronous message configuration. */ 93 Type_GetAsyncRequest = 26 94 Type_GetAsyncReply = 27 95 Type_SetAsync = 28 96 97 /* Meters and rate limiters configuration messages. */ 98 Type_MeterMod = 29 99 ) 100 101 func Parse(b []byte) (message util.Message, err error) { 102 switch b[1] { 103 case Type_Hello: 104 message = new(common.Hello) 105 err = message.UnmarshalBinary(b) 106 case Type_Error: 107 errMsg := new(ErrorMsg) 108 err = errMsg.UnmarshalBinary(b) 109 if err != nil { 110 return 111 } 112 switch errMsg.Type { 113 case ET_EXPERIMENTER: 114 message = new(VendorError) 115 err = message.UnmarshalBinary(b) 116 default: 117 message = errMsg 118 } 119 case Type_EchoRequest: 120 message = new(common.Header) 121 err = message.UnmarshalBinary(b) 122 case Type_EchoReply: 123 message = new(common.Header) 124 err = message.UnmarshalBinary(b) 125 case Type_Experimenter: 126 message = new(VendorHeader) 127 err = message.UnmarshalBinary(b) 128 case Type_FeaturesRequest: 129 message = NewFeaturesRequest() 130 err = message.UnmarshalBinary(b) 131 case Type_FeaturesReply: 132 message = NewFeaturesReply() 133 err = message.UnmarshalBinary(b) 134 case Type_GetConfigRequest: 135 message = new(common.Header) 136 err = message.UnmarshalBinary(b) 137 case Type_GetConfigReply: 138 message = new(SwitchConfig) 139 err = message.UnmarshalBinary(b) 140 case Type_SetConfig: 141 message = NewSetConfig() 142 err = message.UnmarshalBinary(b) 143 case Type_PacketIn: 144 message = new(PacketIn) 145 err = message.UnmarshalBinary(b) 146 case Type_FlowRemoved: 147 message = NewFlowRemoved() 148 err = message.UnmarshalBinary(b) 149 case Type_PortStatus: 150 message = new(PortStatus) 151 err = message.UnmarshalBinary(b) 152 case Type_PacketOut: 153 break 154 case Type_FlowMod: 155 message = NewFlowMod() 156 err = message.UnmarshalBinary(b) 157 case Type_GroupMod: 158 break 159 case Type_PortMod: 160 break 161 case Type_TableMod: 162 break 163 case Type_BarrierRequest: 164 message = new(common.Header) 165 err = message.UnmarshalBinary(b) 166 case Type_BarrierReply: 167 message = new(common.Header) 168 err = message.UnmarshalBinary(b) 169 case Type_QueueGetConfigRequest: 170 break 171 case Type_QueueGetConfigReply: 172 break 173 case Type_MultiPartRequest: 174 message = new(MultipartRequest) 175 err = message.UnmarshalBinary(b) 176 case Type_MultiPartReply: 177 message = new(MultipartReply) 178 err = message.UnmarshalBinary(b) 179 default: 180 err = errors.New("An unknown v1.0 packet type was received. Parse function will discard data.") 181 } 182 return 183 } 184 185 // When the controller wishes to send a packet out through the 186 // datapath, it uses the OFPT_PACKET_OUT message: The buffer_id 187 // is the same given in the ofp_packet_in message. If the 188 // buffer_id is -1, then the packet data is included in the data 189 // array. If OFPP_TABLE is specified as the output port of an 190 // action, the in_port in the packet_out message is used in the 191 // flow table lookup. 192 type PacketOut struct { 193 common.Header 194 BufferId uint32 195 InPort uint32 196 ActionsLen uint16 197 pad []byte 198 Actions []Action 199 Data util.Message 200 } 201 202 func NewPacketOut() *PacketOut { 203 p := new(PacketOut) 204 p.Header = NewOfp13Header() 205 p.Header.Type = Type_PacketOut 206 p.BufferId = 0xffffffff 207 p.InPort = P_ANY 208 p.ActionsLen = 0 209 p.pad = make([]byte, 6) 210 p.Actions = make([]Action, 0) 211 return p 212 } 213 214 func (p *PacketOut) AddAction(act Action) { 215 p.Actions = append(p.Actions, act) 216 p.ActionsLen += act.Len() 217 } 218 219 func (p *PacketOut) Len() (n uint16) { 220 n += p.Header.Len() 221 n += 16 222 for _, a := range p.Actions { 223 n += a.Len() 224 } 225 n += p.Data.Len() 226 //if n < 72 { return 72 } 227 return 228 } 229 230 func (p *PacketOut) MarshalBinary() (data []byte, err error) { 231 data = make([]byte, int(p.Len())) 232 b := make([]byte, 0) 233 n := 0 234 235 p.Header.Length = p.Len() 236 b, err = p.Header.MarshalBinary() 237 copy(data[n:], b) 238 n += len(b) 239 240 binary.BigEndian.PutUint32(data[n:], p.BufferId) 241 n += 4 242 binary.BigEndian.PutUint32(data[n:], p.InPort) 243 n += 4 244 binary.BigEndian.PutUint16(data[n:], p.ActionsLen) 245 n += 2 246 n += 6 // for pad 247 248 for _, a := range p.Actions { 249 b, err = a.MarshalBinary() 250 copy(data[n:], b) 251 n += len(b) 252 } 253 254 b, err = p.Data.MarshalBinary() 255 copy(data[n:], b) 256 n += len(b) 257 return 258 } 259 260 func (p *PacketOut) UnmarshalBinary(data []byte) error { 261 err := p.Header.UnmarshalBinary(data) 262 n := p.Header.Len() 263 264 p.BufferId = binary.BigEndian.Uint32(data[n:]) 265 n += 4 266 p.InPort = binary.BigEndian.Uint32(data[n:]) 267 n += 4 268 p.ActionsLen = binary.BigEndian.Uint16(data[n:]) 269 n += 2 270 271 n += 6 // for pad 272 273 for n < (n + p.ActionsLen) { 274 a, err := DecodeAction(data[n:]) 275 if err != nil { 276 return err 277 } 278 p.Actions = append(p.Actions, a) 279 n += a.Len() 280 } 281 282 err = p.Data.UnmarshalBinary(data[n:]) 283 return err 284 } 285 286 // ofp_packet_in 1.3 287 type PacketIn struct { 288 common.Header 289 BufferId uint32 290 TotalLen uint16 291 Reason uint8 292 TableId uint8 293 Cookie uint64 294 Match Match 295 pad []uint8 296 Data protocol.Ethernet 297 } 298 299 func NewPacketIn() *PacketIn { 300 p := new(PacketIn) 301 p.Header = NewOfp13Header() 302 p.Header.Type = Type_PacketIn 303 p.BufferId = 0xffffffff 304 p.Reason = 0 305 p.TableId = 0 306 p.Cookie = 0 307 p.Match = *NewMatch() 308 return p 309 } 310 311 func (p *PacketIn) Len() (n uint16) { 312 n += p.Header.Len() 313 n += 16 314 n += p.Match.Len() 315 n += 2 316 n += p.Data.Len() 317 return 318 } 319 320 func (p *PacketIn) MarshalBinary() (data []byte, err error) { 321 data, err = p.Header.MarshalBinary() 322 323 b := make([]byte, 16) 324 n := 0 325 binary.BigEndian.PutUint32(b, p.BufferId) 326 n += 4 327 binary.BigEndian.PutUint16(b[n:], p.TotalLen) 328 n += 2 329 b[n] = p.Reason 330 n += 1 331 b[n] = p.TableId 332 n += 1 333 binary.BigEndian.PutUint64(b, p.Cookie) 334 n += 8 335 data = append(data, b...) 336 337 b, err = p.Match.MarshalBinary() 338 data = append(data, b...) 339 340 b = make([]byte, 2) 341 copy(b[0:], p.pad) 342 data = append(data, b...) 343 344 b, err = p.Data.MarshalBinary() 345 data = append(data, b...) 346 return 347 } 348 349 func (p *PacketIn) UnmarshalBinary(data []byte) error { 350 err := p.Header.UnmarshalBinary(data) 351 n := p.Header.Len() 352 353 p.BufferId = binary.BigEndian.Uint32(data[n:]) 354 n += 4 355 p.TotalLen = binary.BigEndian.Uint16(data[n:]) 356 n += 2 357 p.Reason = data[n] 358 n += 1 359 p.TableId = data[n] 360 n += 1 361 p.Cookie = binary.BigEndian.Uint64(data[n:]) 362 n += 8 363 364 if err := p.Match.UnmarshalBinary(data[n:]); err != nil { 365 return err 366 } 367 n += p.Match.Len() 368 369 copy(p.pad, data[n:]) 370 n += 2 371 372 err = p.Data.UnmarshalBinary(data[n:]) 373 return err 374 } 375 376 // ofp_packet_in_reason 1.3 377 const ( 378 R_NO_MATCH = iota /* No matching flow (table-miss flow entry). */ 379 R_ACTION /* Action explicitly output to controller. */ 380 R_INVALID_TTL /* Packet has invalid TTL */ 381 ) 382 383 func NewConfigRequest() *common.Header { 384 h := NewOfp13Header() 385 h.Type = Type_GetConfigRequest 386 return &h 387 } 388 389 // ofp_config_flags 1.3 390 const ( 391 C_FRAG_NORMAL = 0 392 C_FRAG_DROP = 1 393 C_FRAG_REASM = 2 394 C_FRAG_MASK = 3 395 ) 396 397 // ofp_switch_config 1.3 398 type SwitchConfig struct { 399 common.Header 400 Flags uint16 // OFPC_* flags 401 MissSendLen uint16 402 } 403 404 func NewSetConfig() *SwitchConfig { 405 c := new(SwitchConfig) 406 c.Header = NewOfp13Header() 407 c.Header.Type = Type_SetConfig 408 c.Flags = 0 409 c.MissSendLen = 0 410 return c 411 } 412 413 func (c *SwitchConfig) Len() (n uint16) { 414 n = c.Header.Len() 415 n += 4 416 return 417 } 418 419 func (c *SwitchConfig) MarshalBinary() (data []byte, err error) { 420 data = make([]byte, int(c.Len())) 421 bytes := make([]byte, 0) 422 next := 0 423 424 c.Header.Length = c.Len() 425 bytes, err = c.Header.MarshalBinary() 426 copy(data[next:], bytes) 427 next += len(bytes) 428 binary.BigEndian.PutUint16(data[next:], c.Flags) 429 next += 2 430 binary.BigEndian.PutUint16(data[next:], c.MissSendLen) 431 next += 2 432 return 433 } 434 435 func (c *SwitchConfig) UnmarshalBinary(data []byte) error { 436 var err error 437 next := 0 438 439 err = c.Header.UnmarshalBinary(data[next:]) 440 next += int(c.Header.Len()) 441 c.Flags = binary.BigEndian.Uint16(data[next:]) 442 next += 2 443 c.MissSendLen = binary.BigEndian.Uint16(data[next:]) 444 next += 2 445 return err 446 } 447 448 // BEGIN: ofp13 - 7.4.4 449 // ofp_error_msg 1.3 450 type ErrorMsg struct { 451 common.Header 452 Type uint16 453 Code uint16 454 Data util.Buffer 455 } 456 457 func NewErrorMsg() *ErrorMsg { 458 e := new(ErrorMsg) 459 e.Data = *util.NewBuffer(make([]byte, 0)) 460 return e 461 } 462 463 func (e *ErrorMsg) Len() (n uint16) { 464 n = e.Header.Len() 465 n += 2 466 n += 2 467 n += e.Data.Len() 468 return 469 } 470 471 func (e *ErrorMsg) MarshalBinary() (data []byte, err error) { 472 data = make([]byte, int(e.Len())) 473 next := 0 474 475 bytes, err := e.Header.MarshalBinary() 476 copy(data[next:], bytes) 477 next += len(bytes) 478 binary.BigEndian.PutUint16(data[next:], e.Type) 479 next += 2 480 binary.BigEndian.PutUint16(data[next:], e.Code) 481 next += 2 482 bytes, err = e.Data.MarshalBinary() 483 copy(data[next:], bytes) 484 next += len(bytes) 485 return 486 } 487 488 func (e *ErrorMsg) UnmarshalBinary(data []byte) error { 489 next := 0 490 e.Header.UnmarshalBinary(data[next:]) 491 next += int(e.Header.Len()) 492 e.Type = binary.BigEndian.Uint16(data[next:]) 493 next += 2 494 e.Code = binary.BigEndian.Uint16(data[next:]) 495 next += 2 496 e.Data.UnmarshalBinary(data[next:]) 497 next += int(e.Data.Len()) 498 return nil 499 } 500 501 // ofp_error_type 1.3 502 const ( 503 ET_HELLO_FAILED = 0 /* Hello protocol failed. */ 504 ET_BAD_REQUEST = 1 /* Request was not understood. */ 505 ET_BAD_ACTION = 2 /* Error in action description. */ 506 ET_BAD_INSTRUCTION = 3 /* Error in instruction list. */ 507 PET_BAD_MATCH = 4 /* Error in match. */ 508 ET_FLOW_MOD_FAILED = 5 /* Problem modifying flow entry. */ 509 ET_GROUP_MOD_FAILED = 6 /* Problem modifying group entry. */ 510 ET_PORT_MOD_FAILED = 7 /* Port mod request failed. */ 511 ET_TABLE_MOD_FAILED = 8 /* Table mod request failed. */ 512 ET_QUEUE_OP_FAILED = 9 /* Queue operation failed. */ 513 ET_ROLE_REQUEST_FAILED = 11 /* Controller Role request failed. */ 514 ET_METER_MOD_FAILED = 12 /* Error in meter. */ 515 ET_TABLE_FEATURES_FAILED = 13 /* Setting table features failed. */ 516 ET_EXPERIMENTER = 0xffff /* Experimenter error messages. */ 517 ) 518 519 // ofp_hello_failed_code 1.3 520 const ( 521 HFC_INCOMPATIBLE = iota 522 HFC_EPERM 523 ) 524 525 // ofp_bad_request_code 1.3 526 const ( 527 BRC_BAD_VERSION = iota 528 BRC_BAD_TYPE 529 BRC_BAD_MULTIPART 530 BRC_BAD_EXPERIMENTER 531 532 BRC_BAD_EXP_TYPE 533 BRC_EPERM 534 BRC_BAD_LEN 535 BRC_BUFFER_EMPTY 536 BRC_BUFFER_UNKNOWN 537 BRC_BAD_TABLE_ID 538 BRC_IS_SLAVE 539 BRC_BAD_PORT 540 BRC_BAD_PACKET 541 BRC_MULTIPART_BUFFER_OVERFLOW 542 ) 543 544 // ofp_bad_action_code 1.3 545 const ( 546 BAC_BAD_TYPE = iota 547 BAC_BAD_LEN 548 BAC_BAD_EXPERIMENTER 549 BAC_BAD_EXP_TYPE 550 BAC_BAD_OUT_PORT 551 BAC_BAD_ARGUMENT 552 BAC_EPERM 553 BAC_TOO_MANY 554 BAC_BAD_QUEUE 555 BAC_BAD_OUT_GROUP 556 BAC_MATCH_INCONSISTENT 557 BAC_UNSUPPORTED_ORDER 558 BAC_BAD_TAG 559 BAC_BAD_SET_TYPE 560 BAC_BAD_SET_LEN 561 BAC_BAD_SET_ARGUMENT 562 ) 563 564 // ofp_bad_instruction_code 1.3 565 const ( 566 BIC_UNKNOWN_INST = 0 /* Unknown instruction. */ 567 BIC_UNSUP_INST = 1 /* Switch or table does not support the instruction. */ 568 BIC_BAD_TABLE_ID = 2 /* Invalid Table-ID specified. */ 569 BIC_UNSUP_METADATA = 3 /* Metadata value unsupported by datapath. */ 570 BIC_UNSUP_METADATA_MASK = 4 /* Metadata mask value unsupported by datapath. */ 571 BIC_BAD_EXPERIMENTER = 5 /* Unknown experimenter id specified. */ 572 BIC_BAD_EXP_TYPE = 6 /* Unknown instruction for experimenter id. */ 573 BIC_BAD_LEN = 7 /* Length problem in instructions. */ 574 BIC_EPERM = 8 /* Permissions error. */ 575 ) 576 577 // ofp_flow_mod_failed_code 1.3 578 const ( 579 FMFC_UNKNOWN = 0 /* Unspecified error. */ 580 FMFC_TABLE_FULL = 1 /* Flow not added because table was full. */ 581 FMFC_BAD_TABLE_ID = 2 /* Table does not exist */ 582 FMFC_OVERLAP = 3 /* Attempted to add overlapping flow with CHECK_OVERLAP flag set. */ 583 FMFC_EPERM = 4 /* Permissions error. */ 584 FMFC_BAD_TIMEOUT = 5 /* Flow not added because of unsupported idle/hard timeout. */ 585 FMFC_BAD_COMMAND = 6 /* Unsupported or unknown command. */ 586 FMFC_BAD_FLAGS = 7 /* Unsupported or unknown flags. */ 587 ) 588 589 // ofp_bad_match_code 1.3 590 const ( 591 BMC_BAD_TYPE = 0 /* Unsupported match type specified by the match */ 592 BMC_BAD_LEN = 1 /* Length problem in match. */ 593 BMC_BAD_TAG = 2 /* Match uses an unsupported tag/encap. */ 594 BMC_BAD_DL_ADDR_MASK = 3 /* Unsupported datalink addr mask - switch does not support arbitrary datalink address mask. */ 595 BMC_BAD_NW_ADDR_MASK = 4 /* Unsupported network addr mask - switch does not support arbitrary network address mask. */ 596 BMC_BAD_WILDCARDS = 5 /* Unsupported combination of fields masked or omitted in the match. */ 597 BMC_BAD_FIELD = 6 /* Unsupported field type in the match. */ 598 BMC_BAD_VALUE = 7 /* Unsupported value in a match field. */ 599 BMC_BAD_MASK = 8 /* Unsupported mask specified in the match, field is not dl-address or nw-address. */ 600 BMC_BAD_PREREQ = 9 /* A prerequisite was not met. */ 601 BMC_DUP_FIELD = 10 /* A field type was duplicated. */ 602 BMC_EPERM = 11 /* Permissions error. */ 603 ) 604 605 // ofp_group_mod_failed_code 1.3 606 const ( 607 GMFC_GROUP_EXISTS = 0 /* Group not added because a group ADD attempted to replace an already-present group. */ 608 GMFC_INVALID_GROUP = 1 /* Group not added because Group specified is invalid. */ 609 GMFC_WEIGHT_UNSUPPORTED = 2 /* Switch does not support unequal load 105 ➞ 2013; The Open Networking Foundation OpenFlow Switch Specification Version 1.3.3 sharing with select groups. */ 610 GMFC_OUT_OF_GROUPS = 3 /* The group table is full. */ 611 GMFC_OUT_OF_BUCKETS = 4 /* The maximum number of action buckets for a group has been exceeded. */ 612 GMFC_CHAINING_UNSUPPORTED = 5 /* Switch does not support groups that forward to groups. */ 613 GMFC_WATCH_UNSUPPORTED = 6 /* This group cannot watch the watch_port or watch_group specified. */ 614 GMFC_LOOP = 7 /* Group entry would cause a loop. */ 615 GMFC_UNKNOWN_GROUP = 8 /* Group not modified because a group MODIFY attempted to modify a non-existent group. */ 616 GMFC_CHAINED_GROUP = 9 /* Group not deleted because another group is forwarding to it. */ 617 GMFC_BAD_TYPE = 10 /* Unsupported or unknown group type. */ 618 GMFC_BAD_COMMAND = 11 /* Unsupported or unknown command. */ 619 GMFC_BAD_BUCKET = 12 /* Error in bucket. */ 620 GMFC_BAD_WATCH = 13 /* Error in watch port/group. */ 621 GMFC_EPERM = 14 /* Permissions error. */ 622 ) 623 624 // ofp_port_mod_failed_code 1.0 625 const ( 626 PMFC_BAD_PORT = iota 627 PMFC_BAD_HW_ADDR 628 PMFC_BAD_CONFIG 629 PMFC_BAD_ADVERTISE 630 PMFC_EPERM 631 ) 632 633 // ofp_table_mod_failed_code 634 const ( 635 TMFC_BAD_TABLE = 0 /* Specified table does not exist. */ 636 TMFC_BAD_CONFIG = 1 /* Specified config is invalid. */ 637 TMFC_EPERM = 2 /* Permissions error. */ 638 ) 639 640 // ofp_queue_op_failed_code 1.0 641 const ( 642 QOFC_BAD_PORT = iota 643 QOFC_BAD_QUEUE 644 QOFC_EPERM 645 ) 646 647 // END: ofp13 - 7.4.4 648 // END: ofp13 - 7.4 649 650 type SwitchFeatures struct { 651 common.Header 652 DPID net.HardwareAddr // Size 8 653 Buffers uint32 654 NumTables uint8 655 AuxilaryId uint8 656 pad []uint8 // Size 2 657 Capabilities uint32 658 Actions uint32 659 660 Ports []PhyPort 661 } 662 663 // FeaturesRequest constructor 664 func NewFeaturesRequest() *common.Header { 665 req := NewOfp13Header() 666 req.Type = Type_FeaturesRequest 667 return &req 668 } 669 670 // FeaturesReply constructor 671 func NewFeaturesReply() *SwitchFeatures { 672 res := new(SwitchFeatures) 673 res.Header = NewOfp13Header() 674 res.Header.Type = Type_FeaturesReply 675 res.DPID = make([]byte, 8) 676 res.pad = make([]byte, 2) 677 res.Ports = make([]PhyPort, 0) 678 return res 679 } 680 681 func (s *SwitchFeatures) Len() (n uint16) { 682 n = s.Header.Len() 683 n += uint16(len(s.DPID)) 684 n += 16 685 for _, p := range s.Ports { 686 n += p.Len() 687 } 688 return 689 } 690 691 func (s *SwitchFeatures) MarshalBinary() (data []byte, err error) { 692 data = make([]byte, int(s.Len())) 693 bytes := make([]byte, 0) 694 next := 0 695 696 s.Header.Length = s.Len() 697 bytes, err = s.Header.MarshalBinary() 698 copy(data[next:], bytes) 699 next += len(bytes) 700 binary.BigEndian.PutUint32(data[next:], s.Buffers) 701 next += 4 702 data[next] = s.NumTables 703 next += 1 704 data[next] = s.AuxilaryId 705 next += 1 706 copy(data[next:], s.pad) 707 next += len(s.pad) 708 binary.BigEndian.PutUint32(data[next:], s.Capabilities) 709 next += 4 710 binary.BigEndian.PutUint32(data[next:], s.Actions) 711 next += 4 712 713 for _, p := range s.Ports { 714 bytes, err = p.MarshalBinary() 715 if err != nil { 716 return 717 } 718 copy(data[next:], bytes) 719 next += len(bytes) 720 } 721 return 722 } 723 724 func (s *SwitchFeatures) UnmarshalBinary(data []byte) error { 725 var err error 726 next := 0 727 728 err = s.Header.UnmarshalBinary(data[next:]) 729 next = int(s.Header.Len()) 730 copy(s.DPID, data[next:]) 731 next += len(s.DPID) 732 s.Buffers = binary.BigEndian.Uint32(data[next:]) 733 next += 4 734 s.NumTables = data[next] 735 next += 1 736 s.AuxilaryId = data[next] 737 next += 1 738 copy(s.pad, data[next:]) 739 next += len(s.pad) 740 s.Capabilities = binary.BigEndian.Uint32(data[next:]) 741 next += 4 742 s.Actions = binary.BigEndian.Uint32(data[next:]) 743 next += 4 744 745 for next < len(data) { 746 p := NewPhyPort() 747 err = p.UnmarshalBinary(data[next:]) 748 next += int(p.Len()) 749 } 750 return err 751 } 752 753 // ofp_capabilities 1.3 754 const ( 755 C_FLOW_STATS = 1 << 0 756 C_TABLE_STATS = 1 << 1 757 C_PORT_STATS = 1 << 2 758 C_GROUP_STATS = 1 << 3 759 C_RESERVED = 1 << 4 760 C_IP_REASM = 1 << 5 761 C_QUEUE_STATS = 1 << 6 762 C_PORT_BLOCKED = 1 << 8 763 ) 764 765 // ofp_vendor 1.3 766 type VendorHeader struct { 767 Header common.Header /*Type OFPT_VENDOR*/ 768 Vendor uint32 769 ExperimenterType uint32 770 VendorData util.Message 771 } 772 773 func (v *VendorHeader) Len() (n uint16) { 774 length := uint16(16) 775 if v.VendorData != nil { 776 length += v.VendorData.Len() 777 } 778 return length 779 } 780 781 func (v *VendorHeader) MarshalBinary() (data []byte, err error) { 782 v.Header.Length = v.Len() 783 data = make([]byte, v.Len()) 784 b, err := v.Header.MarshalBinary() 785 n := 0 786 copy(data[n:], b) 787 n += len(b) 788 binary.BigEndian.PutUint32(data[n:], v.Vendor) 789 n += 4 790 binary.BigEndian.PutUint32(data[n:], v.ExperimenterType) 791 n += 4 792 if v.VendorData != nil { 793 vd, err := v.VendorData.MarshalBinary() 794 if err != nil { 795 return nil, err 796 } 797 copy(data[n:], vd) 798 n += len(vd) 799 } 800 return 801 } 802 803 func (v *VendorHeader) UnmarshalBinary(data []byte) error { 804 if len(data) < 16 { 805 return errors.New("The []byte the wrong size to unmarshal an " + 806 "VendorHeader message.") 807 } 808 v.Header.UnmarshalBinary(data) 809 n := int(v.Header.Len()) 810 v.Vendor = binary.BigEndian.Uint32(data[n:]) 811 n += 4 812 v.ExperimenterType = binary.BigEndian.Uint32(data[n:]) 813 n += 4 814 if n < int(v.Header.Length) { 815 var err error 816 v.VendorData, err = decodeVendorData(v.ExperimenterType, data[n:v.Header.Length]) 817 if err != nil { 818 return err 819 } 820 } 821 return nil 822 }