github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/openflow13/bundles.go (about) 1 package openflow13 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "unsafe" 7 8 "github.com/contiv/libOpenflow/util" 9 ) 10 11 // Bundle control types 12 const ( 13 OFPBCT_OPEN_REQUEST uint16 = iota 14 OFPBCT_OPEN_REPLY 15 OFPBCT_CLOSE_REQUEST 16 OFPBCT_CLOSE_REPLY 17 OFPBCT_COMMIT_REQUEST 18 OFPBCT_COMMIT_REPLY 19 OFPBCT_DISCARD_REQUEST 20 OFPBCT_DISCARD_REPLY 21 ) 22 23 // Bundle message types 24 const ( 25 Type_BundleCtrl uint32 = 2300 26 Type_BundleAdd uint32 = 2301 27 ) 28 29 // Bundle control flags 30 const ( 31 OFPBCT_ATOMIC = uint16(1 << 0) 32 OFPBCT_ORDERED = uint16(1 << 1) 33 ) 34 35 // Bundle property types 36 const ( 37 OFPBPT_EXPERIMENTER = 0xFFFF 38 ) 39 40 // Bundle error code. 41 const ( 42 BEC_UNKNOWN uint16 = 2300 /* Unspecified error. */ 43 BEC_ERERM uint16 = 2301 /* Permissions error. */ 44 BEC_BAD_ID uint16 = 2302 /* Bundle ID doesn't exist. */ 45 BEC_BUNDLE_EXIST uint16 = 2303 /* Bundle ID already exist. */ 46 BEC_BUNDLE_CLOSED uint16 = 2304 /* Bundle ID is closed. */ 47 BEC_OUT_OF_BUNDLE uint16 = 2305 /* Too many bundle IDs. */ 48 BEC_BAD_TYPE uint16 = 2306 /* Unsupported or unknown message control type. */ 49 BEC_BAD_FLAGS uint16 = 2307 /* Unsupported, unknown or inconsistent flags. */ 50 BEC_MSG_BAD_LEN uint16 = 2308 /* Length problem in included message. */ 51 BEC_MSG_BAD_XID uint16 = 2309 /* Inconsistent or duplicate XID. */ 52 BEC_MSG_UNSUP uint16 = 2310 /* Unsupported message in this bundle. */ 53 BEC_MSG_CONFLICT uint16 = 2311 /* Unsupported message combination in this bundle. */ 54 BEC_MSG_TOO_MANY uint16 = 2312 /* Can't handle this many messages in bundle. */ 55 BEC_MSG_FAILD uint16 = 2313 /* One message in bundle failed. */ 56 BEC_TIMEOUT uint16 = 2314 /* Bundle is taking too long. */ 57 BEC_BUNDLE_IN_PROCESS uint16 = 2315 /* Bundle is locking the resource. */ 58 ) 59 60 // BundleControl is a message to control the bundle. 61 type BundleControl struct { 62 BundleID uint32 63 Type uint16 64 Flags uint16 65 } 66 67 func (b *BundleControl) Len() (n uint16) { 68 return uint16(unsafe.Sizeof(b.BundleID) + unsafe.Sizeof(b.Type) + unsafe.Sizeof(b.Flags)) 69 } 70 71 func (b *BundleControl) MarshalBinary() (data []byte, err error) { 72 data = make([]byte, b.Len()) 73 n := 0 74 binary.BigEndian.PutUint32(data[n:], b.BundleID) 75 n += 4 76 binary.BigEndian.PutUint16(data[n:], b.Type) 77 n += 2 78 binary.BigEndian.PutUint16(data[n:], b.Flags) 79 n += 2 80 return 81 } 82 83 func (b *BundleControl) UnmarshalBinary(data []byte) error { 84 if len(data) < int(b.Len()) { 85 return errors.New("the []byte is too short to unmarshal a full BundleControl message") 86 } 87 n := 0 88 b.BundleID = binary.BigEndian.Uint32(data[n:]) 89 n += 4 90 b.Type = binary.BigEndian.Uint16(data[n:]) 91 n += 2 92 b.Flags = binary.BigEndian.Uint16(data[n:]) 93 n += 2 94 return nil 95 } 96 97 func NewBundleControl(bundleControl *BundleControl) *VendorHeader { 98 h := NewOfp13Header() 99 h.Type = Type_Experimenter 100 return &VendorHeader{ 101 Header: h, 102 Vendor: ONF_EXPERIMENTER_ID, 103 ExperimenterType: Type_BundleCtrl, 104 VendorData: bundleControl, 105 } 106 } 107 108 type BundlePropertyExperimenter struct { 109 Type uint16 110 Length uint16 111 ExperimenterID uint32 112 ExperimenterType uint32 113 data []byte 114 } 115 116 func (p *BundlePropertyExperimenter) Len() uint16 { 117 length := uint16(unsafe.Sizeof(p.Type) + unsafe.Sizeof(p.Length) + unsafe.Sizeof(p.ExperimenterID) + unsafe.Sizeof(p.ExperimenterType)) 118 return length + uint16(len(p.data)) 119 } 120 121 func (p *BundlePropertyExperimenter) MarshalBinary() (data []byte, err error) { 122 data = make([]byte, 0) 123 n := 0 124 binary.BigEndian.PutUint16(data[n:], p.Type) 125 n += 2 126 binary.BigEndian.PutUint16(data[n:], p.Length) 127 n += 2 128 binary.BigEndian.PutUint32(data[n:], p.ExperimenterID) 129 n += 4 130 binary.BigEndian.PutUint32(data[n:], p.ExperimenterType) 131 n += 4 132 if p.data != nil { 133 data = append(data, p.data...) 134 } 135 return 136 } 137 138 func (p *BundlePropertyExperimenter) UnmarshalBinary(data []byte) error { 139 if len(data) < int(p.Len()) { 140 return errors.New("the []byte is too short to unmarshal a full BundlePropertyExperimenter message") 141 } 142 n := 0 143 p.Type = binary.BigEndian.Uint16(data[n:]) 144 n += 2 145 p.Length = binary.BigEndian.Uint16(data[n:]) 146 n += 2 147 p.ExperimenterID = binary.BigEndian.Uint32(data[n:]) 148 n += 4 149 p.ExperimenterType = binary.BigEndian.Uint32(data[n:]) 150 n += 4 151 if len(data) < int(p.Length) { 152 p.data = data[n:] 153 } 154 return nil 155 } 156 157 func NewBundlePropertyExperimenter() *BundlePropertyExperimenter { 158 p := new(BundlePropertyExperimenter) 159 p.Type = OFPBPT_EXPERIMENTER 160 return p 161 } 162 163 // BundleAdd is a message to add supported message in the opened bundle. After all required messages are added, 164 // close the bundle and commit it. The Switch will realized added messages in the bundle. Discard the bundle after close 165 // it, if the added messages are not wanted to realize on the switch. 166 type BundleAdd struct { 167 BundleID uint32 168 pad [2]byte 169 Flags uint16 170 Message util.Message 171 Properties []BundlePropertyExperimenter 172 } 173 174 func (b *BundleAdd) Len() (n uint16) { 175 length := uint16(unsafe.Sizeof(b.BundleID) + unsafe.Sizeof(b.Flags)) 176 length += uint16(len(b.pad)) 177 length += b.Message.Len() 178 if b.Properties != nil { 179 for _, p := range b.Properties { 180 length += p.Len() 181 } 182 } 183 return length 184 } 185 186 func (b *BundleAdd) MarshalBinary() (data []byte, err error) { 187 data = make([]byte, b.Len()) 188 n := 0 189 binary.BigEndian.PutUint32(data[n:], b.BundleID) 190 n += 4 191 // skip padding headerBytes 192 n += 2 193 binary.BigEndian.PutUint16(data[n:], b.Flags) 194 n += 2 195 msgBytes, err := b.Message.MarshalBinary() 196 if err != nil { 197 return nil, err 198 } 199 copy(data[n:], msgBytes) 200 n += len(msgBytes) 201 if b.Properties != nil { 202 for _, property := range b.Properties { 203 propertyData, err := property.MarshalBinary() 204 if err != nil { 205 return data, err 206 } 207 copy(data[n:], propertyData) 208 n += len(propertyData) 209 } 210 } 211 212 return 213 } 214 215 func (b *BundleAdd) UnmarshalBinary(data []byte) error { 216 var err error 217 n := 0 218 b.BundleID = binary.BigEndian.Uint32(data[n:]) 219 n += 4 220 // skip padding bytes 221 n += 2 222 b.Flags = binary.BigEndian.Uint16(data[n:]) 223 n += 2 224 b.Message, err = Parse(data[n:]) 225 if err != nil { 226 return err 227 } 228 n += int(b.Message.Len()) 229 if n < len(data) { 230 b.Properties = make([]BundlePropertyExperimenter, 0) 231 for n < len(data) { 232 var property BundlePropertyExperimenter 233 err = property.UnmarshalBinary(data[n:]) 234 if err != nil { 235 return err 236 } 237 b.Properties = append(b.Properties, property) 238 n += int(property.Len()) 239 } 240 } 241 return err 242 } 243 244 func NewBundleAdd(bundleAdd *BundleAdd) *VendorHeader { 245 h := NewOfp13Header() 246 h.Type = Type_Experimenter 247 return &VendorHeader{ 248 Header: h, 249 Vendor: ONF_EXPERIMENTER_ID, 250 ExperimenterType: Type_BundleAdd, 251 VendorData: bundleAdd, 252 } 253 } 254 255 type VendorError struct { 256 *ErrorMsg 257 ExperimenterID uint32 258 } 259 260 func (e *VendorError) Len() uint16 { 261 return e.ErrorMsg.Len() + uint16(unsafe.Sizeof(e.ExperimenterID)) 262 } 263 264 func (e *VendorError) MarshalBinary() (data []byte, err error) { 265 data = make([]byte, int(e.Len())) 266 n := 0 267 268 headerBytes, err := e.Header.MarshalBinary() 269 copy(data[n:], headerBytes) 270 n += len(headerBytes) 271 binary.BigEndian.PutUint16(data[n:], e.Type) 272 n += 2 273 binary.BigEndian.PutUint16(data[n:], e.Code) 274 n += 2 275 binary.BigEndian.PutUint32(data[n:], e.ExperimenterID) 276 n += 4 277 headerBytes, err = e.Data.MarshalBinary() 278 copy(data[n:], headerBytes) 279 n += len(headerBytes) 280 return 281 } 282 283 func (e *VendorError) UnmarshalBinary(data []byte) error { 284 n := 0 285 e.ErrorMsg = new(ErrorMsg) 286 err := e.Header.UnmarshalBinary(data[n:]) 287 if err != nil { 288 return err 289 } 290 n += int(e.Header.Len()) 291 e.Type = binary.BigEndian.Uint16(data[n:]) 292 n += 2 293 e.Code = binary.BigEndian.Uint16(data[n:]) 294 n += 2 295 e.ExperimenterID = binary.BigEndian.Uint32(data[n:]) 296 n += 4 297 err = e.Data.UnmarshalBinary(data[n:]) 298 if err != nil { 299 return err 300 } 301 n += int(e.Data.Len()) 302 return nil 303 } 304 305 func NewBundleError() *VendorError { 306 e := new(VendorError) 307 e.ErrorMsg = NewErrorMsg() 308 e.Header = NewOfp13Header() 309 e.Type = ET_EXPERIMENTER 310 e.ExperimenterID = ONF_EXPERIMENTER_ID 311 return e 312 } 313 314 // ParseBundleError returns error according to bundle error code. 315 func ParseBundleError(errCode uint16) error { 316 switch errCode { 317 case BEC_UNKNOWN: 318 return errors.New("unknown bundle error") 319 case BEC_ERERM: 320 return errors.New("permissions error") 321 case BEC_BAD_ID: 322 return errors.New("bundle ID doesn't exist") 323 case BEC_BUNDLE_EXIST: 324 return errors.New("bundle ID already exists") 325 case BEC_BUNDLE_CLOSED: 326 return errors.New("bundle ID is closed") 327 case BEC_OUT_OF_BUNDLE: 328 return errors.New("too many bundle IDs") 329 case BEC_BAD_TYPE: 330 return errors.New("unsupported or unknown message control type") 331 case BEC_BAD_FLAGS: 332 return errors.New("unsupported, unknown or inconsistent flags") 333 case BEC_MSG_BAD_LEN: 334 return errors.New("length problem in included message") 335 case BEC_MSG_BAD_XID: 336 return errors.New("inconsistent or duplicate XID") 337 case BEC_MSG_UNSUP: 338 return errors.New("unsupported message in this bundle") 339 case BEC_MSG_CONFLICT: 340 return errors.New("unsupported message combination in this bundle") 341 case BEC_MSG_TOO_MANY: 342 return errors.New("can't handle this many messages in bundle") 343 case BEC_MSG_FAILD: 344 return errors.New("one message in bundle failed") 345 case BEC_TIMEOUT: 346 return errors.New("bundle is taking too long") 347 case BEC_BUNDLE_IN_PROCESS: 348 return errors.New("bundle is locking the resource") 349 } 350 return nil 351 }