blob: 2dbf52d754dd87b3a41102e29b7b6c36ca92c7cb [file] [log] [blame]
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Scott Baker355d1742019-10-24 10:57:52 -070016package flows
Matt Jeanneretcab955f2019-04-10 15:45:57 -040017
18import (
19 "bytes"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040020 "crypto/md5"
21 "fmt"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040022 "github.com/cevaris/ordered_map"
23 "github.com/gogo/protobuf/proto"
Scott Bakerf8424cc2019-10-18 11:26:50 -070024 "github.com/opencord/voltha-lib-go/pkg/log"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040025 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040026 "math/big"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040027 "strings"
28)
29
Matt Jeannereta93dbed2019-05-17 12:40:05 -040030var (
31 // Instructions shortcut
Manikkaraj kb1d51442019-07-23 10:41:02 -040032 APPLY_ACTIONS = ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS
33 WRITE_METADATA = ofp.OfpInstructionType_OFPIT_WRITE_METADATA
34 METER_ACTION = ofp.OfpInstructionType_OFPIT_METER
Matt Jeannereta93dbed2019-05-17 12:40:05 -040035
36 //OFPAT_* shortcuts
37 OUTPUT = ofp.OfpActionType_OFPAT_OUTPUT
38 COPY_TTL_OUT = ofp.OfpActionType_OFPAT_COPY_TTL_OUT
39 COPY_TTL_IN = ofp.OfpActionType_OFPAT_COPY_TTL_IN
40 SET_MPLS_TTL = ofp.OfpActionType_OFPAT_SET_MPLS_TTL
41 DEC_MPLS_TTL = ofp.OfpActionType_OFPAT_DEC_MPLS_TTL
42 PUSH_VLAN = ofp.OfpActionType_OFPAT_PUSH_VLAN
43 POP_VLAN = ofp.OfpActionType_OFPAT_POP_VLAN
44 PUSH_MPLS = ofp.OfpActionType_OFPAT_PUSH_MPLS
45 POP_MPLS = ofp.OfpActionType_OFPAT_POP_MPLS
46 SET_QUEUE = ofp.OfpActionType_OFPAT_SET_QUEUE
47 GROUP = ofp.OfpActionType_OFPAT_GROUP
48 SET_NW_TTL = ofp.OfpActionType_OFPAT_SET_NW_TTL
49 NW_TTL = ofp.OfpActionType_OFPAT_DEC_NW_TTL
50 SET_FIELD = ofp.OfpActionType_OFPAT_SET_FIELD
51 PUSH_PBB = ofp.OfpActionType_OFPAT_PUSH_PBB
52 POP_PBB = ofp.OfpActionType_OFPAT_POP_PBB
53 EXPERIMENTER = ofp.OfpActionType_OFPAT_EXPERIMENTER
54
55 //OFPXMT_OFB_* shortcuts (incomplete)
56 IN_PORT = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT
57 IN_PHY_PORT = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT
58 METADATA = ofp.OxmOfbFieldTypes_OFPXMT_OFB_METADATA
59 ETH_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST
60 ETH_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC
61 ETH_TYPE = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE
62 VLAN_VID = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID
63 VLAN_PCP = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP
64 IP_DSCP = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_DSCP
65 IP_ECN = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_ECN
66 IP_PROTO = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO
67 IPV4_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC
68 IPV4_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST
69 TCP_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TCP_SRC
70 TCP_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TCP_DST
71 UDP_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC
72 UDP_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST
73 SCTP_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_SCTP_SRC
74 SCTP_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_SCTP_DST
75 ICMPV4_TYPE = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV4_TYPE
76 ICMPV4_CODE = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV4_CODE
77 ARP_OP = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_OP
78 ARP_SPA = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_SPA
79 ARP_TPA = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_TPA
80 ARP_SHA = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_SHA
81 ARP_THA = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ARP_THA
82 IPV6_SRC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_SRC
83 IPV6_DST = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_DST
84 IPV6_FLABEL = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_FLABEL
85 ICMPV6_TYPE = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV6_TYPE
86 ICMPV6_CODE = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ICMPV6_CODE
87 IPV6_ND_TARGET = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_TARGET
88 OFB_IPV6_ND_SLL = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_SLL
89 IPV6_ND_TLL = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_ND_TLL
90 MPLS_LABEL = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_LABEL
91 MPLS_TC = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_TC
92 MPLS_BOS = ofp.OxmOfbFieldTypes_OFPXMT_OFB_MPLS_BOS
93 PBB_ISID = ofp.OxmOfbFieldTypes_OFPXMT_OFB_PBB_ISID
94 TUNNEL_ID = ofp.OxmOfbFieldTypes_OFPXMT_OFB_TUNNEL_ID
95 IPV6_EXTHDR = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV6_EXTHDR
96)
97
98//ofp_action_* shortcuts
99
100func Output(port uint32, maxLen ...ofp.OfpControllerMaxLen) *ofp.OfpAction {
101 maxLength := ofp.OfpControllerMaxLen_OFPCML_MAX
102 if len(maxLen) > 0 {
103 maxLength = maxLen[0]
104 }
105 return &ofp.OfpAction{Type: OUTPUT, Action: &ofp.OfpAction_Output{Output: &ofp.OfpActionOutput{Port: port, MaxLen: uint32(maxLength)}}}
106}
107
108func MplsTtl(ttl uint32) *ofp.OfpAction {
109 return &ofp.OfpAction{Type: SET_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: ttl}}}
110}
111
112func PushVlan(ethType uint32) *ofp.OfpAction {
113 return &ofp.OfpAction{Type: PUSH_VLAN, Action: &ofp.OfpAction_Push{Push: &ofp.OfpActionPush{Ethertype: ethType}}}
114}
115
116func PopVlan() *ofp.OfpAction {
117 return &ofp.OfpAction{Type: POP_VLAN}
118}
119
120func PopMpls(ethType uint32) *ofp.OfpAction {
121 return &ofp.OfpAction{Type: POP_MPLS, Action: &ofp.OfpAction_PopMpls{PopMpls: &ofp.OfpActionPopMpls{Ethertype: ethType}}}
122}
123
124func Group(groupId uint32) *ofp.OfpAction {
125 return &ofp.OfpAction{Type: GROUP, Action: &ofp.OfpAction_Group{Group: &ofp.OfpActionGroup{GroupId: groupId}}}
126}
127
128func NwTtl(nwTtl uint32) *ofp.OfpAction {
129 return &ofp.OfpAction{Type: NW_TTL, Action: &ofp.OfpAction_NwTtl{NwTtl: &ofp.OfpActionNwTtl{NwTtl: nwTtl}}}
130}
131
132func SetField(field *ofp.OfpOxmOfbField) *ofp.OfpAction {
133 actionSetField := &ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: &ofp.OfpOxmField_OfbField{OfbField: field}}
134 return &ofp.OfpAction{Type: SET_FIELD, Action: &ofp.OfpAction_SetField{SetField: &ofp.OfpActionSetField{Field: actionSetField}}}
135}
136
137func Experimenter(experimenter uint32, data []byte) *ofp.OfpAction {
138 return &ofp.OfpAction{Type: EXPERIMENTER, Action: &ofp.OfpAction_Experimenter{Experimenter: &ofp.OfpActionExperimenter{Experimenter: experimenter, Data: data}}}
139}
140
141//ofb_field generators (incomplete set)
142
143func InPort(inPort uint32) *ofp.OfpOxmOfbField {
144 return &ofp.OfpOxmOfbField{Type: IN_PORT, Value: &ofp.OfpOxmOfbField_Port{Port: inPort}}
145}
146
147func InPhyPort(inPhyPort uint32) *ofp.OfpOxmOfbField {
148 return &ofp.OfpOxmOfbField{Type: IN_PHY_PORT, Value: &ofp.OfpOxmOfbField_Port{Port: inPhyPort}}
149}
150
151func Metadata_ofp(tableMetadata uint64) *ofp.OfpOxmOfbField {
152 return &ofp.OfpOxmOfbField{Type: METADATA, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: tableMetadata}}
153}
154
155// should Metadata_ofp used here ?????
156func EthDst(ethDst uint64) *ofp.OfpOxmOfbField {
157 return &ofp.OfpOxmOfbField{Type: ETH_DST, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: ethDst}}
158}
159
160// should Metadata_ofp used here ?????
161func EthSrc(ethSrc uint64) *ofp.OfpOxmOfbField {
162 return &ofp.OfpOxmOfbField{Type: ETH_SRC, Value: &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: ethSrc}}
163}
164
165func EthType(ethType uint32) *ofp.OfpOxmOfbField {
166 return &ofp.OfpOxmOfbField{Type: ETH_TYPE, Value: &ofp.OfpOxmOfbField_EthType{EthType: ethType}}
167}
168
169func VlanVid(vlanVid uint32) *ofp.OfpOxmOfbField {
170 return &ofp.OfpOxmOfbField{Type: VLAN_VID, Value: &ofp.OfpOxmOfbField_VlanVid{VlanVid: vlanVid}}
171}
172
173func VlanPcp(vlanPcp uint32) *ofp.OfpOxmOfbField {
174 return &ofp.OfpOxmOfbField{Type: VLAN_PCP, Value: &ofp.OfpOxmOfbField_VlanPcp{VlanPcp: vlanPcp}}
175}
176
177func IpDscp(ipDscp uint32) *ofp.OfpOxmOfbField {
178 return &ofp.OfpOxmOfbField{Type: IP_DSCP, Value: &ofp.OfpOxmOfbField_IpDscp{IpDscp: ipDscp}}
179}
180
181func IpEcn(ipEcn uint32) *ofp.OfpOxmOfbField {
182 return &ofp.OfpOxmOfbField{Type: IP_ECN, Value: &ofp.OfpOxmOfbField_IpEcn{IpEcn: ipEcn}}
183}
184
185func IpProto(ipProto uint32) *ofp.OfpOxmOfbField {
186 return &ofp.OfpOxmOfbField{Type: IP_PROTO, Value: &ofp.OfpOxmOfbField_IpProto{IpProto: ipProto}}
187}
188
189func Ipv4Src(ipv4Src uint32) *ofp.OfpOxmOfbField {
190 return &ofp.OfpOxmOfbField{Type: IPV4_SRC, Value: &ofp.OfpOxmOfbField_Ipv4Src{Ipv4Src: ipv4Src}}
191}
192
193func Ipv4Dst(ipv4Dst uint32) *ofp.OfpOxmOfbField {
194 return &ofp.OfpOxmOfbField{Type: IPV4_DST, Value: &ofp.OfpOxmOfbField_Ipv4Dst{Ipv4Dst: ipv4Dst}}
195}
196
197func TcpSrc(tcpSrc uint32) *ofp.OfpOxmOfbField {
198 return &ofp.OfpOxmOfbField{Type: TCP_SRC, Value: &ofp.OfpOxmOfbField_TcpSrc{TcpSrc: tcpSrc}}
199}
200
201func TcpDst(tcpDst uint32) *ofp.OfpOxmOfbField {
202 return &ofp.OfpOxmOfbField{Type: TCP_DST, Value: &ofp.OfpOxmOfbField_TcpDst{TcpDst: tcpDst}}
203}
204
205func UdpSrc(udpSrc uint32) *ofp.OfpOxmOfbField {
206 return &ofp.OfpOxmOfbField{Type: UDP_SRC, Value: &ofp.OfpOxmOfbField_UdpSrc{UdpSrc: udpSrc}}
207}
208
209func UdpDst(udpDst uint32) *ofp.OfpOxmOfbField {
210 return &ofp.OfpOxmOfbField{Type: UDP_DST, Value: &ofp.OfpOxmOfbField_UdpDst{UdpDst: udpDst}}
211}
212
213func SctpSrc(sctpSrc uint32) *ofp.OfpOxmOfbField {
214 return &ofp.OfpOxmOfbField{Type: SCTP_SRC, Value: &ofp.OfpOxmOfbField_SctpSrc{SctpSrc: sctpSrc}}
215}
216
217func SctpDst(sctpDst uint32) *ofp.OfpOxmOfbField {
218 return &ofp.OfpOxmOfbField{Type: SCTP_DST, Value: &ofp.OfpOxmOfbField_SctpDst{SctpDst: sctpDst}}
219}
220
221func Icmpv4Type(icmpv4Type uint32) *ofp.OfpOxmOfbField {
222 return &ofp.OfpOxmOfbField{Type: ICMPV4_TYPE, Value: &ofp.OfpOxmOfbField_Icmpv4Type{Icmpv4Type: icmpv4Type}}
223}
224
225func Icmpv4Code(icmpv4Code uint32) *ofp.OfpOxmOfbField {
226 return &ofp.OfpOxmOfbField{Type: ICMPV4_CODE, Value: &ofp.OfpOxmOfbField_Icmpv4Code{Icmpv4Code: icmpv4Code}}
227}
228
229func ArpOp(arpOp uint32) *ofp.OfpOxmOfbField {
230 return &ofp.OfpOxmOfbField{Type: ARP_OP, Value: &ofp.OfpOxmOfbField_ArpOp{ArpOp: arpOp}}
231}
232
233func ArpSpa(arpSpa uint32) *ofp.OfpOxmOfbField {
234 return &ofp.OfpOxmOfbField{Type: ARP_SPA, Value: &ofp.OfpOxmOfbField_ArpSpa{ArpSpa: arpSpa}}
235}
236
237func ArpTpa(arpTpa uint32) *ofp.OfpOxmOfbField {
238 return &ofp.OfpOxmOfbField{Type: ARP_TPA, Value: &ofp.OfpOxmOfbField_ArpTpa{ArpTpa: arpTpa}}
239}
240
241func ArpSha(arpSha []byte) *ofp.OfpOxmOfbField {
242 return &ofp.OfpOxmOfbField{Type: ARP_SHA, Value: &ofp.OfpOxmOfbField_ArpSha{ArpSha: arpSha}}
243}
244
245func ArpTha(arpTha []byte) *ofp.OfpOxmOfbField {
246 return &ofp.OfpOxmOfbField{Type: ARP_THA, Value: &ofp.OfpOxmOfbField_ArpTha{ArpTha: arpTha}}
247}
248
249func Ipv6Src(ipv6Src []byte) *ofp.OfpOxmOfbField {
250 return &ofp.OfpOxmOfbField{Type: IPV6_SRC, Value: &ofp.OfpOxmOfbField_Ipv6Src{Ipv6Src: ipv6Src}}
251}
252
253func Ipv6Dst(ipv6Dst []byte) *ofp.OfpOxmOfbField {
254 return &ofp.OfpOxmOfbField{Type: IPV6_DST, Value: &ofp.OfpOxmOfbField_Ipv6Dst{Ipv6Dst: ipv6Dst}}
255}
256
257func Ipv6Flabel(ipv6Flabel uint32) *ofp.OfpOxmOfbField {
258 return &ofp.OfpOxmOfbField{Type: IPV6_FLABEL, Value: &ofp.OfpOxmOfbField_Ipv6Flabel{Ipv6Flabel: ipv6Flabel}}
259}
260
261func Icmpv6Type(icmpv6Type uint32) *ofp.OfpOxmOfbField {
262 return &ofp.OfpOxmOfbField{Type: ICMPV6_TYPE, Value: &ofp.OfpOxmOfbField_Icmpv6Type{Icmpv6Type: icmpv6Type}}
263}
264
265func Icmpv6Code(icmpv6Code uint32) *ofp.OfpOxmOfbField {
266 return &ofp.OfpOxmOfbField{Type: ICMPV6_CODE, Value: &ofp.OfpOxmOfbField_Icmpv6Code{Icmpv6Code: icmpv6Code}}
267}
268
269func Ipv6NdTarget(ipv6NdTarget []byte) *ofp.OfpOxmOfbField {
270 return &ofp.OfpOxmOfbField{Type: IPV6_ND_TARGET, Value: &ofp.OfpOxmOfbField_Ipv6NdTarget{Ipv6NdTarget: ipv6NdTarget}}
271}
272
273func OfbIpv6NdSll(ofbIpv6NdSll []byte) *ofp.OfpOxmOfbField {
274 return &ofp.OfpOxmOfbField{Type: OFB_IPV6_ND_SLL, Value: &ofp.OfpOxmOfbField_Ipv6NdSsl{Ipv6NdSsl: ofbIpv6NdSll}}
275}
276
277func Ipv6NdTll(ipv6NdTll []byte) *ofp.OfpOxmOfbField {
278 return &ofp.OfpOxmOfbField{Type: IPV6_ND_TLL, Value: &ofp.OfpOxmOfbField_Ipv6NdTll{Ipv6NdTll: ipv6NdTll}}
279}
280
281func MplsLabel(mplsLabel uint32) *ofp.OfpOxmOfbField {
282 return &ofp.OfpOxmOfbField{Type: MPLS_LABEL, Value: &ofp.OfpOxmOfbField_MplsLabel{MplsLabel: mplsLabel}}
283}
284
285func MplsTc(mplsTc uint32) *ofp.OfpOxmOfbField {
286 return &ofp.OfpOxmOfbField{Type: MPLS_TC, Value: &ofp.OfpOxmOfbField_MplsTc{MplsTc: mplsTc}}
287}
288
289func MplsBos(mplsBos uint32) *ofp.OfpOxmOfbField {
290 return &ofp.OfpOxmOfbField{Type: MPLS_BOS, Value: &ofp.OfpOxmOfbField_MplsBos{MplsBos: mplsBos}}
291}
292
293func PbbIsid(pbbIsid uint32) *ofp.OfpOxmOfbField {
294 return &ofp.OfpOxmOfbField{Type: PBB_ISID, Value: &ofp.OfpOxmOfbField_PbbIsid{PbbIsid: pbbIsid}}
295}
296
297func TunnelId(tunnelId uint64) *ofp.OfpOxmOfbField {
298 return &ofp.OfpOxmOfbField{Type: TUNNEL_ID, Value: &ofp.OfpOxmOfbField_TunnelId{TunnelId: tunnelId}}
299}
300
301func Ipv6Exthdr(ipv6Exthdr uint32) *ofp.OfpOxmOfbField {
302 return &ofp.OfpOxmOfbField{Type: IPV6_EXTHDR, Value: &ofp.OfpOxmOfbField_Ipv6Exthdr{Ipv6Exthdr: ipv6Exthdr}}
303}
304
305//frequently used extractors
306
307func excludeAction(action *ofp.OfpAction, exclude ...ofp.OfpActionType) bool {
308 for _, actionToExclude := range exclude {
309 if action.Type == actionToExclude {
310 return true
311 }
312 }
313 return false
314}
315
316func GetActions(flow *ofp.OfpFlowStats, exclude ...ofp.OfpActionType) []*ofp.OfpAction {
317 if flow == nil {
318 return nil
319 }
320 for _, instruction := range flow.Instructions {
321 if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
322 instActions := instruction.GetActions()
323 if instActions == nil {
324 return nil
325 }
326 if len(exclude) == 0 {
327 return instActions.Actions
328 } else {
329 filteredAction := make([]*ofp.OfpAction, 0)
330 for _, action := range instActions.Actions {
331 if !excludeAction(action, exclude...) {
332 filteredAction = append(filteredAction, action)
333 }
334 }
335 return filteredAction
336 }
337 }
338 }
339 return nil
340}
341
342func UpdateOutputPortByActionType(flow *ofp.OfpFlowStats, actionType uint32, toPort uint32) *ofp.OfpFlowStats {
343 if flow == nil {
344 return nil
345 }
346 nFlow := (proto.Clone(flow)).(*ofp.OfpFlowStats)
347 nFlow.Instructions = nil
348 nInsts := make([]*ofp.OfpInstruction, 0)
349 for _, instruction := range flow.Instructions {
350 if instruction.Type == actionType {
351 instActions := instruction.GetActions()
352 if instActions == nil {
353 return nil
354 }
355 nActions := make([]*ofp.OfpAction, 0)
356 for _, action := range instActions.Actions {
357 if action.GetOutput() != nil {
358 nActions = append(nActions, Output(toPort))
359 } else {
360 nActions = append(nActions, action)
361 }
362 }
363 instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: nActions}}
364 nInsts = append(nInsts, &ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction})
365 } else {
366 nInsts = append(nInsts, instruction)
367 }
368 }
369 nFlow.Instructions = nInsts
370 return nFlow
371}
372
373func excludeOxmOfbField(field *ofp.OfpOxmOfbField, exclude ...ofp.OxmOfbFieldTypes) bool {
374 for _, fieldToExclude := range exclude {
375 if field.Type == fieldToExclude {
376 return true
377 }
378 }
379 return false
380}
381
382func GetOfbFields(flow *ofp.OfpFlowStats, exclude ...ofp.OxmOfbFieldTypes) []*ofp.OfpOxmOfbField {
383 if flow == nil || flow.Match == nil || flow.Match.Type != ofp.OfpMatchType_OFPMT_OXM {
384 return nil
385 }
386 ofbFields := make([]*ofp.OfpOxmOfbField, 0)
387 for _, field := range flow.Match.OxmFields {
388 if field.OxmClass == ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
389 ofbFields = append(ofbFields, field.GetOfbField())
390 }
391 }
392 if len(exclude) == 0 {
393 return ofbFields
394 } else {
395 filteredFields := make([]*ofp.OfpOxmOfbField, 0)
396 for _, ofbField := range ofbFields {
397 if !excludeOxmOfbField(ofbField, exclude...) {
398 filteredFields = append(filteredFields, ofbField)
399 }
400 }
401 return filteredFields
402 }
403}
404
405func GetPacketOutPort(packet *ofp.OfpPacketOut) uint32 {
406 if packet == nil {
407 return 0
408 }
409 for _, action := range packet.GetActions() {
410 if action.Type == OUTPUT {
411 return action.GetOutput().Port
412 }
413 }
414 return 0
415}
416
417func GetOutPort(flow *ofp.OfpFlowStats) uint32 {
418 if flow == nil {
419 return 0
420 }
421 for _, action := range GetActions(flow) {
422 if action.Type == OUTPUT {
423 out := action.GetOutput()
424 if out == nil {
425 return 0
426 }
427 return out.GetPort()
428 }
429 }
430 return 0
431}
432
433func GetInPort(flow *ofp.OfpFlowStats) uint32 {
434 if flow == nil {
435 return 0
436 }
437 for _, field := range GetOfbFields(flow) {
438 if field.Type == IN_PORT {
439 return field.GetPort()
440 }
441 }
442 return 0
443}
444
445func GetGotoTableId(flow *ofp.OfpFlowStats) uint32 {
446 if flow == nil {
447 return 0
448 }
449 for _, instruction := range flow.Instructions {
450 if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE) {
451 gotoTable := instruction.GetGotoTable()
452 if gotoTable == nil {
453 return 0
454 }
455 return gotoTable.GetTableId()
456 }
457 }
458 return 0
459}
460
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461func GetMeterId(flow *ofp.OfpFlowStats) uint32 {
462 if flow == nil {
463 return 0
464 }
465 for _, instruction := range flow.Instructions {
466 if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_METER) {
467 MeterInstruction := instruction.GetMeter()
468 if MeterInstruction == nil {
469 return 0
470 }
471 return MeterInstruction.GetMeterId()
472 }
473 }
474 return 0
475}
476
Scott Baker355d1742019-10-24 10:57:52 -0700477func GetVlanVid(flow *ofp.OfpFlowStats) *uint32 {
478 if flow == nil {
479 return nil
480 }
481 for _, field := range GetOfbFields(flow) {
482 if field.Type == VLAN_VID {
483 ret := field.GetVlanVid()
484 return &ret
485 }
486 }
487 // Dont return 0 if the field is missing as vlan id value 0 has meaning and cannot be overloaded as "not found"
488 return nil
489}
490
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400491func GetTunnelId(flow *ofp.OfpFlowStats) uint64 {
492 if flow == nil {
493 return 0
494 }
495 for _, field := range GetOfbFields(flow) {
496 if field.Type == TUNNEL_ID {
497 return field.GetTunnelId()
498 }
499 }
500 return 0
501}
502
503//GetMetaData - legacy get method (only want lower 32 bits)
504func GetMetaData(flow *ofp.OfpFlowStats) uint32 {
505 if flow == nil {
506 return 0
507 }
508 for _, field := range GetOfbFields(flow) {
509 if field.Type == METADATA {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400510 return uint32(field.GetTableMetadata() & 0xFFFFFFFF)
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400511 }
512 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 log.Debug("No-metadata-present")
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400514 return 0
515}
516
517func GetMetaData64Bit(flow *ofp.OfpFlowStats) uint64 {
518 if flow == nil {
519 return 0
520 }
521 for _, field := range GetOfbFields(flow) {
522 if field.Type == METADATA {
523 return field.GetTableMetadata()
524 }
525 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400526 log.Debug("No-metadata-present")
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400527 return 0
528}
529
Manikkaraj kb1d51442019-07-23 10:41:02 -0400530// function returns write metadata value from write_metadata action field
531func GetMetadataFromWriteMetadataAction(flow *ofp.OfpFlowStats) uint64 {
532 if flow != nil {
533 for _, instruction := range flow.Instructions {
534 if instruction.Type == uint32(WRITE_METADATA) {
535 if writeMetadata := instruction.GetWriteMetadata(); writeMetadata != nil {
536 return writeMetadata.GetMetadata()
537 }
538 }
539 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400540 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400541 log.Debugw("No-write-metadata-present", log.Fields{"flow": flow})
542 return 0
543}
544
545func GetTechProfileIDFromWriteMetaData(metadata uint64) uint16 {
546 /*
547 Write metadata instruction value (metadata) is 8 bytes:
548 MS 2 bytes: C Tag
549 Next 2 bytes: Technology Profile Id
550 Next 4 bytes: Port number (uni or nni)
551
552 This is set in the ONOS OltPipeline as a write metadata instruction
553 */
554 var tpId uint16 = 0
555 log.Debugw("Write metadata value for Techprofile ID", log.Fields{"metadata": metadata})
556 if metadata != 0 {
557 tpId = uint16((metadata >> 32) & 0xFFFF)
558 log.Debugw("Found techprofile ID from write metadata action", log.Fields{"tpid": tpId})
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400559 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400560 return tpId
561}
562
563func GetEgressPortNumberFromWriteMetadata(flow *ofp.OfpFlowStats) uint32 {
564 /*
565 Write metadata instruction value (metadata) is 8 bytes:
566 MS 2 bytes: C Tag
567 Next 2 bytes: Technology Profile Id
568 Next 4 bytes: Port number (uni or nni)
569 This is set in the ONOS OltPipeline as a write metadata instruction
570 */
571 var uniPort uint32 = 0
572 md := GetMetadataFromWriteMetadataAction(flow)
573 log.Debugw("Metadata found for egress/uni port ", log.Fields{"metadata": md})
574 if md != 0 {
575 uniPort = uint32(md & 0xFFFFFFFF)
576 log.Debugw("Found EgressPort from write metadata action", log.Fields{"egress_port": uniPort})
577 }
578 return uniPort
579
580}
581
582func GetInnerTagFromMetaData(flow *ofp.OfpFlowStats) uint16 {
583 /*
584 Write metadata instruction value (metadata) is 8 bytes:
585 MS 2 bytes: C Tag
586 Next 2 bytes: Technology Profile Id
587 Next 4 bytes: Port number (uni or nni)
588 This is set in the ONOS OltPipeline as a write metadata instruction
589 */
590 var innerTag uint16 = 0
591 md := GetMetadataFromWriteMetadataAction(flow)
592 if md != 0 {
593 innerTag = uint16((md >> 48) & 0xFFFF)
594 log.Debugw("Found CVLAN from write metadate action", log.Fields{"c_vlan": innerTag})
595 }
596 return innerTag
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400597}
598
599//GetInnerTagFromMetaData retrieves the inner tag from the Metadata_ofp. The port number (UNI on ONU) is in the
600// lower 32-bits of Metadata_ofp and the inner_tag is in the upper 32-bits. This is set in the ONOS OltPipeline as
601//// a Metadata_ofp field
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602/*func GetInnerTagFromMetaData(flow *ofp.OfpFlowStats) uint64 {
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400603 md := GetMetaData64Bit(flow)
604 if md == 0 {
605 return 0
606 }
607 if md <= 0xffffffff {
608 log.Debugw("onos-upgrade-suggested", log.Fields{"Metadata_ofp": md, "message": "Legacy MetaData detected form OltPipeline"})
609 return md
610 }
611 return (md >> 32) & 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612}*/
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400613
614// Extract the child device port from a flow that contains the parent device peer port. Typically the UNI port of an
615// ONU child device. Per TST agreement this will be the lower 32 bits of tunnel id reserving upper 32 bits for later
616// use
617func GetChildPortFromTunnelId(flow *ofp.OfpFlowStats) uint32 {
618 tid := GetTunnelId(flow)
619 if tid == 0 {
620 return 0
621 }
622 // Per TST agreement we are keeping any child port id (uni port id) in the lower 32 bits
623 return uint32(tid & 0xffffffff)
624}
625
626func HasNextTable(flow *ofp.OfpFlowStats) bool {
627 if flow == nil {
628 return false
629 }
630 return GetGotoTableId(flow) != 0
631}
632
633func GetGroup(flow *ofp.OfpFlowStats) uint32 {
634 if flow == nil {
635 return 0
636 }
637 for _, action := range GetActions(flow) {
638 if action.Type == GROUP {
639 grp := action.GetGroup()
640 if grp == nil {
641 return 0
642 }
643 return grp.GetGroupId()
644 }
645 }
646 return 0
647}
648
649func HasGroup(flow *ofp.OfpFlowStats) bool {
650 return GetGroup(flow) != 0
651}
652
653// GetNextTableId returns the next table ID if the "table_id" is present in the map, otherwise return nil
654func GetNextTableId(kw OfpFlowModArgs) *uint32 {
655 if val, exist := kw["table_id"]; exist {
656 ret := uint32(val)
657 return &ret
658 }
659 return nil
660}
661
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662// GetMeterIdFlowModArgs returns the meterId if the "meter_id" is present in the map, otherwise return 0
663func GetMeterIdFlowModArgs(kw OfpFlowModArgs) uint32 {
664 if val, exist := kw["meter_id"]; exist {
665 return uint32(val)
666 }
667 return 0
668}
669
670// Function returns the metadata if the "write_metadata" is present in the map, otherwise return nil
671func GetMetadataFlowModArgs(kw OfpFlowModArgs) uint64 {
672 if val, exist := kw["write_metadata"]; exist {
673 ret := uint64(val)
674 return ret
675 }
676 return 0
677}
678
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400679// Return unique 64-bit integer hash for flow covering the following attributes:
680// 'table_id', 'priority', 'flags', 'cookie', 'match', '_instruction_string'
681func HashFlowStats(flow *ofp.OfpFlowStats) uint64 {
682 if flow == nil { // Should never happen
683 return 0
684 }
685 // Create string with the instructions field first
686 var instructionString bytes.Buffer
687 for _, instruction := range flow.Instructions {
688 instructionString.WriteString(instruction.String())
689 }
690 var flowString = fmt.Sprintf("%d%d%d%d%s%s", flow.TableId, flow.Priority, flow.Flags, flow.Cookie, flow.Match.String(), instructionString.String())
691 h := md5.New()
692 h.Write([]byte(flowString))
693 hash := big.NewInt(0)
694 hash.SetBytes(h.Sum(nil))
695 return hash.Uint64()
696}
697
698// flowStatsEntryFromFlowModMessage maps an ofp_flow_mod message to an ofp_flow_stats message
699func FlowStatsEntryFromFlowModMessage(mod *ofp.OfpFlowMod) *ofp.OfpFlowStats {
700 flow := &ofp.OfpFlowStats{}
701 if mod == nil {
702 return flow
703 }
704 flow.TableId = mod.TableId
705 flow.Priority = mod.Priority
706 flow.IdleTimeout = mod.IdleTimeout
707 flow.HardTimeout = mod.HardTimeout
708 flow.Flags = mod.Flags
709 flow.Cookie = mod.Cookie
710 flow.Match = mod.Match
711 flow.Instructions = mod.Instructions
712 flow.Id = HashFlowStats(flow)
713 return flow
714}
715
716func GroupEntryFromGroupMod(mod *ofp.OfpGroupMod) *ofp.OfpGroupEntry {
717 group := &ofp.OfpGroupEntry{}
718 if mod == nil {
719 return group
720 }
721 group.Desc = &ofp.OfpGroupDesc{Type: mod.Type, GroupId: mod.GroupId, Buckets: mod.Buckets}
722 group.Stats = &ofp.OfpGroupStats{GroupId: mod.GroupId}
723 //TODO do we need to instantiate bucket bins?
724 return group
725}
726
Manikkaraj kb1d51442019-07-23 10:41:02 -0400727// flowStatsEntryFromFlowModMessage maps an ofp_flow_mod message to an ofp_flow_stats message
728func MeterEntryFromMeterMod(meterMod *ofp.OfpMeterMod) *ofp.OfpMeterEntry {
729 bandStats := make([]*ofp.OfpMeterBandStats, 0)
730 meter := &ofp.OfpMeterEntry{Config: &ofp.OfpMeterConfig{},
731 Stats: &ofp.OfpMeterStats{BandStats: bandStats}}
732 if meterMod == nil {
733 log.Error("Invalid meter mod command")
734 return meter
735 }
736 // config init
737 meter.Config.MeterId = meterMod.MeterId
738 meter.Config.Flags = meterMod.Flags
739 meter.Config.Bands = meterMod.Bands
740 // meter stats init
741 meter.Stats.MeterId = meterMod.MeterId
742 meter.Stats.FlowCount = 0
743 meter.Stats.PacketInCount = 0
744 meter.Stats.ByteInCount = 0
745 meter.Stats.DurationSec = 0
746 meter.Stats.DurationNsec = 0
747 // band stats init
748 for _, _ = range meterMod.Bands {
749 band := &ofp.OfpMeterBandStats{}
750 band.PacketBandCount = 0
751 band.ByteBandCount = 0
752 bandStats = append(bandStats, band)
753 }
754 meter.Stats.BandStats = bandStats
755 log.Debugw("Allocated meter entry", log.Fields{"meter": *meter})
756 return meter
757
758}
759
760func GetMeterIdFromFlow(flow *ofp.OfpFlowStats) uint32 {
761 if flow != nil {
762 for _, instruction := range flow.Instructions {
763 if instruction.Type == uint32(METER_ACTION) {
764 if meterInst := instruction.GetMeter(); meterInst != nil {
765 return meterInst.GetMeterId()
766 }
767 }
768 }
769 }
770
771 return uint32(0)
772}
773
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400774func MkOxmFields(matchFields []ofp.OfpOxmField) []*ofp.OfpOxmField {
775 oxmFields := make([]*ofp.OfpOxmField, 0)
776 for _, matchField := range matchFields {
777 oxmField := ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: matchField.Field}
778 oxmFields = append(oxmFields, &oxmField)
779 }
780 return oxmFields
781}
782
783func MkInstructionsFromActions(actions []*ofp.OfpAction) []*ofp.OfpInstruction {
784 instructions := make([]*ofp.OfpInstruction, 0)
785 instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: actions}}
786 instruction := ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction}
787 instructions = append(instructions, &instruction)
788 return instructions
789}
790
791// Convenience function to generare ofp_flow_mod message with OXM BASIC match composed from the match_fields, and
792// single APPLY_ACTIONS instruction with a list if ofp_action objects.
793func MkSimpleFlowMod(matchFields []*ofp.OfpOxmField, actions []*ofp.OfpAction, command *ofp.OfpFlowModCommand, kw OfpFlowModArgs) *ofp.OfpFlowMod {
794
795 // Process actions instructions
796 instructions := make([]*ofp.OfpInstruction, 0)
797 instructionAction := ofp.OfpInstruction_Actions{Actions: &ofp.OfpInstructionActions{Actions: actions}}
798 instruction := ofp.OfpInstruction{Type: uint32(APPLY_ACTIONS), Data: &instructionAction}
799 instructions = append(instructions, &instruction)
800
801 // Process next table
802 if tableId := GetNextTableId(kw); tableId != nil {
803 var instGotoTable ofp.OfpInstruction_GotoTable
804 instGotoTable.GotoTable = &ofp.OfpInstructionGotoTable{TableId: *tableId}
805 inst := ofp.OfpInstruction{Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE), Data: &instGotoTable}
806 instructions = append(instructions, &inst)
807 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400808 // Process meter action
809 if meterId := GetMeterIdFlowModArgs(kw); meterId != 0 {
810 var instMeter ofp.OfpInstruction_Meter
811 instMeter.Meter = &ofp.OfpInstructionMeter{MeterId: meterId}
812 inst := ofp.OfpInstruction{Type: uint32(METER_ACTION), Data: &instMeter}
813 instructions = append(instructions, &inst)
814 }
815 //process write_metadata action
816 if metadata := GetMetadataFlowModArgs(kw); metadata != 0 {
817 var instWriteMetadata ofp.OfpInstruction_WriteMetadata
818 instWriteMetadata.WriteMetadata = &ofp.OfpInstructionWriteMetadata{Metadata: metadata}
819 inst := ofp.OfpInstruction{Type: uint32(WRITE_METADATA), Data: &instWriteMetadata}
820 instructions = append(instructions, &inst)
821 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400822
823 // Process match fields
824 oxmFields := make([]*ofp.OfpOxmField, 0)
825 for _, matchField := range matchFields {
826 oxmField := ofp.OfpOxmField{OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC, Field: matchField.Field}
827 oxmFields = append(oxmFields, &oxmField)
828 }
829 var match ofp.OfpMatch
830 match.Type = ofp.OfpMatchType_OFPMT_OXM
831 match.OxmFields = oxmFields
832
833 // Create ofp_flow_message
834 msg := &ofp.OfpFlowMod{}
835 if command == nil {
836 msg.Command = ofp.OfpFlowModCommand_OFPFC_ADD
837 } else {
838 msg.Command = *command
839 }
840 msg.Instructions = instructions
841 msg.Match = &match
842
843 // Set the variadic argument values
844 msg = setVariadicModAttributes(msg, kw)
845
846 return msg
847}
848
849func MkMulticastGroupMod(groupId uint32, buckets []*ofp.OfpBucket, command *ofp.OfpGroupModCommand) *ofp.OfpGroupMod {
850 group := &ofp.OfpGroupMod{}
851 if command == nil {
852 group.Command = ofp.OfpGroupModCommand_OFPGC_ADD
853 } else {
854 group.Command = *command
855 }
856 group.Type = ofp.OfpGroupType_OFPGT_ALL
857 group.GroupId = groupId
858 group.Buckets = buckets
859 return group
860}
861
862//SetVariadicModAttributes sets only uint64 or uint32 fields of the ofp_flow_mod message
863func setVariadicModAttributes(mod *ofp.OfpFlowMod, args OfpFlowModArgs) *ofp.OfpFlowMod {
864 if args == nil {
865 return mod
866 }
867 for key, val := range args {
868 switch key {
869 case "cookie":
870 mod.Cookie = val
871 case "cookie_mask":
872 mod.CookieMask = val
873 case "table_id":
874 mod.TableId = uint32(val)
875 case "idle_timeout":
876 mod.IdleTimeout = uint32(val)
877 case "hard_timeout":
878 mod.HardTimeout = uint32(val)
879 case "priority":
880 mod.Priority = uint32(val)
881 case "buffer_id":
882 mod.BufferId = uint32(val)
883 case "out_port":
884 mod.OutPort = uint32(val)
885 case "out_group":
886 mod.OutGroup = uint32(val)
887 case "flags":
888 mod.Flags = uint32(val)
889 }
890 }
891 return mod
892}
893
894func MkPacketIn(port uint32, packet []byte) *ofp.OfpPacketIn {
895 packetIn := &ofp.OfpPacketIn{
896 Reason: ofp.OfpPacketInReason_OFPR_ACTION,
897 Match: &ofp.OfpMatch{
898 Type: ofp.OfpMatchType_OFPMT_OXM,
899 OxmFields: []*ofp.OfpOxmField{
900 {
901 OxmClass: ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC,
902 Field: &ofp.OfpOxmField_OfbField{
903 OfbField: InPort(port)},
904 },
905 },
906 },
907 Data: packet,
908 }
909 return packetIn
910}
911
912// MkFlowStat is a helper method to build flows
913func MkFlowStat(fa *FlowArgs) *ofp.OfpFlowStats {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400914 //Build the match-fields
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400915 matchFields := make([]*ofp.OfpOxmField, 0)
916 for _, val := range fa.MatchFields {
917 matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
918 }
919 return FlowStatsEntryFromFlowModMessage(MkSimpleFlowMod(matchFields, fa.Actions, fa.Command, fa.KV))
920}
921
922func MkGroupStat(ga *GroupArgs) *ofp.OfpGroupEntry {
923 return GroupEntryFromGroupMod(MkMulticastGroupMod(ga.GroupId, ga.Buckets, ga.Command))
924}
925
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400926type OfpFlowModArgs map[string]uint64
927
928type FlowArgs struct {
929 MatchFields []*ofp.OfpOxmOfbField
930 Actions []*ofp.OfpAction
931 Command *ofp.OfpFlowModCommand
932 Priority uint32
933 KV OfpFlowModArgs
934}
935
936type GroupArgs struct {
937 GroupId uint32
938 Buckets []*ofp.OfpBucket
939 Command *ofp.OfpGroupModCommand
940}
941
942type FlowsAndGroups struct {
943 Flows *ordered_map.OrderedMap
944 Groups *ordered_map.OrderedMap
945}
946
947func NewFlowsAndGroups() *FlowsAndGroups {
948 var fg FlowsAndGroups
949 fg.Flows = ordered_map.NewOrderedMap()
950 fg.Groups = ordered_map.NewOrderedMap()
951 return &fg
952}
953
954func (fg *FlowsAndGroups) Copy() *FlowsAndGroups {
955 copyFG := NewFlowsAndGroups()
956 iter := fg.Flows.IterFunc()
957 for kv, ok := iter(); ok; kv, ok = iter() {
958 if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
959 copyFG.Flows.Set(kv.Key, proto.Clone(protoMsg))
960 }
961 }
962 iter = fg.Groups.IterFunc()
963 for kv, ok := iter(); ok; kv, ok = iter() {
964 if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
965 copyFG.Groups.Set(kv.Key, proto.Clone(protoMsg))
966 }
967 }
968 return copyFG
969}
970
971func (fg *FlowsAndGroups) GetFlow(index int) *ofp.OfpFlowStats {
972 iter := fg.Flows.IterFunc()
973 pos := 0
974 for kv, ok := iter(); ok; kv, ok = iter() {
975 if pos == index {
976 if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
977 return protoMsg
978 }
979 return nil
980 }
981 pos += 1
982 }
983 return nil
984}
985
986func (fg *FlowsAndGroups) ListFlows() []*ofp.OfpFlowStats {
987 flows := make([]*ofp.OfpFlowStats, 0)
988 iter := fg.Flows.IterFunc()
989 for kv, ok := iter(); ok; kv, ok = iter() {
990 if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
991 flows = append(flows, protoMsg)
992 }
993 }
994 return flows
995}
996
997func (fg *FlowsAndGroups) ListGroups() []*ofp.OfpGroupEntry {
998 groups := make([]*ofp.OfpGroupEntry, 0)
999 iter := fg.Groups.IterFunc()
1000 for kv, ok := iter(); ok; kv, ok = iter() {
1001 if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
1002 groups = append(groups, protoMsg)
1003 }
1004 }
1005 return groups
1006}
1007
1008func (fg *FlowsAndGroups) String() string {
1009 var buffer bytes.Buffer
1010 iter := fg.Flows.IterFunc()
1011 for kv, ok := iter(); ok; kv, ok = iter() {
1012 if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
1013 buffer.WriteString("\nFlow:\n")
1014 buffer.WriteString(proto.MarshalTextString(protoMsg))
1015 buffer.WriteString("\n")
1016 }
1017 }
1018 iter = fg.Groups.IterFunc()
1019 for kv, ok := iter(); ok; kv, ok = iter() {
1020 if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
1021 buffer.WriteString("\nGroup:\n")
1022 buffer.WriteString(proto.MarshalTextString(protoMsg))
1023 buffer.WriteString("\n")
1024 }
1025 }
1026 return buffer.String()
1027}
1028
1029func (fg *FlowsAndGroups) AddFlow(flow *ofp.OfpFlowStats) {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001030 if flow == nil {
1031 return
1032 }
1033
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001034 if fg.Flows == nil {
1035 fg.Flows = ordered_map.NewOrderedMap()
1036 }
1037 if fg.Groups == nil {
1038 fg.Groups = ordered_map.NewOrderedMap()
1039 }
1040 //Add flow only if absent
1041 if _, exist := fg.Flows.Get(flow.Id); !exist {
1042 fg.Flows.Set(flow.Id, flow)
1043 }
1044}
1045
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001046func (fg *FlowsAndGroups) AddGroup(group *ofp.OfpGroupEntry) {
1047 if group == nil {
1048 return
1049 }
1050
1051 if fg.Flows == nil {
1052 fg.Flows = ordered_map.NewOrderedMap()
1053 }
1054 if fg.Groups == nil {
1055 fg.Groups = ordered_map.NewOrderedMap()
1056 }
1057 //Add group only if absent
1058 if _, exist := fg.Groups.Get(group.Desc.GroupId); !exist {
1059 fg.Groups.Set(group.Desc.GroupId, group)
1060 }
1061}
1062
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001063//AddFrom add flows and groups from the argument into this structure only if they do not already exist
1064func (fg *FlowsAndGroups) AddFrom(from *FlowsAndGroups) {
1065 iter := from.Flows.IterFunc()
1066 for kv, ok := iter(); ok; kv, ok = iter() {
1067 if protoMsg, isMsg := kv.Value.(*ofp.OfpFlowStats); isMsg {
1068 if _, exist := fg.Flows.Get(protoMsg.Id); !exist {
1069 fg.Flows.Set(protoMsg.Id, protoMsg)
1070 }
1071 }
1072 }
1073 iter = from.Groups.IterFunc()
1074 for kv, ok := iter(); ok; kv, ok = iter() {
1075 if protoMsg, isMsg := kv.Value.(*ofp.OfpGroupEntry); isMsg {
1076 if _, exist := fg.Groups.Get(protoMsg.Stats.GroupId); !exist {
1077 fg.Groups.Set(protoMsg.Stats.GroupId, protoMsg)
1078 }
1079 }
1080 }
1081}
1082
1083type DeviceRules struct {
1084 Rules map[string]*FlowsAndGroups
1085}
1086
1087func NewDeviceRules() *DeviceRules {
1088 var dr DeviceRules
1089 dr.Rules = make(map[string]*FlowsAndGroups)
1090 return &dr
1091}
1092
1093func (dr *DeviceRules) Copy() *DeviceRules {
1094 copyDR := NewDeviceRules()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001095 if dr != nil {
1096 for key, val := range dr.Rules {
1097 if val != nil {
1098 copyDR.Rules[key] = val.Copy()
1099 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001100 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001101 }
1102 return copyDR
1103}
1104
1105func (dr *DeviceRules) ClearFlows(deviceId string) {
1106 if _, exist := dr.Rules[deviceId]; exist {
1107 dr.Rules[deviceId].Flows = ordered_map.NewOrderedMap()
1108 }
1109}
1110
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001111func (dr *DeviceRules) FilterRules(deviceIds map[string]string) *DeviceRules {
1112 filteredDR := NewDeviceRules()
1113 for key, val := range dr.Rules {
1114 if _, exist := deviceIds[key]; exist {
1115 filteredDR.Rules[key] = val.Copy()
1116 }
1117 }
1118 return filteredDR
1119}
1120
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001121func (dr *DeviceRules) AddFlow(deviceId string, flow *ofp.OfpFlowStats) {
1122 if _, exist := dr.Rules[deviceId]; !exist {
1123 dr.Rules[deviceId] = NewFlowsAndGroups()
1124 }
1125 dr.Rules[deviceId].AddFlow(flow)
1126}
1127
1128func (dr *DeviceRules) GetRules() map[string]*FlowsAndGroups {
1129 return dr.Rules
1130}
1131
1132func (dr *DeviceRules) String() string {
1133 var buffer bytes.Buffer
1134 for key, value := range dr.Rules {
1135 buffer.WriteString("DeviceId:")
1136 buffer.WriteString(key)
1137 buffer.WriteString(value.String())
1138 buffer.WriteString("\n\n")
1139 }
1140 return buffer.String()
1141}
1142
1143func (dr *DeviceRules) AddFlowsAndGroup(deviceId string, fg *FlowsAndGroups) {
1144 if _, ok := dr.Rules[deviceId]; !ok {
1145 dr.Rules[deviceId] = NewFlowsAndGroups()
1146 }
1147 dr.Rules[deviceId] = fg
1148}
1149
1150// CreateEntryIfNotExist creates a new deviceId in the Map if it does not exist and assigns an
1151// empty FlowsAndGroups to it. Otherwise, it does nothing.
1152func (dr *DeviceRules) CreateEntryIfNotExist(deviceId string) {
1153 if _, ok := dr.Rules[deviceId]; !ok {
1154 dr.Rules[deviceId] = NewFlowsAndGroups()
1155 }
1156}
1157
1158/*
1159 * Common flow routines
1160 */
1161
1162//FindOverlappingFlows return a list of overlapping flow(s) where mod is the flow request
1163func FindOverlappingFlows(flows []*ofp.OfpFlowStats, mod *ofp.OfpFlowMod) []*ofp.OfpFlowStats {
1164 return nil //TODO - complete implementation
1165}
1166
1167// FindFlowById returns the index of the flow in the flows array if present. Otherwise, it returns -1
1168func FindFlowById(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
1169 for idx, f := range flows {
1170 if flow.Id == f.Id {
1171 return idx
1172 }
1173 }
1174 return -1
1175}
1176
1177// FindFlows returns the index in flows where flow if present. Otherwise, it returns -1
1178func FindFlows(flows []*ofp.OfpFlowStats, flow *ofp.OfpFlowStats) int {
1179 for idx, f := range flows {
1180 if FlowMatch(f, flow) {
1181 return idx
1182 }
1183 }
1184 return -1
1185}
1186
1187//FlowMatch returns true if two flows matches on the following flow attributes:
1188//TableId, Priority, Flags, Cookie, Match
1189func FlowMatch(f1 *ofp.OfpFlowStats, f2 *ofp.OfpFlowStats) bool {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001190 if f1 == nil || f2 == nil {
1191 return false
1192 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001193 keysMatter := []string{"TableId", "Priority", "Flags", "Cookie", "Match"}
1194 for _, key := range keysMatter {
1195 switch key {
1196 case "TableId":
1197 if f1.TableId != f2.TableId {
1198 return false
1199 }
1200 case "Priority":
1201 if f1.Priority != f2.Priority {
1202 return false
1203 }
1204 case "Flags":
1205 if f1.Flags != f2.Flags {
1206 return false
1207 }
1208 case "Cookie":
1209 if f1.Cookie != f2.Cookie {
1210 return false
1211 }
1212 case "Match":
1213 if strings.Compare(f1.Match.String(), f2.Match.String()) != 0 {
1214 return false
1215 }
1216 }
1217 }
1218 return true
1219}
1220
1221//FlowMatchesMod returns True if given flow is "covered" by the wildcard flow_mod, taking into consideration of
1222//both exact matches as well as masks-based match fields if any. Otherwise return False
1223func FlowMatchesMod(flow *ofp.OfpFlowStats, mod *ofp.OfpFlowMod) bool {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001224 if flow == nil || mod == nil {
1225 return false
1226 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001227 //Check if flow.cookie is covered by mod.cookie and mod.cookie_mask
1228 if (flow.Cookie & mod.CookieMask) != (mod.Cookie & mod.CookieMask) {
1229 return false
1230 }
1231
1232 //Check if flow.table_id is covered by flow_mod.table_id
1233 if mod.TableId != uint32(ofp.OfpTable_OFPTT_ALL) && flow.TableId != mod.TableId {
1234 return false
1235 }
1236
1237 //Check out_port
1238 if (mod.OutPort&0x7fffffff) != uint32(ofp.OfpPortNo_OFPP_ANY) && !FlowHasOutPort(flow, mod.OutPort) {
1239 return false
1240 }
1241
1242 // Check out_group
1243 if (mod.OutGroup&0x7fffffff) != uint32(ofp.OfpGroup_OFPG_ANY) && !FlowHasOutGroup(flow, mod.OutGroup) {
1244 return false
1245 }
1246
1247 //Priority is ignored
1248
1249 //Check match condition
1250 //If the flow_mod match field is empty, that is a special case and indicates the flow entry matches
Mahir Gunyele77977b2019-06-27 05:36:22 -07001251 if (mod.Match == nil) || (mod.Match.OxmFields == nil) || (len(mod.Match.OxmFields) == 0) {
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001252 //If we got this far and the match is empty in the flow spec, than the flow matches
1253 return true
1254 } // TODO : implement the flow match analysis
1255 return false
1256
1257}
1258
1259//FlowHasOutPort returns True if flow has a output command with the given out_port
1260func FlowHasOutPort(flow *ofp.OfpFlowStats, outPort uint32) bool {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001261 if flow == nil {
1262 return false
1263 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001264 for _, instruction := range flow.Instructions {
1265 if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
1266 if instruction.GetActions() == nil {
1267 return false
1268 }
1269 for _, action := range instruction.GetActions().Actions {
1270 if action.Type == ofp.OfpActionType_OFPAT_OUTPUT {
1271 if (action.GetOutput() != nil) && (action.GetOutput().Port == outPort) {
1272 return true
1273 }
1274 }
1275
1276 }
1277 }
1278 }
1279 return false
1280}
1281
1282//FlowHasOutGroup return True if flow has a output command with the given out_group
1283func FlowHasOutGroup(flow *ofp.OfpFlowStats, groupID uint32) bool {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001284 if flow == nil {
1285 return false
1286 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001287 for _, instruction := range flow.Instructions {
1288 if instruction.Type == uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
1289 if instruction.GetActions() == nil {
1290 return false
1291 }
1292 for _, action := range instruction.GetActions().Actions {
1293 if action.Type == ofp.OfpActionType_OFPAT_GROUP {
1294 if (action.GetGroup() != nil) && (action.GetGroup().GroupId == groupID) {
1295 return true
1296 }
1297 }
1298
1299 }
1300 }
1301 }
1302 return false
1303}
1304
1305//FindGroup returns index of group if found, else returns -1
1306func FindGroup(groups []*ofp.OfpGroupEntry, groupId uint32) int {
1307 for idx, group := range groups {
1308 if group.Desc.GroupId == groupId {
1309 return idx
1310 }
1311 }
1312 return -1
1313}
1314
1315func FlowsDeleteByGroupId(flows []*ofp.OfpFlowStats, groupId uint32) (bool, []*ofp.OfpFlowStats) {
1316 toKeep := make([]*ofp.OfpFlowStats, 0)
1317
1318 for _, f := range flows {
1319 if !FlowHasOutGroup(f, groupId) {
1320 toKeep = append(toKeep, f)
1321 }
1322 }
1323 return len(toKeep) < len(flows), toKeep
1324}
Mahir Gunyele77977b2019-06-27 05:36:22 -07001325
1326func ToOfpOxmField(from []*ofp.OfpOxmOfbField) []*ofp.OfpOxmField {
1327 matchFields := make([]*ofp.OfpOxmField, 0)
1328 for _, val := range from {
1329 matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
1330 }
1331 return matchFields
1332}