blob: 41a93e44dc78648b961d94ac1d7e7f6ccdd2eb2f [file] [log] [blame]
khenaidoo89b0e942018-10-21 21:11:33 -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 */
16package flow_decomposition
17
18import (
19 "errors"
20 "github.com/opencord/voltha-go/common/log"
khenaidoo89b0e942018-10-21 21:11:33 -040021 "github.com/opencord/voltha-go/rw_core/graph"
22 fu "github.com/opencord/voltha-go/rw_core/utils"
khenaidoo2c6a0992019-04-29 13:46:56 -040023 ofp "github.com/opencord/voltha-protos/go/openflow_13"
24 "github.com/opencord/voltha-protos/go/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040025 "github.com/stretchr/testify/assert"
26
27 "testing"
28)
29
khenaidoo89b0e942018-10-21 21:11:33 -040030func init() {
khenaidood20a5852018-10-22 22:09:55 -040031 log.AddPackage(log.JSON, log.WarnLevel, nil)
khenaidoo910204f2019-04-08 17:56:40 -040032 log.UpdateAllLoggers(log.Fields{"instanceId": "flow-decomposition"})
khenaidood20a5852018-10-22 22:09:55 -040033 log.SetAllLogLevel(log.WarnLevel)
khenaidoo89b0e942018-10-21 21:11:33 -040034}
35
36type testDeviceManager struct {
37 devices map[string]*voltha.Device
38}
39
40func newTestDeviceManager() *testDeviceManager {
41 var tdm testDeviceManager
42 tdm.devices = make(map[string]*voltha.Device)
43 tdm.devices["olt"] = &voltha.Device{
44 Id: "olt",
45 Root: true,
46 ParentId: "logical_device",
47 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040048 {PortNo: 1, Label: "pon"},
49 {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040050 },
51 }
52 tdm.devices["onu1"] = &voltha.Device{
53 Id: "onu1",
54 Root: false,
55 ParentId: "olt",
56 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040057 {PortNo: 1, Label: "pon"},
58 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040059 },
60 }
61 tdm.devices["onu2"] = &voltha.Device{
62 Id: "onu2",
63 Root: false,
64 ParentId: "olt",
65 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040066 {PortNo: 1, Label: "pon"},
67 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040068 },
69 }
70 tdm.devices["onu3"] = &voltha.Device{
71 Id: "onu3",
72 Root: false,
73 ParentId: "olt",
74 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040075 {PortNo: 1, Label: "pon"},
76 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040077 },
78 }
79 tdm.devices["onu4"] = &voltha.Device{
80 Id: "onu4",
81 Root: false,
82 ParentId: "olt",
83 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040084 {PortNo: 1, Label: "pon"},
85 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040086 },
87 }
88 return &tdm
89}
90
91func (tdm *testDeviceManager) GetDevice(deviceId string) (*voltha.Device, error) {
92 if d, ok := tdm.devices[deviceId]; ok {
93 return d, nil
94 }
khenaidood20a5852018-10-22 22:09:55 -040095 return nil, errors.New("ABSENT.")
khenaidoo89b0e942018-10-21 21:11:33 -040096}
khenaidoo19d7b632018-10-30 10:49:50 -040097func (tdm *testDeviceManager) IsRootDevice(deviceId string) (bool, error) {
98 if d, ok := tdm.devices[deviceId]; ok {
99 return d.Root, nil
100 }
101 return false, errors.New("ABSENT.")
102}
khenaidoo89b0e942018-10-21 21:11:33 -0400103
khenaidoo0a822f92019-05-08 15:15:57 -0400104func (tdm *testDeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
105 return nil
106}
107
108func (tdm *testDeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
109 return nil
110}
111
112func (tdm *testDeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
113 return nil
114}
115
116func (tdm *testDeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
117 return nil
118}
119
120func (tdm *testDeviceManager) DisableAllChildDevices(cDevice *voltha.Device) error {
121 return nil
122}
123
124func (tdm *testDeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
125 return nil
126}
127
128func (tdm *testDeviceManager) DeleteLogicalPorts(cDevice *voltha.Device) error {
129 return nil
130}
131
132func (tdm *testDeviceManager) DeleteAllChildDevices(cDevice *voltha.Device) error {
133 return nil
134}
135
136func (tdm *testDeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
137 return nil
138}
139
khenaidoo59ef7be2019-06-21 12:40:28 -0400140func (tdm *testDeviceManager) MarkChildDevicesAsUnReachable(cDevice *voltha.Device) error {
141 return nil
142}
143
khenaidoo89b0e942018-10-21 21:11:33 -0400144type testFlowDecomposer struct {
145 dMgr *testDeviceManager
146 logicalPorts map[uint32]*voltha.LogicalPort
147 routes map[graph.OFPortLink][]graph.RouteHop
148 defaultRules *fu.DeviceRules
149 deviceGraph *graph.DeviceGraph
150 fd *FlowDecomposer
151}
152
153func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
154 var tfd testFlowDecomposer
155 tfd.dMgr = deviceMgr
156
157 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
158 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
159 // port
160 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
161 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
162 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
163 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
164 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
165
166 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
167
168 //DOWNSTREAM ROUTES
169
170 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400171 {
khenaidoo89b0e942018-10-21 21:11:33 -0400172 DeviceID: "olt",
173 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
174 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
175 },
khenaidood20a5852018-10-22 22:09:55 -0400176 {
khenaidoo89b0e942018-10-21 21:11:33 -0400177 DeviceID: "onu1",
178 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
179 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
180 },
181 }
182
183 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400184 {
khenaidoo89b0e942018-10-21 21:11:33 -0400185 DeviceID: "olt",
186 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
187 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
188 },
khenaidood20a5852018-10-22 22:09:55 -0400189 {
khenaidoo89b0e942018-10-21 21:11:33 -0400190 DeviceID: "onu2",
191 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
192 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
193 },
194 }
195 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400196 {
khenaidoo89b0e942018-10-21 21:11:33 -0400197 DeviceID: "olt",
198 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
199 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
200 },
khenaidood20a5852018-10-22 22:09:55 -0400201 {
khenaidoo89b0e942018-10-21 21:11:33 -0400202 DeviceID: "onu3",
203 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
204 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
205 },
206 }
207 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400208 {
khenaidoo89b0e942018-10-21 21:11:33 -0400209 DeviceID: "olt",
210 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
211 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
212 },
khenaidood20a5852018-10-22 22:09:55 -0400213 {
khenaidoo89b0e942018-10-21 21:11:33 -0400214 DeviceID: "onu4",
215 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
216 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
217 },
218 }
219
220 //UPSTREAM DATA PLANE
221
222 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400223 {
khenaidoo89b0e942018-10-21 21:11:33 -0400224 DeviceID: "onu1",
225 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
226 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
227 },
khenaidood20a5852018-10-22 22:09:55 -0400228 {
khenaidoo89b0e942018-10-21 21:11:33 -0400229 DeviceID: "olt",
230 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
231 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
232 },
233 }
234 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400235 {
khenaidoo89b0e942018-10-21 21:11:33 -0400236 DeviceID: "onu2",
237 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
238 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
239 },
khenaidood20a5852018-10-22 22:09:55 -0400240 {
khenaidoo89b0e942018-10-21 21:11:33 -0400241 DeviceID: "olt",
242 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
243 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
244 },
245 }
246 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400247 {
khenaidoo89b0e942018-10-21 21:11:33 -0400248 DeviceID: "onu3",
249 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
250 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
251 },
khenaidood20a5852018-10-22 22:09:55 -0400252 {
khenaidoo89b0e942018-10-21 21:11:33 -0400253 DeviceID: "olt",
254 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
255 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
256 },
257 }
258 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400259 {
khenaidoo89b0e942018-10-21 21:11:33 -0400260 DeviceID: "onu4",
261 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
262 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
263 },
khenaidood20a5852018-10-22 22:09:55 -0400264 {
khenaidoo89b0e942018-10-21 21:11:33 -0400265 DeviceID: "olt",
266 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
267 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
268 },
269 }
270
271 //UPSTREAM NEXT TABLE BASED
272
273 // openflow port 0 means absence of a port - go/protobuf interpretation
274 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400275 {
khenaidoo89b0e942018-10-21 21:11:33 -0400276 DeviceID: "onu1",
277 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
278 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
279 },
khenaidood20a5852018-10-22 22:09:55 -0400280 {
khenaidoo89b0e942018-10-21 21:11:33 -0400281 DeviceID: "olt",
282 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
283 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
284 },
285 }
286 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400287 {
khenaidoo89b0e942018-10-21 21:11:33 -0400288 DeviceID: "onu2",
289 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
290 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
291 },
khenaidood20a5852018-10-22 22:09:55 -0400292 {
khenaidoo89b0e942018-10-21 21:11:33 -0400293 DeviceID: "olt",
294 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
295 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
296 },
297 }
298 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400299 {
khenaidoo89b0e942018-10-21 21:11:33 -0400300 DeviceID: "onu3",
301 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
302 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
303 },
khenaidood20a5852018-10-22 22:09:55 -0400304 {
khenaidoo89b0e942018-10-21 21:11:33 -0400305 DeviceID: "olt",
306 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
307 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
308 },
309 }
310 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400311 {
khenaidoo89b0e942018-10-21 21:11:33 -0400312 DeviceID: "onu4",
313 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
314 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
315 },
khenaidood20a5852018-10-22 22:09:55 -0400316 {
khenaidoo89b0e942018-10-21 21:11:33 -0400317 DeviceID: "olt",
318 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
319 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
320 },
321 }
322
323 // DOWNSTREAM NEXT TABLE BASED
324
325 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400326 {
khenaidoo89b0e942018-10-21 21:11:33 -0400327 DeviceID: "olt",
328 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
329 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
330 },
khenaidood20a5852018-10-22 22:09:55 -0400331 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400332 }
333
334 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400335 {}, // 1st hop is wildcard
336 {
khenaidoo89b0e942018-10-21 21:11:33 -0400337 DeviceID: "olt",
338 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
339 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
340 },
341 }
342
343 // DEFAULT RULES
344
345 tfd.defaultRules = fu.NewDeviceRules()
346 fg := fu.NewFlowsAndGroups()
347 var fa *fu.FlowArgs
348 fa = &fu.FlowArgs{
349 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400350 fu.InPort(2),
351 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400352 },
353 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400354 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
355 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400356 },
357 }
khenaidoo68c930b2019-05-13 11:46:51 -0400358 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400359 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
360
361 fg = fu.NewFlowsAndGroups()
362 fa = &fu.FlowArgs{
363 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400364 fu.InPort(2),
365 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400366 },
367 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400368 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
369 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400370 },
371 }
khenaidoo68c930b2019-05-13 11:46:51 -0400372 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400373 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
374
375 fg = fu.NewFlowsAndGroups()
376 fa = &fu.FlowArgs{
377 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400378 fu.InPort(2),
379 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400380 },
381 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400382 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
383 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400384 },
385 }
khenaidoo68c930b2019-05-13 11:46:51 -0400386 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400387 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
388
389 fg = fu.NewFlowsAndGroups()
390 fa = &fu.FlowArgs{
391 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400392 fu.InPort(2),
393 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400394 },
395 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400396 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
397 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400398 },
399 }
khenaidoo68c930b2019-05-13 11:46:51 -0400400 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400401 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
402
403 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
khenaidoo910204f2019-04-08 17:56:40 -0400404 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400405 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
406 tfd.deviceGraph.RootPorts[10] = 10
407
408 tfd.fd = NewFlowDecomposer(tfd.dMgr)
409
410 return &tfd
411}
412
413func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
414 return tfd.dMgr.GetDevice(deviceId)
415}
416
417func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
418 return ""
419}
420
khenaidoo19d7b632018-10-30 10:49:50 -0400421func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
422 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400423}
424
425func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
426 return tfd.deviceGraph
427}
428
429func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
430 return tfd.defaultRules
431}
432
433func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
434 lPorts := make([]uint32, 0)
435 var exclPort uint32
436 if len(excludePort) == 1 {
437 exclPort = excludePort[0]
438 }
khenaidood20a5852018-10-22 22:09:55 -0400439 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400440 if portno != exclPort {
441 lPorts = append(lPorts, portno)
442 }
443 }
444 return lPorts
445}
446
khenaidoo19d7b632018-10-30 10:49:50 -0400447func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400448 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400449 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400450 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400451 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400452 portLink.Egress = 10
453 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400454 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400455 }
khenaidoo19d7b632018-10-30 10:49:50 -0400456 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400457 portLink.Ingress = 0
458 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400459 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400460 }
461 for key, val := range tfd.routes {
462 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
463 return val
464 }
465 }
466 return nil
467}
468
469func TestEapolReRouteRuleDecomposition(t *testing.T) {
470
471 var fa *fu.FlowArgs
472 fa = &fu.FlowArgs{
473 KV: fu.OfpFlowModArgs{"priority": 1000},
474 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400475 fu.InPort(1),
476 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
477 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400478 },
479 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400480 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
481 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400482 },
483 }
484
khenaidoo68c930b2019-05-13 11:46:51 -0400485 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400486 groups := ofp.FlowGroups{}
487 tfd := newTestFlowDecomposer(newTestDeviceManager())
488
khenaidoo3306c992019-05-24 16:57:35 -0400489 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400490 onu1FlowAndGroup := deviceRules.Rules["onu1"]
491 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400492 assert.Nil(t, onu1FlowAndGroup)
khenaidoo89b0e942018-10-21 21:11:33 -0400493 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
494 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
495
496 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400497 KV: fu.OfpFlowModArgs{"priority": 1000},
498 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400499 fu.InPort(1),
500 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
501 fu.TunnelId(uint64(1)),
502 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400503 },
504 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400505 fu.PushVlan(0x8100),
506 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
507 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400508 },
509 }
khenaidoo68c930b2019-05-13 11:46:51 -0400510 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400511 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400512 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
513
514 fa = &fu.FlowArgs{
515 KV: fu.OfpFlowModArgs{"priority": 1000},
516 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400517 fu.InPort(2),
518 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
519 fu.VlanPcp(0),
520 fu.Metadata_ofp(1),
521 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400522 },
523 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400524 fu.PopVlan(),
525 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400526 },
527 }
khenaidoo68c930b2019-05-13 11:46:51 -0400528 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400529 derivedFlow = oltFlowAndGroup.GetFlow(1)
530 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
531}
532
533func TestDhcpReRouteRuleDecomposition(t *testing.T) {
534
535 var fa *fu.FlowArgs
536 fa = &fu.FlowArgs{
537 KV: fu.OfpFlowModArgs{"priority": 1000},
538 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400539 fu.InPort(1),
540 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
541 fu.EthType(0x0800),
542 fu.Ipv4Dst(0xffffffff),
543 fu.IpProto(17),
544 fu.UdpSrc(68),
545 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400546 },
547 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400548 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400549 },
550 }
551
khenaidoo68c930b2019-05-13 11:46:51 -0400552 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400553 groups := ofp.FlowGroups{}
554 tfd := newTestFlowDecomposer(newTestDeviceManager())
555
khenaidoo3306c992019-05-24 16:57:35 -0400556 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400557 onu1FlowAndGroup := deviceRules.Rules["onu1"]
558 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400559 assert.Nil(t, onu1FlowAndGroup)
khenaidoo89b0e942018-10-21 21:11:33 -0400560 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
561 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
562
563 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400564 KV: fu.OfpFlowModArgs{"priority": 1000},
565 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400566 fu.InPort(1),
567 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
568 fu.TunnelId(uint64(1)),
569 fu.EthType(0x0800),
570 fu.Ipv4Dst(0xffffffff),
571 fu.IpProto(17),
572 fu.UdpSrc(68),
573 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400574 },
575 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400576 fu.PushVlan(0x8100),
577 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
578 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400579 },
580 }
khenaidoo68c930b2019-05-13 11:46:51 -0400581 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400582 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400583 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
584
585 fa = &fu.FlowArgs{
586 KV: fu.OfpFlowModArgs{"priority": 1000},
587 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400588 fu.InPort(2),
589 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
590 fu.VlanPcp(0),
591 fu.Metadata_ofp(1),
592 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400593 },
594 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400595 fu.PopVlan(),
596 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400597 },
598 }
khenaidoo68c930b2019-05-13 11:46:51 -0400599 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400600 derivedFlow = oltFlowAndGroup.GetFlow(1)
601 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
602}
603
khenaidood20a5852018-10-22 22:09:55 -0400604func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
605
606 var fa *fu.FlowArgs
607 fa = &fu.FlowArgs{
608 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
609 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400610 fu.InPort(1),
611 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
612 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400613 },
614 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400615 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400616 },
617 }
618
619 var fa2 *fu.FlowArgs
620 fa2 = &fu.FlowArgs{
621 KV: fu.OfpFlowModArgs{"priority": 500},
622 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400623 fu.InPort(1),
624 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
625 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400626 },
627 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400628 fu.PushVlan(0x8100),
629 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
630 fu.SetField(fu.VlanPcp(0)),
631 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400632 },
633 }
634
khenaidoo68c930b2019-05-13 11:46:51 -0400635 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400636 groups := ofp.FlowGroups{}
637 tfd := newTestFlowDecomposer(newTestDeviceManager())
638
khenaidoo3306c992019-05-24 16:57:35 -0400639 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400640 onu1FlowAndGroup := deviceRules.Rules["onu1"]
641 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400642 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400643 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
644 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
645 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
646
647 fa = &fu.FlowArgs{
648 KV: fu.OfpFlowModArgs{"priority": 500},
649 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400650 fu.InPort(2),
651 fu.TunnelId(uint64(1)),
652 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
653 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400654 },
655 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400656 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
657 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400658 },
659 }
khenaidoo68c930b2019-05-13 11:46:51 -0400660 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400661 derivedFlow := onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400662 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
663
664 fa = &fu.FlowArgs{
665 KV: fu.OfpFlowModArgs{"priority": 500},
666 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400667 fu.InPort(1),
668 fu.TunnelId(uint64(1)),
669 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
670 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400671 },
672 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400673 fu.PushVlan(0x8100),
674 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
675 fu.SetField(fu.VlanPcp(0)),
676 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400677 },
678 }
khenaidoo68c930b2019-05-13 11:46:51 -0400679 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400680 derivedFlow = oltFlowAndGroup.GetFlow(0)
681 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
682}
683
684func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
685 var fa1 *fu.FlowArgs
686 fa1 = &fu.FlowArgs{
687 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
688 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400689 fu.InPort(10),
690 fu.Metadata_ofp((1000 << 32) | 1),
691 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400692 },
693 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400694 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400695 },
696 }
697
698 var fa2 *fu.FlowArgs
699 fa2 = &fu.FlowArgs{
700 KV: fu.OfpFlowModArgs{"priority": 500},
701 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400702 fu.InPort(10),
703 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
704 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400705 },
706 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400707 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
708 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400709 },
710 }
711
khenaidoo68c930b2019-05-13 11:46:51 -0400712 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa1), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400713 groups := ofp.FlowGroups{}
714 tfd := newTestFlowDecomposer(newTestDeviceManager())
715
khenaidoo3306c992019-05-24 16:57:35 -0400716 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400717 onu1FlowAndGroup := deviceRules.Rules["onu1"]
718 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400719 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400720 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
721 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
722 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
723
724 fa1 = &fu.FlowArgs{
725 KV: fu.OfpFlowModArgs{"priority": 500},
726 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400727 fu.InPort(2),
728 fu.Metadata_ofp(1000),
729 fu.TunnelId(uint64(1)),
730 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400731 },
732 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400733 fu.PopVlan(),
734 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400735 },
736 }
khenaidoo68c930b2019-05-13 11:46:51 -0400737 expectedOltFlow := fu.MkFlowStat(fa1)
khenaidood20a5852018-10-22 22:09:55 -0400738 derivedFlow := oltFlowAndGroup.GetFlow(0)
739 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
740
741 fa1 = &fu.FlowArgs{
742 KV: fu.OfpFlowModArgs{"priority": 500},
743 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400744 fu.InPort(1),
745 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
746 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400747 },
748 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400749 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
750 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400751 },
752 }
khenaidoo68c930b2019-05-13 11:46:51 -0400753 expectedOnu1Flow := fu.MkFlowStat(fa1)
khenaidoo3306c992019-05-24 16:57:35 -0400754 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400755 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
756}
757
758func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
759 var fa *fu.FlowArgs
760 fa = &fu.FlowArgs{
761 KV: fu.OfpFlowModArgs{"priority": 500},
762 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400763 fu.InPort(10),
764 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
765 fu.VlanPcp(0),
766 fu.EthType(0x800),
767 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400768 },
769 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400770 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400771 },
772 }
773
774 var ga *fu.GroupArgs
775 ga = &fu.GroupArgs{
776 GroupId: 10,
777 Buckets: []*ofp.OfpBucket{
778 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400779 fu.PopVlan(),
780 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400781 },
782 },
783 },
784 }
785
khenaidoo68c930b2019-05-13 11:46:51 -0400786 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
787 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{fu.MkGroupStat(ga)}}
khenaidood20a5852018-10-22 22:09:55 -0400788 tfd := newTestFlowDecomposer(newTestDeviceManager())
789
khenaidoo3306c992019-05-24 16:57:35 -0400790 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400791 onu1FlowAndGroup := deviceRules.Rules["onu1"]
792 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400793 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400794 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
795 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
796 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
797
798 fa = &fu.FlowArgs{
799 KV: fu.OfpFlowModArgs{"priority": 500},
800 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400801 fu.InPort(2),
802 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
803 fu.VlanPcp(0),
804 fu.EthType(0x800),
805 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400806 },
807 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400808 fu.PopVlan(),
809 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400810 },
811 }
khenaidoo68c930b2019-05-13 11:46:51 -0400812 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400813 derivedFlow := oltFlowAndGroup.GetFlow(0)
814 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
815
816 fa = &fu.FlowArgs{
817 KV: fu.OfpFlowModArgs{"priority": 500},
818 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400819 fu.InPort(1),
820 fu.EthType(0x800),
821 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400822 },
823 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400824 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400825 },
826 }
khenaidoo68c930b2019-05-13 11:46:51 -0400827 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400828 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400829 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
830}