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

     1  package openflow13
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"github.com/contiv/libOpenflow/common"
     7  	log "github.com/sirupsen/logrus"
     8  )
     9  
    10  // ofp_flow_mod     1.3
    11  type FlowMod struct {
    12  	common.Header
    13  	Cookie     uint64
    14  	CookieMask uint64
    15  
    16  	TableId uint8 /* ID of the table to put the flow in */
    17  	Command uint8 /* flowmod command */
    18  
    19  	IdleTimeout uint16 /* Idle time before discarding (seconds). */
    20  	HardTimeout uint16 /* Max time before discarding (seconds). */
    21  
    22  	Priority uint16 /* Priority level of flow entry. */
    23  	BufferId uint32 /* Buffered packet to apply to */
    24  
    25  	OutPort  uint32
    26  	OutGroup uint32
    27  	Flags    uint16
    28  
    29  	pad []byte // 2bytes
    30  
    31  	Match        Match         // Fields to match
    32  	Instructions []Instruction //  Instruction set - 0 or more.
    33  }
    34  
    35  func NewFlowMod() *FlowMod {
    36  	f := new(FlowMod)
    37  	f.Header = NewOfp13Header()
    38  	f.Header.Type = Type_FlowMod
    39  	// Add a generator for f.Cookie here
    40  	f.Cookie = 0
    41  	f.CookieMask = 0
    42  
    43  	f.TableId = 0
    44  	f.Command = FC_ADD
    45  
    46  	f.IdleTimeout = 0
    47  	f.HardTimeout = 0
    48  	// Add a priority gen here
    49  	f.Priority = 1000
    50  	f.BufferId = 0xffffffff
    51  	f.OutPort = P_ANY
    52  	f.OutGroup = OFPG_ANY
    53  	f.Flags = 0
    54  
    55  	f.Match = *NewMatch()
    56  	f.Instructions = make([]Instruction, 0)
    57  	return f
    58  }
    59  
    60  func (f *FlowMod) AddInstruction(instr Instruction) {
    61  	f.Instructions = append(f.Instructions, instr)
    62  }
    63  
    64  func (f *FlowMod) Len() (n uint16) {
    65  	n = f.Header.Len()
    66  	n += 40
    67  	n += f.Match.Len()
    68  	if f.Command == FC_DELETE || f.Command == FC_DELETE_STRICT {
    69  		return
    70  	}
    71  	for _, v := range f.Instructions {
    72  		n += v.Len()
    73  	}
    74  	return
    75  }
    76  
    77  func (f *FlowMod) MarshalBinary() (data []byte, err error) {
    78  	f.Header.Length = f.Len()
    79  	data, err = f.Header.MarshalBinary()
    80  
    81  	bytes := make([]byte, 40)
    82  	n := 0
    83  	binary.BigEndian.PutUint64(bytes[n:], f.Cookie)
    84  	n += 8
    85  	binary.BigEndian.PutUint64(bytes[n:], f.CookieMask)
    86  	n += 8
    87  	bytes[n] = f.TableId
    88  	n += 1
    89  	bytes[n] = f.Command
    90  	n += 1
    91  	binary.BigEndian.PutUint16(bytes[n:], f.IdleTimeout)
    92  	n += 2
    93  	binary.BigEndian.PutUint16(bytes[n:], f.HardTimeout)
    94  	n += 2
    95  	binary.BigEndian.PutUint16(bytes[n:], f.Priority)
    96  	n += 2
    97  	binary.BigEndian.PutUint32(bytes[n:], f.BufferId)
    98  	n += 4
    99  	binary.BigEndian.PutUint32(bytes[n:], f.OutPort)
   100  	n += 4
   101  	binary.BigEndian.PutUint32(bytes[n:], f.OutPort)
   102  	n += 4
   103  	binary.BigEndian.PutUint16(bytes[n:], f.Flags)
   104  	n += 2
   105  	n += 2 // for pad
   106  	data = append(data, bytes...)
   107  
   108  	bytes, err = f.Match.MarshalBinary()
   109  	data = append(data, bytes...)
   110  
   111  	for _, instr := range f.Instructions {
   112  		bytes, err = instr.MarshalBinary()
   113  		data = append(data, bytes...)
   114  		log.Debugf("flowmod instr: %v", bytes)
   115  	}
   116  
   117  	log.Debugf("Flowmod(%d): %v", len(data), data)
   118  	return
   119  }
   120  
   121  func (f *FlowMod) UnmarshalBinary(data []byte) error {
   122  	n := 0
   123  	f.Header.UnmarshalBinary(data[n:])
   124  	n += int(f.Header.Len())
   125  
   126  	f.Cookie = binary.BigEndian.Uint64(data[n:])
   127  	n += 8
   128  	f.CookieMask = binary.BigEndian.Uint64(data[n:])
   129  	n += 8
   130  	f.TableId = data[n]
   131  	n += 1
   132  	f.Command = data[n]
   133  	n += 1
   134  	f.IdleTimeout = binary.BigEndian.Uint16(data[n:])
   135  	n += 2
   136  	f.HardTimeout = binary.BigEndian.Uint16(data[n:])
   137  	n += 2
   138  	f.Priority = binary.BigEndian.Uint16(data[n:])
   139  	n += 2
   140  	f.BufferId = binary.BigEndian.Uint32(data[n:])
   141  	n += 4
   142  	f.OutPort = binary.BigEndian.Uint32(data[n:])
   143  	n += 4
   144  	f.OutGroup = binary.BigEndian.Uint32(data[n:])
   145  	n += 4
   146  	f.Flags = binary.BigEndian.Uint16(data[n:])
   147  	n += 2
   148  	n += 2 // for pad
   149  
   150  	f.Match.UnmarshalBinary(data[n:])
   151  	n += int(f.Match.Len())
   152  
   153  	for n < int(f.Header.Length) {
   154  		instr := DecodeInstr(data[n:])
   155  		f.Instructions = append(f.Instructions, instr)
   156  		n += int(instr.Len())
   157  	}
   158  	return nil
   159  }
   160  
   161  // ofp_flow_mod_command 1.3
   162  const (
   163  	FC_ADD = iota // OFPFC_ADD = 0
   164  	FC_MODIFY
   165  	FC_MODIFY_STRICT
   166  	FC_DELETE
   167  	FC_DELETE_STRICT
   168  )
   169  
   170  // ofp_flow_mod_flags 1.3
   171  const (
   172  	FF_SEND_FLOW_REM = 1 << 0 /* Send flow removed message when flow expires or is deleted. */
   173  	FF_CHECK_OVERLAP = 1 << 1 /* Check for overlapping entries first */
   174  	FF_RESET_COUNTS  = 1 << 2 /* Reset flow packet and byte counts */
   175  	FF_NO_PKT_COUNTS = 1 << 3 /* Don’t keep track of packet count */
   176  	FF_NO_BYT_COUNTS = 1 << 4 /* Don’t keep track of byte count */
   177  )
   178  
   179  // BEGIN: ofp13 - 7.4.2
   180  type FlowRemoved struct {
   181  	common.Header
   182  	Cookie   uint64
   183  	Priority uint16
   184  	Reason   uint8
   185  	TableId  uint8
   186  
   187  	DurationSec  uint32
   188  	DurationNSec uint32
   189  
   190  	IdleTimeout uint16
   191  	HardTimeout uint16
   192  
   193  	PacketCount uint64
   194  	ByteCount   uint64
   195  
   196  	Match Match
   197  }
   198  
   199  func NewFlowRemoved() *FlowRemoved {
   200  	f := new(FlowRemoved)
   201  	f.Header = NewOfp13Header()
   202  	f.Match = *NewMatch()
   203  	return f
   204  }
   205  
   206  func (f *FlowRemoved) Len() (n uint16) {
   207  	n = f.Header.Len()
   208  	n += f.Match.Len()
   209  	n += 40
   210  	return
   211  }
   212  
   213  func (f *FlowRemoved) MarshalBinary() (data []byte, err error) {
   214  	data = make([]byte, int(f.Len()))
   215  	next := 0
   216  
   217  	bytes, err := f.Header.MarshalBinary()
   218  	copy(data[next:], bytes)
   219  	next += int(f.Header.Len())
   220  
   221  	binary.BigEndian.PutUint64(data[next:], f.Cookie)
   222  	next += 8
   223  	binary.BigEndian.PutUint16(data[next:], f.Priority)
   224  	next += 2
   225  	data[next] = f.Reason
   226  	next += 1
   227  	data[next] = f.TableId
   228  	next += 1
   229  
   230  	binary.BigEndian.PutUint32(data[next:], f.DurationSec)
   231  	next += 4
   232  	binary.BigEndian.PutUint32(data[next:], f.DurationNSec)
   233  	next += 4
   234  	binary.BigEndian.PutUint16(data[next:], f.IdleTimeout)
   235  	next += 2
   236  	binary.BigEndian.PutUint16(data[next:], f.HardTimeout)
   237  	next += 2
   238  
   239  	binary.BigEndian.PutUint64(data[next:], f.PacketCount)
   240  	next += 8
   241  	binary.BigEndian.PutUint64(data[next:], f.ByteCount)
   242  	next += 8
   243  
   244  	bytes, err = f.Match.MarshalBinary()
   245  	copy(data[next:], bytes)
   246  	next += int(f.Match.Len())
   247  	return
   248  }
   249  
   250  func (f *FlowRemoved) UnmarshalBinary(data []byte) error {
   251  	next := 0
   252  	var err error
   253  	err = f.Header.UnmarshalBinary(data[next:])
   254  	next += int(f.Header.Len())
   255  
   256  	f.Cookie = binary.BigEndian.Uint64(data[next:])
   257  	next += 8
   258  	f.Priority = binary.BigEndian.Uint16(data[next:])
   259  	next += 2
   260  	f.Reason = data[next]
   261  	next += 1
   262  	f.TableId = data[next]
   263  	next += 1
   264  	f.DurationSec = binary.BigEndian.Uint32(data[next:])
   265  	next += 4
   266  	f.DurationNSec = binary.BigEndian.Uint32(data[next:])
   267  	next += 4
   268  	f.IdleTimeout = binary.BigEndian.Uint16(data[next:])
   269  	next += 2
   270  	f.HardTimeout = binary.BigEndian.Uint16(data[next:])
   271  	next += 2
   272  	f.PacketCount = binary.BigEndian.Uint64(data[next:])
   273  	next += 8
   274  	f.ByteCount = binary.BigEndian.Uint64(data[next:])
   275  	next += 8
   276  
   277  	err = f.Match.UnmarshalBinary(data[next:])
   278  	next += int(f.Match.Len())
   279  
   280  	return err
   281  }
   282  
   283  // ofp_flow_removed_reason 1.3
   284  const (
   285  	RR_IDLE_TIMEOUT = iota /* Flow idle time exceeded idle_timeout. */
   286  	RR_HARD_TIMEOUT        /* Time exceeded hard_timeout. */
   287  	RR_DELETE              /* Evicted by a DELETE flow mod. */
   288  	RR_GROUP_DELETE        /* Group was removed. */
   289  )