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 )