From c0fd55c0dccc80d4a661abc2543b498ba291d7bb Mon Sep 17 00:00:00 2001 From: Sukhesh Halemane Date: Wed, 25 May 2016 11:24:28 -0700 Subject: [PATCH] fix multipart request; gofmt libopenflow --- common/header.go | 260 +++---- libOpenflow.go | 1 + openflow13/action.go | 501 +++++++------ openflow13/flowmod.go | 455 ++++++------ openflow13/group.go | 288 ++++---- openflow13/instruction.go | 284 ++++---- openflow13/multipart.go | 1452 +++++++++++++++++++------------------ openflow13/openflow13.go | 1119 ++++++++++++++-------------- openflow13/port.go | 365 +++++----- protocol/dhcp.go | 890 +++++++++++------------ protocol/ethernet.go | 258 +++---- protocol/icmp.go | 52 +- protocol/ip.go | 254 +++---- protocol/lldp.go | 266 +++---- protocol/tcp.go | 104 +-- protocol/udp.go | 64 +- util/stream.go | 243 ++++--- util/util.go | 30 +- 18 files changed, 3441 insertions(+), 3445 deletions(-) diff --git a/common/header.go b/common/header.go index 4a7fef5..6ff7dc2 100644 --- a/common/header.go +++ b/common/header.go @@ -3,20 +3,20 @@ package common // Package common defines OpenFlow message types that are version independent. import ( - "encoding/binary" - "errors" + "encoding/binary" + "errors" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/util" ) var messageXid uint32 = 1 func NewHeaderGenerator(ver int) func() Header { - return func() Header { - messageXid += 1 - p := Header{uint8(ver), 0, 8, messageXid} - return p - } + return func() Header { + messageXid += 1 + p := Header{uint8(ver), 0, 8, messageXid} + return p + } } // The version specifies the OpenFlow protocol version being @@ -28,141 +28,141 @@ func NewHeaderGenerator(ver int) func() Header { // indicates the total length of the message, so no additional // framing is used to distinguish one frame from the next. type Header struct { - Version uint8 - Type uint8 - Length uint16 - Xid uint32 + Version uint8 + Type uint8 + Length uint16 + Xid uint32 } func (h *Header) Header() *Header { - return h + return h } func (h *Header) Len() (n uint16) { - return 8 + return 8 } func (h *Header) MarshalBinary() (data []byte, err error) { - data = make([]byte, 8) - data[0] = h.Version - data[1] = h.Type - binary.BigEndian.PutUint16(data[2:4], h.Length) - binary.BigEndian.PutUint32(data[4:8], h.Xid) - return + data = make([]byte, 8) + data[0] = h.Version + data[1] = h.Type + binary.BigEndian.PutUint16(data[2:4], h.Length) + binary.BigEndian.PutUint32(data[4:8], h.Xid) + return } func (h *Header) UnmarshalBinary(data []byte) error { - if len(data) < 4 { - return errors.New("The []byte is too short to unmarshel a full HelloElemHeader.") - } - h.Version = data[0] - h.Type = data[1] - h.Length = binary.BigEndian.Uint16(data[2:4]) - h.Xid = binary.BigEndian.Uint32(data[4:8]) - return nil + if len(data) < 4 { + return errors.New("The []byte is too short to unmarshel a full HelloElemHeader.") + } + h.Version = data[0] + h.Type = data[1] + h.Length = binary.BigEndian.Uint16(data[2:4]) + h.Xid = binary.BigEndian.Uint32(data[4:8]) + return nil } const ( - reserved = iota - HelloElemType_VersionBitmap - ) + reserved = iota + HelloElemType_VersionBitmap +) type HelloElem interface { - Header() *HelloElemHeader - util.Message + Header() *HelloElemHeader + util.Message } type HelloElemHeader struct { - Type uint16 - Length uint16 + Type uint16 + Length uint16 } func NewHelloElemHeader() *HelloElemHeader { - h := new(HelloElemHeader) - h.Type = HelloElemType_VersionBitmap - h.Length = 4 - return h + h := new(HelloElemHeader) + h.Type = HelloElemType_VersionBitmap + h.Length = 4 + return h } func (h *HelloElemHeader) Header() *HelloElemHeader { - return h + return h } func (h *HelloElemHeader) Len() (n uint16) { - return 4 + return 4 } func (h *HelloElemHeader) MarshalBinary() (data []byte, err error) { - data = make([]byte, 4) - binary.BigEndian.PutUint16(data[:2], h.Type) - binary.BigEndian.PutUint16(data[2:4], h.Length) - return + data = make([]byte, 4) + binary.BigEndian.PutUint16(data[:2], h.Type) + binary.BigEndian.PutUint16(data[2:4], h.Length) + return } func (h *HelloElemHeader) UnmarshalBinary(data []byte) error { - if len(data) < 4 { - return errors.New("The []byte is too short to unmarshal a full HelloElemHeader.") - } - h.Type = binary.BigEndian.Uint16(data[:2]) - h.Length = binary.BigEndian.Uint16(data[2:4]) - return nil + if len(data) < 4 { + return errors.New("The []byte is too short to unmarshal a full HelloElemHeader.") + } + h.Type = binary.BigEndian.Uint16(data[:2]) + h.Length = binary.BigEndian.Uint16(data[2:4]) + return nil } type HelloElemVersionBitmap struct { - HelloElemHeader - Bitmaps []uint32 + HelloElemHeader + Bitmaps []uint32 } func NewHelloElemVersionBitmap() *HelloElemVersionBitmap { - h := new(HelloElemVersionBitmap) - h.HelloElemHeader = *NewHelloElemHeader() - h.Bitmaps = make([]uint32, 0) - // 10010 meaning openflow 1.0 & 1.3 support - h.Bitmaps = append(h.Bitmaps, uint32(1<<4) | uint32(1<<1)) - h.Length = h.Length + uint16(len(h.Bitmaps) * 4) - return h + h := new(HelloElemVersionBitmap) + h.HelloElemHeader = *NewHelloElemHeader() + h.Bitmaps = make([]uint32, 0) + // 10010 meaning openflow 1.0 & 1.3 support + h.Bitmaps = append(h.Bitmaps, uint32(1<<4)|uint32(1<<1)) + h.Length = h.Length + uint16(len(h.Bitmaps)*4) + return h } func (h *HelloElemVersionBitmap) Header() *HelloElemHeader { - return &h.HelloElemHeader + return &h.HelloElemHeader } func (h *HelloElemVersionBitmap) Len() (n uint16) { - n = h.HelloElemHeader.Len() - n += uint16(len(h.Bitmaps) * 4) - return + n = h.HelloElemHeader.Len() + n += uint16(len(h.Bitmaps) * 4) + return } func (h *HelloElemVersionBitmap) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(h.Len())) - bytes := make([]byte, 0) - next := 0 + data = make([]byte, int(h.Len())) + bytes := make([]byte, 0) + next := 0 - bytes, err = h.HelloElemHeader.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) + bytes, err = h.HelloElemHeader.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) - for _, m := range h.Bitmaps { - binary.BigEndian.PutUint32(data[next:], m) - next += 4 - } - return + for _, m := range h.Bitmaps { + binary.BigEndian.PutUint32(data[next:], m) + next += 4 + } + return } func (h *HelloElemVersionBitmap) UnmarshalBinary(data []byte) error { - length := len(data) - read := 0 - if err := h.HelloElemHeader.UnmarshalBinary(data[:4]); err != nil { - return err - } - read += int(h.HelloElemHeader.Len()) + length := len(data) + read := 0 + if err := h.HelloElemHeader.UnmarshalBinary(data[:4]); err != nil { + return err + } + read += int(h.HelloElemHeader.Len()) - h.Bitmaps = make([]uint32, 0) - for read < length { - h.Bitmaps = append(h.Bitmaps, binary.BigEndian.Uint32(data[read:read+4])) - read += 4 - } - return nil + h.Bitmaps = make([]uint32, 0) + for read < length { + h.Bitmaps = append(h.Bitmaps, binary.BigEndian.Uint32(data[read:read+4])) + read += 4 + } + return nil } // The OFPT_HELLO message consists of an OpenFlow header plus a set of variable @@ -178,62 +178,62 @@ func (h *HelloElemVersionBitmap) UnmarshalBinary(data []byte) error { // inform the initial handshake of the connection. Implementations must ignore // (skip) all elements of a Hello message that they do not support. type Hello struct { - Header - Elements []HelloElem + Header + Elements []HelloElem } func NewHello(ver int) (h *Hello, err error) { - h = new(Hello) - h.Header = NewHeaderGenerator(ver)() - h.Elements = make([]HelloElem, 0) - h.Elements = append(h.Elements, NewHelloElemVersionBitmap()) + h = new(Hello) + h.Header = NewHeaderGenerator(ver)() + h.Elements = make([]HelloElem, 0) + h.Elements = append(h.Elements, NewHelloElemVersionBitmap()) - return + return } func (h *Hello) Len() (n uint16) { - n = h.Header.Len() - for _, e := range h.Elements { - n += e.Len() - } - return + n = h.Header.Len() + for _, e := range h.Elements { + n += e.Len() + } + return } func (h *Hello) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(h.Len())) - bytes := make([]byte, 0) - next := 0 + data = make([]byte, int(h.Len())) + bytes := make([]byte, 0) + next := 0 - h.Header.Length = h.Len() - bytes, err = h.Header.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) + h.Header.Length = h.Len() + bytes, err = h.Header.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) - for _, e := range h.Elements { - bytes, err = e.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) - } - return + for _, e := range h.Elements { + bytes, err = e.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) + } + return } func (h *Hello) UnmarshalBinary(data []byte) error { - next := 0 - err := h.Header.UnmarshalBinary(data[next:]) - next += int(h.Header.Len()) - - h.Elements = make([]HelloElem, 0) - for next < len(data) { - e := NewHelloElemHeader() - e.UnmarshalBinary(data[next:]) - - switch e.Type { - case HelloElemType_VersionBitmap: - v := NewHelloElemVersionBitmap() - err = v.UnmarshalBinary(data[next:]) - next += int(v.Len()) - h.Elements = append(h.Elements, v) - } - } - return err + next := 0 + err := h.Header.UnmarshalBinary(data[next:]) + next += int(h.Header.Len()) + + h.Elements = make([]HelloElem, 0) + for next < len(data) { + e := NewHelloElemHeader() + e.UnmarshalBinary(data[next:]) + + switch e.Type { + case HelloElemType_VersionBitmap: + v := NewHelloElemVersionBitmap() + err = v.UnmarshalBinary(data[next:]) + next += int(v.Len()) + h.Elements = append(h.Elements, v) + } + } + return err } diff --git a/libOpenflow.go b/libOpenflow.go index 587ae89..9dbf41d 100644 --- a/libOpenflow.go +++ b/libOpenflow.go @@ -1,3 +1,4 @@ package libOpenflow + // This library implements the openflow1.3 encap/decap. // Please use packages in common and openflow13 subdirectories diff --git a/openflow13/action.go b/openflow13/action.go index c6a9652..8904f92 100644 --- a/openflow13/action.go +++ b/openflow13/action.go @@ -1,109 +1,109 @@ package openflow13 import ( - "encoding/binary" - "errors" + "encoding/binary" + "errors" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/util" ) // ofp_action_type 1.3 const ( - ActionType_Output = 0 - ActionType_CopyTtlOut = 11 - ActionType_CopyTtlIn = 12 - ActionType_SetMplsTtl = 15 - ActionType_DecMplsTtl = 16 - ActionType_PushVlan = 17 - ActionType_PopVlan = 18 - ActionType_PushMpls = 19 - ActionType_PopMpls = 20 - ActionType_SetQueue = 21 - ActionType_Group = 22 - ActionType_SetNwTtl = 23 - ActionType_DecNwTtl = 24 - ActionType_SetField = 25 - ActionType_PushPbb = 26 - ActionType_PopPbb = 27 - - ActionType_Experimenter = 0xffff + ActionType_Output = 0 + ActionType_CopyTtlOut = 11 + ActionType_CopyTtlIn = 12 + ActionType_SetMplsTtl = 15 + ActionType_DecMplsTtl = 16 + ActionType_PushVlan = 17 + ActionType_PopVlan = 18 + ActionType_PushMpls = 19 + ActionType_PopMpls = 20 + ActionType_SetQueue = 21 + ActionType_Group = 22 + ActionType_SetNwTtl = 23 + ActionType_DecNwTtl = 24 + ActionType_SetField = 25 + ActionType_PushPbb = 26 + ActionType_PopPbb = 27 + + ActionType_Experimenter = 0xffff ) type Action interface { - Header() *ActionHeader - util.Message + Header() *ActionHeader + util.Message } type ActionHeader struct { - Type uint16 - Length uint16 + Type uint16 + Length uint16 } func (a *ActionHeader) Header() *ActionHeader { - return a + return a } func (a *ActionHeader) Len() (n uint16) { - return 4 + return 4 } func (a *ActionHeader) MarshalBinary() (data []byte, err error) { - data = make([]byte, a.Len()) - binary.BigEndian.PutUint16(data[:2], a.Type) - binary.BigEndian.PutUint16(data[2:4], a.Length) - return + data = make([]byte, a.Len()) + binary.BigEndian.PutUint16(data[:2], a.Type) + binary.BigEndian.PutUint16(data[2:4], a.Length) + return } func (a *ActionHeader) UnmarshalBinary(data []byte) error { - if len(data) != 4 { - return errors.New("The []byte the wrong size to unmarshal an " + - "ActionHeader message.") - } - a.Type = binary.BigEndian.Uint16(data[:2]) - a.Length = binary.BigEndian.Uint16(data[2:4]) - return nil + if len(data) != 4 { + return errors.New("The []byte the wrong size to unmarshal an " + + "ActionHeader message.") + } + a.Type = binary.BigEndian.Uint16(data[:2]) + a.Length = binary.BigEndian.Uint16(data[2:4]) + return nil } // Decode Action types. func DecodeAction(data []byte) Action { - t := binary.BigEndian.Uint16(data[:2]) - var a Action - switch t { - case ActionType_Output: - a = new(ActionOutput) - case ActionType_CopyTtlOut: - a = new(ActionHeader) - case ActionType_CopyTtlIn: - a = new(ActionHeader) - case ActionType_SetMplsTtl: - a = new(ActionMplsTtl) - case ActionType_DecMplsTtl: - a = new(ActionHeader) - case ActionType_PushVlan: - a = new(ActionPush) - case ActionType_PopVlan: - a = new(ActionHeader) - case ActionType_PushMpls: - a = new(ActionPush) - case ActionType_PopMpls: - a = new(ActionPopMpls) - case ActionType_SetQueue: - a = new(ActionSetqueue) - case ActionType_Group: - a = new(ActionGroup) - case ActionType_SetNwTtl: - a = new(ActionNwTtl) - case ActionType_DecNwTtl: - a = new(ActionHeader) - case ActionType_SetField: - a = new(ActionSetField) - case ActionType_PushPbb: - a = new(ActionPush) - case ActionType_PopPbb: - a = new(ActionHeader) - } - a.UnmarshalBinary(data) - return a + t := binary.BigEndian.Uint16(data[:2]) + var a Action + switch t { + case ActionType_Output: + a = new(ActionOutput) + case ActionType_CopyTtlOut: + a = new(ActionHeader) + case ActionType_CopyTtlIn: + a = new(ActionHeader) + case ActionType_SetMplsTtl: + a = new(ActionMplsTtl) + case ActionType_DecMplsTtl: + a = new(ActionHeader) + case ActionType_PushVlan: + a = new(ActionPush) + case ActionType_PopVlan: + a = new(ActionHeader) + case ActionType_PushMpls: + a = new(ActionPush) + case ActionType_PopMpls: + a = new(ActionPopMpls) + case ActionType_SetQueue: + a = new(ActionSetqueue) + case ActionType_Group: + a = new(ActionGroup) + case ActionType_SetNwTtl: + a = new(ActionNwTtl) + case ActionType_DecNwTtl: + a = new(ActionHeader) + case ActionType_SetField: + a = new(ActionSetField) + case ActionType_PushPbb: + a = new(ActionPush) + case ActionType_PopPbb: + a = new(ActionHeader) + } + a.UnmarshalBinary(data) + return a } // Action structure for OFPAT_OUTPUT, which sends packets out ’port’. @@ -111,315 +111,312 @@ func DecodeAction(data []byte) Action { // number of bytes to send. A ’max_len’ of zero means no bytes of the // packet should be sent. type ActionOutput struct { - ActionHeader - Port uint32 - MaxLen uint16 - pad []byte // 6 bytes to make it 64bit aligned + ActionHeader + Port uint32 + MaxLen uint16 + pad []byte // 6 bytes to make it 64bit aligned } // ofp_controller_max_len 1.3 const ( - OFPCML_MAX = 0xffe5 /* maximum max_len value which can be used to request a specific byte length. */ - OFPCML_NO_BUFFER = 0xffff /* indicates that no buffering should be applied and the whole packet is to be sent to the controller. */ + OFPCML_MAX = 0xffe5 /* maximum max_len value which can be used to request a specific byte length. */ + OFPCML_NO_BUFFER = 0xffff /* indicates that no buffering should be applied and the whole packet is to be sent to the controller. */ ) // Returns a new Action Output message which sends packets out // port number. func NewActionOutput(portNum uint32) *ActionOutput { - act := new(ActionOutput) - act.Type = ActionType_Output - act.Length = act.Len() - act.Port = portNum - act.MaxLen = 256 - act.pad = make([]byte, 6) - return act + act := new(ActionOutput) + act.Type = ActionType_Output + act.Length = act.Len() + act.Port = portNum + act.MaxLen = 256 + act.pad = make([]byte, 6) + return act } func (a *ActionOutput) Len() (n uint16) { - return a.ActionHeader.Len() + 12 + return a.ActionHeader.Len() + 12 } func (a *ActionOutput) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(a.Len())) - b := make([]byte, 0) - n := 0 + data = make([]byte, int(a.Len())) + b := make([]byte, 0) + n := 0 - b, err = a.ActionHeader.MarshalBinary() - copy(data[n:], b) - n += len(b) - binary.BigEndian.PutUint32(data[n:], a.Port) - n += 4 - binary.BigEndian.PutUint16(data[n:], a.MaxLen) - n += 2 - copy(data[n:], a.pad) - n += len(a.pad) + b, err = a.ActionHeader.MarshalBinary() + copy(data[n:], b) + n += len(b) + binary.BigEndian.PutUint32(data[n:], a.Port) + n += 4 + binary.BigEndian.PutUint16(data[n:], a.MaxLen) + n += 2 + copy(data[n:], a.pad) + n += len(a.pad) - return + return } func (a *ActionOutput) UnmarshalBinary(data []byte) error { - if len(data) < int(a.Len()) { - return errors.New("The []byte the wrong size to unmarshal an " + - "ActionOutput message.") - } - n := 0 - err := a.ActionHeader.UnmarshalBinary(data[n:]) - n += int(a.ActionHeader.Len()) - a.Port = binary.BigEndian.Uint32(data[n:]) - n += 4 - a.MaxLen = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(a.pad, data[n:n+6]) - n += 6 - return err + if len(data) < int(a.Len()) { + return errors.New("The []byte the wrong size to unmarshal an " + + "ActionOutput message.") + } + n := 0 + err := a.ActionHeader.UnmarshalBinary(data[n:]) + n += int(a.ActionHeader.Len()) + a.Port = binary.BigEndian.Uint32(data[n:]) + n += 4 + a.MaxLen = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(a.pad, data[n:n+6]) + n += 6 + return err } type ActionSetqueue struct { - ActionHeader - QueueId uint32 + ActionHeader + QueueId uint32 } func NewActionSetQueue(queue uint32) *ActionSetqueue { - a := new(ActionSetqueue) - a.Type = ActionType_SetQueue - a.Length = 8 - a.QueueId = queue - return a + a := new(ActionSetqueue) + a.Type = ActionType_SetQueue + a.Length = 8 + a.QueueId = queue + return a } func (a *ActionSetqueue) Len() (n uint16) { - return a.ActionHeader.Len() + 12 + return a.ActionHeader.Len() + 12 } func (a *ActionSetqueue) MarshalBinary() (data []byte, err error) { - data, err = a.ActionHeader.MarshalBinary() + data, err = a.ActionHeader.MarshalBinary() - bytes := make([]byte, 4) - binary.BigEndian.PutUint32(bytes[0:], a.QueueId) + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes[0:], a.QueueId) - data = append(data, bytes...) - return + data = append(data, bytes...) + return } func (a *ActionSetqueue) UnmarshalBinary(data []byte) error { - if len(data) != int(a.Len()) { - return errors.New("The []byte the wrong size to unmarshal an " + - "ActionEnqueue message.") - } - a.ActionHeader.UnmarshalBinary(data[:4]) - a.QueueId = binary.BigEndian.Uint32(data[4:8]) - return nil + if len(data) != int(a.Len()) { + return errors.New("The []byte the wrong size to unmarshal an " + + "ActionEnqueue message.") + } + a.ActionHeader.UnmarshalBinary(data[:4]) + a.QueueId = binary.BigEndian.Uint32(data[4:8]) + return nil } type ActionGroup struct { - ActionHeader - GroupId uint32 + ActionHeader + GroupId uint32 } func NewActionGroup(group uint32) *ActionGroup { - a := new(ActionGroup) - a.Type = ActionType_Group - a.Length = 8 - a.GroupId = group - return a + a := new(ActionGroup) + a.Type = ActionType_Group + a.Length = 8 + a.GroupId = group + return a } func (a *ActionGroup) Len() (n uint16) { - return a.ActionHeader.Len() + 4 + return a.ActionHeader.Len() + 4 } func (a *ActionGroup) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(a.Len())) - b := make([]byte, 0) - n := 0 + data = make([]byte, int(a.Len())) + b := make([]byte, 0) + n := 0 - b, err = a.ActionHeader.MarshalBinary() - copy(data[n:], b) - n += len(b) - binary.BigEndian.PutUint32(data[n:], a.GroupId) - n += 4 + b, err = a.ActionHeader.MarshalBinary() + copy(data[n:], b) + n += len(b) + binary.BigEndian.PutUint32(data[n:], a.GroupId) + n += 4 - return + return } func (a *ActionGroup) UnmarshalBinary(data []byte) error { - if len(data) < int(a.Len()) { - return errors.New("The []byte the wrong size to unmarshal an " + - "ActionOutput message.") - } - n := 0 - err := a.ActionHeader.UnmarshalBinary(data[n:]) - n += int(a.ActionHeader.Len()) - a.GroupId = binary.BigEndian.Uint32(data[n:]) - n += 4 + if len(data) < int(a.Len()) { + return errors.New("The []byte the wrong size to unmarshal an " + + "ActionOutput message.") + } + n := 0 + err := a.ActionHeader.UnmarshalBinary(data[n:]) + n += int(a.ActionHeader.Len()) + a.GroupId = binary.BigEndian.Uint32(data[n:]) + n += 4 - return err + return err } - type ActionMplsTtl struct { - ActionHeader - MplsTtl uint8 - pad []byte // 3bytes + ActionHeader + MplsTtl uint8 + pad []byte // 3bytes } type ActionNwTtl struct { - ActionHeader - NwTtl uint8 - pad []byte // 3bytes + ActionHeader + NwTtl uint8 + pad []byte // 3bytes } type ActionPush struct { - ActionHeader - EtherType uint16 - pad []byte // 2bytes + ActionHeader + EtherType uint16 + pad []byte // 2bytes } func NewActionPushVlan(etherType uint16) *ActionPush { - a := new(ActionPush) - a.Type = ActionType_PushVlan - a.Length = 8 - a.EtherType = etherType - return a + a := new(ActionPush) + a.Type = ActionType_PushVlan + a.Length = 8 + a.EtherType = etherType + return a } func NewActionPushMpls(etherType uint16) *ActionPush { - a := new(ActionPush) - a.Type = ActionType_PushMpls - a.Length = 8 - a.EtherType = etherType - return a + a := new(ActionPush) + a.Type = ActionType_PushMpls + a.Length = 8 + a.EtherType = etherType + return a } func (a *ActionPush) Len() (n uint16) { - return a.ActionHeader.Len() + 4 + return a.ActionHeader.Len() + 4 } func (a *ActionPush) MarshalBinary() (data []byte, err error) { - data, err = a.ActionHeader.MarshalBinary() + data, err = a.ActionHeader.MarshalBinary() - bytes := make([]byte, 4) - binary.BigEndian.PutUint16(bytes[0:], a.EtherType) + bytes := make([]byte, 4) + binary.BigEndian.PutUint16(bytes[0:], a.EtherType) - data = append(data, bytes...) - return + data = append(data, bytes...) + return } func (a *ActionPush) UnmarshalBinary(data []byte) error { - a.ActionHeader.UnmarshalBinary(data[:4]) - a.EtherType = binary.BigEndian.Uint16(data[4:]) - return nil + a.ActionHeader.UnmarshalBinary(data[:4]) + a.EtherType = binary.BigEndian.Uint16(data[4:]) + return nil } - type ActionPopVlan struct { - ActionHeader - pad []byte // 4bytes + ActionHeader + pad []byte // 4bytes } func NewActionPopVlan() *ActionPopVlan { - act := new(ActionPopVlan) - act.Type = ActionType_PopVlan - act.Length = 8 + act := new(ActionPopVlan) + act.Type = ActionType_PopVlan + act.Length = 8 - return act + return act } func (a *ActionPopVlan) Len() (n uint16) { - return a.ActionHeader.Len() + 4 + return a.ActionHeader.Len() + 4 } func (a *ActionPopVlan) MarshalBinary() (data []byte, err error) { - data, err = a.ActionHeader.MarshalBinary() + data, err = a.ActionHeader.MarshalBinary() - // Padding - bytes := make([]byte, 4) + // Padding + bytes := make([]byte, 4) - data = append(data, bytes...) - return + data = append(data, bytes...) + return } func (a *ActionPopVlan) UnmarshalBinary(data []byte) error { - a.ActionHeader.UnmarshalBinary(data[:4]) - return nil + a.ActionHeader.UnmarshalBinary(data[:4]) + return nil } type ActionPopMpls struct { - ActionHeader - EtherType uint16 - pad []byte // 2bytes + ActionHeader + EtherType uint16 + pad []byte // 2bytes } - func NewActionPopMpls(etherType uint16) *ActionPopMpls { - act := new(ActionPopMpls) - act.Type = ActionType_PopMpls - act.EtherType = etherType - act.Length = 8 + act := new(ActionPopMpls) + act.Type = ActionType_PopMpls + act.EtherType = etherType + act.Length = 8 - return act + return act } func (a *ActionPopMpls) Len() (n uint16) { - return a.ActionHeader.Len() + 4 + return a.ActionHeader.Len() + 4 } func (a *ActionPopMpls) MarshalBinary() (data []byte, err error) { - data, err = a.ActionHeader.MarshalBinary() + data, err = a.ActionHeader.MarshalBinary() - // Padding - bytes := make([]byte, 4) - binary.BigEndian.PutUint16(bytes[0:], a.EtherType) + // Padding + bytes := make([]byte, 4) + binary.BigEndian.PutUint16(bytes[0:], a.EtherType) - data = append(data, bytes...) - return + data = append(data, bytes...) + return } func (a *ActionPopMpls) UnmarshalBinary(data []byte) error { - a.ActionHeader.UnmarshalBinary(data[:4]) - a.EtherType = binary.BigEndian.Uint16(data[4:]) - return nil + a.ActionHeader.UnmarshalBinary(data[:4]) + a.EtherType = binary.BigEndian.Uint16(data[4:]) + return nil } type ActionSetField struct { - ActionHeader - Field MatchField + ActionHeader + Field MatchField } func NewActionSetField(field MatchField) *ActionSetField { - a := new(ActionSetField) - a.Type = ActionType_SetField - a.Field = field - a.Length = a.Len() - return a + a := new(ActionSetField) + a.Type = ActionType_SetField + a.Field = field + a.Length = a.Len() + return a } func (a *ActionSetField) Len() (n uint16) { - n = a.ActionHeader.Len() + a.Field.Len() - // Round it to closest multiple of 8 - n = ((n + 7)/8)*8 + n = a.ActionHeader.Len() + a.Field.Len() + // Round it to closest multiple of 8 + n = ((n + 7) / 8) * 8 - return + return } func (a *ActionSetField) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(a.Len())) - n := 0 - b, err := a.ActionHeader.MarshalBinary() - copy(data, b) - n += int(a.ActionHeader.Len()) + data = make([]byte, int(a.Len())) + n := 0 + b, err := a.ActionHeader.MarshalBinary() + copy(data, b) + n += int(a.ActionHeader.Len()) - b, err = a.Field.MarshalBinary() - copy(data[n:], b) + b, err = a.Field.MarshalBinary() + copy(data[n:], b) - return + return } func (a *ActionSetField) UnmarshalBinary(data []byte) error { - n := 0 - err := a.ActionHeader.UnmarshalBinary(data[n:]) - n += int(a.ActionHeader.Len()) - err = a.Field.UnmarshalBinary(data[n:]) - n += int(a.Field.Len()) + n := 0 + err := a.ActionHeader.UnmarshalBinary(data[n:]) + n += int(a.ActionHeader.Len()) + err = a.Field.UnmarshalBinary(data[n:]) + n += int(a.Field.Len()) - return err + return err } diff --git a/openflow13/flowmod.go b/openflow13/flowmod.go index 983036e..cda7266 100644 --- a/openflow13/flowmod.go +++ b/openflow13/flowmod.go @@ -1,290 +1,289 @@ package openflow13 import ( - "encoding/binary" + "encoding/binary" - "github.com/shaleman/libOpenflow/common" - log "github.com/Sirupsen/logrus" + log "github.com/Sirupsen/logrus" + "github.com/shaleman/libOpenflow/common" ) // ofp_flow_mod 1.3 type FlowMod struct { - common.Header - Cookie uint64 - CookieMask uint64 + common.Header + Cookie uint64 + CookieMask uint64 - TableId uint8 /* ID of the table to put the flow in */ - Command uint8 /* flowmod command */ + TableId uint8 /* ID of the table to put the flow in */ + Command uint8 /* flowmod command */ - IdleTimeout uint16 /* Idle time before discarding (seconds). */ - HardTimeout uint16 /* Max time before discarding (seconds). */ + IdleTimeout uint16 /* Idle time before discarding (seconds). */ + HardTimeout uint16 /* Max time before discarding (seconds). */ - Priority uint16 /* Priority level of flow entry. */ - BufferId uint32 /* Buffered packet to apply to */ + Priority uint16 /* Priority level of flow entry. */ + BufferId uint32 /* Buffered packet to apply to */ - OutPort uint32 - OutGroup uint32 - Flags uint16 + OutPort uint32 + OutGroup uint32 + Flags uint16 - pad []byte // 2bytes + pad []byte // 2bytes - Match Match // Fields to match - Instructions []Instruction // Instruction set - 0 or more. + Match Match // Fields to match + Instructions []Instruction // Instruction set - 0 or more. } func NewFlowMod() *FlowMod { - f := new(FlowMod) - f.Header = NewOfp13Header() - f.Header.Type = Type_FlowMod - // Add a generator for f.Cookie here - f.Cookie = 0 - f.CookieMask = 0 - - f.TableId = 0 - f.Command = FC_ADD - - f.IdleTimeout = 0 - f.HardTimeout = 0 - // Add a priority gen here - f.Priority = 1000 - f.BufferId = 0xffffffff - f.OutPort = P_ANY - f.OutGroup = OFPG_ANY - f.Flags = 0 - - f.Match = *NewMatch() - f.Instructions = make([]Instruction, 0) - return f + f := new(FlowMod) + f.Header = NewOfp13Header() + f.Header.Type = Type_FlowMod + // Add a generator for f.Cookie here + f.Cookie = 0 + f.CookieMask = 0 + + f.TableId = 0 + f.Command = FC_ADD + + f.IdleTimeout = 0 + f.HardTimeout = 0 + // Add a priority gen here + f.Priority = 1000 + f.BufferId = 0xffffffff + f.OutPort = P_ANY + f.OutGroup = OFPG_ANY + f.Flags = 0 + + f.Match = *NewMatch() + f.Instructions = make([]Instruction, 0) + return f } func (f *FlowMod) AddInstruction(instr Instruction) { - f.Instructions = append(f.Instructions, instr) + f.Instructions = append(f.Instructions, instr) } func (f *FlowMod) Len() (n uint16) { - n = f.Header.Len() - n += 40 - n += f.Match.Len() - if f.Command == FC_DELETE || f.Command == FC_DELETE_STRICT { - return - } - for _, v := range f.Instructions { - n += v.Len() - } - return + n = f.Header.Len() + n += 40 + n += f.Match.Len() + if f.Command == FC_DELETE || f.Command == FC_DELETE_STRICT { + return + } + for _, v := range f.Instructions { + n += v.Len() + } + return } func (f *FlowMod) MarshalBinary() (data []byte, err error) { - f.Header.Length = f.Len() - data, err = f.Header.MarshalBinary() - - bytes := make([]byte, 40) - n := 0 - binary.BigEndian.PutUint64(bytes[n:], f.Cookie) - n += 8 - binary.BigEndian.PutUint64(bytes[n:], f.CookieMask) - n += 8 - bytes[n] = f.TableId - n += 1 - bytes[n] = f.Command - n += 1 - binary.BigEndian.PutUint16(bytes[n:], f.IdleTimeout) - n += 2 - binary.BigEndian.PutUint16(bytes[n:], f.HardTimeout) - n += 2 - binary.BigEndian.PutUint16(bytes[n:], f.Priority) - n += 2 - binary.BigEndian.PutUint32(bytes[n:], f.BufferId) - n += 4 - binary.BigEndian.PutUint32(bytes[n:], f.OutPort) - n += 4 - binary.BigEndian.PutUint32(bytes[n:], f.OutPort) - n += 4 - binary.BigEndian.PutUint16(bytes[n:], f.Flags) - n += 2 - n += 2 // for pad - data = append(data, bytes...) - - bytes, err = f.Match.MarshalBinary() - data = append(data, bytes...) - - for _, instr := range f.Instructions { - bytes, err = instr.MarshalBinary() - data = append(data, bytes...) - log.Debugf("flowmod instr: %v", bytes) - } - - log.Debugf("Flowmod(%d): %v", len(data), data) - return + f.Header.Length = f.Len() + data, err = f.Header.MarshalBinary() + + bytes := make([]byte, 40) + n := 0 + binary.BigEndian.PutUint64(bytes[n:], f.Cookie) + n += 8 + binary.BigEndian.PutUint64(bytes[n:], f.CookieMask) + n += 8 + bytes[n] = f.TableId + n += 1 + bytes[n] = f.Command + n += 1 + binary.BigEndian.PutUint16(bytes[n:], f.IdleTimeout) + n += 2 + binary.BigEndian.PutUint16(bytes[n:], f.HardTimeout) + n += 2 + binary.BigEndian.PutUint16(bytes[n:], f.Priority) + n += 2 + binary.BigEndian.PutUint32(bytes[n:], f.BufferId) + n += 4 + binary.BigEndian.PutUint32(bytes[n:], f.OutPort) + n += 4 + binary.BigEndian.PutUint32(bytes[n:], f.OutPort) + n += 4 + binary.BigEndian.PutUint16(bytes[n:], f.Flags) + n += 2 + n += 2 // for pad + data = append(data, bytes...) + + bytes, err = f.Match.MarshalBinary() + data = append(data, bytes...) + + for _, instr := range f.Instructions { + bytes, err = instr.MarshalBinary() + data = append(data, bytes...) + log.Debugf("flowmod instr: %v", bytes) + } + + log.Debugf("Flowmod(%d): %v", len(data), data) + return } func (f *FlowMod) UnmarshalBinary(data []byte) error { - n := 0 - f.Header.UnmarshalBinary(data[n:]) - n += int(f.Header.Len()) - - f.Cookie = binary.BigEndian.Uint64(data[n:]) - n += 8 - f.CookieMask = binary.BigEndian.Uint64(data[n:]) - n += 8 - f.TableId = data[n] - n += 1 - f.Command = data[n] - n += 1 - f.IdleTimeout = binary.BigEndian.Uint16(data[n:]) - n += 2 - f.HardTimeout = binary.BigEndian.Uint16(data[n:]) - n += 2 - f.Priority = binary.BigEndian.Uint16(data[n:]) - n += 2 - f.BufferId = binary.BigEndian.Uint32(data[n:]) - n += 4 - f.OutPort = binary.BigEndian.Uint32(data[n:]) - n += 4 - f.OutGroup = binary.BigEndian.Uint32(data[n:]) - n += 4 - f.Flags = binary.BigEndian.Uint16(data[n:]) - n += 2 - n += 2 // for pad - - f.Match.UnmarshalBinary(data[n:]) - n += int(f.Match.Len()) - - for n < int(f.Header.Length) { - instr := DecodeInstr(data[n:]) - f.Instructions = append(f.Instructions, instr) - n += int(instr.Len()) - } - return nil + n := 0 + f.Header.UnmarshalBinary(data[n:]) + n += int(f.Header.Len()) + + f.Cookie = binary.BigEndian.Uint64(data[n:]) + n += 8 + f.CookieMask = binary.BigEndian.Uint64(data[n:]) + n += 8 + f.TableId = data[n] + n += 1 + f.Command = data[n] + n += 1 + f.IdleTimeout = binary.BigEndian.Uint16(data[n:]) + n += 2 + f.HardTimeout = binary.BigEndian.Uint16(data[n:]) + n += 2 + f.Priority = binary.BigEndian.Uint16(data[n:]) + n += 2 + f.BufferId = binary.BigEndian.Uint32(data[n:]) + n += 4 + f.OutPort = binary.BigEndian.Uint32(data[n:]) + n += 4 + f.OutGroup = binary.BigEndian.Uint32(data[n:]) + n += 4 + f.Flags = binary.BigEndian.Uint16(data[n:]) + n += 2 + n += 2 // for pad + + f.Match.UnmarshalBinary(data[n:]) + n += int(f.Match.Len()) + + for n < int(f.Header.Length) { + instr := DecodeInstr(data[n:]) + f.Instructions = append(f.Instructions, instr) + n += int(instr.Len()) + } + return nil } // ofp_flow_mod_command 1.3 const ( - FC_ADD = iota // OFPFC_ADD = 0 - FC_MODIFY - FC_MODIFY_STRICT - FC_DELETE - FC_DELETE_STRICT + FC_ADD = iota // OFPFC_ADD = 0 + FC_MODIFY + FC_MODIFY_STRICT + FC_DELETE + FC_DELETE_STRICT ) // ofp_flow_mod_flags 1.3 const ( - FF_SEND_FLOW_REM = 1 << 0 /* Send flow removed message when flow expires or is deleted. */ - FF_CHECK_OVERLAP = 1 << 1 /* Check for overlapping entries first */ - FF_RESET_COUNTS = 1 << 2 /* Reset flow packet and byte counts */ - FF_NO_PKT_COUNTS = 1 << 3 /* Don’t keep track of packet count */ - FF_NO_BYT_COUNTS = 1 << 4 /* Don’t keep track of byte count */ + FF_SEND_FLOW_REM = 1 << 0 /* Send flow removed message when flow expires or is deleted. */ + FF_CHECK_OVERLAP = 1 << 1 /* Check for overlapping entries first */ + FF_RESET_COUNTS = 1 << 2 /* Reset flow packet and byte counts */ + FF_NO_PKT_COUNTS = 1 << 3 /* Don’t keep track of packet count */ + FF_NO_BYT_COUNTS = 1 << 4 /* Don’t keep track of byte count */ ) // BEGIN: ofp13 - 7.4.2 type FlowRemoved struct { - common.Header - Cookie uint64 - Priority uint16 - Reason uint8 - TableId uint8 + common.Header + Cookie uint64 + Priority uint16 + Reason uint8 + TableId uint8 - DurationSec uint32 - DurationNSec uint32 + DurationSec uint32 + DurationNSec uint32 - IdleTimeout uint16 - HardTimeout uint16 + IdleTimeout uint16 + HardTimeout uint16 - PacketCount uint64 - ByteCount uint64 - - Match Match + PacketCount uint64 + ByteCount uint64 + Match Match } func NewFlowRemoved() *FlowRemoved { - f := new(FlowRemoved) - f.Header = NewOfp13Header() - f.Match = *NewMatch() - return f + f := new(FlowRemoved) + f.Header = NewOfp13Header() + f.Match = *NewMatch() + return f } func (f *FlowRemoved) Len() (n uint16) { - n = f.Header.Len() - n += f.Match.Len() - n += 40 - return + n = f.Header.Len() + n += f.Match.Len() + n += 40 + return } func (f *FlowRemoved) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(f.Len())) - next := 0 - - bytes, err := f.Header.MarshalBinary() - copy(data[next:], bytes) - next += int(f.Header.Len()) - - binary.BigEndian.PutUint64(data[next:], f.Cookie) - next += 8 - binary.BigEndian.PutUint16(data[next:], f.Priority) - next += 2 - data[next] = f.Reason - next += 1 - data[next] = f.TableId - next += 1 - - binary.BigEndian.PutUint32(data[next:], f.DurationSec) - next += 4 - binary.BigEndian.PutUint32(data[next:], f.DurationNSec) - next += 4 - binary.BigEndian.PutUint16(data[next:], f.IdleTimeout) - next += 2 - binary.BigEndian.PutUint16(data[next:], f.HardTimeout) - next += 2 - - binary.BigEndian.PutUint64(data[next:], f.PacketCount) - next += 8 - binary.BigEndian.PutUint64(data[next:], f.ByteCount) - next += 8 - - bytes, err = f.Match.MarshalBinary() - copy(data[next:], bytes) - next += int(f.Match.Len()) - return + data = make([]byte, int(f.Len())) + next := 0 + + bytes, err := f.Header.MarshalBinary() + copy(data[next:], bytes) + next += int(f.Header.Len()) + + binary.BigEndian.PutUint64(data[next:], f.Cookie) + next += 8 + binary.BigEndian.PutUint16(data[next:], f.Priority) + next += 2 + data[next] = f.Reason + next += 1 + data[next] = f.TableId + next += 1 + + binary.BigEndian.PutUint32(data[next:], f.DurationSec) + next += 4 + binary.BigEndian.PutUint32(data[next:], f.DurationNSec) + next += 4 + binary.BigEndian.PutUint16(data[next:], f.IdleTimeout) + next += 2 + binary.BigEndian.PutUint16(data[next:], f.HardTimeout) + next += 2 + + binary.BigEndian.PutUint64(data[next:], f.PacketCount) + next += 8 + binary.BigEndian.PutUint64(data[next:], f.ByteCount) + next += 8 + + bytes, err = f.Match.MarshalBinary() + copy(data[next:], bytes) + next += int(f.Match.Len()) + return } func (f *FlowRemoved) UnmarshalBinary(data []byte) error { - next := 0 - var err error - err = f.Header.UnmarshalBinary(data[next:]) - next += int(f.Header.Len()) - - f.Cookie = binary.BigEndian.Uint64(data[next:]) - next += 8 - f.Priority = binary.BigEndian.Uint16(data[next:]) - next += 2 - f.Reason = data[next] - next += 1 - f.TableId = data[next] - next += 1 - f.DurationSec = binary.BigEndian.Uint32(data[next:]) - next += 4 - f.DurationNSec = binary.BigEndian.Uint32(data[next:]) - next += 4 - f.IdleTimeout = binary.BigEndian.Uint16(data[next:]) - next += 2 - f.HardTimeout = binary.BigEndian.Uint16(data[next:]) - next += 2 - f.PacketCount = binary.BigEndian.Uint64(data[next:]) - next += 8 - f.ByteCount = binary.BigEndian.Uint64(data[next:]) - next += 8 - - err = f.Match.UnmarshalBinary(data[next:]) - next += int(f.Match.Len()) - - return err + next := 0 + var err error + err = f.Header.UnmarshalBinary(data[next:]) + next += int(f.Header.Len()) + + f.Cookie = binary.BigEndian.Uint64(data[next:]) + next += 8 + f.Priority = binary.BigEndian.Uint16(data[next:]) + next += 2 + f.Reason = data[next] + next += 1 + f.TableId = data[next] + next += 1 + f.DurationSec = binary.BigEndian.Uint32(data[next:]) + next += 4 + f.DurationNSec = binary.BigEndian.Uint32(data[next:]) + next += 4 + f.IdleTimeout = binary.BigEndian.Uint16(data[next:]) + next += 2 + f.HardTimeout = binary.BigEndian.Uint16(data[next:]) + next += 2 + f.PacketCount = binary.BigEndian.Uint64(data[next:]) + next += 8 + f.ByteCount = binary.BigEndian.Uint64(data[next:]) + next += 8 + + err = f.Match.UnmarshalBinary(data[next:]) + next += int(f.Match.Len()) + + return err } // ofp_flow_removed_reason 1.3 const ( - RR_IDLE_TIMEOUT = iota /* Flow idle time exceeded idle_timeout. */ - RR_HARD_TIMEOUT /* Time exceeded hard_timeout. */ - RR_DELETE /* Evicted by a DELETE flow mod. */ - RR_GROUP_DELETE /* Group was removed. */ + RR_IDLE_TIMEOUT = iota /* Flow idle time exceeded idle_timeout. */ + RR_HARD_TIMEOUT /* Time exceeded hard_timeout. */ + RR_DELETE /* Evicted by a DELETE flow mod. */ + RR_GROUP_DELETE /* Group was removed. */ ) diff --git a/openflow13/group.go b/openflow13/group.go index 54cca0b..f25e209 100644 --- a/openflow13/group.go +++ b/openflow13/group.go @@ -3,205 +3,205 @@ package openflow13 // This file has all group related defs import ( - "encoding/binary" + "encoding/binary" - "github.com/shaleman/libOpenflow/common" - log "github.com/Sirupsen/logrus" + log "github.com/Sirupsen/logrus" + "github.com/shaleman/libOpenflow/common" ) const ( - OFPG_MAX = 0xffffff00 /* Last usable group number. */ - /* Fake groups. */ - OFPG_ALL = 0xfffffffc /* Represents all groups for group delete commands. */ - OFPG_ANY = 0xffffffff /* Wildcard group used only for flow stats requests. Selects all flows regardless of group (including flows with no group). - */ + OFPG_MAX = 0xffffff00 /* Last usable group number. */ + /* Fake groups. */ + OFPG_ALL = 0xfffffffc /* Represents all groups for group delete commands. */ + OFPG_ANY = 0xffffffff /* Wildcard group used only for flow stats requests. Selects all flows regardless of group (including flows with no group). + */ ) const ( - OFPGC_ADD = 0 /* New group. */ - OFPGC_MODIFY = 1 /* Modify all matching groups. */ - OFPGC_DELETE = 2 /* Delete all matching groups. */ + OFPGC_ADD = 0 /* New group. */ + OFPGC_MODIFY = 1 /* Modify all matching groups. */ + OFPGC_DELETE = 2 /* Delete all matching groups. */ ) const ( - OFPGT_ALL = 0 /* All (multicast/broadcast) group. */ - OFPGT_SELECT = 1 /* Select group. */ - OFPGT_INDIRECT = 2 /* Indirect group. */ - OFPGT_FF = 3 /* Fast failover group. */ + OFPGT_ALL = 0 /* All (multicast/broadcast) group. */ + OFPGT_SELECT = 1 /* Select group. */ + OFPGT_INDIRECT = 2 /* Indirect group. */ + OFPGT_FF = 3 /* Fast failover group. */ ) // GroupMod message type GroupMod struct { - common.Header - Command uint16 /* One of OFPGC_*. */ - Type uint8 /* One of OFPGT_*. */ - pad uint8 /* Pad to 64 bits. */ - GroupId uint32 /* Group identifier. */ - Buckets []Bucket /* List of buckets */ + common.Header + Command uint16 /* One of OFPGC_*. */ + Type uint8 /* One of OFPGT_*. */ + pad uint8 /* Pad to 64 bits. */ + GroupId uint32 /* Group identifier. */ + Buckets []Bucket /* List of buckets */ } // Create a new group mode message func NewGroupMod() *GroupMod { - g := new(GroupMod) - g.Header = NewOfp13Header() - g.Header.Type = Type_GroupMod - - g.Command = OFPGC_ADD - g.Type = OFPGT_ALL - g.GroupId = 0 - g.Buckets = make([]Bucket, 0) - return g + g := new(GroupMod) + g.Header = NewOfp13Header() + g.Header.Type = Type_GroupMod + + g.Command = OFPGC_ADD + g.Type = OFPGT_ALL + g.GroupId = 0 + g.Buckets = make([]Bucket, 0) + return g } // Add a bucket to group mod func (g *GroupMod) AddBucket(bkt Bucket) { - g.Buckets = append(g.Buckets, bkt) + g.Buckets = append(g.Buckets, bkt) } func (g *GroupMod) Len() (n uint16) { - n = g.Header.Len() - n += 8 - if g.Command == OFPGC_DELETE { - return - } + n = g.Header.Len() + n += 8 + if g.Command == OFPGC_DELETE { + return + } - for _, b := range g.Buckets { - n += b.Len() - } + for _, b := range g.Buckets { + n += b.Len() + } - return + return } func (g *GroupMod) MarshalBinary() (data []byte, err error) { - g.Header.Length = g.Len() - data, err = g.Header.MarshalBinary() - - bytes := make([]byte, 8) - n := 0 - binary.BigEndian.PutUint16(bytes[n:], g.Command) - n += 2 - bytes[n] = g.Type - n += 1 - bytes[n] = g.pad - n += 1 - binary.BigEndian.PutUint32(bytes[n:], g.GroupId) - n += 4 - data = append(data, bytes...) - - for _, bkt := range g.Buckets { - bytes, err = bkt.MarshalBinary() - data = append(data, bytes...) - log.Debugf("Groupmod bucket: %v", bytes) - } - - log.Debugf("GroupMod(%d): %v", len(data), data) - - return + g.Header.Length = g.Len() + data, err = g.Header.MarshalBinary() + + bytes := make([]byte, 8) + n := 0 + binary.BigEndian.PutUint16(bytes[n:], g.Command) + n += 2 + bytes[n] = g.Type + n += 1 + bytes[n] = g.pad + n += 1 + binary.BigEndian.PutUint32(bytes[n:], g.GroupId) + n += 4 + data = append(data, bytes...) + + for _, bkt := range g.Buckets { + bytes, err = bkt.MarshalBinary() + data = append(data, bytes...) + log.Debugf("Groupmod bucket: %v", bytes) + } + + log.Debugf("GroupMod(%d): %v", len(data), data) + + return } func (g *GroupMod) UnmarshalBinary(data []byte) error { - n := 0 - g.Header.UnmarshalBinary(data[n:]) - n += int(g.Header.Len()) - - g.Command = binary.BigEndian.Uint16(data[n:]) - n += 2 - g.Type = data[n] - n += 1 - g.pad = data[n] - n += 1 - g.GroupId = binary.BigEndian.Uint32(data[n:]) - n += 4 - - for n < int(g.Header.Length) { - bkt := new(Bucket) - bkt.UnmarshalBinary(data[n:]) - g.Buckets = append(g.Buckets, *bkt) - n += int(bkt.Len()) - } - - return nil + n := 0 + g.Header.UnmarshalBinary(data[n:]) + n += int(g.Header.Len()) + + g.Command = binary.BigEndian.Uint16(data[n:]) + n += 2 + g.Type = data[n] + n += 1 + g.pad = data[n] + n += 1 + g.GroupId = binary.BigEndian.Uint32(data[n:]) + n += 4 + + for n < int(g.Header.Length) { + bkt := new(Bucket) + bkt.UnmarshalBinary(data[n:]) + g.Buckets = append(g.Buckets, *bkt) + n += int(bkt.Len()) + } + + return nil } type Bucket struct { - Length uint16 /* Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. */ - Weight uint16 /* Relative weight of bucket. Only defined for select groups. */ - WatchPort uint32 /* Used for FRR groups */ - WatchGroup uint32 /* Used for FRR groups */ - pad []byte /* 4 bytes */ - Actions []Action /* zero or more actions */ + Length uint16 /* Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. */ + Weight uint16 /* Relative weight of bucket. Only defined for select groups. */ + WatchPort uint32 /* Used for FRR groups */ + WatchGroup uint32 /* Used for FRR groups */ + pad []byte /* 4 bytes */ + Actions []Action /* zero or more actions */ } // Create a new Bucket func NewBucket() *Bucket { - bkt := new(Bucket) + bkt := new(Bucket) - bkt.Weight = 1 - bkt.pad = make([]byte, 4) - bkt.Actions = make([]Action, 0) - bkt.WatchPort = P_ANY - bkt.WatchGroup = OFPG_ANY - bkt.Length = bkt.Len() + bkt.Weight = 1 + bkt.pad = make([]byte, 4) + bkt.Actions = make([]Action, 0) + bkt.WatchPort = P_ANY + bkt.WatchGroup = OFPG_ANY + bkt.Length = bkt.Len() - return bkt + return bkt } // Add an action to the bucket func (b *Bucket) AddAction(act Action) { - b.Actions = append(b.Actions, act) + b.Actions = append(b.Actions, act) } func (b *Bucket) Len() (n uint16) { - n = 16 + n = 16 - for _, a := range b.Actions { - n += a.Len() - } + for _, a := range b.Actions { + n += a.Len() + } - // Round it to closest multiple of 8 - n = ((n + 7)/8)*8 - return + // Round it to closest multiple of 8 + n = ((n + 7) / 8) * 8 + return } func (b *Bucket) MarshalBinary() (data []byte, err error) { - bytes := make([]byte, 16) - n := 0 - b.Length = b.Len() // Calculate length first - binary.BigEndian.PutUint16(bytes[n:], b.Length) - n += 2 - binary.BigEndian.PutUint16(bytes[n:], b.Weight) - n += 2 - binary.BigEndian.PutUint32(bytes[n:], b.WatchPort) - n += 4 - binary.BigEndian.PutUint32(bytes[n:], b.WatchGroup) - n += 4 - data = append(data, bytes...) - - for _, a := range b.Actions { - bytes, err = a.MarshalBinary() - data = append(data, bytes...) - } - - return + bytes := make([]byte, 16) + n := 0 + b.Length = b.Len() // Calculate length first + binary.BigEndian.PutUint16(bytes[n:], b.Length) + n += 2 + binary.BigEndian.PutUint16(bytes[n:], b.Weight) + n += 2 + binary.BigEndian.PutUint32(bytes[n:], b.WatchPort) + n += 4 + binary.BigEndian.PutUint32(bytes[n:], b.WatchGroup) + n += 4 + data = append(data, bytes...) + + for _, a := range b.Actions { + bytes, err = a.MarshalBinary() + data = append(data, bytes...) + } + + return } func (b *Bucket) UnmarshalBinary(data []byte) error { - n := 0 - b.Length = binary.BigEndian.Uint16(data[n:]) - n += 2 - b.Weight = binary.BigEndian.Uint16(data[n:]) - n += 2 - b.WatchPort = binary.BigEndian.Uint32(data[n:]) - n += 4 - b.WatchGroup = binary.BigEndian.Uint32(data[n:]) - n += 4 - n += 4 // for padding - - for n < int(b.Length) { - a := DecodeAction(data[n:]) - b.Actions = append(b.Actions, a) - n += int(a.Len()) - } - - return nil + n := 0 + b.Length = binary.BigEndian.Uint16(data[n:]) + n += 2 + b.Weight = binary.BigEndian.Uint16(data[n:]) + n += 2 + b.WatchPort = binary.BigEndian.Uint32(data[n:]) + n += 4 + b.WatchGroup = binary.BigEndian.Uint32(data[n:]) + n += 4 + n += 4 // for padding + + for n < int(b.Length) { + a := DecodeAction(data[n:]) + b.Actions = append(b.Actions, a) + n += int(a.Len()) + } + + return nil } diff --git a/openflow13/instruction.go b/openflow13/instruction.go index 25c905d..f08d279 100644 --- a/openflow13/instruction.go +++ b/openflow13/instruction.go @@ -3,254 +3,252 @@ package openflow13 // This file contains OFP 1.3 instruction defenitions import ( - "errors" - "encoding/binary" + "encoding/binary" + "errors" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/util" ) - - // ofp_instruction_type 1.3 const ( - InstrType_GOTO_TABLE = 1 /* Setup the next table in the lookup pipeline */ - InstrType_WRITE_METADATA = 2 /* Setup the metadata field for use later in pipeline */ - InstrType_WRITE_ACTIONS = 3 /* Write the action(s) onto the datapath action set */ - InstrType_APPLY_ACTIONS = 4 /* Applies the action(s) immediately */ - InstrType_CLEAR_ACTIONS = 5 /* Clears all actions from the datapath action set */ - InstrType_METER = 6 /* Apply meter (rate limiter) */ - InstrType_EXPERIMENTER = 0xFFFF /* Experimenter instruction */ + InstrType_GOTO_TABLE = 1 /* Setup the next table in the lookup pipeline */ + InstrType_WRITE_METADATA = 2 /* Setup the metadata field for use later in pipeline */ + InstrType_WRITE_ACTIONS = 3 /* Write the action(s) onto the datapath action set */ + InstrType_APPLY_ACTIONS = 4 /* Applies the action(s) immediately */ + InstrType_CLEAR_ACTIONS = 5 /* Clears all actions from the datapath action set */ + InstrType_METER = 6 /* Apply meter (rate limiter) */ + InstrType_EXPERIMENTER = 0xFFFF /* Experimenter instruction */ ) // Generic instruction header type InstrHeader struct { - Type uint16 - Length uint16 + Type uint16 + Length uint16 } type Instruction interface { - util.Message - AddAction(act Action, prepend bool) error + util.Message + AddAction(act Action, prepend bool) error } func (a *InstrHeader) Len() (n uint16) { - return 4 + return 4 } func (a *InstrHeader) MarshalBinary() (data []byte, err error) { - data = make([]byte, a.Len()) - binary.BigEndian.PutUint16(data[:2], a.Type) - binary.BigEndian.PutUint16(data[2:4], a.Length) - return + data = make([]byte, a.Len()) + binary.BigEndian.PutUint16(data[:2], a.Type) + binary.BigEndian.PutUint16(data[2:4], a.Length) + return } func (a *InstrHeader) UnmarshalBinary(data []byte) error { - if len(data) != 4 { - return errors.New("Wrong size to unmarshal an InstrHeader message.") - } - a.Type = binary.BigEndian.Uint16(data[:2]) - a.Length = binary.BigEndian.Uint16(data[2:4]) - return nil + if len(data) != 4 { + return errors.New("Wrong size to unmarshal an InstrHeader message.") + } + a.Type = binary.BigEndian.Uint16(data[:2]) + a.Length = binary.BigEndian.Uint16(data[2:4]) + return nil } func DecodeInstr(data []byte) Instruction { - t := binary.BigEndian.Uint16(data[:2]) - var a Instruction - switch t { - case InstrType_GOTO_TABLE: - a = new(InstrGotoTable) - case InstrType_WRITE_METADATA: - a = new(InstrWriteMetadata) - case InstrType_WRITE_ACTIONS: - a = new(InstrActions) - case InstrType_APPLY_ACTIONS: - a = new(InstrActions) - case InstrType_CLEAR_ACTIONS: - a = new(InstrActions) - case InstrType_METER: - a = new(InstrMeter) - case InstrType_EXPERIMENTER: - } - - a.UnmarshalBinary(data) - return a + t := binary.BigEndian.Uint16(data[:2]) + var a Instruction + switch t { + case InstrType_GOTO_TABLE: + a = new(InstrGotoTable) + case InstrType_WRITE_METADATA: + a = new(InstrWriteMetadata) + case InstrType_WRITE_ACTIONS: + a = new(InstrActions) + case InstrType_APPLY_ACTIONS: + a = new(InstrActions) + case InstrType_CLEAR_ACTIONS: + a = new(InstrActions) + case InstrType_METER: + a = new(InstrMeter) + case InstrType_EXPERIMENTER: + } + + a.UnmarshalBinary(data) + return a } type InstrGotoTable struct { - InstrHeader - TableId uint8 - pad []byte // 3 bytes + InstrHeader + TableId uint8 + pad []byte // 3 bytes } func (instr *InstrGotoTable) Len() (n uint16) { - return 8 + return 8 } func (instr *InstrGotoTable) MarshalBinary() (data []byte, err error) { - data, err = instr.InstrHeader.MarshalBinary() + data, err = instr.InstrHeader.MarshalBinary() - b := make([]byte, 4) - b[0] = instr.TableId - copy(b[3:], instr.pad) + b := make([]byte, 4) + b[0] = instr.TableId + copy(b[3:], instr.pad) - data = append(data, b...) - return + data = append(data, b...) + return } func (instr *InstrGotoTable) UnmarshalBinary(data []byte) error { - instr.InstrHeader.UnmarshalBinary(data[:4]) + instr.InstrHeader.UnmarshalBinary(data[:4]) - instr.TableId = data[4] - copy(instr.pad, data[5:8]) + instr.TableId = data[4] + copy(instr.pad, data[5:8]) - return nil + return nil } func NewInstrGotoTable(tableId uint8) *InstrGotoTable { - instr := new(InstrGotoTable) - instr.Type = InstrType_GOTO_TABLE - instr.TableId = tableId - instr.pad = make([]byte, 3) - instr.Length = instr.Len() + instr := new(InstrGotoTable) + instr.Type = InstrType_GOTO_TABLE + instr.TableId = tableId + instr.pad = make([]byte, 3) + instr.Length = instr.Len() - return instr + return instr } func (instr *InstrGotoTable) AddAction(act Action, prepend bool) error { - return errors.New("Not supported on this instrction") + return errors.New("Not supported on this instrction") } type InstrWriteMetadata struct { - InstrHeader - pad []byte // 4 bytes - Metadata uint64 /* Metadata value to write */ - MetadataMask uint64 /* Metadata write bitmask */ + InstrHeader + pad []byte // 4 bytes + Metadata uint64 /* Metadata value to write */ + MetadataMask uint64 /* Metadata write bitmask */ } // FIXME: we need marshall/unmarshall/len/new functions for write metadata instr func (instr *InstrWriteMetadata) Len() (n uint16) { - return 24 + return 24 } func (instr *InstrWriteMetadata) MarshalBinary() (data []byte, err error) { - data, err = instr.InstrHeader.MarshalBinary() + data, err = instr.InstrHeader.MarshalBinary() - b := make([]byte, 20) - copy(b, instr.pad) - binary.BigEndian.PutUint64(b[4:], instr.Metadata) - binary.BigEndian.PutUint64(b[12:], instr.MetadataMask) + b := make([]byte, 20) + copy(b, instr.pad) + binary.BigEndian.PutUint64(b[4:], instr.Metadata) + binary.BigEndian.PutUint64(b[12:], instr.MetadataMask) - data = append(data, b...) - return + data = append(data, b...) + return } func (instr *InstrWriteMetadata) UnmarshalBinary(data []byte) error { - instr.InstrHeader.UnmarshalBinary(data[:4]) + instr.InstrHeader.UnmarshalBinary(data[:4]) - copy(instr.pad, data[4:8]) - instr.Metadata = binary.BigEndian.Uint64(data[8:16]) - instr.MetadataMask = binary.BigEndian.Uint64(data[16:24]) + copy(instr.pad, data[4:8]) + instr.Metadata = binary.BigEndian.Uint64(data[8:16]) + instr.MetadataMask = binary.BigEndian.Uint64(data[16:24]) - return nil + return nil } func NewInstrWriteMetadata(metadata, metadataMask uint64) *InstrWriteMetadata { - instr := new(InstrWriteMetadata) - instr.Type = InstrType_WRITE_METADATA - instr.pad = make([]byte, 4) - instr.Metadata = metadata - instr.MetadataMask = metadataMask - instr.Length = instr.Len() - - return instr + instr := new(InstrWriteMetadata) + instr.Type = InstrType_WRITE_METADATA + instr.pad = make([]byte, 4) + instr.Metadata = metadata + instr.MetadataMask = metadataMask + instr.Length = instr.Len() + + return instr } func (instr *InstrWriteMetadata) AddAction(act Action, prepend bool) error { - return errors.New("Not supported on this instrction") + return errors.New("Not supported on this instrction") } // *_ACTION instructions type InstrActions struct { - InstrHeader - pad []byte // 4 bytes - Actions []Action /* 0 or more actions associated with OFPIT_WRITE_ACTIONS and OFPIT_APPLY_ACTIONS */ + InstrHeader + pad []byte // 4 bytes + Actions []Action /* 0 or more actions associated with OFPIT_WRITE_ACTIONS and OFPIT_APPLY_ACTIONS */ } func (instr *InstrActions) Len() (n uint16) { - n = 8 + n = 8 - for _, act := range instr.Actions { - n += act.Len() - } + for _, act := range instr.Actions { + n += act.Len() + } - return + return } func (instr *InstrActions) MarshalBinary() (data []byte, err error) { - data, err = instr.InstrHeader.MarshalBinary() + data, err = instr.InstrHeader.MarshalBinary() - b := make([]byte, 4) - copy(b, instr.pad) - data = append(data, b...) + b := make([]byte, 4) + copy(b, instr.pad) + data = append(data, b...) - for _, act := range instr.Actions { - b, err = act.MarshalBinary() - data = append(data, b...) - } + for _, act := range instr.Actions { + b, err = act.MarshalBinary() + data = append(data, b...) + } - return + return } func (instr *InstrActions) UnmarshalBinary(data []byte) error { - instr.InstrHeader.UnmarshalBinary(data[:4]) + instr.InstrHeader.UnmarshalBinary(data[:4]) - n := 8 - for ;n < int(instr.Length); { - act := DecodeAction(data[n:]) - instr.Actions = append(instr.Actions, act) - n += int(act.Len()) - } + n := 8 + for n < int(instr.Length) { + act := DecodeAction(data[n:]) + instr.Actions = append(instr.Actions, act) + n += int(act.Len()) + } - return nil + return nil } func (instr *InstrActions) AddAction(act Action, prepend bool) error { - // Append or prepend to the list - if (prepend) { - instr.Actions = append([]Action{act}, instr.Actions...) - } else { - instr.Actions = append(instr.Actions, act) - } - - instr.Length = instr.Len() - return nil + // Append or prepend to the list + if prepend { + instr.Actions = append([]Action{act}, instr.Actions...) + } else { + instr.Actions = append(instr.Actions, act) + } + + instr.Length = instr.Len() + return nil } func NewInstrWriteActions() *InstrActions { - instr := new(InstrActions) - instr.Type = InstrType_WRITE_ACTIONS - instr.pad = make([]byte, 4) - instr.Actions = make([]Action, 0) - instr.Length = instr.Len() + instr := new(InstrActions) + instr.Type = InstrType_WRITE_ACTIONS + instr.pad = make([]byte, 4) + instr.Actions = make([]Action, 0) + instr.Length = instr.Len() - return instr + return instr } func NewInstrApplyActions() *InstrActions { - instr := new(InstrActions) - instr.Type = InstrType_APPLY_ACTIONS - instr.pad = make([]byte, 4) - instr.Actions = make([]Action, 0) - instr.Length = instr.Len() + instr := new(InstrActions) + instr.Type = InstrType_APPLY_ACTIONS + instr.pad = make([]byte, 4) + instr.Actions = make([]Action, 0) + instr.Length = instr.Len() - return instr + return instr } type InstrMeter struct { - InstrHeader - MeterId uint32 + InstrHeader + MeterId uint32 } func (instr *InstrMeter) AddAction(act Action, prepend bool) error { - return errors.New("Not supported on this instrction") + return errors.New("Not supported on this instrction") } diff --git a/openflow13/multipart.go b/openflow13/multipart.go index e91f5b4..e3595ed 100644 --- a/openflow13/multipart.go +++ b/openflow13/multipart.go @@ -1,958 +1,966 @@ package openflow13 import ( - "log" - "encoding/binary" + "encoding/binary" - "github.com/shaleman/libOpenflow/common" - "github.com/shaleman/libOpenflow/util" + log "github.com/Sirupsen/logrus" + + "github.com/shaleman/libOpenflow/common" + "github.com/shaleman/libOpenflow/util" ) // ofp_multipart_request 1.3 type MultipartRequest struct { - common.Header - Type uint16 - Flags uint16 - pad []byte // 4 bytes - Body util.Message + common.Header + Type uint16 + Flags uint16 + pad []byte // 4 bytes + Body util.Message } func (s *MultipartRequest) Len() (n uint16) { - return s.Header.Len() + 8 + s.Body.Len() + return s.Header.Len() + 8 + s.Body.Len() } func (s *MultipartRequest) MarshalBinary() (data []byte, err error) { - data, err = s.Header.MarshalBinary() + s.Header.Length = s.Len() + data, err = s.Header.MarshalBinary() + + b := make([]byte, 8) + n := 0 + binary.BigEndian.PutUint16(b[n:], s.Type) + n += 2 + binary.BigEndian.PutUint16(b[n:], s.Flags) + n += 2 + n += 4 // for padding + data = append(data, b...) + + b, err = s.Body.MarshalBinary() + data = append(data, b...) - b := make([]byte, 8) - n := 0 - binary.BigEndian.PutUint16(b[n:], s.Type) - n += 2 - binary.BigEndian.PutUint16(b[n:], s.Flags) - n += 2 - n += 4 // for padding - data = append(data, b...) + log.Debugf("Sending MultipartRequest (%d): %v", len(data), data) - b, err = s.Body.MarshalBinary() - data = append(data, b...) - return + return } func (s *MultipartRequest) UnmarshalBinary(data []byte) error { - err := s.Header.UnmarshalBinary(data) - n := s.Header.Len() - - s.Type = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.Flags = binary.BigEndian.Uint16(data[n:]) - n += 2 - n += 4 // for padding - - var req util.Message - switch s.Type { - case MultipartType_Aggregate: - req = s.Body.(*AggregateStatsRequest) - err = req.UnmarshalBinary(data[n:]) - case MultipartType_Desc: - break - case MultipartType_Flow: - req = s.Body.(*FlowStatsRequest) - err = req.UnmarshalBinary(data[n:]) - case MultipartType_Port: - req = s.Body.(*PortStatsRequest) - err = req.UnmarshalBinary(data[n:]) - case MultipartType_Table: - break - case MultipartType_Queue: - req = s.Body.(*QueueStatsRequest) - err = req.UnmarshalBinary(data[n:]) - case MultipartType_Experimenter: - break - } - return err + err := s.Header.UnmarshalBinary(data) + n := s.Header.Len() + + s.Type = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.Flags = binary.BigEndian.Uint16(data[n:]) + n += 2 + n += 4 // for padding + + var req util.Message + switch s.Type { + case MultipartType_Aggregate: + req = s.Body.(*AggregateStatsRequest) + err = req.UnmarshalBinary(data[n:]) + case MultipartType_Desc: + break + case MultipartType_Flow: + req = s.Body.(*FlowStatsRequest) + err = req.UnmarshalBinary(data[n:]) + case MultipartType_Port: + req = s.Body.(*PortStatsRequest) + err = req.UnmarshalBinary(data[n:]) + case MultipartType_Table: + break + case MultipartType_Queue: + req = s.Body.(*QueueStatsRequest) + err = req.UnmarshalBinary(data[n:]) + case MultipartType_Experimenter: + break + } + return err } // ofp_multipart_reply 1.3 type MultipartReply struct { - common.Header - Type uint16 - Flags uint16 - pad []byte // 4 bytes - Body []util.Message + common.Header + Type uint16 + Flags uint16 + pad []byte // 4 bytes + Body []util.Message } func (s *MultipartReply) Len() (n uint16) { - n = s.Header.Len() - n += 8 - for _, r := range s.Body { - n += uint16(r.Len()) - } - return + n = s.Header.Len() + n += 8 + for _, r := range s.Body { + n += uint16(r.Len()) + } + return } func (s *MultipartReply) MarshalBinary() (data []byte, err error) { - data, err = s.Header.MarshalBinary() + s.Header.Length = s.Len() + data, err = s.Header.MarshalBinary() - b := make([]byte, 8) - n := 0 - binary.BigEndian.PutUint16(b[n:], s.Type) - n += 2 - binary.BigEndian.PutUint16(b[n:], s.Flags) - n += 2 - n += 4 // for padding - data = append(data, b...) + b := make([]byte, 8) + n := 0 + binary.BigEndian.PutUint16(b[n:], s.Type) + n += 2 + binary.BigEndian.PutUint16(b[n:], s.Flags) + n += 2 + n += 4 // for padding + data = append(data, b...) - for _, r := range s.Body { - b, err = r.MarshalBinary() - data = append(data, b...) - } + for _, r := range s.Body { + b, err = r.MarshalBinary() + data = append(data, b...) + } - return + return } func (s *MultipartReply) UnmarshalBinary(data []byte) error { - err := s.Header.UnmarshalBinary(data) - n := s.Header.Len() - - s.Type = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.Flags = binary.BigEndian.Uint16(data[n:]) - n += 2 - n += 4 // for padding - var req []util.Message - for ; n < s.Header.Length; { - var repl util.Message - switch s.Type { - case MultipartType_Aggregate: - repl = new(AggregateStats) - case MultipartType_Desc: - repl = new(DescStats) - case MultipartType_Flow: - repl = new(FlowStats) - case MultipartType_Port: - repl = new(PortStats) - case MultipartType_Table: - repl = new(TableStats) - case MultipartType_Queue: - repl = new(QueueStats) - // FIXME: Support all types - case MultipartType_Experimenter: - break - } - - err = repl.UnmarshalBinary(data[n:]) - if err != nil { - log.Printf("Error parsing stats reply") - } - n += repl.Len() - req = append(req, repl) - - } - - s.Body = req - - return err + err := s.Header.UnmarshalBinary(data) + n := s.Header.Len() + + s.Type = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.Flags = binary.BigEndian.Uint16(data[n:]) + n += 2 + n += 4 // for padding + var req []util.Message + for n < s.Header.Length { + var repl util.Message + switch s.Type { + case MultipartType_Aggregate: + repl = new(AggregateStats) + case MultipartType_Desc: + repl = new(DescStats) + case MultipartType_Flow: + repl = new(FlowStats) + case MultipartType_Port: + repl = new(PortStats) + case MultipartType_Table: + repl = new(TableStats) + case MultipartType_Queue: + repl = new(QueueStats) + // FIXME: Support all types + case MultipartType_Experimenter: + break + } + + err = repl.UnmarshalBinary(data[n:]) + if err != nil { + log.Printf("Error parsing stats reply") + } + n += repl.Len() + req = append(req, repl) + + } + + s.Body = req + + return err } // ofp_multipart_request_flags & ofp_multipart_reply_flags 1.3 const ( - OFPMPF_REQ_MORE = 1 << 0 /* More requests to follow. */ - OFPMPF_REPLY_MORE = 1 << 0 /* More replies to follow. */ + OFPMPF_REQ_MORE = 1 << 0 /* More requests to follow. */ + OFPMPF_REPLY_MORE = 1 << 0 /* More replies to follow. */ ) // _stats_types const ( - /* Description of this OpenFlow switch. - * The request body is empty. - * The reply body is struct ofp_desc_stats. */ - MultipartType_Desc = iota - - /* Individual flow statistics. - * The request body is struct ofp_flow_stats_request. - * The reply body is an array of struct ofp_flow_stats. */ - MultipartType_Flow - - /* Aggregate flow statistics. - * The request body is struct ofp_aggregate_stats_request. - * The reply body is struct ofp_aggregate_stats_reply. */ - MultipartType_Aggregate - - /* Flow table statistics. - * The request body is empty. - * The reply body is an array of struct ofp_table_stats. */ - MultipartType_Table - - /* Port statistics. - * The request body is struct ofp_port_stats_request. - * The reply body is an array of struct ofp_port_stats. */ - MultipartType_Port - - /* Queue statistics for a port - * The request body is struct _queue_stats_request. - * The reply body is an array of struct ofp_queue_stats */ - MultipartType_Queue - - /* Group counter statistics. - * The request body is struct ofp_group_stats_request. - * The reply is an array of struct ofp_group_stats. */ - MultipartType_Group - - /* Group description. - * The request body is empty. - * The reply body is an array of struct ofp_group_desc. */ - MultipartType_GroupDesc - - /* Group features. - * The request body is empty. - * The reply body is struct ofp_group_features. */ - MultipartType_GroupFeatures - - /* Meter statistics. - * The request body is struct ofp_meter_multipart_requests. - * The reply body is an array of struct ofp_meter_stats. */ - MultipartType_Meter - - /* Meter configuration. - * The request body is struct ofp_meter_multipart_requests. - * The reply body is an array of struct ofp_meter_config. */ - MultipartType_MeterConfig - - /* Meter features. - * The request body is empty. - * The reply body is struct ofp_meter_features. */ - MultipartType_MeterFeatures - - /* Table features. - * The request body is either empty or contains an array of - * struct ofp_table_features containing the controller’s - * desired view of the switch. If the switch is unable to - * set the specified view an error is returned. - * The reply body is an array of struct ofp_table_features. */ - MultipartType_TableFeatures - - /* Port description. - * The request body is empty. - * The reply body is an array of struct ofp_port. */ - MultipartType_PortDesc - - /* Experimenter extension. - * The request and reply bodies begin with - * struct ofp_experimenter_multipart_header. - * The request and reply bodies are otherwise experimenter-defined. */ - MultipartType_Experimenter = 0xffff + /* Description of this OpenFlow switch. + * The request body is empty. + * The reply body is struct ofp_desc_stats. */ + MultipartType_Desc = iota + + /* Individual flow statistics. + * The request body is struct ofp_flow_stats_request. + * The reply body is an array of struct ofp_flow_stats. */ + MultipartType_Flow + + /* Aggregate flow statistics. + * The request body is struct ofp_aggregate_stats_request. + * The reply body is struct ofp_aggregate_stats_reply. */ + MultipartType_Aggregate + + /* Flow table statistics. + * The request body is empty. + * The reply body is an array of struct ofp_table_stats. */ + MultipartType_Table + + /* Port statistics. + * The request body is struct ofp_port_stats_request. + * The reply body is an array of struct ofp_port_stats. */ + MultipartType_Port + + /* Queue statistics for a port + * The request body is struct _queue_stats_request. + * The reply body is an array of struct ofp_queue_stats */ + MultipartType_Queue + + /* Group counter statistics. + * The request body is struct ofp_group_stats_request. + * The reply is an array of struct ofp_group_stats. */ + MultipartType_Group + + /* Group description. + * The request body is empty. + * The reply body is an array of struct ofp_group_desc. */ + MultipartType_GroupDesc + + /* Group features. + * The request body is empty. + * The reply body is struct ofp_group_features. */ + MultipartType_GroupFeatures + + /* Meter statistics. + * The request body is struct ofp_meter_multipart_requests. + * The reply body is an array of struct ofp_meter_stats. */ + MultipartType_Meter + + /* Meter configuration. + * The request body is struct ofp_meter_multipart_requests. + * The reply body is an array of struct ofp_meter_config. */ + MultipartType_MeterConfig + + /* Meter features. + * The request body is empty. + * The reply body is struct ofp_meter_features. */ + MultipartType_MeterFeatures + + /* Table features. + * The request body is either empty or contains an array of + * struct ofp_table_features containing the controller’s + * desired view of the switch. If the switch is unable to + * set the specified view an error is returned. + * The reply body is an array of struct ofp_table_features. */ + MultipartType_TableFeatures + + /* Port description. + * The request body is empty. + * The reply body is an array of struct ofp_port. */ + MultipartType_PortDesc + + /* Experimenter extension. + * The request and reply bodies begin with + * struct ofp_experimenter_multipart_header. + * The request and reply bodies are otherwise experimenter-defined. */ + MultipartType_Experimenter = 0xffff ) // ofp_desc_stats 1.3 type DescStats struct { - MfrDesc []byte // Size DESC_STR_LEN - HWDesc []byte // Size DESC_STR_LEN - SWDesc []byte // Size DESC_STR_LEN - SerialNum []byte // Size SERIAL_NUM_LEN - DPDesc []byte // Size DESC_STR_LEN + MfrDesc []byte // Size DESC_STR_LEN + HWDesc []byte // Size DESC_STR_LEN + SWDesc []byte // Size DESC_STR_LEN + SerialNum []byte // Size SERIAL_NUM_LEN + DPDesc []byte // Size DESC_STR_LEN } func NewDescStats() *DescStats { - s := new(DescStats) - s.MfrDesc = make([]byte, DESC_STR_LEN) - s.HWDesc = make([]byte, DESC_STR_LEN) - s.SWDesc = make([]byte, DESC_STR_LEN) - s.SerialNum = make([]byte, SERIAL_NUM_LEN) - s.DPDesc = make([]byte, DESC_STR_LEN) - return s + s := new(DescStats) + s.MfrDesc = make([]byte, DESC_STR_LEN) + s.HWDesc = make([]byte, DESC_STR_LEN) + s.SWDesc = make([]byte, DESC_STR_LEN) + s.SerialNum = make([]byte, SERIAL_NUM_LEN) + s.DPDesc = make([]byte, DESC_STR_LEN) + return s } func (s *DescStats) Len() (n uint16) { - return uint16(DESC_STR_LEN * 4 + SERIAL_NUM_LEN) + return uint16(DESC_STR_LEN*4 + SERIAL_NUM_LEN) } func (s *DescStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - copy(data[n:], s.MfrDesc) - n += len(s.MfrDesc) - copy(data[n:], s.HWDesc) - n += len(s.HWDesc) - copy(data[n:], s.SWDesc) - n += len(s.SWDesc) - copy(data[n:], s.SerialNum) - n += len(s.SerialNum) - copy(data[n:], s.DPDesc) - n += len(s.DPDesc) - return + data = make([]byte, int(s.Len())) + n := 0 + copy(data[n:], s.MfrDesc) + n += len(s.MfrDesc) + copy(data[n:], s.HWDesc) + n += len(s.HWDesc) + copy(data[n:], s.SWDesc) + n += len(s.SWDesc) + copy(data[n:], s.SerialNum) + n += len(s.SerialNum) + copy(data[n:], s.DPDesc) + n += len(s.DPDesc) + return } func (s *DescStats) UnmarshalBinary(data []byte) error { - n := 0 - copy(s.MfrDesc, data[n:]) - n += len(s.MfrDesc) - copy(s.HWDesc, data[n:]) - n += len(s.HWDesc) - copy(s.SWDesc, data[n:]) - n += len(s.SWDesc) - copy(s.SerialNum, data[n:]) - n += len(s.SerialNum) - copy(s.DPDesc, data[n:]) - n += len(s.DPDesc) - return nil + n := 0 + copy(s.MfrDesc, data[n:]) + n += len(s.MfrDesc) + copy(s.HWDesc, data[n:]) + n += len(s.HWDesc) + copy(s.SWDesc, data[n:]) + n += len(s.SWDesc) + copy(s.SerialNum, data[n:]) + n += len(s.SerialNum) + copy(s.DPDesc, data[n:]) + n += len(s.DPDesc) + return nil } const ( - DESC_STR_LEN = 256 - SERIAL_NUM_LEN = 32 + DESC_STR_LEN = 256 + SERIAL_NUM_LEN = 32 ) const ( - OFPTT_MAX = 0xfe - /* Fake tables. */ - OFPTT_ALL = 0xff /* Wildcard table used for table config, flow stats and flow deletes. */ + OFPTT_MAX = 0xfe + /* Fake tables. */ + OFPTT_ALL = 0xff /* Wildcard table used for table config, flow stats and flow deletes. */ ) // ofp_flow_stats_request 1.3 type FlowStatsRequest struct { - TableId uint8 - pad []byte // 3 bytes - OutPort uint32 - OutGroup uint32 - pad2 []byte // 4 bytes - Cookie uint64 - CookieMask uint64 - Match Match + TableId uint8 + pad []byte // 3 bytes + OutPort uint32 + OutGroup uint32 + pad2 []byte // 4 bytes + Cookie uint64 + CookieMask uint64 + Match Match } func NewFlowStatsRequest() *FlowStatsRequest { - s := new(FlowStatsRequest) - s.pad = make([]byte, 3) - s.pad2 = make([]byte, 4) - s.Match = *NewMatch() - return s + s := new(FlowStatsRequest) + s.OutPort = P_ANY + s.OutGroup = OFPG_ANY + s.pad = make([]byte, 3) + s.pad2 = make([]byte, 4) + s.Match = *NewMatch() + return s } func (s *FlowStatsRequest) Len() (n uint16) { - return s.Match.Len() + 32 + return s.Match.Len() + 32 } func (s *FlowStatsRequest) MarshalBinary() (data []byte, err error) { - data = make([]byte, 32) - n := 0 - data[n] = s.TableId - n += 1 - copy(data[n:], s.pad) - n += 3 - binary.BigEndian.PutUint32(data[n:], s.OutPort) - n += 4 - binary.BigEndian.PutUint32(data[n:], s.OutGroup) - n += 4 - copy(data[n:], s.pad2) - n += 4 - binary.BigEndian.PutUint64(data[n:], s.Cookie) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.CookieMask) - n += 8 - - b, err := s.Match.MarshalBinary() - data = append(data, b...) - return + data = make([]byte, 32) + n := 0 + data[n] = s.TableId + n += 1 + copy(data[n:], s.pad) + n += 3 + binary.BigEndian.PutUint32(data[n:], s.OutPort) + n += 4 + binary.BigEndian.PutUint32(data[n:], s.OutGroup) + n += 4 + copy(data[n:], s.pad2) + n += 4 + binary.BigEndian.PutUint64(data[n:], s.Cookie) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.CookieMask) + n += 8 + + b, err := s.Match.MarshalBinary() + data = append(data, b...) + return } func (s *FlowStatsRequest) UnmarshalBinary(data []byte) error { - n := 0 - s.TableId = data[n] - n += 1 - copy(s.pad, data[n:n+3]) - n += 3 - s.OutPort = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.OutGroup = binary.BigEndian.Uint32(data[n:]) - n += 4 - copy(s.pad2, data[n:n+4]) - n += 4 - s.Cookie = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.CookieMask = binary.BigEndian.Uint64(data[n:]) - n += 8 - - err := s.Match.UnmarshalBinary(data[n:]) - n += int(s.Match.Len()) - - return err + n := 0 + s.TableId = data[n] + n += 1 + copy(s.pad, data[n:n+3]) + n += 3 + s.OutPort = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.OutGroup = binary.BigEndian.Uint32(data[n:]) + n += 4 + copy(s.pad2, data[n:n+4]) + n += 4 + s.Cookie = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.CookieMask = binary.BigEndian.Uint64(data[n:]) + n += 8 + + err := s.Match.UnmarshalBinary(data[n:]) + n += int(s.Match.Len()) + + return err } // ofp_flow_stats 1.3 type FlowStats struct { - Length uint16 - TableId uint8 - pad uint8 - DurationSec uint32 - DurationNSec uint32 - Priority uint16 - IdleTimeout uint16 - HardTimeout uint16 - Flags uint16 - pad2 []uint8 // Size 4 - Cookie uint64 - PacketCount uint64 - ByteCount uint64 - Match Match - Instructions []Instruction + Length uint16 + TableId uint8 + pad uint8 + DurationSec uint32 + DurationNSec uint32 + Priority uint16 + IdleTimeout uint16 + HardTimeout uint16 + Flags uint16 + pad2 []uint8 // Size 4 + Cookie uint64 + PacketCount uint64 + ByteCount uint64 + Match Match + Instructions []Instruction } func NewFlowStats() *FlowStats { - f := new(FlowStats) - f.Match = *NewMatch() - f.pad2 = make([]byte, 4) - f.Instructions = make([]Instruction, 0) - return f + f := new(FlowStats) + f.Match = *NewMatch() + f.pad2 = make([]byte, 4) + f.Instructions = make([]Instruction, 0) + return f } func (s *FlowStats) Len() (n uint16) { - n = 48 + s.Match.Len() - for _, instr := range s.Instructions { - n += instr.Len() - } - return + n = 48 + s.Match.Len() + for _, instr := range s.Instructions { + n += instr.Len() + } + return } func (s *FlowStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, 48) - n := 0 - - binary.BigEndian.PutUint16(data[n:], s.Length) - n += 2 - data[n] = s.TableId - n += 1 - data[n] = s.pad - n += 1 - - binary.BigEndian.PutUint32(data[n:], s.DurationSec) - n += 4 - binary.BigEndian.PutUint32(data[n:], s.DurationNSec) - n += 4 - binary.BigEndian.PutUint16(data[n:], s.Priority) - n += 2 - binary.BigEndian.PutUint16(data[n:], s.IdleTimeout) - n += 2 - binary.BigEndian.PutUint16(data[n:], s.HardTimeout) - n += 2 - binary.BigEndian.PutUint16(data[n:], s.Flags) - n += 2 - copy(data[n:], s.pad2) - n += len(s.pad2) - binary.BigEndian.PutUint64(data[n:], s.Cookie) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.PacketCount) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.ByteCount) - n += 8 - - b, err := s.Match.MarshalBinary() - data = append(data, b...) - n += len(b) - - for _, instr := range s.Instructions { - b, err = instr.MarshalBinary() - data = append(data, b...) - n += len(b) - } - return + data = make([]byte, 48) + n := 0 + + binary.BigEndian.PutUint16(data[n:], s.Length) + n += 2 + data[n] = s.TableId + n += 1 + data[n] = s.pad + n += 1 + + binary.BigEndian.PutUint32(data[n:], s.DurationSec) + n += 4 + binary.BigEndian.PutUint32(data[n:], s.DurationNSec) + n += 4 + binary.BigEndian.PutUint16(data[n:], s.Priority) + n += 2 + binary.BigEndian.PutUint16(data[n:], s.IdleTimeout) + n += 2 + binary.BigEndian.PutUint16(data[n:], s.HardTimeout) + n += 2 + binary.BigEndian.PutUint16(data[n:], s.Flags) + n += 2 + copy(data[n:], s.pad2) + n += len(s.pad2) + binary.BigEndian.PutUint64(data[n:], s.Cookie) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.PacketCount) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.ByteCount) + n += 8 + + b, err := s.Match.MarshalBinary() + data = append(data, b...) + n += len(b) + + for _, instr := range s.Instructions { + b, err = instr.MarshalBinary() + data = append(data, b...) + n += len(b) + } + return } func (s *FlowStats) UnmarshalBinary(data []byte) error { - n := 0 - s.Length = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.TableId = data[n] - n += 1 - s.pad = data[n] - n += 1 - s.DurationSec = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.DurationNSec = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.Priority = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.IdleTimeout = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.HardTimeout = binary.BigEndian.Uint16(data[n:]) - n += 2 - s.Flags = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(s.pad2, data[n:n+4]) - n += 4 - s.Cookie = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.PacketCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.ByteCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - err := s.Match.UnmarshalBinary(data[n:]) - n += int(s.Match.Len()) - - for ;n < int(s.Length); { - instr := DecodeInstr(data[n:]) - s.Instructions = append(s.Instructions, instr) - n += int(instr.Len()) - } - return err + n := 0 + s.Length = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.TableId = data[n] + n += 1 + s.pad = data[n] + n += 1 + s.DurationSec = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.DurationNSec = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.Priority = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.IdleTimeout = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.HardTimeout = binary.BigEndian.Uint16(data[n:]) + n += 2 + s.Flags = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(s.pad2, data[n:n+4]) + n += 4 + s.Cookie = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.PacketCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.ByteCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + err := s.Match.UnmarshalBinary(data[n:]) + n += int(s.Match.Len()) + + for n < int(s.Length) { + instr := DecodeInstr(data[n:]) + s.Instructions = append(s.Instructions, instr) + n += int(instr.Len()) + } + return err } // ofp_aggregate_stats_request 1.3 type AggregateStatsRequest struct { - TableId uint8 - pad []byte // 3 bytes - OutPort uint32 - OutGroup uint32 - pad2 []byte // 4 bytes - Cookie uint64 - CookieMask uint64 - Match + TableId uint8 + pad []byte // 3 bytes + OutPort uint32 + OutGroup uint32 + pad2 []byte // 4 bytes + Cookie uint64 + CookieMask uint64 + Match } func NewAggregateStatsRequest() *AggregateStatsRequest { - a := new(AggregateStatsRequest) - a.pad = make([]byte, 3) - a.pad2 = make([]byte, 4) - a.Match = *NewMatch() + a := new(AggregateStatsRequest) + a.pad = make([]byte, 3) + a.pad2 = make([]byte, 4) + a.Match = *NewMatch() - return a + return a } func (s *AggregateStatsRequest) Len() (n uint16) { - return s.Match.Len() + 32 + return s.Match.Len() + 32 } func (s *AggregateStatsRequest) MarshalBinary() (data []byte, err error) { - data = make([]byte, 32) - n := 0 - data[n] = s.TableId - n += 1 - copy(data[n:], s.pad) - n += 3 - binary.BigEndian.PutUint32(data[n:], s.OutPort) - n += 4 - binary.BigEndian.PutUint32(data[n:], s.OutGroup) - n += 4 - copy(data[n:], s.pad2) - n += 4 - binary.BigEndian.PutUint64(data[n:], s.Cookie) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.CookieMask) - n += 8 - - b, err := s.Match.MarshalBinary() - data = append(data, b...) - return + data = make([]byte, 32) + n := 0 + data[n] = s.TableId + n += 1 + copy(data[n:], s.pad) + n += 3 + binary.BigEndian.PutUint32(data[n:], s.OutPort) + n += 4 + binary.BigEndian.PutUint32(data[n:], s.OutGroup) + n += 4 + copy(data[n:], s.pad2) + n += 4 + binary.BigEndian.PutUint64(data[n:], s.Cookie) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.CookieMask) + n += 8 + + b, err := s.Match.MarshalBinary() + data = append(data, b...) + return } func (s *AggregateStatsRequest) UnmarshalBinary(data []byte) error { - n := 0 - s.TableId = data[n] - n += 1 - copy(s.pad, data[n:n+3]) - n += 3 - s.OutPort = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.OutGroup = binary.BigEndian.Uint32(data[n:]) - n += 4 - copy(s.pad2, data[n:n+4]) - n += 4 - s.Cookie = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.CookieMask = binary.BigEndian.Uint64(data[n:]) - n += 8 - - s.Match.UnmarshalBinary(data[n:]) - n += int(s.Match.Len()) - return nil + n := 0 + s.TableId = data[n] + n += 1 + copy(s.pad, data[n:n+3]) + n += 3 + s.OutPort = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.OutGroup = binary.BigEndian.Uint32(data[n:]) + n += 4 + copy(s.pad2, data[n:n+4]) + n += 4 + s.Cookie = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.CookieMask = binary.BigEndian.Uint64(data[n:]) + n += 8 + + s.Match.UnmarshalBinary(data[n:]) + n += int(s.Match.Len()) + return nil } // ofp_aggregate_stats_reply 1.3 type AggregateStats struct { - PacketCount uint64 - ByteCount uint64 - FlowCount uint32 - pad []uint8 // Size 4 + PacketCount uint64 + ByteCount uint64 + FlowCount uint32 + pad []uint8 // Size 4 } func NewAggregateStats() *AggregateStats { - s := new(AggregateStats) - s.pad = make([]byte, 4) - return s + s := new(AggregateStats) + s.pad = make([]byte, 4) + return s } func (s *AggregateStats) Len() (n uint16) { - return 24 + return 24 } func (s *AggregateStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - binary.BigEndian.PutUint64(data[n:], s.PacketCount) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.ByteCount) - n += 8 - binary.BigEndian.PutUint32(data[n:], s.FlowCount) - n += 4 - copy(data[n:], s.pad) - n += 4 - return + data = make([]byte, int(s.Len())) + n := 0 + binary.BigEndian.PutUint64(data[n:], s.PacketCount) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.ByteCount) + n += 8 + binary.BigEndian.PutUint32(data[n:], s.FlowCount) + n += 4 + copy(data[n:], s.pad) + n += 4 + return } func (s *AggregateStats) UnmarshalBinary(data []byte) error { - n := 0 - s.PacketCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.ByteCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.FlowCount = binary.BigEndian.Uint32(data[n:]) - n += 4 - copy(s.pad, data[n:]) - return nil + n := 0 + s.PacketCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.ByteCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.FlowCount = binary.BigEndian.Uint32(data[n:]) + n += 4 + copy(s.pad, data[n:]) + return nil } // FIXME: Everything below this needs to be changed for ofp1.3 // ofp_table_stats 1.0 type TableStats struct { - TableId uint8 - pad []uint8 // Size 3 - Name []byte // Size MAX_TABLE_NAME_LEN - Wildcards uint32 - MaxEntries uint32 - ActiveCount uint32 - LookupCount uint64 - MatchedCount uint64 + TableId uint8 + pad []uint8 // Size 3 + Name []byte // Size MAX_TABLE_NAME_LEN + Wildcards uint32 + MaxEntries uint32 + ActiveCount uint32 + LookupCount uint64 + MatchedCount uint64 } func NewTableStats() *TableStats { - s := new(TableStats) - s.pad = make([]byte, 3) - s.Name = make([]byte, MAX_TABLE_NAME_LEN) - return s + s := new(TableStats) + s.pad = make([]byte, 3) + s.Name = make([]byte, MAX_TABLE_NAME_LEN) + return s } func (s *TableStats) Len() (n uint16) { - return 4 + MAX_TABLE_NAME_LEN + 28 + return 4 + MAX_TABLE_NAME_LEN + 28 } func (s *TableStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - data[n] = s.TableId - n += 1 - copy(data[n:], s.pad) - n += len(s.pad) - copy(data[n:], s.Name) - n += len(s.Name) - binary.BigEndian.PutUint32(data[n:], s.Wildcards) - n += 4 - binary.BigEndian.PutUint32(data[n:], s.MaxEntries) - n += 4 - binary.BigEndian.PutUint32(data[n:], s.ActiveCount) - n += 4 - binary.BigEndian.PutUint64(data[n:], s.LookupCount) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.MatchedCount) - n += 8 - return + data = make([]byte, int(s.Len())) + n := 0 + data[n] = s.TableId + n += 1 + copy(data[n:], s.pad) + n += len(s.pad) + copy(data[n:], s.Name) + n += len(s.Name) + binary.BigEndian.PutUint32(data[n:], s.Wildcards) + n += 4 + binary.BigEndian.PutUint32(data[n:], s.MaxEntries) + n += 4 + binary.BigEndian.PutUint32(data[n:], s.ActiveCount) + n += 4 + binary.BigEndian.PutUint64(data[n:], s.LookupCount) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.MatchedCount) + n += 8 + return } func (s *TableStats) UnmarshalBinary(data []byte) error { - n := 0 - s.TableId = data[0] - n += 1 - copy(s.pad, data[n:]) - n += len(s.pad) - copy(s.Name, data[n:]) - n += len(s.Name) - s.Wildcards = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.MaxEntries = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.ActiveCount = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.LookupCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.MatchedCount = binary.BigEndian.Uint64(data[n:]) - n += 8 - return nil + n := 0 + s.TableId = data[0] + n += 1 + copy(s.pad, data[n:]) + n += len(s.pad) + copy(s.Name, data[n:]) + n += len(s.Name) + s.Wildcards = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.MaxEntries = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.ActiveCount = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.LookupCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.MatchedCount = binary.BigEndian.Uint64(data[n:]) + n += 8 + return nil } const ( - MAX_TABLE_NAME_LEN = 32 + MAX_TABLE_NAME_LEN = 32 ) // ofp_port_stats_request 1.0 type PortStatsRequest struct { - PortNo uint16 - pad []uint8 // Size 6 + PortNo uint16 + pad []uint8 // Size 6 } func NewPortStatsRequest() *PortStatsRequest { - p := new(PortStatsRequest) - p.pad = make([]byte, 6) - return p + p := new(PortStatsRequest) + p.pad = make([]byte, 6) + return p } func (s *PortStatsRequest) Len() (n uint16) { - return 8 + return 8 } func (s *PortStatsRequest) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - binary.BigEndian.PutUint16(data[n:], s.PortNo) - n += 2 - copy(data[n:], s.pad) - n += len(s.pad) - return + data = make([]byte, int(s.Len())) + n := 0 + binary.BigEndian.PutUint16(data[n:], s.PortNo) + n += 2 + copy(data[n:], s.pad) + n += len(s.pad) + return } func (s *PortStatsRequest) UnmarshalBinary(data []byte) error { - n := 0 - s.PortNo = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(s.pad, data[n:]) - n += len(s.pad) - return nil + n := 0 + s.PortNo = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(s.pad, data[n:]) + n += len(s.pad) + return nil } // ofp_port_stats 1.0 type PortStats struct { - PortNo uint16 - pad []uint8 // Size 6 - RxPackets uint64 - TxPackets uint64 - RxBytes uint64 - TxBytes uint64 - RxDropped uint64 - TxDropped uint64 - RxErrors uint64 - TxErrors uint64 - RxFrameErr uint64 - RxOverErr uint64 - RxCRCErr uint64 - Collisions uint64 + PortNo uint16 + pad []uint8 // Size 6 + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + RxDropped uint64 + TxDropped uint64 + RxErrors uint64 + TxErrors uint64 + RxFrameErr uint64 + RxOverErr uint64 + RxCRCErr uint64 + Collisions uint64 } func NewPortStats() *PortStats { - p := new(PortStats) - p.pad = make([]byte, 6) - return p + p := new(PortStats) + p.pad = make([]byte, 6) + return p } func (s *PortStats) Len() (n uint16) { - return 104 + return 104 } func (s *PortStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - binary.BigEndian.PutUint16(data[n:], s.PortNo) - n += 2 - copy(data[n:], s.pad) - n += len(s.pad) - binary.BigEndian.PutUint64(data[n:], s.RxPackets) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxPackets) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxBytes) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxBytes) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxDropped) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxDropped) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxErrors) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxErrors) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxFrameErr) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxOverErr) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.RxCRCErr) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.Collisions) - n += 8 - return + data = make([]byte, int(s.Len())) + n := 0 + binary.BigEndian.PutUint16(data[n:], s.PortNo) + n += 2 + copy(data[n:], s.pad) + n += len(s.pad) + binary.BigEndian.PutUint64(data[n:], s.RxPackets) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxPackets) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxBytes) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxBytes) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxDropped) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxDropped) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxErrors) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxErrors) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxFrameErr) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxOverErr) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.RxCRCErr) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.Collisions) + n += 8 + return } func (s *PortStats) UnmarshalBinary(data []byte) error { - n := 0 - s.PortNo = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(s.pad, data[n:]) - n += len(s.pad) - s.RxPackets = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxPackets = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxBytes = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxBytes = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxDropped = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxDropped = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxErrors = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxErrors = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxFrameErr = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxOverErr = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.RxCRCErr = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.Collisions = binary.BigEndian.Uint64(data[n:]) - n += 8 - return nil + n := 0 + s.PortNo = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(s.pad, data[n:]) + n += len(s.pad) + s.RxPackets = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxPackets = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxBytes = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxBytes = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxDropped = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxDropped = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxErrors = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxErrors = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxFrameErr = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxOverErr = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.RxCRCErr = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.Collisions = binary.BigEndian.Uint64(data[n:]) + n += 8 + return nil } // ofp_queue_stats_request 1.0 type QueueStatsRequest struct { - PortNo uint16 - pad []uint8 // Size 2 - QueueId uint32 + PortNo uint16 + pad []uint8 // Size 2 + QueueId uint32 } func NewQueueStatsRequest() *QueueStatsRequest { - q := new(QueueStatsRequest) - q.pad = make([]byte, 2) - return q + q := new(QueueStatsRequest) + q.pad = make([]byte, 2) + return q } func (s *QueueStatsRequest) Len() (n uint16) { - return 8 + return 8 } func (s *QueueStatsRequest) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - n := 0 - binary.BigEndian.PutUint16(data[n:], s.PortNo) - n += 2 - copy(data[n:], s.pad) - n += 2 - binary.BigEndian.PutUint32(data[n:], s.QueueId) - n += 4 - return + data = make([]byte, int(s.Len())) + n := 0 + binary.BigEndian.PutUint16(data[n:], s.PortNo) + n += 2 + copy(data[n:], s.pad) + n += 2 + binary.BigEndian.PutUint32(data[n:], s.QueueId) + n += 4 + return } func (s *QueueStatsRequest) UnmarshalBinary(data []byte) error { - n := 0 - s.PortNo = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(s.pad, data[n:]) - n += 2 - s.QueueId = binary.BigEndian.Uint32(data[n:]) - return nil + n := 0 + s.PortNo = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(s.pad, data[n:]) + n += 2 + s.QueueId = binary.BigEndian.Uint32(data[n:]) + return nil } // ofp_queue_stats 1.0 type QueueStats struct { - PortNo uint16 - pad []uint8 // Size 2 - QueueId uint32 - TxBytes uint64 - TxPackets uint64 - TxErrors uint64 + PortNo uint16 + pad []uint8 // Size 2 + QueueId uint32 + TxBytes uint64 + TxPackets uint64 + TxErrors uint64 } func (s *QueueStats) Len() (n uint16) { - return 32 + return 32 } func (s *QueueStats) MarshalBinary() (data []byte, err error) { - data = make([]byte, 32) - n := 0 - - binary.BigEndian.PutUint16(data[n:], s.PortNo) - n += 2 - copy(data[n:], s.pad) - n += 2 - binary.BigEndian.PutUint32(data[n:], s.QueueId) - n += 4 - binary.BigEndian.PutUint64(data[n:], s.TxBytes) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxPackets) - n += 8 - binary.BigEndian.PutUint64(data[n:], s.TxErrors) - n += 8 - return + data = make([]byte, 32) + n := 0 + + binary.BigEndian.PutUint16(data[n:], s.PortNo) + n += 2 + copy(data[n:], s.pad) + n += 2 + binary.BigEndian.PutUint32(data[n:], s.QueueId) + n += 4 + binary.BigEndian.PutUint64(data[n:], s.TxBytes) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxPackets) + n += 8 + binary.BigEndian.PutUint64(data[n:], s.TxErrors) + n += 8 + return } func (s *QueueStats) UnmarshalBinary(data []byte) error { - n := 0 - s.PortNo = binary.BigEndian.Uint16(data[n:]) - n += 2 - copy(s.pad, data[n:]) - n += len(s.pad) - s.QueueId = binary.BigEndian.Uint32(data[n:]) - n += 4 - s.TxBytes = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxPackets = binary.BigEndian.Uint64(data[n:]) - n += 8 - s.TxErrors = binary.BigEndian.Uint64(data[n:]) - n += 8 - return nil + n := 0 + s.PortNo = binary.BigEndian.Uint16(data[n:]) + n += 2 + copy(s.pad, data[n:]) + n += len(s.pad) + s.QueueId = binary.BigEndian.Uint32(data[n:]) + n += 4 + s.TxBytes = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxPackets = binary.BigEndian.Uint64(data[n:]) + n += 8 + s.TxErrors = binary.BigEndian.Uint64(data[n:]) + n += 8 + return nil } // ofp_port_status type PortStatus struct { - common.Header - Reason uint8 - pad []uint8 // Size 7 - Desc PhyPort + common.Header + Reason uint8 + pad []uint8 // Size 7 + Desc PhyPort } func NewPortStatus() *PortStatus { - p := new(PortStatus) - p.Header = NewOfp13Header() - p.pad = make([]byte, 7) - return p + p := new(PortStatus) + p.Header = NewOfp13Header() + p.pad = make([]byte, 7) + return p } func (p *PortStatus) Len() (n uint16) { - n = p.Header.Len() - n += 8 - n += p.Desc.Len() - return + n = p.Header.Len() + n += 8 + n += p.Desc.Len() + return } func (s *PortStatus) MarshalBinary() (data []byte, err error) { - s.Header.Length = s.Len() - data, err = s.Header.MarshalBinary() + s.Header.Length = s.Len() + data, err = s.Header.MarshalBinary() - b := make([]byte, 8) - n := 0 - b[0] = s.Reason - n += 1 - copy(b[n:], s.pad) - data = append(data, b...) + b := make([]byte, 8) + n := 0 + b[0] = s.Reason + n += 1 + copy(b[n:], s.pad) + data = append(data, b...) - b, err = s.Desc.MarshalBinary() - data = append(data, b...) - return + b, err = s.Desc.MarshalBinary() + data = append(data, b...) + return } func (s *PortStatus) UnmarshalBinary(data []byte) error { - err := s.Header.UnmarshalBinary(data) - n := int(s.Header.Len()) + err := s.Header.UnmarshalBinary(data) + n := int(s.Header.Len()) - s.Reason = data[n] - n += 1 - copy(s.pad, data[n:]) - n += len(s.pad) + s.Reason = data[n] + n += 1 + copy(s.pad, data[n:]) + n += len(s.pad) - err = s.Desc.UnmarshalBinary(data[n:]) - return err + err = s.Desc.UnmarshalBinary(data[n:]) + return err } // ofp_port_reason 1.0 const ( - PR_ADD = iota - PR_DELETE - PR_MODIFY + PR_ADD = iota + PR_DELETE + PR_MODIFY ) diff --git a/openflow13/openflow13.go b/openflow13/openflow13.go index dfdf779..6666f9c 100644 --- a/openflow13/openflow13.go +++ b/openflow13/openflow13.go @@ -9,17 +9,17 @@ package openflow13 // https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.3.3.pdf import ( - "net" - "encoding/binary" - "errors" + "encoding/binary" + "errors" + "net" - "github.com/shaleman/libOpenflow/protocol" - "github.com/shaleman/libOpenflow/common" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/common" + "github.com/shaleman/libOpenflow/protocol" + "github.com/shaleman/libOpenflow/util" ) const ( - VERSION = 4 + VERSION = 4 ) // Returns a new OpenFlow header with version field set to v1.3. @@ -30,9 +30,9 @@ var NewOfp13Header func() common.Header = common.NewHeaderGenerator(VERSION) // can be used to indicate the latency, bandwidth, and/or // liveness of a controller-switch connection. func NewEchoRequest() *common.Header { - h := NewOfp13Header() - h.Type = Type_EchoRequest - return &h + h := NewOfp13Header() + h.Type = Type_EchoRequest + return &h } // Echo request/reply messages can be sent from either the @@ -40,137 +40,136 @@ func NewEchoRequest() *common.Header { // can be used to indicate the latency, bandwidth, and/or // liveness of a controller-switch connection. func NewEchoReply() *common.Header { - h := NewOfp13Header() - h.Type = Type_EchoReply - return &h + h := NewOfp13Header() + h.Type = Type_EchoReply + return &h } // ofp_type 1.3 const ( - /* Immutable messages. */ - Type_Hello = 0 - Type_Error = 1 - Type_EchoRequest = 2 - Type_EchoReply = 3 - Type_Experimenter = 4 - - /* Switch configuration messages. */ - Type_FeaturesRequest = 5 - Type_FeaturesReply = 6 - Type_GetConfigRequest = 7 - Type_GetConfigReply = 8 - Type_SetConfig = 9 - - /* Asynchronous messages. */ - Type_PacketIn = 10 - Type_FlowRemoved = 11 - Type_PortStatus = 12 - - /* Controller command messages. */ - Type_PacketOut = 13 - Type_FlowMod = 14 - Type_GroupMod = 15 - Type_PortMod = 16 - Type_TableMod = 17 - - /* Multipart messages. */ - Type_MultiPartRequest = 18 - Type_MultiPartReply = 19 - - /* Barrier messages. */ - Type_BarrierRequest = 20 - Type_BarrierReply = 21 - - /* Queue Configuration messages. */ - Type_QueueGetConfigRequest = 22 - Type_QueueGetConfigReply = 23 - - /* Controller role change request messages. */ - Type_RoleRequest = 24 - Type_RoleReply = 25 - - /* Asynchronous message configuration. */ - Type_GetAsyncRequest = 26 - Type_GetAsyncReply = 27 - Type_SetAsync = 28 - - /* Meters and rate limiters configuration messages. */ - Type_MeterMod = 29 + /* Immutable messages. */ + Type_Hello = 0 + Type_Error = 1 + Type_EchoRequest = 2 + Type_EchoReply = 3 + Type_Experimenter = 4 + + /* Switch configuration messages. */ + Type_FeaturesRequest = 5 + Type_FeaturesReply = 6 + Type_GetConfigRequest = 7 + Type_GetConfigReply = 8 + Type_SetConfig = 9 + + /* Asynchronous messages. */ + Type_PacketIn = 10 + Type_FlowRemoved = 11 + Type_PortStatus = 12 + + /* Controller command messages. */ + Type_PacketOut = 13 + Type_FlowMod = 14 + Type_GroupMod = 15 + Type_PortMod = 16 + Type_TableMod = 17 + + /* Multipart messages. */ + Type_MultiPartRequest = 18 + Type_MultiPartReply = 19 + + /* Barrier messages. */ + Type_BarrierRequest = 20 + Type_BarrierReply = 21 + + /* Queue Configuration messages. */ + Type_QueueGetConfigRequest = 22 + Type_QueueGetConfigReply = 23 + + /* Controller role change request messages. */ + Type_RoleRequest = 24 + Type_RoleReply = 25 + + /* Asynchronous message configuration. */ + Type_GetAsyncRequest = 26 + Type_GetAsyncReply = 27 + Type_SetAsync = 28 + + /* Meters and rate limiters configuration messages. */ + Type_MeterMod = 29 ) - func Parse(b []byte) (message util.Message, err error) { - switch b[1] { - case Type_Hello: - message = new(common.Hello) - message.UnmarshalBinary(b) - case Type_Error: - message = new(ErrorMsg) - message.UnmarshalBinary(b) - case Type_EchoRequest: - message = new(common.Header) - message.UnmarshalBinary(b) - case Type_EchoReply: - message = new(common.Header) - message.UnmarshalBinary(b) - case Type_Experimenter: - message = new(VendorHeader) - message.UnmarshalBinary(b) - case Type_FeaturesRequest: - message = NewFeaturesRequest() - message.UnmarshalBinary(b) - case Type_FeaturesReply: - message = NewFeaturesReply() - message.UnmarshalBinary(b) - case Type_GetConfigRequest: - message = new(common.Header) - message.UnmarshalBinary(b) - case Type_GetConfigReply: - message = new(SwitchConfig) - message.UnmarshalBinary(b) - case Type_SetConfig: - message = NewSetConfig() - message.UnmarshalBinary(b) - case Type_PacketIn: - message = new(PacketIn) - message.UnmarshalBinary(b) - case Type_FlowRemoved: - message = NewFlowRemoved() - message.UnmarshalBinary(b) - case Type_PortStatus: - message = new(PortStatus) - message.UnmarshalBinary(b) - case Type_PacketOut: - break - case Type_FlowMod: - message = NewFlowMod() - message.UnmarshalBinary(b) - case Type_GroupMod: - break - case Type_PortMod: - break - case Type_TableMod: - break - case Type_BarrierRequest: - message = new(common.Header) - message.UnmarshalBinary(b) - case Type_BarrierReply: - message = new(common.Header) - message.UnmarshalBinary(b) - case Type_QueueGetConfigRequest: - break - case Type_QueueGetConfigReply: - break - case Type_MultiPartRequest: - message = new(MultipartRequest) - message.UnmarshalBinary(b) - case Type_MultiPartReply: - message = new(MultipartReply) - message.UnmarshalBinary(b) - default: - err = errors.New("An unknown v1.0 packet type was received. Parse function will discard data.") - } - return + switch b[1] { + case Type_Hello: + message = new(common.Hello) + message.UnmarshalBinary(b) + case Type_Error: + message = new(ErrorMsg) + message.UnmarshalBinary(b) + case Type_EchoRequest: + message = new(common.Header) + message.UnmarshalBinary(b) + case Type_EchoReply: + message = new(common.Header) + message.UnmarshalBinary(b) + case Type_Experimenter: + message = new(VendorHeader) + message.UnmarshalBinary(b) + case Type_FeaturesRequest: + message = NewFeaturesRequest() + message.UnmarshalBinary(b) + case Type_FeaturesReply: + message = NewFeaturesReply() + message.UnmarshalBinary(b) + case Type_GetConfigRequest: + message = new(common.Header) + message.UnmarshalBinary(b) + case Type_GetConfigReply: + message = new(SwitchConfig) + message.UnmarshalBinary(b) + case Type_SetConfig: + message = NewSetConfig() + message.UnmarshalBinary(b) + case Type_PacketIn: + message = new(PacketIn) + message.UnmarshalBinary(b) + case Type_FlowRemoved: + message = NewFlowRemoved() + message.UnmarshalBinary(b) + case Type_PortStatus: + message = new(PortStatus) + message.UnmarshalBinary(b) + case Type_PacketOut: + break + case Type_FlowMod: + message = NewFlowMod() + message.UnmarshalBinary(b) + case Type_GroupMod: + break + case Type_PortMod: + break + case Type_TableMod: + break + case Type_BarrierRequest: + message = new(common.Header) + message.UnmarshalBinary(b) + case Type_BarrierReply: + message = new(common.Header) + message.UnmarshalBinary(b) + case Type_QueueGetConfigRequest: + break + case Type_QueueGetConfigReply: + break + case Type_MultiPartRequest: + message = new(MultipartRequest) + message.UnmarshalBinary(b) + case Type_MultiPartReply: + message = new(MultipartReply) + message.UnmarshalBinary(b) + default: + err = errors.New("An unknown v1.0 packet type was received. Parse function will discard data.") + } + return } // When the controller wishes to send a packet out through the @@ -181,604 +180,600 @@ func Parse(b []byte) (message util.Message, err error) { // action, the in_port in the packet_out message is used in the // flow table lookup. type PacketOut struct { - common.Header - BufferId uint32 - InPort uint32 - ActionsLen uint16 - pad []byte - Actions []Action - Data util.Message + common.Header + BufferId uint32 + InPort uint32 + ActionsLen uint16 + pad []byte + Actions []Action + Data util.Message } func NewPacketOut() *PacketOut { - p := new(PacketOut) - p.Header = NewOfp13Header() - p.Header.Type = Type_PacketOut - p.BufferId = 0xffffffff - p.InPort = P_ANY - p.ActionsLen = 0 - p.pad = make([]byte, 6) - p.Actions = make([]Action, 0) - return p + p := new(PacketOut) + p.Header = NewOfp13Header() + p.Header.Type = Type_PacketOut + p.BufferId = 0xffffffff + p.InPort = P_ANY + p.ActionsLen = 0 + p.pad = make([]byte, 6) + p.Actions = make([]Action, 0) + return p } func (p *PacketOut) AddAction(act Action) { - p.Actions = append(p.Actions, act) - p.ActionsLen += act.Len() + p.Actions = append(p.Actions, act) + p.ActionsLen += act.Len() } func (p *PacketOut) Len() (n uint16) { - n += p.Header.Len() - n += 16 - for _, a := range p.Actions { - n += a.Len() - } - n += p.Data.Len() - //if n < 72 { return 72 } - return + n += p.Header.Len() + n += 16 + for _, a := range p.Actions { + n += a.Len() + } + n += p.Data.Len() + //if n < 72 { return 72 } + return } func (p *PacketOut) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(p.Len())) - b := make([]byte, 0) - n := 0 - - p.Header.Length = p.Len() - b, err = p.Header.MarshalBinary() - copy(data[n:], b) - n += len(b) - - binary.BigEndian.PutUint32(data[n:], p.BufferId) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.InPort) - n += 4 - binary.BigEndian.PutUint16(data[n:], p.ActionsLen) - n += 2 - n += 6 // for pad - - for _, a := range p.Actions { - b, err = a.MarshalBinary() - copy(data[n:], b) - n += len(b) - } - - b, err = p.Data.MarshalBinary() - copy(data[n:], b) - n += len(b) - return + data = make([]byte, int(p.Len())) + b := make([]byte, 0) + n := 0 + + p.Header.Length = p.Len() + b, err = p.Header.MarshalBinary() + copy(data[n:], b) + n += len(b) + + binary.BigEndian.PutUint32(data[n:], p.BufferId) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.InPort) + n += 4 + binary.BigEndian.PutUint16(data[n:], p.ActionsLen) + n += 2 + n += 6 // for pad + + for _, a := range p.Actions { + b, err = a.MarshalBinary() + copy(data[n:], b) + n += len(b) + } + + b, err = p.Data.MarshalBinary() + copy(data[n:], b) + n += len(b) + return } func (p *PacketOut) UnmarshalBinary(data []byte) error { - err := p.Header.UnmarshalBinary(data) - n := p.Header.Len() + err := p.Header.UnmarshalBinary(data) + n := p.Header.Len() - p.BufferId = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.InPort = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.ActionsLen = binary.BigEndian.Uint16(data[n:]) - n += 2 + p.BufferId = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.InPort = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.ActionsLen = binary.BigEndian.Uint16(data[n:]) + n += 2 - n += 6 // for pad + n += 6 // for pad - for n < (n + p.ActionsLen) { - a := DecodeAction(data[n:]) - p.Actions = append(p.Actions, a) - n += a.Len() - } + for n < (n + p.ActionsLen) { + a := DecodeAction(data[n:]) + p.Actions = append(p.Actions, a) + n += a.Len() + } - err = p.Data.UnmarshalBinary(data[n:]) - return err + err = p.Data.UnmarshalBinary(data[n:]) + return err } // ofp_packet_in 1.3 type PacketIn struct { - common.Header - BufferId uint32 - TotalLen uint16 - Reason uint8 - TableId uint8 - Cookie uint64 - Match Match - pad []uint8 - Data protocol.Ethernet + common.Header + BufferId uint32 + TotalLen uint16 + Reason uint8 + TableId uint8 + Cookie uint64 + Match Match + pad []uint8 + Data protocol.Ethernet } func NewPacketIn() *PacketIn { - p := new(PacketIn) - p.Header = NewOfp13Header() - p.Header.Type = Type_PacketIn - p.BufferId = 0xffffffff - p.Reason = 0 - p.TableId = 0 - p.Cookie = 0 - p.Match = *NewMatch() - return p + p := new(PacketIn) + p.Header = NewOfp13Header() + p.Header.Type = Type_PacketIn + p.BufferId = 0xffffffff + p.Reason = 0 + p.TableId = 0 + p.Cookie = 0 + p.Match = *NewMatch() + return p } func (p *PacketIn) Len() (n uint16) { - n += p.Header.Len() - n += 16 - n += p.Match.Len() - n += 2 - n += p.Data.Len() - return + n += p.Header.Len() + n += 16 + n += p.Match.Len() + n += 2 + n += p.Data.Len() + return } func (p *PacketIn) MarshalBinary() (data []byte, err error) { - data, err = p.Header.MarshalBinary() - - b := make([]byte, 16) - n := 0 - binary.BigEndian.PutUint32(b, p.BufferId) - n += 4 - binary.BigEndian.PutUint16(b[n:], p.TotalLen) - n += 2 - b[n] = p.Reason - n += 1 - b[n] = p.TableId - n += 1 - binary.BigEndian.PutUint64(b, p.Cookie) - n += 8 - data = append(data, b...) - - b, err = p.Match.MarshalBinary() - data = append(data, b...) - - b = make([]byte, 2) - copy(b[0:], p.pad) - data = append(data, b...) - - b, err = p.Data.MarshalBinary() - data = append(data, b...) - return + data, err = p.Header.MarshalBinary() + + b := make([]byte, 16) + n := 0 + binary.BigEndian.PutUint32(b, p.BufferId) + n += 4 + binary.BigEndian.PutUint16(b[n:], p.TotalLen) + n += 2 + b[n] = p.Reason + n += 1 + b[n] = p.TableId + n += 1 + binary.BigEndian.PutUint64(b, p.Cookie) + n += 8 + data = append(data, b...) + + b, err = p.Match.MarshalBinary() + data = append(data, b...) + + b = make([]byte, 2) + copy(b[0:], p.pad) + data = append(data, b...) + + b, err = p.Data.MarshalBinary() + data = append(data, b...) + return } func (p *PacketIn) UnmarshalBinary(data []byte) error { - err := p.Header.UnmarshalBinary(data) - n := p.Header.Len() + err := p.Header.UnmarshalBinary(data) + n := p.Header.Len() - p.BufferId = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.TotalLen = binary.BigEndian.Uint16(data[n:]) - n += 2 - p.Reason = data[n] - n += 1 - p.TableId = data[n] - n += 1 - p.Cookie = binary.BigEndian.Uint64(data[n:]) - n += 8 + p.BufferId = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.TotalLen = binary.BigEndian.Uint16(data[n:]) + n += 2 + p.Reason = data[n] + n += 1 + p.TableId = data[n] + n += 1 + p.Cookie = binary.BigEndian.Uint64(data[n:]) + n += 8 - err = p.Match.UnmarshalBinary(data[n:]) - n += p.Match.Len() + err = p.Match.UnmarshalBinary(data[n:]) + n += p.Match.Len() - copy(p.pad, data[n:]) - n += 2 + copy(p.pad, data[n:]) + n += 2 - err = p.Data.UnmarshalBinary(data[n:]) - return err + err = p.Data.UnmarshalBinary(data[n:]) + return err } // ofp_packet_in_reason 1.3 const ( - R_NO_MATCH = iota /* No matching flow (table-miss flow entry). */ - R_ACTION /* Action explicitly output to controller. */ - R_INVALID_TTL /* Packet has invalid TTL */ + R_NO_MATCH = iota /* No matching flow (table-miss flow entry). */ + R_ACTION /* Action explicitly output to controller. */ + R_INVALID_TTL /* Packet has invalid TTL */ ) - func NewConfigRequest() *common.Header { - h := NewOfp13Header() - h.Type = Type_GetConfigRequest - return &h + h := NewOfp13Header() + h.Type = Type_GetConfigRequest + return &h } // ofp_config_flags 1.3 const ( - C_FRAG_NORMAL = 0 - C_FRAG_DROP = 1 - C_FRAG_REASM = 2 - C_FRAG_MASK = 3 + C_FRAG_NORMAL = 0 + C_FRAG_DROP = 1 + C_FRAG_REASM = 2 + C_FRAG_MASK = 3 ) // ofp_switch_config 1.3 type SwitchConfig struct { - common.Header - Flags uint16 // OFPC_* flags - MissSendLen uint16 + common.Header + Flags uint16 // OFPC_* flags + MissSendLen uint16 } func NewSetConfig() *SwitchConfig { - c := new(SwitchConfig) - c.Header = NewOfp13Header() - c.Header.Type = Type_SetConfig - c.Flags = 0 - c.MissSendLen = 0 - return c + c := new(SwitchConfig) + c.Header = NewOfp13Header() + c.Header.Type = Type_SetConfig + c.Flags = 0 + c.MissSendLen = 0 + return c } func (c *SwitchConfig) Len() (n uint16) { - n = c.Header.Len() - n += 4 - return + n = c.Header.Len() + n += 4 + return } func (c *SwitchConfig) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(c.Len())) - bytes := make([]byte, 0) - next := 0 + data = make([]byte, int(c.Len())) + bytes := make([]byte, 0) + next := 0 - c.Header.Length = c.Len() - bytes, err = c.Header.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) - binary.BigEndian.PutUint16(data[next:], c.Flags) - next += 2 - binary.BigEndian.PutUint16(data[next:], c.MissSendLen) - next += 2 - return + c.Header.Length = c.Len() + bytes, err = c.Header.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) + binary.BigEndian.PutUint16(data[next:], c.Flags) + next += 2 + binary.BigEndian.PutUint16(data[next:], c.MissSendLen) + next += 2 + return } func (c *SwitchConfig) UnmarshalBinary(data []byte) error { - var err error - next := 0 + var err error + next := 0 - err = c.Header.UnmarshalBinary(data[next:]) - next += int(c.Header.Len()) - c.Flags = binary.BigEndian.Uint16(data[next:]) - next += 2 - c.MissSendLen = binary.BigEndian.Uint16(data[next:]) - next += 2 - return err + err = c.Header.UnmarshalBinary(data[next:]) + next += int(c.Header.Len()) + c.Flags = binary.BigEndian.Uint16(data[next:]) + next += 2 + c.MissSendLen = binary.BigEndian.Uint16(data[next:]) + next += 2 + return err } - - // BEGIN: ofp13 - 7.4.4 // ofp_error_msg 1.3 type ErrorMsg struct { - common.Header - Type uint16 - Code uint16 - Data util.Buffer + common.Header + Type uint16 + Code uint16 + Data util.Buffer } func NewErrorMsg() *ErrorMsg { - e := new(ErrorMsg) - e.Data = *util.NewBuffer(make([]byte, 0)) - return e + e := new(ErrorMsg) + e.Data = *util.NewBuffer(make([]byte, 0)) + return e } func (e *ErrorMsg) Len() (n uint16) { - n = e.Header.Len() - n += 2 - n += 2 - n += e.Data.Len() - return + n = e.Header.Len() + n += 2 + n += 2 + n += e.Data.Len() + return } func (e *ErrorMsg) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(e.Len())) - next := 0 - - bytes, err := e.Header.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) - binary.BigEndian.PutUint16(data[next:], e.Type) - next += 2 - binary.BigEndian.PutUint16(data[next:], e.Code) - next += 2 - bytes, err = e.Data.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) - return + data = make([]byte, int(e.Len())) + next := 0 + + bytes, err := e.Header.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) + binary.BigEndian.PutUint16(data[next:], e.Type) + next += 2 + binary.BigEndian.PutUint16(data[next:], e.Code) + next += 2 + bytes, err = e.Data.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) + return } func (e *ErrorMsg) UnmarshalBinary(data []byte) error { - next := 0 - e.Header.UnmarshalBinary(data[next:]) - next += int(e.Header.Len()) - e.Type = binary.BigEndian.Uint16(data[next:]) - next += 2 - e.Code = binary.BigEndian.Uint16(data[next:]) - next += 2 - e.Data.UnmarshalBinary(data[next:]) - next += int(e.Data.Len()) - return nil + next := 0 + e.Header.UnmarshalBinary(data[next:]) + next += int(e.Header.Len()) + e.Type = binary.BigEndian.Uint16(data[next:]) + next += 2 + e.Code = binary.BigEndian.Uint16(data[next:]) + next += 2 + e.Data.UnmarshalBinary(data[next:]) + next += int(e.Data.Len()) + return nil } // ofp_error_type 1.3 const ( - ET_HELLO_FAILED = 0 /* Hello protocol failed. */ - ET_BAD_REQUEST = 1 /* Request was not understood. */ - ET_BAD_ACTION = 2 /* Error in action description. */ - ET_BAD_INSTRUCTION = 3 /* Error in instruction list. */ - PET_BAD_MATCH = 4 /* Error in match. */ - ET_FLOW_MOD_FAILED = 5 /* Problem modifying flow entry. */ - ET_GROUP_MOD_FAILED = 6 /* Problem modifying group entry. */ - ET_PORT_MOD_FAILED = 7 /* Port mod request failed. */ - ET_TABLE_MOD_FAILED = 8 /* Table mod request failed. */ - ET_QUEUE_OP_FAILED = 9 /* Queue operation failed. */ - ET_ROLE_REQUEST_FAILED = 11 /* Controller Role request failed. */ - ET_METER_MOD_FAILED = 12 /* Error in meter. */ - ET_TABLE_FEATURES_FAILED = 13 /* Setting table features failed. */ - ET_EXPERIMENTER = 0xffff /* Experimenter error messages. */ + ET_HELLO_FAILED = 0 /* Hello protocol failed. */ + ET_BAD_REQUEST = 1 /* Request was not understood. */ + ET_BAD_ACTION = 2 /* Error in action description. */ + ET_BAD_INSTRUCTION = 3 /* Error in instruction list. */ + PET_BAD_MATCH = 4 /* Error in match. */ + ET_FLOW_MOD_FAILED = 5 /* Problem modifying flow entry. */ + ET_GROUP_MOD_FAILED = 6 /* Problem modifying group entry. */ + ET_PORT_MOD_FAILED = 7 /* Port mod request failed. */ + ET_TABLE_MOD_FAILED = 8 /* Table mod request failed. */ + ET_QUEUE_OP_FAILED = 9 /* Queue operation failed. */ + ET_ROLE_REQUEST_FAILED = 11 /* Controller Role request failed. */ + ET_METER_MOD_FAILED = 12 /* Error in meter. */ + ET_TABLE_FEATURES_FAILED = 13 /* Setting table features failed. */ + ET_EXPERIMENTER = 0xffff /* Experimenter error messages. */ ) // ofp_hello_failed_code 1.3 const ( - HFC_INCOMPATIBLE = iota - HFC_EPERM + HFC_INCOMPATIBLE = iota + HFC_EPERM ) // ofp_bad_request_code 1.3 const ( - BRC_BAD_VERSION = iota - BRC_BAD_TYPE - BRC_BAD_MULTIPART - BRC_BAD_EXPERIMENTER - - BRC_BAD_EXP_TYPE - BRC_EPERM - BRC_BAD_LEN - BRC_BUFFER_EMPTY - BRC_BUFFER_UNKNOWN - BRC_BAD_TABLE_ID - BRC_IS_SLAVE - BRC_BAD_PORT - BRC_BAD_PACKET - BRC_MULTIPART_BUFFER_OVERFLOW + BRC_BAD_VERSION = iota + BRC_BAD_TYPE + BRC_BAD_MULTIPART + BRC_BAD_EXPERIMENTER + + BRC_BAD_EXP_TYPE + BRC_EPERM + BRC_BAD_LEN + BRC_BUFFER_EMPTY + BRC_BUFFER_UNKNOWN + BRC_BAD_TABLE_ID + BRC_IS_SLAVE + BRC_BAD_PORT + BRC_BAD_PACKET + BRC_MULTIPART_BUFFER_OVERFLOW ) // ofp_bad_action_code 1.3 const ( - BAC_BAD_TYPE = iota - BAC_BAD_LEN - BAC_BAD_EXPERIMENTER - BAC_BAD_EXP_TYPE - BAC_BAD_OUT_PORT - BAC_BAD_ARGUMENT - BAC_EPERM - BAC_TOO_MANY - BAC_BAD_QUEUE - BAC_BAD_OUT_GROUP - BAC_MATCH_INCONSISTENT - BAC_UNSUPPORTED_ORDER - BAC_BAD_TAG - BAC_BAD_SET_TYPE - BAC_BAD_SET_LEN - BAC_BAD_SET_ARGUMENT + BAC_BAD_TYPE = iota + BAC_BAD_LEN + BAC_BAD_EXPERIMENTER + BAC_BAD_EXP_TYPE + BAC_BAD_OUT_PORT + BAC_BAD_ARGUMENT + BAC_EPERM + BAC_TOO_MANY + BAC_BAD_QUEUE + BAC_BAD_OUT_GROUP + BAC_MATCH_INCONSISTENT + BAC_UNSUPPORTED_ORDER + BAC_BAD_TAG + BAC_BAD_SET_TYPE + BAC_BAD_SET_LEN + BAC_BAD_SET_ARGUMENT ) // ofp_bad_instruction_code 1.3 const ( - BIC_UNKNOWN_INST = 0 /* Unknown instruction. */ - BIC_UNSUP_INST = 1 /* Switch or table does not support the instruction. */ - BIC_BAD_TABLE_ID = 2 /* Invalid Table-ID specified. */ - BIC_UNSUP_METADATA = 3 /* Metadata value unsupported by datapath. */ - BIC_UNSUP_METADATA_MASK = 4 /* Metadata mask value unsupported by datapath. */ - BIC_BAD_EXPERIMENTER = 5 /* Unknown experimenter id specified. */ - BIC_BAD_EXP_TYPE = 6 /* Unknown instruction for experimenter id. */ - BIC_BAD_LEN = 7 /* Length problem in instructions. */ - BIC_EPERM = 8 /* Permissions error. */ + BIC_UNKNOWN_INST = 0 /* Unknown instruction. */ + BIC_UNSUP_INST = 1 /* Switch or table does not support the instruction. */ + BIC_BAD_TABLE_ID = 2 /* Invalid Table-ID specified. */ + BIC_UNSUP_METADATA = 3 /* Metadata value unsupported by datapath. */ + BIC_UNSUP_METADATA_MASK = 4 /* Metadata mask value unsupported by datapath. */ + BIC_BAD_EXPERIMENTER = 5 /* Unknown experimenter id specified. */ + BIC_BAD_EXP_TYPE = 6 /* Unknown instruction for experimenter id. */ + BIC_BAD_LEN = 7 /* Length problem in instructions. */ + BIC_EPERM = 8 /* Permissions error. */ ) // ofp_flow_mod_failed_code 1.3 const ( - FMFC_UNKNOWN = 0 /* Unspecified error. */ - FMFC_TABLE_FULL = 1 /* Flow not added because table was full. */ - FMFC_BAD_TABLE_ID = 2 /* Table does not exist */ - FMFC_OVERLAP = 3 /* Attempted to add overlapping flow with CHECK_OVERLAP flag set. */ - FMFC_EPERM = 4 /* Permissions error. */ - FMFC_BAD_TIMEOUT = 5 /* Flow not added because of unsupported idle/hard timeout. */ - FMFC_BAD_COMMAND = 6 /* Unsupported or unknown command. */ - FMFC_BAD_FLAGS = 7 /* Unsupported or unknown flags. */ + FMFC_UNKNOWN = 0 /* Unspecified error. */ + FMFC_TABLE_FULL = 1 /* Flow not added because table was full. */ + FMFC_BAD_TABLE_ID = 2 /* Table does not exist */ + FMFC_OVERLAP = 3 /* Attempted to add overlapping flow with CHECK_OVERLAP flag set. */ + FMFC_EPERM = 4 /* Permissions error. */ + FMFC_BAD_TIMEOUT = 5 /* Flow not added because of unsupported idle/hard timeout. */ + FMFC_BAD_COMMAND = 6 /* Unsupported or unknown command. */ + FMFC_BAD_FLAGS = 7 /* Unsupported or unknown flags. */ ) // ofp_bad_match_code 1.3 const ( - BMC_BAD_TYPE = 0 /* Unsupported match type specified by the match */ - BMC_BAD_LEN = 1 /* Length problem in match. */ - BMC_BAD_TAG = 2 /* Match uses an unsupported tag/encap. */ - BMC_BAD_DL_ADDR_MASK = 3 /* Unsupported datalink addr mask - switch does not support arbitrary datalink address mask. */ - BMC_BAD_NW_ADDR_MASK = 4 /* Unsupported network addr mask - switch does not support arbitrary network address mask. */ - BMC_BAD_WILDCARDS = 5 /* Unsupported combination of fields masked or omitted in the match. */ - BMC_BAD_FIELD = 6 /* Unsupported field type in the match. */ - BMC_BAD_VALUE = 7 /* Unsupported value in a match field. */ - BMC_BAD_MASK = 8 /* Unsupported mask specified in the match, field is not dl-address or nw-address. */ - BMC_BAD_PREREQ = 9 /* A prerequisite was not met. */ - BMC_DUP_FIELD = 10 /* A field type was duplicated. */ - BMC_EPERM = 11 /* Permissions error. */ + BMC_BAD_TYPE = 0 /* Unsupported match type specified by the match */ + BMC_BAD_LEN = 1 /* Length problem in match. */ + BMC_BAD_TAG = 2 /* Match uses an unsupported tag/encap. */ + BMC_BAD_DL_ADDR_MASK = 3 /* Unsupported datalink addr mask - switch does not support arbitrary datalink address mask. */ + BMC_BAD_NW_ADDR_MASK = 4 /* Unsupported network addr mask - switch does not support arbitrary network address mask. */ + BMC_BAD_WILDCARDS = 5 /* Unsupported combination of fields masked or omitted in the match. */ + BMC_BAD_FIELD = 6 /* Unsupported field type in the match. */ + BMC_BAD_VALUE = 7 /* Unsupported value in a match field. */ + BMC_BAD_MASK = 8 /* Unsupported mask specified in the match, field is not dl-address or nw-address. */ + BMC_BAD_PREREQ = 9 /* A prerequisite was not met. */ + BMC_DUP_FIELD = 10 /* A field type was duplicated. */ + BMC_EPERM = 11 /* Permissions error. */ ) // ofp_group_mod_failed_code 1.3 const ( - GMFC_GROUP_EXISTS = 0 /* Group not added because a group ADD attempted to replace an already-present group. */ - GMFC_INVALID_GROUP = 1 /* Group not added because Group specified is invalid. */ - 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. */ - GMFC_OUT_OF_GROUPS = 3 /* The group table is full. */ - GMFC_OUT_OF_BUCKETS = 4 /* The maximum number of action buckets for a group has been exceeded. */ - GMFC_CHAINING_UNSUPPORTED = 5 /* Switch does not support groups that forward to groups. */ - GMFC_WATCH_UNSUPPORTED = 6 /* This group cannot watch the watch_port or watch_group specified. */ - GMFC_LOOP = 7 /* Group entry would cause a loop. */ - GMFC_UNKNOWN_GROUP = 8 /* Group not modified because a group MODIFY attempted to modify a non-existent group. */ - GMFC_CHAINED_GROUP = 9 /* Group not deleted because another group is forwarding to it. */ - GMFC_BAD_TYPE = 10 /* Unsupported or unknown group type. */ - GMFC_BAD_COMMAND = 11 /* Unsupported or unknown command. */ - GMFC_BAD_BUCKET = 12 /* Error in bucket. */ - GMFC_BAD_WATCH = 13 /* Error in watch port/group. */ - GMFC_EPERM = 14 /* Permissions error. */ + GMFC_GROUP_EXISTS = 0 /* Group not added because a group ADD attempted to replace an already-present group. */ + GMFC_INVALID_GROUP = 1 /* Group not added because Group specified is invalid. */ + 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. */ + GMFC_OUT_OF_GROUPS = 3 /* The group table is full. */ + GMFC_OUT_OF_BUCKETS = 4 /* The maximum number of action buckets for a group has been exceeded. */ + GMFC_CHAINING_UNSUPPORTED = 5 /* Switch does not support groups that forward to groups. */ + GMFC_WATCH_UNSUPPORTED = 6 /* This group cannot watch the watch_port or watch_group specified. */ + GMFC_LOOP = 7 /* Group entry would cause a loop. */ + GMFC_UNKNOWN_GROUP = 8 /* Group not modified because a group MODIFY attempted to modify a non-existent group. */ + GMFC_CHAINED_GROUP = 9 /* Group not deleted because another group is forwarding to it. */ + GMFC_BAD_TYPE = 10 /* Unsupported or unknown group type. */ + GMFC_BAD_COMMAND = 11 /* Unsupported or unknown command. */ + GMFC_BAD_BUCKET = 12 /* Error in bucket. */ + GMFC_BAD_WATCH = 13 /* Error in watch port/group. */ + GMFC_EPERM = 14 /* Permissions error. */ ) // ofp_port_mod_failed_code 1.0 const ( - PMFC_BAD_PORT = iota - PMFC_BAD_HW_ADDR - PMFC_BAD_CONFIG - PMFC_BAD_ADVERTISE - PMFC_EPERM + PMFC_BAD_PORT = iota + PMFC_BAD_HW_ADDR + PMFC_BAD_CONFIG + PMFC_BAD_ADVERTISE + PMFC_EPERM ) // ofp_table_mod_failed_code const ( - TMFC_BAD_TABLE = 0 /* Specified table does not exist. */ - TMFC_BAD_CONFIG = 1 /* Specified config is invalid. */ - TMFC_EPERM = 2 /* Permissions error. */ + TMFC_BAD_TABLE = 0 /* Specified table does not exist. */ + TMFC_BAD_CONFIG = 1 /* Specified config is invalid. */ + TMFC_EPERM = 2 /* Permissions error. */ ) // ofp_queue_op_failed_code 1.0 const ( - QOFC_BAD_PORT = iota - QOFC_BAD_QUEUE - QOFC_EPERM + QOFC_BAD_PORT = iota + QOFC_BAD_QUEUE + QOFC_EPERM ) // END: ofp13 - 7.4.4 // END: ofp13 - 7.4 - type SwitchFeatures struct { - common.Header - DPID net.HardwareAddr // Size 8 - Buffers uint32 - NumTables uint8 - AuxilaryId uint8 - pad []uint8 // Size 2 - Capabilities uint32 - Actions uint32 + common.Header + DPID net.HardwareAddr // Size 8 + Buffers uint32 + NumTables uint8 + AuxilaryId uint8 + pad []uint8 // Size 2 + Capabilities uint32 + Actions uint32 - Ports []PhyPort + Ports []PhyPort } // FeaturesRequest constructor func NewFeaturesRequest() *common.Header { - req := NewOfp13Header() - req.Type = Type_FeaturesRequest - return &req + req := NewOfp13Header() + req.Type = Type_FeaturesRequest + return &req } // FeaturesReply constructor func NewFeaturesReply() *SwitchFeatures { - res := new(SwitchFeatures) - res.Header = NewOfp13Header() - res.Header.Type = Type_FeaturesReply - res.DPID = make([]byte, 8) - res.pad = make([]byte, 2) - res.Ports = make([]PhyPort, 0) - return res + res := new(SwitchFeatures) + res.Header = NewOfp13Header() + res.Header.Type = Type_FeaturesReply + res.DPID = make([]byte, 8) + res.pad = make([]byte, 2) + res.Ports = make([]PhyPort, 0) + return res } func (s *SwitchFeatures) Len() (n uint16) { - n = s.Header.Len() - n += uint16(len(s.DPID)) - n += 16 - for _, p := range s.Ports { - n += p.Len() - } - return + n = s.Header.Len() + n += uint16(len(s.DPID)) + n += 16 + for _, p := range s.Ports { + n += p.Len() + } + return } func (s *SwitchFeatures) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(s.Len())) - bytes := make([]byte, 0) - next := 0 - - s.Header.Length = s.Len() - bytes, err = s.Header.MarshalBinary() - copy(data[next:], bytes) - next += len(bytes) - binary.BigEndian.PutUint32(data[next:], s.Buffers) - next += 4 - data[next] = s.NumTables - next += 1 - data[next] = s.AuxilaryId - next += 1 - copy(data[next:], s.pad) - next += len(s.pad) - binary.BigEndian.PutUint32(data[next:], s.Capabilities) - next += 4 - binary.BigEndian.PutUint32(data[next:], s.Actions) - next += 4 - - for _, p := range s.Ports { - bytes, err = p.MarshalBinary() - if err != nil { - return - } - copy(data[next:], bytes) - next += len(bytes) - } - return + data = make([]byte, int(s.Len())) + bytes := make([]byte, 0) + next := 0 + + s.Header.Length = s.Len() + bytes, err = s.Header.MarshalBinary() + copy(data[next:], bytes) + next += len(bytes) + binary.BigEndian.PutUint32(data[next:], s.Buffers) + next += 4 + data[next] = s.NumTables + next += 1 + data[next] = s.AuxilaryId + next += 1 + copy(data[next:], s.pad) + next += len(s.pad) + binary.BigEndian.PutUint32(data[next:], s.Capabilities) + next += 4 + binary.BigEndian.PutUint32(data[next:], s.Actions) + next += 4 + + for _, p := range s.Ports { + bytes, err = p.MarshalBinary() + if err != nil { + return + } + copy(data[next:], bytes) + next += len(bytes) + } + return } func (s *SwitchFeatures) UnmarshalBinary(data []byte) error { - var err error - next := 0 - - err = s.Header.UnmarshalBinary(data[next:]) - next = int(s.Header.Len()) - copy(s.DPID, data[next:]) - next += len(s.DPID) - s.Buffers = binary.BigEndian.Uint32(data[next:]) - next += 4 - s.NumTables = data[next] - next += 1 - s.AuxilaryId = data[next] - next += 1 - copy(s.pad, data[next:]) - next += len(s.pad) - s.Capabilities = binary.BigEndian.Uint32(data[next:]) - next += 4 - s.Actions = binary.BigEndian.Uint32(data[next:]) - next += 4 - - for next < len(data) { - p := NewPhyPort() - err = p.UnmarshalBinary(data[next:]) - next += int(p.Len()) - } - return err + var err error + next := 0 + + err = s.Header.UnmarshalBinary(data[next:]) + next = int(s.Header.Len()) + copy(s.DPID, data[next:]) + next += len(s.DPID) + s.Buffers = binary.BigEndian.Uint32(data[next:]) + next += 4 + s.NumTables = data[next] + next += 1 + s.AuxilaryId = data[next] + next += 1 + copy(s.pad, data[next:]) + next += len(s.pad) + s.Capabilities = binary.BigEndian.Uint32(data[next:]) + next += 4 + s.Actions = binary.BigEndian.Uint32(data[next:]) + next += 4 + + for next < len(data) { + p := NewPhyPort() + err = p.UnmarshalBinary(data[next:]) + next += int(p.Len()) + } + return err } // ofp_capabilities 1.3 const ( - C_FLOW_STATS = 1 << 0 - C_TABLE_STATS = 1 << 1 - C_PORT_STATS = 1 << 2 - C_GROUP_STATS = 1 << 3 - C_RESERVED = 1 << 4 - C_IP_REASM = 1 << 5 - C_QUEUE_STATS = 1 << 6 - C_PORT_BLOCKED = 1 << 8 + C_FLOW_STATS = 1 << 0 + C_TABLE_STATS = 1 << 1 + C_PORT_STATS = 1 << 2 + C_GROUP_STATS = 1 << 3 + C_RESERVED = 1 << 4 + C_IP_REASM = 1 << 5 + C_QUEUE_STATS = 1 << 6 + C_PORT_BLOCKED = 1 << 8 ) // ofp_vendor 1.3 type VendorHeader struct { - Header common.Header /*Type OFPT_VENDOR*/ - Vendor uint32 + Header common.Header /*Type OFPT_VENDOR*/ + Vendor uint32 } func (v *VendorHeader) Len() (n uint16) { - return v.Header.Len() + 4 + return v.Header.Len() + 4 } func (v *VendorHeader) MarshalBinary() (data []byte, err error) { - data, err = v.Header.MarshalBinary() + data, err = v.Header.MarshalBinary() - b := make([]byte, 4) - binary.BigEndian.PutUint32(data[:4], v.Vendor) + b := make([]byte, 4) + binary.BigEndian.PutUint32(data[:4], v.Vendor) - data = append(data, b...) - return + data = append(data, b...) + return } func (v *VendorHeader) UnmarshalBinary(data []byte) error { - if len(data) < int(v.Len()) { - return errors.New("The []byte the wrong size to unmarshal an " + - "VendorHeader message.") - } - v.Header.UnmarshalBinary(data) - n := int(v.Header.Len()) - v.Vendor = binary.BigEndian.Uint32(data[n:]) - return nil + if len(data) < int(v.Len()) { + return errors.New("The []byte the wrong size to unmarshal an " + + "VendorHeader message.") + } + v.Header.UnmarshalBinary(data) + n := int(v.Header.Len()) + v.Vendor = binary.BigEndian.Uint32(data[n:]) + return nil } diff --git a/openflow13/port.go b/openflow13/port.go index aabe1b6..88fdb3a 100644 --- a/openflow13/port.go +++ b/openflow13/port.go @@ -1,245 +1,244 @@ package openflow13 import ( - "encoding/binary" - "net" + "encoding/binary" + "net" - "github.com/shaleman/libOpenflow/common" + "github.com/shaleman/libOpenflow/common" ) // ofp_port 1.3 type PhyPort struct { - PortNo uint32 - pad []byte // 4 bytes - HWAddr net.HardwareAddr - pad2 []byte // 2 bytes for 64bit alignment - Name []byte // Size 16 - - Config uint32 - State uint32 - - Curr uint32 - Advertised uint32 - Supported uint32 - Peer uint32 - - CurrSpeed uint32 - MaxSpeed uint32 + PortNo uint32 + pad []byte // 4 bytes + HWAddr net.HardwareAddr + pad2 []byte // 2 bytes for 64bit alignment + Name []byte // Size 16 + + Config uint32 + State uint32 + + Curr uint32 + Advertised uint32 + Supported uint32 + Peer uint32 + + CurrSpeed uint32 + MaxSpeed uint32 } func NewPhyPort() *PhyPort { - p := new(PhyPort) - p.HWAddr = make([]byte, ETH_ALEN) - p.Name = make([]byte, 16) - return p + p := new(PhyPort) + p.HWAddr = make([]byte, ETH_ALEN) + p.Name = make([]byte, 16) + return p } func (p *PhyPort) Len() (n uint16) { - n += 4 - n += 6 // padding - n += uint16(len(p.HWAddr) + len(p.Name)) - n += 32 - return + n += 4 + n += 6 // padding + n += uint16(len(p.HWAddr) + len(p.Name)) + n += 32 + return } func (p *PhyPort) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(p.Len())) - binary.BigEndian.PutUint32(data, p.PortNo) - n := 4 - copy(data[n:], p.pad) - n += 4 - copy(data[n:], p.HWAddr) - n += len(p.HWAddr) - copy(data[n:], p.pad2) - n += 2 - copy(data[n:], p.Name) - n += len(p.Name) - - binary.BigEndian.PutUint32(data[n:], p.Config) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.State) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.Curr) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.Advertised) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.Supported) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.Peer) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.CurrSpeed) - n += 4 - binary.BigEndian.PutUint32(data[n:], p.MaxSpeed) - n += 4 - return + data = make([]byte, int(p.Len())) + binary.BigEndian.PutUint32(data, p.PortNo) + n := 4 + copy(data[n:], p.pad) + n += 4 + copy(data[n:], p.HWAddr) + n += len(p.HWAddr) + copy(data[n:], p.pad2) + n += 2 + copy(data[n:], p.Name) + n += len(p.Name) + + binary.BigEndian.PutUint32(data[n:], p.Config) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.State) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.Curr) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.Advertised) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.Supported) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.Peer) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.CurrSpeed) + n += 4 + binary.BigEndian.PutUint32(data[n:], p.MaxSpeed) + n += 4 + return } func (p *PhyPort) UnmarshalBinary(data []byte) error { - p.PortNo = binary.BigEndian.Uint32(data) - n := 4 - copy(p.pad, data[n:n+4]) - n += 4 - copy(p.HWAddr, data[n:n+6]) - n += 6 - copy(p.pad2, data[n:n+2]) - n += 2 - copy(p.Name, data[n:n+16]) - n += 16 - - p.Config = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.State = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Curr = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Advertised = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Supported = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Peer = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.CurrSpeed = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.MaxSpeed = binary.BigEndian.Uint32(data[n:]) - n += 4 - return nil + p.PortNo = binary.BigEndian.Uint32(data) + n := 4 + copy(p.pad, data[n:n+4]) + n += 4 + copy(p.HWAddr, data[n:n+6]) + n += 6 + copy(p.pad2, data[n:n+2]) + n += 2 + copy(p.Name, data[n:n+16]) + n += 16 + + p.Config = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.State = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Curr = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Advertised = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Supported = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Peer = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.CurrSpeed = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.MaxSpeed = binary.BigEndian.Uint32(data[n:]) + n += 4 + return nil } // ofp_port_mod 1.3 type PortMod struct { - common.Header - PortNo uint32 - pad []byte // 4 bytes - HWAddr []uint8 - pad2 []byte // 2 bytes for 64byte alignment - - Config uint32 - Mask uint32 - Advertise uint32 - pad3 []uint8 // Size 4 + common.Header + PortNo uint32 + pad []byte // 4 bytes + HWAddr []uint8 + pad2 []byte // 2 bytes for 64byte alignment + + Config uint32 + Mask uint32 + Advertise uint32 + pad3 []uint8 // Size 4 } func NewPortMod(port int) *PortMod { - p := new(PortMod) - p.Header.Type = Type_PortMod - p.PortNo = uint32(port) - p.HWAddr = make([]byte, ETH_ALEN) - p.pad = make([]byte, 4) - p.pad2 = make([]byte, 2) - p.pad3 = make([]byte, 4) - return p + p := new(PortMod) + p.Header.Type = Type_PortMod + p.PortNo = uint32(port) + p.HWAddr = make([]byte, ETH_ALEN) + p.pad = make([]byte, 4) + p.pad2 = make([]byte, 2) + p.pad3 = make([]byte, 4) + return p } func (p *PortMod) Len() (n uint16) { - return p.Header.Len() + 4 + 4 + ETH_ALEN + 2 + 12 + 4 + return p.Header.Len() + 4 + 4 + ETH_ALEN + 2 + 12 + 4 } func (p *PortMod) MarshalBinary() (data []byte, err error) { - p.Header.Length = p.Len() - data, err = p.Header.MarshalBinary() - - b := make([]byte, 32) - n := 0 - binary.BigEndian.PutUint32(b[n:], p.PortNo) - n += 4 - copy(b[n:], p.pad) - n += 4 - copy(b[n:], p.HWAddr) - n += ETH_ALEN - copy(b[n:], p.pad2) - n += 2 - binary.BigEndian.PutUint32(b[n:], p.Config) - n += 4 - binary.BigEndian.PutUint32(b[n:], p.Mask) - n += 4 - binary.BigEndian.PutUint32(b[n:], p.Advertise) - n += 4 - copy(b[n:], p.pad3) - n += 4 - data = append(data, b...) - return + p.Header.Length = p.Len() + data, err = p.Header.MarshalBinary() + + b := make([]byte, 32) + n := 0 + binary.BigEndian.PutUint32(b[n:], p.PortNo) + n += 4 + copy(b[n:], p.pad) + n += 4 + copy(b[n:], p.HWAddr) + n += ETH_ALEN + copy(b[n:], p.pad2) + n += 2 + binary.BigEndian.PutUint32(b[n:], p.Config) + n += 4 + binary.BigEndian.PutUint32(b[n:], p.Mask) + n += 4 + binary.BigEndian.PutUint32(b[n:], p.Advertise) + n += 4 + copy(b[n:], p.pad3) + n += 4 + data = append(data, b...) + return } func (p *PortMod) UnmarshalBinary(data []byte) error { - err := p.Header.UnmarshalBinary(data) - n := int(p.Header.Len()) - - p.PortNo = binary.BigEndian.Uint32(data[n:]) - n += 4 - copy(p.pad, data[n:n+4]) - n += 4 - copy(p.HWAddr, data[n:]) - n += len(p.HWAddr) - copy(p.pad2, data[n:n+2]) - n += 2 - p.Config = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Mask = binary.BigEndian.Uint32(data[n:]) - n += 4 - p.Advertise = binary.BigEndian.Uint32(data[n:]) - n += 4 - copy(p.pad3, data[n:]) - n += 4 - return err + err := p.Header.UnmarshalBinary(data) + n := int(p.Header.Len()) + + p.PortNo = binary.BigEndian.Uint32(data[n:]) + n += 4 + copy(p.pad, data[n:n+4]) + n += 4 + copy(p.HWAddr, data[n:]) + n += len(p.HWAddr) + copy(p.pad2, data[n:n+2]) + n += 2 + p.Config = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Mask = binary.BigEndian.Uint32(data[n:]) + n += 4 + p.Advertise = binary.BigEndian.Uint32(data[n:]) + n += 4 + copy(p.pad3, data[n:]) + n += 4 + return err } - const ( - ETH_ALEN = 6 - MAX_PORT_NAME_LEN = 16 + ETH_ALEN = 6 + MAX_PORT_NAME_LEN = 16 ) // ofp_port_config 1.3 const ( - PC_PORT_DOWN = 1 << 0 + PC_PORT_DOWN = 1 << 0 - PC_NO_RECV = 1 << 2 - PC_NO_FWD = 1 << 5 - PC_NO_PACKET_IN = 1 << 6 + PC_NO_RECV = 1 << 2 + PC_NO_FWD = 1 << 5 + PC_NO_PACKET_IN = 1 << 6 ) // ofp_port_state 1.3 const ( - PS_LINK_DOWN = 1 << 0 - PS_BLOCKED = 1 << 1 - PS_LIVE = 1 << 2 + PS_LINK_DOWN = 1 << 0 + PS_BLOCKED = 1 << 1 + PS_LIVE = 1 << 2 ) // ofp_port_no 1.3 const ( - P_MAX = 0xffffff00 + P_MAX = 0xffffff00 - P_IN_PORT = 0xfffffff8 - P_TABLE = 0xfffffff9 + P_IN_PORT = 0xfffffff8 + P_TABLE = 0xfffffff9 - P_NORMAL = 0xfffffffa - P_FLOOD = 0xfffffffb + P_NORMAL = 0xfffffffa + P_FLOOD = 0xfffffffb - P_ALL = 0xfffffffc - P_CONTROLLER = 0xfffffffd - P_LOCAL = 0xfffffffe - P_ANY = 0xffffffff + P_ALL = 0xfffffffc + P_CONTROLLER = 0xfffffffd + P_LOCAL = 0xfffffffe + P_ANY = 0xffffffff ) // ofp_port_features 1.3 const ( - PF_10MB_HD = 1 << 0 - PF_10MB_FD = 1 << 1 - PF_100MB_HD = 1 << 2 - PF_100MB_FD = 1 << 3 - PF_1GB_HD = 1 << 4 - PF_1GB_FD = 1 << 5 - PF_10GB_FD = 1 << 6 - PF_40GB_FD = 1 << 7 - PF_100GB_FD = 1 << 8 - PF_1TB_FD = 1 << 9 - PF_OTHER = 1 << 10 - - PF_COPPER = 1 << 11 - PF_FIBER = 1 << 12 - PF_AUTONEG = 1 << 13 - PF_PAUSE = 1 << 14 - PF_PAUSE_ASYM = 1 << 15 + PF_10MB_HD = 1 << 0 + PF_10MB_FD = 1 << 1 + PF_100MB_HD = 1 << 2 + PF_100MB_FD = 1 << 3 + PF_1GB_HD = 1 << 4 + PF_1GB_FD = 1 << 5 + PF_10GB_FD = 1 << 6 + PF_40GB_FD = 1 << 7 + PF_100GB_FD = 1 << 8 + PF_1TB_FD = 1 << 9 + PF_OTHER = 1 << 10 + + PF_COPPER = 1 << 11 + PF_FIBER = 1 << 12 + PF_AUTONEG = 1 << 13 + PF_PAUSE = 1 << 14 + PF_PAUSE_ASYM = 1 << 15 ) // END: 13 - 7.2.1 diff --git a/protocol/dhcp.go b/protocol/dhcp.go index fae4f8e..9a92a98 100644 --- a/protocol/dhcp.go +++ b/protocol/dhcp.go @@ -1,434 +1,434 @@ package protocol import ( - "bytes" - "encoding/binary" - "errors" - "io" - "math/rand" - "net" + "bytes" + "encoding/binary" + "errors" + "io" + "math/rand" + "net" ) const ( - DHCP_MSG_BOOT_REQ byte = iota - DHCP_MSG_BOOT_RES + DHCP_MSG_BOOT_REQ byte = iota + DHCP_MSG_BOOT_RES ) type DHCPOperation byte const ( - DHCP_MSG_UNSPEC DHCPOperation = iota - DHCP_MSG_DISCOVER - DHCP_MSG_OFFER - DHCP_MSG_REQUEST - DHCP_MSG_DECLINE - DHCP_MSG_ACK - DHCP_MSG_NAK - DHCP_MSG_RELEASE - DHCP_MSG_INFORM + DHCP_MSG_UNSPEC DHCPOperation = iota + DHCP_MSG_DISCOVER + DHCP_MSG_OFFER + DHCP_MSG_REQUEST + DHCP_MSG_DECLINE + DHCP_MSG_ACK + DHCP_MSG_NAK + DHCP_MSG_RELEASE + DHCP_MSG_INFORM ) var dhcpMagic uint32 = 0x63825363 type DHCP struct { - Operation DHCPOperation - HardwareType byte - HardwareLen uint8 - HardwareOpts uint8 - Xid uint32 - Secs uint16 - Flags uint16 - ClientIP net.IP - YourIP net.IP - ServerIP net.IP - GatewayIP net.IP - ClientHWAddr net.HardwareAddr - ServerName [64]byte - File [128]byte - Options []DHCPOption + Operation DHCPOperation + HardwareType byte + HardwareLen uint8 + HardwareOpts uint8 + Xid uint32 + Secs uint16 + Flags uint16 + ClientIP net.IP + YourIP net.IP + ServerIP net.IP + GatewayIP net.IP + ClientHWAddr net.HardwareAddr + ServerName [64]byte + File [128]byte + Options []DHCPOption } const ( - DHCP_OPT_REQUEST_IP byte = iota + 50 // 0x32, 4, net.IP - DHCP_OPT_LEASE_TIME // 0x33, 4, uint32 - DHCP_OPT_EXT_OPTS // 0x34, 1, 1/2/3 - DHCP_OPT_MESSAGE_TYPE // 0x35, 1, 1-7 - DHCP_OPT_SERVER_ID // 0x36, 4, net.IP - DHCP_OPT_PARAMS_REQUEST // 0x37, n, []byte - DHCP_OPT_MESSAGE // 0x38, n, string - DHCP_OPT_MAX_DHCP_SIZE // 0x39, 2, uint16 - DHCP_OPT_T1 // 0x3a, 4, uint32 - DHCP_OPT_T2 // 0x3b, 4, uint32 - DHCP_OPT_CLASS_ID // 0x3c, n, []byte - DHCP_OPT_CLIENT_ID // 0x3d, n >= 2, []byte + DHCP_OPT_REQUEST_IP byte = iota + 50 // 0x32, 4, net.IP + DHCP_OPT_LEASE_TIME // 0x33, 4, uint32 + DHCP_OPT_EXT_OPTS // 0x34, 1, 1/2/3 + DHCP_OPT_MESSAGE_TYPE // 0x35, 1, 1-7 + DHCP_OPT_SERVER_ID // 0x36, 4, net.IP + DHCP_OPT_PARAMS_REQUEST // 0x37, n, []byte + DHCP_OPT_MESSAGE // 0x38, n, string + DHCP_OPT_MAX_DHCP_SIZE // 0x39, 2, uint16 + DHCP_OPT_T1 // 0x3a, 4, uint32 + DHCP_OPT_T2 // 0x3b, 4, uint32 + DHCP_OPT_CLASS_ID // 0x3c, n, []byte + DHCP_OPT_CLIENT_ID // 0x3d, n >= 2, []byte ) const ( - DHCP_HW_ETHERNET byte = 0x01 + DHCP_HW_ETHERNET byte = 0x01 ) const ( - DHCP_FLAG_BROADCAST uint16 = 0x80 + DHCP_FLAG_BROADCAST uint16 = 0x80 // FLAG_BROADCAST_MASK uint16 = (1 << FLAG_BROADCAST) ) func NewDHCP(xid uint32, op DHCPOperation, hwtype byte) (*DHCP, error) { - if xid == 0 { - xid = rand.Uint32() - } - switch hwtype { - case DHCP_HW_ETHERNET: - break - default: - return nil, errors.New("Bad HardwareType") - } - d := &DHCP{ - Operation: op, - HardwareType: hwtype, - Xid: xid, - ClientIP: make([]byte, 4), - YourIP: make([]byte, 4), - ServerIP: make([]byte, 4), - GatewayIP: make([]byte, 4), - ClientHWAddr: make([]byte, 16), - } - return d, nil + if xid == 0 { + xid = rand.Uint32() + } + switch hwtype { + case DHCP_HW_ETHERNET: + break + default: + return nil, errors.New("Bad HardwareType") + } + d := &DHCP{ + Operation: op, + HardwareType: hwtype, + Xid: xid, + ClientIP: make([]byte, 4), + YourIP: make([]byte, 4), + ServerIP: make([]byte, 4), + GatewayIP: make([]byte, 4), + ClientHWAddr: make([]byte, 16), + } + return d, nil } func (d *DHCP) Len() (n uint16) { - n += uint16(240) - optend := false - for _, opt := range d.Options { - n += opt.Len() - if opt.OptionType() == DHCP_OPT_END { - optend = true - } - } - if !optend { - n += 1 - } - return + n += uint16(240) + optend := false + for _, opt := range d.Options { + n += opt.Len() + if opt.OptionType() == DHCP_OPT_END { + optend = true + } + } + if !optend { + n += 1 + } + return } func (d *DHCP) Read(b []byte) (n int, err error) { - buf := new(bytes.Buffer) - binary.Write(buf, binary.BigEndian, d.Operation) - n += 1 - binary.Write(buf, binary.BigEndian, d.HardwareType) - n += 1 - binary.Write(buf, binary.BigEndian, d.HardwareLen) - n += 1 - binary.Write(buf, binary.BigEndian, d.HardwareOpts) - n += 1 - binary.Write(buf, binary.BigEndian, d.Xid) - n += 4 - binary.Write(buf, binary.BigEndian, d.Secs) - n += 2 - binary.Write(buf, binary.BigEndian, d.Flags) - n += 2 - binary.Write(buf, binary.BigEndian, d.ClientIP) - n += 4 - binary.Write(buf, binary.BigEndian, d.YourIP) - n += 4 - binary.Write(buf, binary.BigEndian, d.ServerIP) - n += 4 - binary.Write(buf, binary.BigEndian, d.GatewayIP) - n += 4 - clientHWAddr := make([]byte, 16) - copy(clientHWAddr[0:], d.ClientHWAddr) - binary.Write(buf, binary.BigEndian, clientHWAddr) - n += 16 - binary.Write(buf, binary.BigEndian, d.ServerName) - n += 64 - binary.Write(buf, binary.BigEndian, d.File) - n += 128 - binary.Write(buf, binary.BigEndian, dhcpMagic) - n += 4 - - optend := false - for _, opt := range d.Options { - m, err := DHCPWriteOption(buf, opt) - n += m - if err != nil { - return n, err - } - if opt.OptionType() == DHCP_OPT_END { - optend = true - } - } - if !optend { - m, err := DHCPWriteOption(buf, DHCPNewOption(DHCP_OPT_END, nil)) - n += m - if err != nil { - return n, err - } - } - if n, err = buf.Read(b); n == 0 { - return - } - return n, nil + buf := new(bytes.Buffer) + binary.Write(buf, binary.BigEndian, d.Operation) + n += 1 + binary.Write(buf, binary.BigEndian, d.HardwareType) + n += 1 + binary.Write(buf, binary.BigEndian, d.HardwareLen) + n += 1 + binary.Write(buf, binary.BigEndian, d.HardwareOpts) + n += 1 + binary.Write(buf, binary.BigEndian, d.Xid) + n += 4 + binary.Write(buf, binary.BigEndian, d.Secs) + n += 2 + binary.Write(buf, binary.BigEndian, d.Flags) + n += 2 + binary.Write(buf, binary.BigEndian, d.ClientIP) + n += 4 + binary.Write(buf, binary.BigEndian, d.YourIP) + n += 4 + binary.Write(buf, binary.BigEndian, d.ServerIP) + n += 4 + binary.Write(buf, binary.BigEndian, d.GatewayIP) + n += 4 + clientHWAddr := make([]byte, 16) + copy(clientHWAddr[0:], d.ClientHWAddr) + binary.Write(buf, binary.BigEndian, clientHWAddr) + n += 16 + binary.Write(buf, binary.BigEndian, d.ServerName) + n += 64 + binary.Write(buf, binary.BigEndian, d.File) + n += 128 + binary.Write(buf, binary.BigEndian, dhcpMagic) + n += 4 + + optend := false + for _, opt := range d.Options { + m, err := DHCPWriteOption(buf, opt) + n += m + if err != nil { + return n, err + } + if opt.OptionType() == DHCP_OPT_END { + optend = true + } + } + if !optend { + m, err := DHCPWriteOption(buf, DHCPNewOption(DHCP_OPT_END, nil)) + n += m + if err != nil { + return n, err + } + } + if n, err = buf.Read(b); n == 0 { + return + } + return n, nil } func (d *DHCP) Write(b []byte) (n int, err error) { - if len(b) < 240 { - return 0, errors.New("ErrTruncated") - } - buf := bytes.NewBuffer(b) - - if err = binary.Read(buf, binary.BigEndian, &d.Operation); err != nil { - return - } - n += 1 - if err = binary.Read(buf, binary.BigEndian, &d.HardwareType); err != nil { - return - } - n += 1 - if err = binary.Read(buf, binary.BigEndian, &d.HardwareLen); err != nil { - return - } - n += 1 - if err = binary.Read(buf, binary.BigEndian, &d.HardwareOpts); err != nil { - return - } - n += 1 - if err = binary.Read(buf, binary.BigEndian, &d.Xid); err != nil { - return - } - n += 4 - if err = binary.Read(buf, binary.BigEndian, &d.Secs); err != nil { - return - } - n += 2 - if err = binary.Read(buf, binary.BigEndian, &d.Flags); err != nil { - return - } - n += 2 - d.ClientIP = make([]byte, 4) - if err = binary.Read(buf, binary.BigEndian, &d.ClientIP); err != nil { - return - } - n += 4 - d.YourIP = make([]byte, 4) - if err = binary.Read(buf, binary.BigEndian, &d.YourIP); err != nil { - return - } - n += 4 - d.ServerIP = make([]byte, 4) - if err = binary.Read(buf, binary.BigEndian, &d.ServerIP); err != nil { - return - } - n += 4 - d.GatewayIP = make([]byte, 4) - if err = binary.Read(buf, binary.BigEndian, &d.GatewayIP); err != nil { - return - } - n += 4 - clientHWAddr := make([]byte, 16) - if err = binary.Read(buf, binary.BigEndian, &clientHWAddr); err != nil { - return - } - d.ClientHWAddr = net.HardwareAddr(clientHWAddr[:d.HardwareLen]) - n += 16 - - if err = binary.Read(buf, binary.BigEndian, &d.ServerName); err != nil { - return - } - n += 64 - if err = binary.Read(buf, binary.BigEndian, &d.File); err != nil { - return - } - n += 128 - - var magic uint32 - if err = binary.Read(buf, binary.BigEndian, &magic); err != nil { - return - } - n += 4 - - if magic != dhcpMagic { - return n, errors.New("Bad DHCP header") - } - - optlen := buf.Len() - opts := make([]byte, optlen) - if err = binary.Read(buf, binary.BigEndian, &opts); err != nil { - return - } - n += optlen - - if d.Options, err = DHCPParseOptions(opts); err != nil { - return - } - - return + if len(b) < 240 { + return 0, errors.New("ErrTruncated") + } + buf := bytes.NewBuffer(b) + + if err = binary.Read(buf, binary.BigEndian, &d.Operation); err != nil { + return + } + n += 1 + if err = binary.Read(buf, binary.BigEndian, &d.HardwareType); err != nil { + return + } + n += 1 + if err = binary.Read(buf, binary.BigEndian, &d.HardwareLen); err != nil { + return + } + n += 1 + if err = binary.Read(buf, binary.BigEndian, &d.HardwareOpts); err != nil { + return + } + n += 1 + if err = binary.Read(buf, binary.BigEndian, &d.Xid); err != nil { + return + } + n += 4 + if err = binary.Read(buf, binary.BigEndian, &d.Secs); err != nil { + return + } + n += 2 + if err = binary.Read(buf, binary.BigEndian, &d.Flags); err != nil { + return + } + n += 2 + d.ClientIP = make([]byte, 4) + if err = binary.Read(buf, binary.BigEndian, &d.ClientIP); err != nil { + return + } + n += 4 + d.YourIP = make([]byte, 4) + if err = binary.Read(buf, binary.BigEndian, &d.YourIP); err != nil { + return + } + n += 4 + d.ServerIP = make([]byte, 4) + if err = binary.Read(buf, binary.BigEndian, &d.ServerIP); err != nil { + return + } + n += 4 + d.GatewayIP = make([]byte, 4) + if err = binary.Read(buf, binary.BigEndian, &d.GatewayIP); err != nil { + return + } + n += 4 + clientHWAddr := make([]byte, 16) + if err = binary.Read(buf, binary.BigEndian, &clientHWAddr); err != nil { + return + } + d.ClientHWAddr = net.HardwareAddr(clientHWAddr[:d.HardwareLen]) + n += 16 + + if err = binary.Read(buf, binary.BigEndian, &d.ServerName); err != nil { + return + } + n += 64 + if err = binary.Read(buf, binary.BigEndian, &d.File); err != nil { + return + } + n += 128 + + var magic uint32 + if err = binary.Read(buf, binary.BigEndian, &magic); err != nil { + return + } + n += 4 + + if magic != dhcpMagic { + return n, errors.New("Bad DHCP header") + } + + optlen := buf.Len() + opts := make([]byte, optlen) + if err = binary.Read(buf, binary.BigEndian, &opts); err != nil { + return + } + n += optlen + + if d.Options, err = DHCPParseOptions(opts); err != nil { + return + } + + return } // Standard options (RFC1533) const ( - DHCP_OPT_PAD byte = iota - DHCP_OPT_SUBNET_MASK // 0x01, 4, net.IP - DHCP_OPT_TIME_OFFSET // 0x02, 4, int32 (signed seconds from UTC) - DHCP_OPT_DEFAULT_GATEWAY // 0x03, n*4, [n]net.IP - DHCP_OPT_TIME_SERVER // 0x04, n*4, [n]net.IP - DHCP_OPT_NAME_SERVER // 0x05, n*4, [n]net.IP - DHCP_OPT_DOMAIN_NAME_SERVERS // 0x06, n*4, [n]net.IP - DHCP_OPT_LOG_SERVER // 0x07, n*4, [n]net.IP - DHCP_OPT_COOKIE_SERVER // 0x08, n*4, [n]net.IP - DHCP_OPT_LPR_SERVER // 0x09, n*4, [n]net.IP - DHCP_OPT_IMPRESS_SERVER // 0x0a, n*4, [n]net.IP - DHCP_OPT_RLSERVER // 0x0b, n*4, [n]net.IP - DHCP_OPT_HOST_NAME // 0x0c, n, string - DHCP_OPT_BOOTFILE_SIZE // 0x0d, 2, uint16 - DHCP_OPT_MERIT_DUMP_FILE // 0x0e, >1, string - DHCP_OPT_DOMAIN_NAME // 0x0f, n, string - DHCP_OPT_SWAP_SERVER // 0x10, n*4, [n]net.IP - DHCP_OPT_ROOT_PATH // 0x11, n, string - DHCP_OPT_EXTENSIONS_PATH // 0x12, n, string - DHCP_OPT_IP_FORWARDING // 0x13, 1, bool - DHCP_OPT_SOURCE_ROUTING // 0x14, 1, bool - DHCP_OPT_POLICY_FILTER // 0x15, 8*n, [n]{net.IP/net.IP} - DHCP_OPT_DGRAM_MTU // 0x16, 2, uint16 - DHCP_OPT_DEFAULT_TTL // 0x17, 1, byte - DHCP_OPT_PATH_MTU_AGING_TIMEOUT // 0x18, 4, uint32 - DHCP_OPT_PATH_PLATEU_TABLE_OPTION // 0x19, 2*n, []uint16 - DHCP_OPT_INTERFACE_MTU //0x1a, 2, uint16 - DHCP_OPT_ALL_SUBS_LOCAL // 0x1b, 1, bool - DHCP_OPT_BROADCAST_ADDR // 0x1c, 4, net.IP - DHCP_OPT_MASK_DISCOVERY // 0x1d, 1, bool - DHCP_OPT_MASK_SUPPLIER // 0x1e, 1, bool - DHCP_OPT_ROUTER_DISCOVERY // 0x1f, 1, bool - DHCP_OPT_ROUTER_SOLICIT_ADDR // 0x20, 4, net.IP - DHCP_OPT_STATIC_ROUTE // 0x21, n*8, [n]{net.IP/net.IP} -- note the 2nd is router not mask - DHCP_OPT_ARP_TRAILERS // 0x22, 1, bool - DHCP_OPT_ARP_TIMEOUT // 0x23, 4, uint32 - DHCP_OPT_ETHERNET_ENCAP // 0x24, 1, bool - DHCP_OPT_TCP_TTL // 0x25,1, byte - DHCP_OPT_TCP_KEEPALIVE_INT // 0x26,4, uint32 - DHCP_OPT_TCP_KEEPALIVE_GARBAGE // 0x27,1, bool - DHCP_OPT_NIS_DOMAIN // 0x28,n, string - DHCP_OPT_NIS_SERVERS // 0x29,4*n, [n]net.IP - DHCP_OPT_NTP_SERVERS // 0x2a, 4*n, [n]net.IP - DHCP_OPT_VENDOR_OPT // 0x2b, n, [n]byte // may be encapsulated. - DHCP_OPT_NETBIOS_IPNS // 0x2c, 4*n, [n]net.IP - DHCP_OPT_NETBIOS_DDS // 0x2d, 4*n, [n]net.IP - DHCP_OPT_NETBIOS_NODE_TYPE // 0x2e, 1, magic byte - DHCP_OPT_NETBIOS_SCOPE // 0x2f, n, string - DHCP_OPT_X_FONT_SERVER // 0x30, n, string - DHCP_OPT_X_DISPLAY_MANAGER // 0x31, n, string - - DHCP_OPT_SIP_SERVERS byte = 0x78 // 0x78!, n, url - DHCP_OPT_END byte = 0xff + DHCP_OPT_PAD byte = iota + DHCP_OPT_SUBNET_MASK // 0x01, 4, net.IP + DHCP_OPT_TIME_OFFSET // 0x02, 4, int32 (signed seconds from UTC) + DHCP_OPT_DEFAULT_GATEWAY // 0x03, n*4, [n]net.IP + DHCP_OPT_TIME_SERVER // 0x04, n*4, [n]net.IP + DHCP_OPT_NAME_SERVER // 0x05, n*4, [n]net.IP + DHCP_OPT_DOMAIN_NAME_SERVERS // 0x06, n*4, [n]net.IP + DHCP_OPT_LOG_SERVER // 0x07, n*4, [n]net.IP + DHCP_OPT_COOKIE_SERVER // 0x08, n*4, [n]net.IP + DHCP_OPT_LPR_SERVER // 0x09, n*4, [n]net.IP + DHCP_OPT_IMPRESS_SERVER // 0x0a, n*4, [n]net.IP + DHCP_OPT_RLSERVER // 0x0b, n*4, [n]net.IP + DHCP_OPT_HOST_NAME // 0x0c, n, string + DHCP_OPT_BOOTFILE_SIZE // 0x0d, 2, uint16 + DHCP_OPT_MERIT_DUMP_FILE // 0x0e, >1, string + DHCP_OPT_DOMAIN_NAME // 0x0f, n, string + DHCP_OPT_SWAP_SERVER // 0x10, n*4, [n]net.IP + DHCP_OPT_ROOT_PATH // 0x11, n, string + DHCP_OPT_EXTENSIONS_PATH // 0x12, n, string + DHCP_OPT_IP_FORWARDING // 0x13, 1, bool + DHCP_OPT_SOURCE_ROUTING // 0x14, 1, bool + DHCP_OPT_POLICY_FILTER // 0x15, 8*n, [n]{net.IP/net.IP} + DHCP_OPT_DGRAM_MTU // 0x16, 2, uint16 + DHCP_OPT_DEFAULT_TTL // 0x17, 1, byte + DHCP_OPT_PATH_MTU_AGING_TIMEOUT // 0x18, 4, uint32 + DHCP_OPT_PATH_PLATEU_TABLE_OPTION // 0x19, 2*n, []uint16 + DHCP_OPT_INTERFACE_MTU //0x1a, 2, uint16 + DHCP_OPT_ALL_SUBS_LOCAL // 0x1b, 1, bool + DHCP_OPT_BROADCAST_ADDR // 0x1c, 4, net.IP + DHCP_OPT_MASK_DISCOVERY // 0x1d, 1, bool + DHCP_OPT_MASK_SUPPLIER // 0x1e, 1, bool + DHCP_OPT_ROUTER_DISCOVERY // 0x1f, 1, bool + DHCP_OPT_ROUTER_SOLICIT_ADDR // 0x20, 4, net.IP + DHCP_OPT_STATIC_ROUTE // 0x21, n*8, [n]{net.IP/net.IP} -- note the 2nd is router not mask + DHCP_OPT_ARP_TRAILERS // 0x22, 1, bool + DHCP_OPT_ARP_TIMEOUT // 0x23, 4, uint32 + DHCP_OPT_ETHERNET_ENCAP // 0x24, 1, bool + DHCP_OPT_TCP_TTL // 0x25,1, byte + DHCP_OPT_TCP_KEEPALIVE_INT // 0x26,4, uint32 + DHCP_OPT_TCP_KEEPALIVE_GARBAGE // 0x27,1, bool + DHCP_OPT_NIS_DOMAIN // 0x28,n, string + DHCP_OPT_NIS_SERVERS // 0x29,4*n, [n]net.IP + DHCP_OPT_NTP_SERVERS // 0x2a, 4*n, [n]net.IP + DHCP_OPT_VENDOR_OPT // 0x2b, n, [n]byte // may be encapsulated. + DHCP_OPT_NETBIOS_IPNS // 0x2c, 4*n, [n]net.IP + DHCP_OPT_NETBIOS_DDS // 0x2d, 4*n, [n]net.IP + DHCP_OPT_NETBIOS_NODE_TYPE // 0x2e, 1, magic byte + DHCP_OPT_NETBIOS_SCOPE // 0x2f, n, string + DHCP_OPT_X_FONT_SERVER // 0x30, n, string + DHCP_OPT_X_DISPLAY_MANAGER // 0x31, n, string + + DHCP_OPT_SIP_SERVERS byte = 0x78 // 0x78!, n, url + DHCP_OPT_END byte = 0xff ) // I'm amazed that this is syntactically valid. // cool though. var DHCPOptionTypeStrings = [256]string{ - DHCP_OPT_PAD: "(padding)", - DHCP_OPT_SUBNET_MASK: "SubnetMask", - DHCP_OPT_TIME_OFFSET: "TimeOffset", - DHCP_OPT_DEFAULT_GATEWAY: "DefaultGateway", - DHCP_OPT_TIME_SERVER: "rfc868", // old time server protocol, stringified to dissuade confusion w. NTP - DHCP_OPT_NAME_SERVER: "ien116", // obscure nameserver protocol, stringified to dissuade confusion w. DNS - DHCP_OPT_DOMAIN_NAME_SERVERS: "DNS", - DHCP_OPT_LOG_SERVER: "mitLCS", // MIT LCS server protocol, yada yada w. Syslog - DHCP_OPT_COOKIE_SERVER: "OPT_COOKIE_SERVER", - DHCP_OPT_LPR_SERVER: "OPT_LPR_SERVER", - DHCP_OPT_IMPRESS_SERVER: "OPT_IMPRESS_SERVER", - DHCP_OPT_RLSERVER: "OPT_RLSERVER", - DHCP_OPT_HOST_NAME: "Hostname", - DHCP_OPT_BOOTFILE_SIZE: "BootfileSize", - DHCP_OPT_MERIT_DUMP_FILE: "OPT_MERIT_DUMP_FILE", - DHCP_OPT_DOMAIN_NAME: "DomainName", - DHCP_OPT_SWAP_SERVER: "OPT_SWAP_SERVER", - DHCP_OPT_ROOT_PATH: "RootPath", - DHCP_OPT_EXTENSIONS_PATH: "OPT_EXTENSIONS_PATH", - DHCP_OPT_IP_FORWARDING: "OPT_IP_FORWARDING", - DHCP_OPT_SOURCE_ROUTING: "OPT_SOURCE_ROUTING", - DHCP_OPT_POLICY_FILTER: "OPT_POLICY_FILTER", - DHCP_OPT_DGRAM_MTU: "OPT_DGRAM_MTU", - DHCP_OPT_DEFAULT_TTL: "OPT_DEFAULT_TTL", - DHCP_OPT_PATH_MTU_AGING_TIMEOUT: "OPT_PATH_MTU_AGING_TIMEOUT", - DHCP_OPT_PATH_PLATEU_TABLE_OPTION: "OPT_PATH_PLATEU_TABLE_OPTION", - DHCP_OPT_INTERFACE_MTU: "OPT_INTERFACE_MTU", - DHCP_OPT_ALL_SUBS_LOCAL: "OPT_ALL_SUBS_LOCAL", - DHCP_OPT_BROADCAST_ADDR: "OPT_BROADCAST_ADDR", - DHCP_OPT_MASK_DISCOVERY: "OPT_MASK_DISCOVERY", - DHCP_OPT_MASK_SUPPLIER: "OPT_MASK_SUPPLIER", - DHCP_OPT_ROUTER_DISCOVERY: "OPT_ROUTER_DISCOVERY", - DHCP_OPT_ROUTER_SOLICIT_ADDR: "OPT_ROUTER_SOLICIT_ADDR", - DHCP_OPT_STATIC_ROUTE: "OPT_STATIC_ROUTE", - DHCP_OPT_ARP_TRAILERS: "OPT_ARP_TRAILERS", - DHCP_OPT_ARP_TIMEOUT: "OPT_ARP_TIMEOUT", - DHCP_OPT_ETHERNET_ENCAP: "OPT_ETHERNET_ENCAP", - DHCP_OPT_TCP_TTL: "OPT_TCP_TTL", - DHCP_OPT_TCP_KEEPALIVE_INT: "OPT_TCP_KEEPALIVE_INT", - DHCP_OPT_TCP_KEEPALIVE_GARBAGE: "OPT_TCP_KEEPALIVE_GARBAGE", - DHCP_OPT_NIS_DOMAIN: "OPT_NIS_DOMAIN", - DHCP_OPT_NIS_SERVERS: "OPT_NIS_SERVERS", - DHCP_OPT_NTP_SERVERS: "OPT_NTP_SERVERS", - DHCP_OPT_VENDOR_OPT: "OPT_VENDOR_OPT", - DHCP_OPT_NETBIOS_IPNS: "OPT_NETBIOS_IPNS", - DHCP_OPT_NETBIOS_DDS: "OPT_NETBIOS_DDS", - DHCP_OPT_NETBIOS_NODE_TYPE: "OPT_NETBIOS_NODE_TYPE", - DHCP_OPT_NETBIOS_SCOPE: "OPT_NETBIOS_SCOPE", - DHCP_OPT_X_FONT_SERVER: "OPT_X_FONT_SERVER", - DHCP_OPT_X_DISPLAY_MANAGER: "OPT_X_DISPLAY_MANAGER", - DHCP_OPT_END: "(end)", - DHCP_OPT_SIP_SERVERS: "SipServers", - DHCP_OPT_REQUEST_IP: "RequestIP", - DHCP_OPT_LEASE_TIME: "LeaseTime", - DHCP_OPT_EXT_OPTS: "ExtOpts", - DHCP_OPT_MESSAGE_TYPE: "MessageType", - DHCP_OPT_SERVER_ID: "ServerID", - DHCP_OPT_PARAMS_REQUEST: "ParamsRequest", - DHCP_OPT_MESSAGE: "Message", - DHCP_OPT_MAX_DHCP_SIZE: "MaxDHCPSize", - DHCP_OPT_T1: "Timer1", - DHCP_OPT_T2: "Timer2", - DHCP_OPT_CLASS_ID: "ClassID", - DHCP_OPT_CLIENT_ID: "ClientID", + DHCP_OPT_PAD: "(padding)", + DHCP_OPT_SUBNET_MASK: "SubnetMask", + DHCP_OPT_TIME_OFFSET: "TimeOffset", + DHCP_OPT_DEFAULT_GATEWAY: "DefaultGateway", + DHCP_OPT_TIME_SERVER: "rfc868", // old time server protocol, stringified to dissuade confusion w. NTP + DHCP_OPT_NAME_SERVER: "ien116", // obscure nameserver protocol, stringified to dissuade confusion w. DNS + DHCP_OPT_DOMAIN_NAME_SERVERS: "DNS", + DHCP_OPT_LOG_SERVER: "mitLCS", // MIT LCS server protocol, yada yada w. Syslog + DHCP_OPT_COOKIE_SERVER: "OPT_COOKIE_SERVER", + DHCP_OPT_LPR_SERVER: "OPT_LPR_SERVER", + DHCP_OPT_IMPRESS_SERVER: "OPT_IMPRESS_SERVER", + DHCP_OPT_RLSERVER: "OPT_RLSERVER", + DHCP_OPT_HOST_NAME: "Hostname", + DHCP_OPT_BOOTFILE_SIZE: "BootfileSize", + DHCP_OPT_MERIT_DUMP_FILE: "OPT_MERIT_DUMP_FILE", + DHCP_OPT_DOMAIN_NAME: "DomainName", + DHCP_OPT_SWAP_SERVER: "OPT_SWAP_SERVER", + DHCP_OPT_ROOT_PATH: "RootPath", + DHCP_OPT_EXTENSIONS_PATH: "OPT_EXTENSIONS_PATH", + DHCP_OPT_IP_FORWARDING: "OPT_IP_FORWARDING", + DHCP_OPT_SOURCE_ROUTING: "OPT_SOURCE_ROUTING", + DHCP_OPT_POLICY_FILTER: "OPT_POLICY_FILTER", + DHCP_OPT_DGRAM_MTU: "OPT_DGRAM_MTU", + DHCP_OPT_DEFAULT_TTL: "OPT_DEFAULT_TTL", + DHCP_OPT_PATH_MTU_AGING_TIMEOUT: "OPT_PATH_MTU_AGING_TIMEOUT", + DHCP_OPT_PATH_PLATEU_TABLE_OPTION: "OPT_PATH_PLATEU_TABLE_OPTION", + DHCP_OPT_INTERFACE_MTU: "OPT_INTERFACE_MTU", + DHCP_OPT_ALL_SUBS_LOCAL: "OPT_ALL_SUBS_LOCAL", + DHCP_OPT_BROADCAST_ADDR: "OPT_BROADCAST_ADDR", + DHCP_OPT_MASK_DISCOVERY: "OPT_MASK_DISCOVERY", + DHCP_OPT_MASK_SUPPLIER: "OPT_MASK_SUPPLIER", + DHCP_OPT_ROUTER_DISCOVERY: "OPT_ROUTER_DISCOVERY", + DHCP_OPT_ROUTER_SOLICIT_ADDR: "OPT_ROUTER_SOLICIT_ADDR", + DHCP_OPT_STATIC_ROUTE: "OPT_STATIC_ROUTE", + DHCP_OPT_ARP_TRAILERS: "OPT_ARP_TRAILERS", + DHCP_OPT_ARP_TIMEOUT: "OPT_ARP_TIMEOUT", + DHCP_OPT_ETHERNET_ENCAP: "OPT_ETHERNET_ENCAP", + DHCP_OPT_TCP_TTL: "OPT_TCP_TTL", + DHCP_OPT_TCP_KEEPALIVE_INT: "OPT_TCP_KEEPALIVE_INT", + DHCP_OPT_TCP_KEEPALIVE_GARBAGE: "OPT_TCP_KEEPALIVE_GARBAGE", + DHCP_OPT_NIS_DOMAIN: "OPT_NIS_DOMAIN", + DHCP_OPT_NIS_SERVERS: "OPT_NIS_SERVERS", + DHCP_OPT_NTP_SERVERS: "OPT_NTP_SERVERS", + DHCP_OPT_VENDOR_OPT: "OPT_VENDOR_OPT", + DHCP_OPT_NETBIOS_IPNS: "OPT_NETBIOS_IPNS", + DHCP_OPT_NETBIOS_DDS: "OPT_NETBIOS_DDS", + DHCP_OPT_NETBIOS_NODE_TYPE: "OPT_NETBIOS_NODE_TYPE", + DHCP_OPT_NETBIOS_SCOPE: "OPT_NETBIOS_SCOPE", + DHCP_OPT_X_FONT_SERVER: "OPT_X_FONT_SERVER", + DHCP_OPT_X_DISPLAY_MANAGER: "OPT_X_DISPLAY_MANAGER", + DHCP_OPT_END: "(end)", + DHCP_OPT_SIP_SERVERS: "SipServers", + DHCP_OPT_REQUEST_IP: "RequestIP", + DHCP_OPT_LEASE_TIME: "LeaseTime", + DHCP_OPT_EXT_OPTS: "ExtOpts", + DHCP_OPT_MESSAGE_TYPE: "MessageType", + DHCP_OPT_SERVER_ID: "ServerID", + DHCP_OPT_PARAMS_REQUEST: "ParamsRequest", + DHCP_OPT_MESSAGE: "Message", + DHCP_OPT_MAX_DHCP_SIZE: "MaxDHCPSize", + DHCP_OPT_T1: "Timer1", + DHCP_OPT_T2: "Timer2", + DHCP_OPT_CLASS_ID: "ClassID", + DHCP_OPT_CLIENT_ID: "ClientID", } type DHCPOption interface { - OptionType() byte - Bytes() []byte - Len() uint16 + OptionType() byte + Bytes() []byte + Len() uint16 } // Write an option to an io.Writer, including tag & length // (if length is appropriate to the tag type). // Utilizes the MarshalOption as the underlying serializer. func DHCPWriteOption(w io.Writer, a DHCPOption) (n int, err error) { - out, err := DHCPMarshalOption(a) - if err == nil { - n, err = w.Write(out) - } - return + out, err := DHCPMarshalOption(a) + if err == nil { + n, err = w.Write(out) + } + return } type dhcpoption struct { - tag byte - data []byte + tag byte + data []byte } // A more json.Marshal like version of WriteOption. func DHCPMarshalOption(o DHCPOption) (out []byte, err error) { - switch o.OptionType() { - case DHCP_OPT_PAD, DHCP_OPT_END: - out = []byte{o.OptionType()} - default: - dlen := len(o.Bytes()) - if dlen > 253 { - err = errors.New("Data too long to marshal") - } else { - out = make([]byte, dlen+2) - out[0], out[1] = o.OptionType(), byte(dlen) - copy(out[2:], o.Bytes()) - } - } - return + switch o.OptionType() { + case DHCP_OPT_PAD, DHCP_OPT_END: + out = []byte{o.OptionType()} + default: + dlen := len(o.Bytes()) + if dlen > 253 { + err = errors.New("Data too long to marshal") + } else { + out = make([]byte, dlen+2) + out[0], out[1] = o.OptionType(), byte(dlen) + copy(out[2:], o.Bytes()) + } + } + return } func (self dhcpoption) Len() uint16 { return uint16(len(self.data) + 2) } @@ -436,117 +436,117 @@ func (self dhcpoption) Bytes() []byte { return self.data } func (self dhcpoption) OptionType() byte { return self.tag } func DHCPNewOption(tag byte, data []byte) DHCPOption { - return &dhcpoption{tag: tag, data: data} + return &dhcpoption{tag: tag, data: data} } // NB: We don't validate that you have /any/ IP's in the option here, // simply that if you do that they're valid. Most DHCP options are only // valid with 1(+|) values func DHCPIP4sOption(tag byte, ips []net.IP) (opt DHCPOption, err error) { - var out []byte = make([]byte, 4*len(ips)) - for i := range ips { - ip := ips[i].To4() - if ip == nil { - err = errors.New("ip is not a valid IPv4 address") - } else { - copy(out[i*4:], []byte(ip)) - } - if err != nil { - break - } - } - opt = DHCPNewOption(tag, out) - return + var out []byte = make([]byte, 4*len(ips)) + for i := range ips { + ip := ips[i].To4() + if ip == nil { + err = errors.New("ip is not a valid IPv4 address") + } else { + copy(out[i*4:], []byte(ip)) + } + if err != nil { + break + } + } + opt = DHCPNewOption(tag, out) + return } // NB: We don't validate that you have /any/ IP's in the option here, // simply that if you do that they're valid. Most DHCP options are only // valid with 1(+|) values func DHCPIP4Option(tag byte, ips net.IP) (opt DHCPOption, err error) { - ips = ips.To4() - if ips == nil { - err = errors.New("ip is not a valid IPv4 address") - return - } - opt = DHCPNewOption(tag, []byte(ips)) - return + ips = ips.To4() + if ips == nil { + err = errors.New("ip is not a valid IPv4 address") + return + } + opt = DHCPNewOption(tag, []byte(ips)) + return } // NB: I'm not checking tag : min length here! func DHCPStringOption(tag byte, s string) (opt DHCPOption, err error) { - opt = &dhcpoption{tag: tag, data: bytes.NewBufferString(s).Bytes()} - return + opt = &dhcpoption{tag: tag, data: bytes.NewBufferString(s).Bytes()} + return } func DHCPParseOptions(in []byte) (opts []DHCPOption, err error) { - pos := 0 - for pos < len(in) && err == nil { - var tag = in[pos] - pos++ - switch tag { - case DHCP_OPT_PAD: - opts = append(opts, DHCPNewOption(tag, []byte{})) - case DHCP_OPT_END: - return - default: - if len(in)-pos >= 1 { - _len := in[pos] - pos++ - opts = append(opts, DHCPNewOption(tag, in[pos:pos+int(_len)])) - pos += int(_len) - } - } - } - return + pos := 0 + for pos < len(in) && err == nil { + var tag = in[pos] + pos++ + switch tag { + case DHCP_OPT_PAD: + opts = append(opts, DHCPNewOption(tag, []byte{})) + case DHCP_OPT_END: + return + default: + if len(in)-pos >= 1 { + _len := in[pos] + pos++ + opts = append(opts, DHCPNewOption(tag, in[pos:pos+int(_len)])) + pos += int(_len) + } + } + } + return } func NewDHCPDiscover(xid uint32, hwAddr net.HardwareAddr) (d *DHCP, err error) { - if d, err = NewDHCP(xid, DHCP_MSG_DISCOVER, DHCP_HW_ETHERNET); err != nil { - return - } - d.HardwareLen = uint8(len(hwAddr)) - d.ClientHWAddr = hwAddr - d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_DISCOVER)})) - d.Options = append(d.Options, DHCPNewOption(DHCP_OPT_CLIENT_ID, hwAddr)) - return + if d, err = NewDHCP(xid, DHCP_MSG_DISCOVER, DHCP_HW_ETHERNET); err != nil { + return + } + d.HardwareLen = uint8(len(hwAddr)) + d.ClientHWAddr = hwAddr + d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_DISCOVER)})) + d.Options = append(d.Options, DHCPNewOption(DHCP_OPT_CLIENT_ID, hwAddr)) + return } func NewDHCPOffer(xid uint32, hwAddr net.HardwareAddr) (d *DHCP, err error) { - if d, err = NewDHCP(xid, DHCP_MSG_OFFER, DHCP_HW_ETHERNET); err != nil { - return - } - d.HardwareLen = uint8(len(hwAddr)) - d.ClientHWAddr = hwAddr - d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_OFFER)})) - return + if d, err = NewDHCP(xid, DHCP_MSG_OFFER, DHCP_HW_ETHERNET); err != nil { + return + } + d.HardwareLen = uint8(len(hwAddr)) + d.ClientHWAddr = hwAddr + d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_OFFER)})) + return } func NewDHCPRequest(xid uint32, hwAddr net.HardwareAddr) (d *DHCP, err error) { - if d, err = NewDHCP(xid, DHCP_MSG_REQUEST, DHCP_HW_ETHERNET); err != nil { - return - } - d.HardwareLen = uint8(len(hwAddr)) - d.ClientHWAddr = hwAddr - d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_REQUEST)})) - return + if d, err = NewDHCP(xid, DHCP_MSG_REQUEST, DHCP_HW_ETHERNET); err != nil { + return + } + d.HardwareLen = uint8(len(hwAddr)) + d.ClientHWAddr = hwAddr + d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_REQUEST)})) + return } func NewDHCPAck(xid uint32, hwAddr net.HardwareAddr) (d *DHCP, err error) { - if d, err = NewDHCP(xid, DHCP_MSG_ACK, DHCP_HW_ETHERNET); err != nil { - return - } - d.HardwareLen = uint8(len(hwAddr)) - d.ClientHWAddr = hwAddr - d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_ACK)})) - return + if d, err = NewDHCP(xid, DHCP_MSG_ACK, DHCP_HW_ETHERNET); err != nil { + return + } + d.HardwareLen = uint8(len(hwAddr)) + d.ClientHWAddr = hwAddr + d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_ACK)})) + return } func NewDHCPNak(xid uint32, hwAddr net.HardwareAddr) (d *DHCP, err error) { - if d, err = NewDHCP(xid, DHCP_MSG_NAK, DHCP_HW_ETHERNET); err != nil { - return - } - d.HardwareLen = uint8(len(hwAddr)) - d.ClientHWAddr = hwAddr - d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_NAK)})) - return + if d, err = NewDHCP(xid, DHCP_MSG_NAK, DHCP_HW_ETHERNET); err != nil { + return + } + d.HardwareLen = uint8(len(hwAddr)) + d.ClientHWAddr = hwAddr + d.Options = append(d.Options, DHCPNewOption(53, []byte{byte(DHCP_MSG_NAK)})) + return } diff --git a/protocol/ethernet.go b/protocol/ethernet.go index 722f8ec..45d64a2 100644 --- a/protocol/ethernet.go +++ b/protocol/ethernet.go @@ -1,171 +1,171 @@ package protocol import ( - "encoding/binary" - "errors" - "net" + "encoding/binary" + "errors" + "net" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/util" ) // see http://en.wikipedia.org/wiki/EtherType const ( - IPv4_MSG = 0x0800 - ARP_MSG = 0x0806 - LLDP_MSG = 0x88cc - WOL_MSG = 0x0842 - RARP_MSG = 0x8035 - VLAN_MSG = 0x8100 - - IPv6_MSG = 0x86DD - STP_MSG = 0x4242 - STP_BPDU_MSG = 0xAAAA + IPv4_MSG = 0x0800 + ARP_MSG = 0x0806 + LLDP_MSG = 0x88cc + WOL_MSG = 0x0842 + RARP_MSG = 0x8035 + VLAN_MSG = 0x8100 + + IPv6_MSG = 0x86DD + STP_MSG = 0x4242 + STP_BPDU_MSG = 0xAAAA ) type Ethernet struct { - Delimiter uint8 - HWDst net.HardwareAddr - HWSrc net.HardwareAddr - VLANID VLAN - Ethertype uint16 - Data util.Message + Delimiter uint8 + HWDst net.HardwareAddr + HWSrc net.HardwareAddr + VLANID VLAN + Ethertype uint16 + Data util.Message } func NewEthernet() *Ethernet { - eth := new(Ethernet) - eth.HWDst = net.HardwareAddr(make([]byte, 6)) - eth.HWSrc = net.HardwareAddr(make([]byte, 6)) - eth.VLANID = *NewVLAN() - eth.Ethertype = 0x800 - eth.Data = nil - return eth + eth := new(Ethernet) + eth.HWDst = net.HardwareAddr(make([]byte, 6)) + eth.HWSrc = net.HardwareAddr(make([]byte, 6)) + eth.VLANID = *NewVLAN() + eth.Ethertype = 0x800 + eth.Data = nil + return eth } func (e *Ethernet) Len() (n uint16) { - n = 0 - n += 12 - if e.VLANID.VID != 0 { - n += 4 - } - n += 2 - if e.Data != nil { - n += e.Data.Len() - } - return + n = 0 + n += 12 + if e.VLANID.VID != 0 { + n += 4 + } + n += 2 + if e.Data != nil { + n += e.Data.Len() + } + return } func (e *Ethernet) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(e.Len())) - bytes := make([]byte, 0) - n := 0 - copy(data[n:], e.HWDst) - n += len(e.HWDst) - copy(data[n:], e.HWSrc) - n += len(e.HWSrc) - - if e.VLANID.VID != 0 { - bytes, err = e.VLANID.MarshalBinary() - if err != nil { - return - } - copy(data[n:], bytes) - n += len(bytes) - } - - binary.BigEndian.PutUint16(data[n:n+2], e.Ethertype) - n += 2 - - if e.Data != nil { - bytes, err = e.Data.MarshalBinary() - if err != nil { - return - } - copy(data[n:n+len(bytes)], bytes) - } - return + data = make([]byte, int(e.Len())) + bytes := make([]byte, 0) + n := 0 + copy(data[n:], e.HWDst) + n += len(e.HWDst) + copy(data[n:], e.HWSrc) + n += len(e.HWSrc) + + if e.VLANID.VID != 0 { + bytes, err = e.VLANID.MarshalBinary() + if err != nil { + return + } + copy(data[n:], bytes) + n += len(bytes) + } + + binary.BigEndian.PutUint16(data[n:n+2], e.Ethertype) + n += 2 + + if e.Data != nil { + bytes, err = e.Data.MarshalBinary() + if err != nil { + return + } + copy(data[n:n+len(bytes)], bytes) + } + return } func (e *Ethernet) UnmarshalBinary(data []byte) error { - if len(data) < 14 { - return errors.New("The []byte is too short to unmarshal a full Ethernet message.") - } - n := 0 - e.HWDst = net.HardwareAddr(make([]byte, 6)) - copy(e.HWDst, data[n:n+6]) - n += 6 - e.HWSrc = net.HardwareAddr(make([]byte, 6)) - copy(e.HWSrc, data[n:n+6]) - n += 6 - - e.Ethertype = binary.BigEndian.Uint16(data[n:]) - if e.Ethertype == VLAN_MSG { - e.VLANID = *new(VLAN) - err := e.VLANID.UnmarshalBinary(data[n:]) - if err != nil { - return err - } - n += int(e.VLANID.Len()) - - e.Ethertype = binary.BigEndian.Uint16(data[n:]) - } else { - e.VLANID = *new(VLAN) - e.VLANID.VID = 0 - } - n += 2 - - switch e.Ethertype { - case IPv4_MSG: - e.Data = new(IPv4) - case ARP_MSG: - e.Data = new(ARP) - default: - e.Data = new(util.Buffer) - } - return e.Data.UnmarshalBinary(data[n:]) + if len(data) < 14 { + return errors.New("The []byte is too short to unmarshal a full Ethernet message.") + } + n := 0 + e.HWDst = net.HardwareAddr(make([]byte, 6)) + copy(e.HWDst, data[n:n+6]) + n += 6 + e.HWSrc = net.HardwareAddr(make([]byte, 6)) + copy(e.HWSrc, data[n:n+6]) + n += 6 + + e.Ethertype = binary.BigEndian.Uint16(data[n:]) + if e.Ethertype == VLAN_MSG { + e.VLANID = *new(VLAN) + err := e.VLANID.UnmarshalBinary(data[n:]) + if err != nil { + return err + } + n += int(e.VLANID.Len()) + + e.Ethertype = binary.BigEndian.Uint16(data[n:]) + } else { + e.VLANID = *new(VLAN) + e.VLANID.VID = 0 + } + n += 2 + + switch e.Ethertype { + case IPv4_MSG: + e.Data = new(IPv4) + case ARP_MSG: + e.Data = new(ARP) + default: + e.Data = new(util.Buffer) + } + return e.Data.UnmarshalBinary(data[n:]) } const ( - PCP_MASK = 0xe000 - DEI_MASK = 0x1000 - VID_MASK = 0x0fff + PCP_MASK = 0xe000 + DEI_MASK = 0x1000 + VID_MASK = 0x0fff ) type VLAN struct { - TPID uint16 - PCP uint8 - DEI uint8 - VID uint16 + TPID uint16 + PCP uint8 + DEI uint8 + VID uint16 } func NewVLAN() *VLAN { - v := new(VLAN) - v.TPID = 0x8100 - v.VID = 0 - return v + v := new(VLAN) + v.TPID = 0x8100 + v.VID = 0 + return v } func (v *VLAN) Len() (n uint16) { - return 4 + return 4 } func (v *VLAN) MarshalBinary() (data []byte, err error) { - data = make([]byte, v.Len()) - binary.BigEndian.PutUint16(data[:2], v.TPID) - var tci uint16 - tci = (tci | uint16(v.PCP)<<13) + (tci | uint16(v.DEI)<<12) + (tci | v.VID) - binary.BigEndian.PutUint16(data[2:], tci) - return + data = make([]byte, v.Len()) + binary.BigEndian.PutUint16(data[:2], v.TPID) + var tci uint16 + tci = (tci | uint16(v.PCP)<<13) + (tci | uint16(v.DEI)<<12) + (tci | v.VID) + binary.BigEndian.PutUint16(data[2:], tci) + return } func (v *VLAN) UnmarshalBinary(data []byte) error { - if len(data) < 4 { - return errors.New("The []byte is too short to unmarshal a full VLAN header.") - } - v.TPID = binary.BigEndian.Uint16(data[:2]) - var tci uint16 - tci = binary.BigEndian.Uint16(data[2:]) - v.PCP = uint8(PCP_MASK & tci >> 13) - v.DEI = uint8(DEI_MASK & tci >> 12) - v.VID = VID_MASK & tci - return nil + if len(data) < 4 { + return errors.New("The []byte is too short to unmarshal a full VLAN header.") + } + v.TPID = binary.BigEndian.Uint16(data[:2]) + var tci uint16 + tci = binary.BigEndian.Uint16(data[2:]) + v.PCP = uint8(PCP_MASK & tci >> 13) + v.DEI = uint8(DEI_MASK & tci >> 12) + v.VID = VID_MASK & tci + return nil } diff --git a/protocol/icmp.go b/protocol/icmp.go index 23235ab..d942568 100644 --- a/protocol/icmp.go +++ b/protocol/icmp.go @@ -1,46 +1,46 @@ package protocol import ( - "encoding/binary" - "errors" + "encoding/binary" + "errors" ) type ICMP struct { - Type uint8 - Code uint8 - Checksum uint16 - Data []byte + Type uint8 + Code uint8 + Checksum uint16 + Data []byte } func NewICMP() *ICMP { - i := new(ICMP) - i.Data = make([]byte, 0) - return i + i := new(ICMP) + i.Data = make([]byte, 0) + return i } func (i *ICMP) Len() (n uint16) { - return uint16(4 + len(i.Data)) + return uint16(4 + len(i.Data)) } func (i *ICMP) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(i.Len())) - data[0] = i.Type - data[1] = i.Code - binary.BigEndian.PutUint16(data[2:4], i.Checksum) - copy(data[4:], i.Data) - return + data = make([]byte, int(i.Len())) + data[0] = i.Type + data[1] = i.Code + binary.BigEndian.PutUint16(data[2:4], i.Checksum) + copy(data[4:], i.Data) + return } func (i *ICMP) UnmarshalBinary(data []byte) error { - if len(data) < 4 { - return errors.New("The []byte is too short to unmarshal a full ARP message.") - } - i.Type = data[0] - i.Code = data[1] - i.Checksum = binary.BigEndian.Uint16(data[2:4]) + if len(data) < 4 { + return errors.New("The []byte is too short to unmarshal a full ARP message.") + } + i.Type = data[0] + i.Code = data[1] + i.Checksum = binary.BigEndian.Uint16(data[2:4]) - for n, _ := range data[4:] { - i.Data = append(i.Data, data[n]) - } - return nil + for n, _ := range data[4:] { + i.Data = append(i.Data, data[n]) + } + return nil } diff --git a/protocol/ip.go b/protocol/ip.go index af5799f..8c5a06e 100644 --- a/protocol/ip.go +++ b/protocol/ip.go @@ -1,150 +1,150 @@ package protocol import ( - "encoding/binary" - "errors" - "net" + "encoding/binary" + "errors" + "net" - "github.com/shaleman/libOpenflow/util" + "github.com/shaleman/libOpenflow/util" ) const ( - Type_ICMP = 0x01 - Type_TCP = 0x06 - Type_UDP = 0x11 - Type_IPv6 = 0x29 - Type_IPv6ICMP = 0x3a + Type_ICMP = 0x01 + Type_TCP = 0x06 + Type_UDP = 0x11 + Type_IPv6 = 0x29 + Type_IPv6ICMP = 0x3a ) type IPv4 struct { - Version uint8 //4-bits - IHL uint8 //4-bits - DSCP uint8 //6-bits - ECN uint8 //2-bits - Length uint16 - Id uint16 - Flags uint16 //3-bits - FragmentOffset uint16 //13-bits - TTL uint8 - Protocol uint8 - Checksum uint16 - NWSrc net.IP - NWDst net.IP - Options util.Buffer - Data util.Message + Version uint8 //4-bits + IHL uint8 //4-bits + DSCP uint8 //6-bits + ECN uint8 //2-bits + Length uint16 + Id uint16 + Flags uint16 //3-bits + FragmentOffset uint16 //13-bits + TTL uint8 + Protocol uint8 + Checksum uint16 + NWSrc net.IP + NWDst net.IP + Options util.Buffer + Data util.Message } func NewIPv4() *IPv4 { - ip := new(IPv4) - ip.NWSrc = make([]byte, 4) - ip.NWDst = make([]byte, 4) - ip.Options = *new(util.Buffer) - return ip + ip := new(IPv4) + ip.NWSrc = make([]byte, 4) + ip.NWDst = make([]byte, 4) + ip.Options = *new(util.Buffer) + return ip } func (i *IPv4) Len() (n uint16) { - i.IHL = 5 - if i.Data != nil { - return uint16(i.IHL*4) + i.Data.Len() - } - return uint16(i.IHL * 4) + i.IHL = 5 + if i.Data != nil { + return uint16(i.IHL*4) + i.Data.Len() + } + return uint16(i.IHL * 4) } func (i *IPv4) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(i.Len())) - b := make([]byte, 0) - n := 0 - - var ihl uint8 = (i.Version << 4) + i.IHL - data[n] = ihl - n += 1 - var ecn uint8 = (i.DSCP << 2) + i.ECN - data[n] = ecn - n += 1 - binary.BigEndian.PutUint16(data[n:], i.Length) - n += 2 - binary.BigEndian.PutUint16(data[n:], i.Id) - n += 2 - var flg uint16 = (i.Flags << 13) + i.FragmentOffset - binary.BigEndian.PutUint16(data[n:], flg) - n += 2 - data[n] = i.TTL - n += 1 - data[n] = i.Protocol - n += 1 - binary.BigEndian.PutUint16(data[n:], i.Checksum) - n += 2 - - copy(data[n:], i.NWSrc.To4()) - n += 4 // Underlying rep can be 16 bytes. - copy(data[n:], i.NWDst.To4()) - n += 4 // Underlying rep can be 16 bytes. - - b, err = i.Options.MarshalBinary() - copy(data[n:], b) - n += len(b) - - if i.Data != nil { - b, err = i.Data.MarshalBinary() - if err != nil { - return - } - copy(data[n:], b) - n += len(b) - } - return + data = make([]byte, int(i.Len())) + b := make([]byte, 0) + n := 0 + + var ihl uint8 = (i.Version << 4) + i.IHL + data[n] = ihl + n += 1 + var ecn uint8 = (i.DSCP << 2) + i.ECN + data[n] = ecn + n += 1 + binary.BigEndian.PutUint16(data[n:], i.Length) + n += 2 + binary.BigEndian.PutUint16(data[n:], i.Id) + n += 2 + var flg uint16 = (i.Flags << 13) + i.FragmentOffset + binary.BigEndian.PutUint16(data[n:], flg) + n += 2 + data[n] = i.TTL + n += 1 + data[n] = i.Protocol + n += 1 + binary.BigEndian.PutUint16(data[n:], i.Checksum) + n += 2 + + copy(data[n:], i.NWSrc.To4()) + n += 4 // Underlying rep can be 16 bytes. + copy(data[n:], i.NWDst.To4()) + n += 4 // Underlying rep can be 16 bytes. + + b, err = i.Options.MarshalBinary() + copy(data[n:], b) + n += len(b) + + if i.Data != nil { + b, err = i.Data.MarshalBinary() + if err != nil { + return + } + copy(data[n:], b) + n += len(b) + } + return } func (i *IPv4) UnmarshalBinary(data []byte) error { - if len(data) < 20 { - return errors.New("The []byte is too short to unmarshal a full IPv4 message.") - } - n := 0 - - var ihl uint8 - ihl = data[n] - i.Version = ihl >> 4 - i.IHL = ihl & 0x0f - n += 1 - - var ecn uint8 - ecn = data[n] - i.DSCP = ecn >> 2 - i.ECN = ecn & 0x03 - n += 1 - - i.Length = binary.BigEndian.Uint16(data[n:]) - n += 2 - i.Id = binary.BigEndian.Uint16(data[n:]) - n += 2 - - var flg uint16 - flg = binary.BigEndian.Uint16(data[n:]) - i.Flags = flg >> 13 - i.FragmentOffset = flg & 0x1fff - n += 2 - - i.TTL = data[n] - n += 1 - i.Protocol = data[n] - n += 1 - i.Checksum = binary.BigEndian.Uint16(data[n:]) - n += 2 - i.NWSrc = data[n:n+4] - n += 4 - i.NWDst = data[n:n+4] - n += 4 - - i.Options.UnmarshalBinary(data[n:int(i.IHL * 4)]) - n += int(i.IHL * 4) - n - - switch i.Protocol { - case Type_ICMP: - i.Data = NewICMP() - case Type_UDP: - i.Data = NewUDP() - default: - i.Data = new(util.Buffer) - } - return i.Data.UnmarshalBinary(data[n:]) + if len(data) < 20 { + return errors.New("The []byte is too short to unmarshal a full IPv4 message.") + } + n := 0 + + var ihl uint8 + ihl = data[n] + i.Version = ihl >> 4 + i.IHL = ihl & 0x0f + n += 1 + + var ecn uint8 + ecn = data[n] + i.DSCP = ecn >> 2 + i.ECN = ecn & 0x03 + n += 1 + + i.Length = binary.BigEndian.Uint16(data[n:]) + n += 2 + i.Id = binary.BigEndian.Uint16(data[n:]) + n += 2 + + var flg uint16 + flg = binary.BigEndian.Uint16(data[n:]) + i.Flags = flg >> 13 + i.FragmentOffset = flg & 0x1fff + n += 2 + + i.TTL = data[n] + n += 1 + i.Protocol = data[n] + n += 1 + i.Checksum = binary.BigEndian.Uint16(data[n:]) + n += 2 + i.NWSrc = data[n : n+4] + n += 4 + i.NWDst = data[n : n+4] + n += 4 + + i.Options.UnmarshalBinary(data[n:int(i.IHL*4)]) + n += int(i.IHL*4) - n + + switch i.Protocol { + case Type_ICMP: + i.Data = NewICMP() + case Type_UDP: + i.Data = NewUDP() + default: + i.Data = new(util.Buffer) + } + return i.Data.UnmarshalBinary(data[n:]) } diff --git a/protocol/lldp.go b/protocol/lldp.go index a83d15f..d169ecc 100644 --- a/protocol/lldp.go +++ b/protocol/lldp.go @@ -1,184 +1,184 @@ package protocol import ( - "bytes" - "encoding/binary" + "bytes" + "encoding/binary" ) type LLDP struct { - Chassis ChassisTLV - Port PortTLV - TTL TTLTLV + Chassis ChassisTLV + Port PortTLV + TTL TTLTLV } func (d *LLDP) Len() (n uint16) { - return 15 + return 15 } func (d *LLDP) Read(b []byte) (n int, err error) { - m, o, p := 0, 0, 0 - if m, err = d.Chassis.Read(b); m == 0 { - return - } - n += m - if o, err = d.Port.Read(b); o == 0 { - return - } - n += o - if p, err = d.Chassis.Read(b); p == 0 { - return - } - n += p - return + m, o, p := 0, 0, 0 + if m, err = d.Chassis.Read(b); m == 0 { + return + } + n += m + if o, err = d.Port.Read(b); o == 0 { + return + } + n += o + if p, err = d.Chassis.Read(b); p == 0 { + return + } + n += p + return } func (d *LLDP) Write(b []byte) (n int, err error) { - m, o, p := 0, 0, 0 - if m, err = d.Chassis.Write(b); m == 0 { - return - } - n += m - if o, err = d.Port.Write(b[n:]); o == 0 { - return - } - n += o - if p, err = d.Chassis.Write(b[n:]); p == 0 { - return - } - n += p - return + m, o, p := 0, 0, 0 + if m, err = d.Chassis.Write(b); m == 0 { + return + } + n += m + if o, err = d.Port.Write(b[n:]); o == 0 { + return + } + n += o + if p, err = d.Chassis.Write(b[n:]); p == 0 { + return + } + n += p + return } // Chassis ID subtypes const ( - _ = iota - CH_CHASSIS_COMPONENT - CH_IFACE_ALIAS - CH_PORT_COMPONENT - CH_MAC_ADDR - CH_NET_ADDR - CH_IFACE_NAME - CH_LOCAL_ASSGN + _ = iota + CH_CHASSIS_COMPONENT + CH_IFACE_ALIAS + CH_PORT_COMPONENT + CH_MAC_ADDR + CH_NET_ADDR + CH_IFACE_NAME + CH_LOCAL_ASSGN ) type ChassisTLV struct { - Type uint8 - Length uint16 - Subtype uint8 - Data []uint8 + Type uint8 + Length uint16 + Subtype uint8 + Data []uint8 } func (t *ChassisTLV) Read(b []byte) (n int, err error) { - buf := new(bytes.Buffer) - var tni uint16 = 0 - typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) - binary.Write(buf, binary.BigEndian, typeAndLen) - binary.Write(buf, binary.BigEndian, t.Subtype) - binary.Write(buf, binary.BigEndian, t.Data) - n, err = buf.Read(b) - return + buf := new(bytes.Buffer) + var tni uint16 = 0 + typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) + binary.Write(buf, binary.BigEndian, typeAndLen) + binary.Write(buf, binary.BigEndian, t.Subtype) + binary.Write(buf, binary.BigEndian, t.Data) + n, err = buf.Read(b) + return } func (t *ChassisTLV) Write(b []byte) (n int, err error) { - buf := bytes.NewBuffer(b) - var typeAndLen uint16 = 0 - if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { - return - } - n += 2 - t.Type = uint8(typeAndLen >> 9) - t.Length = uint16(uint16(0x01ff) & typeAndLen) - if err = binary.Read(buf, binary.BigEndian, &t.Subtype); err != nil { - return - } - n += 1 - t.Data = make([]uint8, t.Length) - if err = binary.Read(buf, binary.BigEndian, &t.Data); err != nil { - return - } - n += int(t.Length) - return + buf := bytes.NewBuffer(b) + var typeAndLen uint16 = 0 + if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { + return + } + n += 2 + t.Type = uint8(typeAndLen >> 9) + t.Length = uint16(uint16(0x01ff) & typeAndLen) + if err = binary.Read(buf, binary.BigEndian, &t.Subtype); err != nil { + return + } + n += 1 + t.Data = make([]uint8, t.Length) + if err = binary.Read(buf, binary.BigEndian, &t.Data); err != nil { + return + } + n += int(t.Length) + return } // Port ID subtypes const ( - _ = iota - PT_IFACE_ALIAS - PT_PORT_COMPONENT - PT_MAC_ADDR - PT_NET_ADDR - PT_IFACE_NAME - PT_CIRCUIT_ID - PT_LOCAL_ASSGN + _ = iota + PT_IFACE_ALIAS + PT_PORT_COMPONENT + PT_MAC_ADDR + PT_NET_ADDR + PT_IFACE_NAME + PT_CIRCUIT_ID + PT_LOCAL_ASSGN ) type PortTLV struct { - Type uint8 //7bits - Length uint16 //9bits - Subtype uint8 - Data []uint8 + Type uint8 //7bits + Length uint16 //9bits + Subtype uint8 + Data []uint8 } func (t *PortTLV) Read(b []byte) (n int, err error) { - buf := new(bytes.Buffer) - var tni uint16 = 0 - typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) - binary.Write(buf, binary.BigEndian, typeAndLen) - binary.Write(buf, binary.BigEndian, t.Subtype) - binary.Write(buf, binary.BigEndian, t.Data) - n, err = buf.Read(b) - return + buf := new(bytes.Buffer) + var tni uint16 = 0 + typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) + binary.Write(buf, binary.BigEndian, typeAndLen) + binary.Write(buf, binary.BigEndian, t.Subtype) + binary.Write(buf, binary.BigEndian, t.Data) + n, err = buf.Read(b) + return } func (t *PortTLV) Write(b []byte) (n int, err error) { - buf := bytes.NewBuffer(b) - var typeAndLen uint16 = 0 - if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { - return - } - n += 2 - t.Type = uint8(typeAndLen >> 9) - t.Length = uint16(uint16(0x01ff) & typeAndLen) - if err = binary.Read(buf, binary.BigEndian, &t.Subtype); err != nil { - return - } - n += 1 - t.Data = make([]uint8, t.Length) - if err = binary.Read(buf, binary.BigEndian, &t.Data); err != nil { - return - } - n += int(t.Length) - return + buf := bytes.NewBuffer(b) + var typeAndLen uint16 = 0 + if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { + return + } + n += 2 + t.Type = uint8(typeAndLen >> 9) + t.Length = uint16(uint16(0x01ff) & typeAndLen) + if err = binary.Read(buf, binary.BigEndian, &t.Subtype); err != nil { + return + } + n += 1 + t.Data = make([]uint8, t.Length) + if err = binary.Read(buf, binary.BigEndian, &t.Data); err != nil { + return + } + n += int(t.Length) + return } type TTLTLV struct { - Type uint8 //7 bits - Length uint16 //9 bits - Seconds uint16 + Type uint8 //7 bits + Length uint16 //9 bits + Seconds uint16 } func (t *TTLTLV) Read(b []byte) (n int, err error) { - buf := new(bytes.Buffer) - var tni uint16 = 0 - typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) - binary.Write(buf, binary.BigEndian, typeAndLen) - binary.Write(buf, binary.BigEndian, t.Seconds) - n, err = buf.Read(b) - return + buf := new(bytes.Buffer) + var tni uint16 = 0 + typeAndLen := (tni | uint16(t.Type)<<9) + (tni | uint16(t.Length)) + binary.Write(buf, binary.BigEndian, typeAndLen) + binary.Write(buf, binary.BigEndian, t.Seconds) + n, err = buf.Read(b) + return } func (t *TTLTLV) Write(b []byte) (n int, err error) { - buf := bytes.NewBuffer(b) - var typeAndLen uint16 = 0 - if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { - return - } - n += 2 - t.Type = uint8(typeAndLen >> 9) - t.Length = uint16(uint16(0x01ff) & typeAndLen) - if err = binary.Read(buf, binary.BigEndian, &t.Seconds); err != nil { - return - } - n += 2 - return + buf := bytes.NewBuffer(b) + var typeAndLen uint16 = 0 + if err = binary.Read(buf, binary.BigEndian, &typeAndLen); err != nil { + return + } + n += 2 + t.Type = uint8(typeAndLen >> 9) + t.Length = uint16(uint16(0x01ff) & typeAndLen) + if err = binary.Read(buf, binary.BigEndian, &t.Seconds); err != nil { + return + } + n += 2 + return } diff --git a/protocol/tcp.go b/protocol/tcp.go index 19dd6cb..f755a30 100644 --- a/protocol/tcp.go +++ b/protocol/tcp.go @@ -1,79 +1,79 @@ package protocol import ( - "errors" - "encoding/binary" + "encoding/binary" + "errors" ) type TCP struct { - PortSrc uint16 - PortDst uint16 - SeqNum uint32 - AckNum uint32 + PortSrc uint16 + PortDst uint16 + SeqNum uint32 + AckNum uint32 - HdrLen uint8 - Code uint8 + HdrLen uint8 + Code uint8 - WinSize uint16 - Checksum uint16 - UrgFlag uint16 + WinSize uint16 + Checksum uint16 + UrgFlag uint16 - Data []byte + Data []byte } func NewTCP() *TCP { - u := new(TCP) - u.Data = make([]byte, 0) - return u + u := new(TCP) + u.Data = make([]byte, 0) + return u } func (t *TCP) Len() (n uint16) { - if t.Data != nil { - return uint16(20 + len(t.Data)) - } - return uint16(20) + if t.Data != nil { + return uint16(20 + len(t.Data)) + } + return uint16(20) } func (t *TCP) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(t.Len())) - binary.BigEndian.PutUint16(data[:2], t.PortSrc) - binary.BigEndian.PutUint16(data[2:4], t.PortDst) - binary.BigEndian.PutUint32(data[4:8], t.SeqNum) - binary.BigEndian.PutUint32(data[8:12], t.AckNum) + data = make([]byte, int(t.Len())) + binary.BigEndian.PutUint16(data[:2], t.PortSrc) + binary.BigEndian.PutUint16(data[2:4], t.PortDst) + binary.BigEndian.PutUint32(data[4:8], t.SeqNum) + binary.BigEndian.PutUint32(data[8:12], t.AckNum) - data[12] = (t.HdrLen << 4) & 0xf0 - data[13] = t.Code & 0x3f + data[12] = (t.HdrLen << 4) & 0xf0 + data[13] = t.Code & 0x3f - binary.BigEndian.PutUint16(data[14:16], t.WinSize) - binary.BigEndian.PutUint16(data[16:18], t.Checksum) - binary.BigEndian.PutUint16(data[18:20], t.UrgFlag) + binary.BigEndian.PutUint16(data[14:16], t.WinSize) + binary.BigEndian.PutUint16(data[16:18], t.Checksum) + binary.BigEndian.PutUint16(data[18:20], t.UrgFlag) - copy(data[20:], t.Data) + copy(data[20:], t.Data) - return + return } func (t *TCP) UnmarshalBinary(data []byte) error { - if len(data) < 20 { - return errors.New("The []byte is too short to unmarshal a full ARP message.") - } - t.PortSrc = binary.BigEndian.Uint16(data[:2]) - t.PortDst = binary.BigEndian.Uint16(data[2:4]) - t.SeqNum = binary.BigEndian.Uint32(data[4:8]) - t.AckNum = binary.BigEndian.Uint32(data[8:12]) - - t.HdrLen = (data[12] >> 4) & 0xf - t.Code = data[13] & 0x3f - - t.WinSize = binary.BigEndian.Uint16(data[14:16]) - t.Checksum = binary.BigEndian.Uint16(data[16:18]) - t.UrgFlag = binary.BigEndian.Uint16(data[18:20]) - - if (len(data) > 20) { - t.Data = make([]byte, (len(data) - 20)) - copy(t.Data, data[20:]) - } - - return nil + if len(data) < 20 { + return errors.New("The []byte is too short to unmarshal a full ARP message.") + } + t.PortSrc = binary.BigEndian.Uint16(data[:2]) + t.PortDst = binary.BigEndian.Uint16(data[2:4]) + t.SeqNum = binary.BigEndian.Uint32(data[4:8]) + t.AckNum = binary.BigEndian.Uint32(data[8:12]) + + t.HdrLen = (data[12] >> 4) & 0xf + t.Code = data[13] & 0x3f + + t.WinSize = binary.BigEndian.Uint16(data[14:16]) + t.Checksum = binary.BigEndian.Uint16(data[16:18]) + t.UrgFlag = binary.BigEndian.Uint16(data[18:20]) + + if len(data) > 20 { + t.Data = make([]byte, (len(data) - 20)) + copy(t.Data, data[20:]) + } + + return nil } diff --git a/protocol/udp.go b/protocol/udp.go index 5352167..ad40063 100644 --- a/protocol/udp.go +++ b/protocol/udp.go @@ -1,52 +1,52 @@ package protocol import ( - "encoding/binary" - "errors" + "encoding/binary" + "errors" ) type UDP struct { - PortSrc uint16 - PortDst uint16 - Length uint16 - Checksum uint16 - Data []byte + PortSrc uint16 + PortDst uint16 + Length uint16 + Checksum uint16 + Data []byte } func NewUDP() *UDP { - u := new(UDP) - u.Data = make([]byte, 0) - return u + u := new(UDP) + u.Data = make([]byte, 0) + return u } func (u *UDP) Len() (n uint16) { - if u.Data != nil { - return uint16(8 + len(u.Data)) - } - return uint16(8) + if u.Data != nil { + return uint16(8 + len(u.Data)) + } + return uint16(8) } func (u *UDP) MarshalBinary() (data []byte, err error) { - data = make([]byte, int(u.Len())) - binary.BigEndian.PutUint16(data[:2], u.PortSrc) - binary.BigEndian.PutUint16(data[2:4], u.PortDst) - binary.BigEndian.PutUint16(data[4:6], u.Length) - binary.BigEndian.PutUint16(data[6:8], u.Checksum) - copy(data[8:], u.Data) - return + data = make([]byte, int(u.Len())) + binary.BigEndian.PutUint16(data[:2], u.PortSrc) + binary.BigEndian.PutUint16(data[2:4], u.PortDst) + binary.BigEndian.PutUint16(data[4:6], u.Length) + binary.BigEndian.PutUint16(data[6:8], u.Checksum) + copy(data[8:], u.Data) + return } func (u *UDP) UnmarshalBinary(data []byte) error { - if len(data) < 8 { - return errors.New("The []byte is too short to unmarshal a full ARP message.") - } - u.PortSrc = binary.BigEndian.Uint16(data[:2]) - u.PortDst = binary.BigEndian.Uint16(data[2:4]) - u.Length = binary.BigEndian.Uint16(data[4:6]) - u.Checksum = binary.BigEndian.Uint16(data[6:8]) + if len(data) < 8 { + return errors.New("The []byte is too short to unmarshal a full ARP message.") + } + u.PortSrc = binary.BigEndian.Uint16(data[:2]) + u.PortDst = binary.BigEndian.Uint16(data[2:4]) + u.Length = binary.BigEndian.Uint16(data[4:6]) + u.Checksum = binary.BigEndian.Uint16(data[6:8]) - for n, _ := range data[8:] { - u.Data = append(u.Data, data[n]) - } - return nil + for n, _ := range data[8:] { + u.Data = append(u.Data, data[n]) + } + return nil } diff --git a/util/stream.go b/util/stream.go index 646a0b9..e662e04 100644 --- a/util/stream.go +++ b/util/stream.go @@ -1,160 +1,159 @@ package util import ( - "encoding/binary" - "net" - "bytes" - "strings" + "bytes" + "encoding/binary" + "net" + "strings" - log "github.com/Sirupsen/logrus" + log "github.com/Sirupsen/logrus" ) - type BufferPool struct { - Empty chan *bytes.Buffer - Full chan *bytes.Buffer + Empty chan *bytes.Buffer + Full chan *bytes.Buffer } func NewBufferPool() *BufferPool { - m := new(BufferPool) - m.Empty = make(chan *bytes.Buffer, 50) - m.Full = make(chan *bytes.Buffer, 50) - - for i := 0; i < 50; i++ { - m.Empty <- bytes.NewBuffer(make([]byte, 0, 2048)) - } - return m + m := new(BufferPool) + m.Empty = make(chan *bytes.Buffer, 50) + m.Full = make(chan *bytes.Buffer, 50) + + for i := 0; i < 50; i++ { + m.Empty <- bytes.NewBuffer(make([]byte, 0, 2048)) + } + return m } // Parser interface type Parser interface { - Parse(b []byte) (message Message, err error) + Parse(b []byte) (message Message, err error) } type MessageStream struct { - conn net.Conn - pool *BufferPool - // Message parser - parser Parser - // OpenFlow Version - Version uint8 - // Channel on which to publish connection errors - Error chan error - // Channel on which to publish inbound messages - Inbound chan Message - // Channel on which to receive outbound messages - Outbound chan Message - // Channel on which to receive a shutdown command - Shutdown chan bool + conn net.Conn + pool *BufferPool + // Message parser + parser Parser + // OpenFlow Version + Version uint8 + // Channel on which to publish connection errors + Error chan error + // Channel on which to publish inbound messages + Inbound chan Message + // Channel on which to receive outbound messages + Outbound chan Message + // Channel on which to receive a shutdown command + Shutdown chan bool } // Returns a pointer to a new MessageStream. Used to parse // OpenFlow messages from conn. func NewMessageStream(conn net.Conn, parser Parser) *MessageStream { - m := &MessageStream{ - conn, - NewBufferPool(), - parser, - 0, - make(chan error, 1), // Error - make(chan Message, 1), // Inbound - make(chan Message, 1), // Outbound - make(chan bool, 1), // Shutdown - } - - go m.outbound() - go m.inbound() - - for i := 0; i < 25; i++ { - go m.parse() - } - return m + m := &MessageStream{ + conn, + NewBufferPool(), + parser, + 0, + make(chan error, 1), // Error + make(chan Message, 1), // Inbound + make(chan Message, 1), // Outbound + make(chan bool, 1), // Shutdown + } + + go m.outbound() + go m.inbound() + + for i := 0; i < 25; i++ { + go m.parse() + } + return m } func (m *MessageStream) GetAddr() net.Addr { - return m.conn.RemoteAddr() + return m.conn.RemoteAddr() } // Listen for a Shutdown signal or Outbound messages. func (m *MessageStream) outbound() { - for { - select { - case <-m.Shutdown: - log.Infof("Closing OpenFlow message stream.") - m.conn.Close() - return - case msg := <-m.Outbound: - // Forward outbound messages to conn - data, _ := msg.MarshalBinary() - if _, err := m.conn.Write(data); err != nil { - log.Warnln("OutboundError:", err) - m.Error <- err - m.Shutdown <- true - } - - log.Debugf("Sent(%d): %v", len(data), data) - } - } + for { + select { + case <-m.Shutdown: + log.Infof("Closing OpenFlow message stream.") + m.conn.Close() + return + case msg := <-m.Outbound: + // Forward outbound messages to conn + data, _ := msg.MarshalBinary() + if _, err := m.conn.Write(data); err != nil { + log.Warnln("OutboundError:", err) + m.Error <- err + m.Shutdown <- true + } + + log.Debugf("Sent(%d): %v", len(data), data) + } + } } // Handle inbound messages func (m *MessageStream) inbound() { - msg := 0 - hdr := 0 - hdrBuf := make([]byte, 4) - - tmp := make([]byte, 2048) - buf := <- m.pool.Empty - for { - n, err := m.conn.Read(tmp) - if err != nil { - // Handle explicitly disconnecting by closing connection - if strings.Contains(err.Error(), "use of closed network connection") { - return - } - log.Warnln("InboundError", err) - m.Error <- err - m.Shutdown <- true - return - } - - for i := 0; i < n; i++ { - if hdr < 4 { - hdrBuf[hdr] = tmp[i] - buf.WriteByte(tmp[i]) - hdr += 1 - if hdr >= 4 { - msg = int(binary.BigEndian.Uint16(hdrBuf[2:])) - 4 - } - continue - } - if msg > 0 { - buf.WriteByte(tmp[i]) - msg = msg - 1 - if msg == 0 { - hdr = 0 - m.pool.Full <- buf - buf = <- m.pool.Empty - } - continue - } - } - } + msg := 0 + hdr := 0 + hdrBuf := make([]byte, 4) + + tmp := make([]byte, 2048) + buf := <-m.pool.Empty + for { + n, err := m.conn.Read(tmp) + if err != nil { + // Handle explicitly disconnecting by closing connection + if strings.Contains(err.Error(), "use of closed network connection") { + return + } + log.Warnln("InboundError", err) + m.Error <- err + m.Shutdown <- true + return + } + + for i := 0; i < n; i++ { + if hdr < 4 { + hdrBuf[hdr] = tmp[i] + buf.WriteByte(tmp[i]) + hdr += 1 + if hdr >= 4 { + msg = int(binary.BigEndian.Uint16(hdrBuf[2:])) - 4 + } + continue + } + if msg > 0 { + buf.WriteByte(tmp[i]) + msg = msg - 1 + if msg == 0 { + hdr = 0 + m.pool.Full <- buf + buf = <-m.pool.Empty + } + continue + } + } + } } // Parse incoming message func (m *MessageStream) parse() { - for { - b := <- m.pool.Full - log.Debugf("Rcvd: %v", b.Bytes()) - msg, err := m.parser.Parse(b.Bytes()) - // Log all message parsing errors. - if err != nil { - log.Print(err) - } - - m.Inbound <- msg - b.Reset() - m.pool.Empty <- b - } + for { + b := <-m.pool.Full + log.Debugf("Rcvd: %v", b.Bytes()) + msg, err := m.parser.Parse(b.Bytes()) + // Log all message parsing errors. + if err != nil { + log.Print(err) + } + + m.Inbound <- msg + b.Reset() + m.pool.Empty <- b + } } diff --git a/util/util.go b/util/util.go index 908e0c8..85d96df 100644 --- a/util/util.go +++ b/util/util.go @@ -1,36 +1,36 @@ package util import ( - "bytes" + "bytes" ) type Message interface { - //encoding.BinaryMarshaler - //encoding.BinaryUnmarshaler - MarshalBinary() (data []byte, err error) - UnmarshalBinary(data []byte) error + //encoding.BinaryMarshaler + //encoding.BinaryUnmarshaler + MarshalBinary() (data []byte, err error) + UnmarshalBinary(data []byte) error - Len() uint16 + Len() uint16 } -type Buffer struct { bytes.Buffer } +type Buffer struct{ bytes.Buffer } func NewBuffer(buf []byte) *Buffer { - b := new(Buffer) - b.Buffer = *bytes.NewBuffer(buf) - return b + b := new(Buffer) + b.Buffer = *bytes.NewBuffer(buf) + return b } func (b *Buffer) Len() uint16 { - return uint16(b.Buffer.Len()) + return uint16(b.Buffer.Len()) } func (b *Buffer) MarshalBinary() (data []byte, err error) { - return b.Buffer.Bytes(), nil + return b.Buffer.Bytes(), nil } func (b *Buffer) UnmarshalBinary(data []byte) error { - b.Buffer.Reset() - _, err := b.Buffer.Write(data) - return err + b.Buffer.Reset() + _, err := b.Buffer.Write(data) + return err }