github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/openflow13/group.go (about)

     1  package openflow13
     2  
     3  // This file has all group related defs
     4  
     5  import (
     6  	"encoding/binary"
     7  
     8  	"github.com/contiv/libOpenflow/common"
     9  	log "github.com/sirupsen/logrus"
    10  )
    11  
    12  const (
    13  	OFPG_MAX = 0xffffff00 /* Last usable group number. */
    14  	/* Fake groups. */
    15  	OFPG_ALL = 0xfffffffc /* Represents all groups for group delete commands. */
    16  	OFPG_ANY = 0xffffffff /* Wildcard group used only for flow stats requests. Selects all flows regardless of group (including flows with no group).
    17  	 */
    18  )
    19  
    20  const (
    21  	OFPGC_ADD           = 0 /* New group. */
    22  	OFPGC_MODIFY        = 1 /* Modify all matching groups. */
    23  	OFPGC_DELETE        = 2 /* Delete all matching groups. */
    24  	OFPGC_INSERT_BUCKET = 3 /* Insert action buckets to the already available
    25  	list of action buckets in a matching group */
    26  )
    27  
    28  const (
    29  	OFPGT_ALL      = 0 /* All (multicast/broadcast) group. */
    30  	OFPGT_SELECT   = 1 /* Select group. */
    31  	OFPGT_INDIRECT = 2 /* Indirect group. */
    32  	OFPGT_FF       = 3 /* Fast failover group. */
    33  )
    34  
    35  // GroupMod message
    36  type GroupMod struct {
    37  	common.Header
    38  	Command uint16   /* One of OFPGC_*. */
    39  	Type    uint8    /* One of OFPGT_*. */
    40  	pad     uint8    /* Pad to 64 bits. */
    41  	GroupId uint32   /* Group identifier. */
    42  	Buckets []Bucket /* List of buckets */
    43  }
    44  
    45  // Create a new group mode message
    46  func NewGroupMod() *GroupMod {
    47  	g := new(GroupMod)
    48  	g.Header = NewOfp13Header()
    49  	g.Header.Type = Type_GroupMod
    50  
    51  	g.Command = OFPGC_ADD
    52  	g.Type = OFPGT_ALL
    53  	g.GroupId = 0
    54  	g.Buckets = make([]Bucket, 0)
    55  	return g
    56  }
    57  
    58  // Add a bucket to group mod
    59  func (g *GroupMod) AddBucket(bkt Bucket) {
    60  	g.Buckets = append(g.Buckets, bkt)
    61  }
    62  
    63  func (g *GroupMod) Len() (n uint16) {
    64  	n = g.Header.Len()
    65  	n += 8
    66  	if g.Command == OFPGC_DELETE {
    67  		return
    68  	}
    69  
    70  	for _, b := range g.Buckets {
    71  		n += b.Len()
    72  	}
    73  
    74  	return
    75  }
    76  
    77  func (g *GroupMod) MarshalBinary() (data []byte, err error) {
    78  	g.Header.Length = g.Len()
    79  	data, err = g.Header.MarshalBinary()
    80  
    81  	bytes := make([]byte, 8)
    82  	n := 0
    83  	binary.BigEndian.PutUint16(bytes[n:], g.Command)
    84  	n += 2
    85  	bytes[n] = g.Type
    86  	n += 1
    87  	bytes[n] = g.pad
    88  	n += 1
    89  	binary.BigEndian.PutUint32(bytes[n:], g.GroupId)
    90  	n += 4
    91  	data = append(data, bytes...)
    92  
    93  	for _, bkt := range g.Buckets {
    94  		bytes, err = bkt.MarshalBinary()
    95  		data = append(data, bytes...)
    96  		log.Debugf("Groupmod bucket: %v", bytes)
    97  	}
    98  
    99  	log.Debugf("GroupMod(%d): %v", len(data), data)
   100  
   101  	return
   102  }
   103  
   104  func (g *GroupMod) UnmarshalBinary(data []byte) error {
   105  	n := 0
   106  	g.Header.UnmarshalBinary(data[n:])
   107  	n += int(g.Header.Len())
   108  
   109  	g.Command = binary.BigEndian.Uint16(data[n:])
   110  	n += 2
   111  	g.Type = data[n]
   112  	n += 1
   113  	g.pad = data[n]
   114  	n += 1
   115  	g.GroupId = binary.BigEndian.Uint32(data[n:])
   116  	n += 4
   117  
   118  	for n < int(g.Header.Length) {
   119  		bkt := new(Bucket)
   120  		bkt.UnmarshalBinary(data[n:])
   121  		g.Buckets = append(g.Buckets, *bkt)
   122  		n += int(bkt.Len())
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  type Bucket struct {
   129  	Length     uint16   /* Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. */
   130  	Weight     uint16   /* Relative weight of bucket. Only defined for select groups. */
   131  	WatchPort  uint32   /* Used for FRR groups */
   132  	WatchGroup uint32   /* Used for FRR groups */
   133  	pad        []byte   /* 4 bytes */
   134  	Actions    []Action /* zero or more actions */
   135  }
   136  
   137  // Create a new Bucket
   138  func NewBucket() *Bucket {
   139  	bkt := new(Bucket)
   140  
   141  	bkt.Weight = 0
   142  	bkt.pad = make([]byte, 4)
   143  	bkt.Actions = make([]Action, 0)
   144  	bkt.WatchPort = P_ANY
   145  	bkt.WatchGroup = OFPG_ANY
   146  	bkt.Length = bkt.Len()
   147  
   148  	return bkt
   149  }
   150  
   151  // Add an action to the bucket
   152  func (b *Bucket) AddAction(act Action) {
   153  	b.Actions = append(b.Actions, act)
   154  }
   155  
   156  func (b *Bucket) Len() (n uint16) {
   157  	n = 16
   158  
   159  	for _, a := range b.Actions {
   160  		n += a.Len()
   161  	}
   162  
   163  	// Round it to closest multiple of 8
   164  	n = ((n + 7) / 8) * 8
   165  	return
   166  }
   167  
   168  func (b *Bucket) MarshalBinary() (data []byte, err error) {
   169  	bytes := make([]byte, 16)
   170  	n := 0
   171  	b.Length = b.Len() // Calculate length first
   172  	binary.BigEndian.PutUint16(bytes[n:], b.Length)
   173  	n += 2
   174  	binary.BigEndian.PutUint16(bytes[n:], b.Weight)
   175  	n += 2
   176  	binary.BigEndian.PutUint32(bytes[n:], b.WatchPort)
   177  	n += 4
   178  	binary.BigEndian.PutUint32(bytes[n:], b.WatchGroup)
   179  	n += 4
   180  	data = append(data, bytes...)
   181  
   182  	for _, a := range b.Actions {
   183  		bytes, err = a.MarshalBinary()
   184  		data = append(data, bytes...)
   185  	}
   186  
   187  	return
   188  }
   189  
   190  func (b *Bucket) UnmarshalBinary(data []byte) error {
   191  	n := 0
   192  	b.Length = binary.BigEndian.Uint16(data[n:])
   193  	n += 2
   194  	b.Weight = binary.BigEndian.Uint16(data[n:])
   195  	n += 2
   196  	b.WatchPort = binary.BigEndian.Uint32(data[n:])
   197  	n += 4
   198  	b.WatchGroup = binary.BigEndian.Uint32(data[n:])
   199  	n += 4
   200  	n += 4 // for padding
   201  
   202  	for n < int(b.Length) {
   203  		a, err := DecodeAction(data[n:])
   204  		if err != nil {
   205  			return err
   206  		}
   207  		b.Actions = append(b.Actions, a)
   208  		n += int(a.Len())
   209  	}
   210  
   211  	return nil
   212  }