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  }