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  }