github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/common/header.go (about) 1 package common 2 3 // Package common defines OpenFlow message types that are version independent. 4 5 import ( 6 "encoding/binary" 7 "errors" 8 "sync/atomic" 9 10 "github.com/contiv/libOpenflow/util" 11 ) 12 13 var messageXid uint32 = 1 14 15 func NewHeaderGenerator(ver int) func() Header { 16 return func() Header { 17 xid := atomic.AddUint32(&messageXid, 1) 18 p := Header{uint8(ver), 0, 8, xid} 19 return p 20 } 21 } 22 23 // The version specifies the OpenFlow protocol version being 24 // used. During the current draft phase of the OpenFlow 25 // Protocol, the most significant bit will be set to indicate an 26 // experimental version and the lower bits will indicate a 27 // revision number. The current version is 0x01. The final 28 // version for a Type 0 switch will be 0x00. The length field 29 // indicates the total length of the message, so no additional 30 // framing is used to distinguish one frame from the next. 31 type Header struct { 32 Version uint8 33 Type uint8 34 Length uint16 35 Xid uint32 36 } 37 38 func (h *Header) Header() *Header { 39 return h 40 } 41 42 func (h *Header) Len() (n uint16) { 43 return 8 44 } 45 46 func (h *Header) MarshalBinary() (data []byte, err error) { 47 data = make([]byte, 8) 48 data[0] = h.Version 49 data[1] = h.Type 50 binary.BigEndian.PutUint16(data[2:4], h.Length) 51 binary.BigEndian.PutUint32(data[4:8], h.Xid) 52 return 53 } 54 55 func (h *Header) UnmarshalBinary(data []byte) error { 56 if len(data) < 4 { 57 return errors.New("The []byte is too short to unmarshel a full HelloElemHeader.") 58 } 59 h.Version = data[0] 60 h.Type = data[1] 61 h.Length = binary.BigEndian.Uint16(data[2:4]) 62 h.Xid = binary.BigEndian.Uint32(data[4:8]) 63 return nil 64 } 65 66 const ( 67 reserved = iota 68 HelloElemType_VersionBitmap 69 ) 70 71 type HelloElem interface { 72 Header() *HelloElemHeader 73 util.Message 74 } 75 76 type HelloElemHeader struct { 77 Type uint16 78 Length uint16 79 } 80 81 func NewHelloElemHeader() *HelloElemHeader { 82 h := new(HelloElemHeader) 83 h.Type = HelloElemType_VersionBitmap 84 h.Length = 4 85 return h 86 } 87 88 func (h *HelloElemHeader) Header() *HelloElemHeader { 89 return h 90 } 91 92 func (h *HelloElemHeader) Len() (n uint16) { 93 return 4 94 } 95 96 func (h *HelloElemHeader) MarshalBinary() (data []byte, err error) { 97 data = make([]byte, 4) 98 binary.BigEndian.PutUint16(data[:2], h.Type) 99 binary.BigEndian.PutUint16(data[2:4], h.Length) 100 return 101 } 102 103 func (h *HelloElemHeader) UnmarshalBinary(data []byte) error { 104 if len(data) < 4 { 105 return errors.New("The []byte is too short to unmarshal a full HelloElemHeader.") 106 } 107 h.Type = binary.BigEndian.Uint16(data[:2]) 108 h.Length = binary.BigEndian.Uint16(data[2:4]) 109 return nil 110 } 111 112 type HelloElemVersionBitmap struct { 113 HelloElemHeader 114 Bitmaps []uint32 115 } 116 117 func NewHelloElemVersionBitmap() *HelloElemVersionBitmap { 118 h := new(HelloElemVersionBitmap) 119 h.HelloElemHeader = *NewHelloElemHeader() 120 h.Bitmaps = make([]uint32, 0) 121 // 10010 meaning openflow 1.0 & 1.3 support 122 h.Bitmaps = append(h.Bitmaps, uint32(1<<4)|uint32(1<<1)) 123 h.Length = h.Length + uint16(len(h.Bitmaps)*4) 124 return h 125 } 126 127 func (h *HelloElemVersionBitmap) Header() *HelloElemHeader { 128 return &h.HelloElemHeader 129 } 130 131 func (h *HelloElemVersionBitmap) Len() (n uint16) { 132 n = h.HelloElemHeader.Len() 133 n += uint16(len(h.Bitmaps) * 4) 134 return 135 } 136 137 func (h *HelloElemVersionBitmap) MarshalBinary() (data []byte, err error) { 138 data = make([]byte, int(h.Len())) 139 bytes := make([]byte, 0) 140 next := 0 141 142 bytes, err = h.HelloElemHeader.MarshalBinary() 143 copy(data[next:], bytes) 144 next += len(bytes) 145 146 for _, m := range h.Bitmaps { 147 binary.BigEndian.PutUint32(data[next:], m) 148 next += 4 149 } 150 return 151 } 152 153 func (h *HelloElemVersionBitmap) UnmarshalBinary(data []byte) error { 154 length := len(data) 155 read := 0 156 if err := h.HelloElemHeader.UnmarshalBinary(data[:4]); err != nil { 157 return err 158 } 159 read += int(h.HelloElemHeader.Len()) 160 161 h.Bitmaps = make([]uint32, 0) 162 for read < length { 163 h.Bitmaps = append(h.Bitmaps, binary.BigEndian.Uint32(data[read:read+4])) 164 read += 4 165 } 166 return nil 167 } 168 169 // The OFPT_HELLO message consists of an OpenFlow header plus a set of variable 170 // size hello elements. The version field part of the header field (see 7.1) 171 // must be set to the highest OpenFlow switch protocol version supported by the 172 // sender (see 6.3.1). The elements field is a set of hello elements, 173 // containing optional data to inform the initial handshake of the connection. 174 // Implementations must ignore (skip) all elements of a Hello message that they 175 // do not support. 176 // The version field part of the header field (see 7.1) must be set to the 177 // highest OpenFlow switch protocol version supported by the sender (see 6.3.1). 178 // The elements field is a set of hello elements, containing optional data to 179 // inform the initial handshake of the connection. Implementations must ignore 180 // (skip) all elements of a Hello message that they do not support. 181 type Hello struct { 182 Header 183 Elements []HelloElem 184 } 185 186 func NewHello(ver int) (h *Hello, err error) { 187 h = new(Hello) 188 h.Header = NewHeaderGenerator(ver)() 189 h.Elements = make([]HelloElem, 0) 190 h.Elements = append(h.Elements, NewHelloElemVersionBitmap()) 191 192 return 193 } 194 195 func (h *Hello) Len() (n uint16) { 196 n = h.Header.Len() 197 for _, e := range h.Elements { 198 n += e.Len() 199 } 200 return 201 } 202 203 func (h *Hello) MarshalBinary() (data []byte, err error) { 204 data = make([]byte, int(h.Len())) 205 bytes := make([]byte, 0) 206 next := 0 207 208 h.Header.Length = h.Len() 209 bytes, err = h.Header.MarshalBinary() 210 copy(data[next:], bytes) 211 next += len(bytes) 212 213 for _, e := range h.Elements { 214 bytes, err = e.MarshalBinary() 215 copy(data[next:], bytes) 216 next += len(bytes) 217 } 218 return 219 } 220 221 func (h *Hello) UnmarshalBinary(data []byte) error { 222 next := 0 223 err := h.Header.UnmarshalBinary(data[next:]) 224 next += int(h.Header.Len()) 225 226 h.Elements = make([]HelloElem, 0) 227 for next < len(data) { 228 e := NewHelloElemHeader() 229 e.UnmarshalBinary(data[next:]) 230 231 switch e.Type { 232 case HelloElemType_VersionBitmap: 233 v := NewHelloElemVersionBitmap() 234 err = v.UnmarshalBinary(data[next:]) 235 next += int(v.Len()) 236 h.Elements = append(h.Elements, v) 237 } 238 } 239 return err 240 }