blob: 42e42e6730aaa69349297798fac9fd78ba3db010 [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
khenaidoo89b0e942018-10-21 21:11:33 -0400140type testFlowDecomposer struct {
141 dMgr *testDeviceManager
142 logicalPorts map[uint32]*voltha.LogicalPort
143 routes map[graph.OFPortLink][]graph.RouteHop
144 defaultRules *fu.DeviceRules
145 deviceGraph *graph.DeviceGraph
146 fd *FlowDecomposer
147}
148
149func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
150 var tfd testFlowDecomposer
151 tfd.dMgr = deviceMgr
152
153 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
154 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
155 // port
156 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
157 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
158 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
159 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
160 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
161
162 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
163
164 //DOWNSTREAM ROUTES
165
166 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400167 {
khenaidoo89b0e942018-10-21 21:11:33 -0400168 DeviceID: "olt",
169 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
170 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
171 },
khenaidood20a5852018-10-22 22:09:55 -0400172 {
khenaidoo89b0e942018-10-21 21:11:33 -0400173 DeviceID: "onu1",
174 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
175 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
176 },
177 }
178
179 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400180 {
khenaidoo89b0e942018-10-21 21:11:33 -0400181 DeviceID: "olt",
182 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
183 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
184 },
khenaidood20a5852018-10-22 22:09:55 -0400185 {
khenaidoo89b0e942018-10-21 21:11:33 -0400186 DeviceID: "onu2",
187 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
188 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
189 },
190 }
191 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400192 {
khenaidoo89b0e942018-10-21 21:11:33 -0400193 DeviceID: "olt",
194 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
195 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
196 },
khenaidood20a5852018-10-22 22:09:55 -0400197 {
khenaidoo89b0e942018-10-21 21:11:33 -0400198 DeviceID: "onu3",
199 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
200 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
201 },
202 }
203 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400204 {
khenaidoo89b0e942018-10-21 21:11:33 -0400205 DeviceID: "olt",
206 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
207 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
208 },
khenaidood20a5852018-10-22 22:09:55 -0400209 {
khenaidoo89b0e942018-10-21 21:11:33 -0400210 DeviceID: "onu4",
211 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
212 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
213 },
214 }
215
216 //UPSTREAM DATA PLANE
217
218 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400219 {
khenaidoo89b0e942018-10-21 21:11:33 -0400220 DeviceID: "onu1",
221 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
222 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
223 },
khenaidood20a5852018-10-22 22:09:55 -0400224 {
khenaidoo89b0e942018-10-21 21:11:33 -0400225 DeviceID: "olt",
226 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
227 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
228 },
229 }
230 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400231 {
khenaidoo89b0e942018-10-21 21:11:33 -0400232 DeviceID: "onu2",
233 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
234 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
235 },
khenaidood20a5852018-10-22 22:09:55 -0400236 {
khenaidoo89b0e942018-10-21 21:11:33 -0400237 DeviceID: "olt",
238 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
239 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
240 },
241 }
242 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400243 {
khenaidoo89b0e942018-10-21 21:11:33 -0400244 DeviceID: "onu3",
245 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
246 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
247 },
khenaidood20a5852018-10-22 22:09:55 -0400248 {
khenaidoo89b0e942018-10-21 21:11:33 -0400249 DeviceID: "olt",
250 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
251 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
252 },
253 }
254 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400255 {
khenaidoo89b0e942018-10-21 21:11:33 -0400256 DeviceID: "onu4",
257 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
258 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
259 },
khenaidood20a5852018-10-22 22:09:55 -0400260 {
khenaidoo89b0e942018-10-21 21:11:33 -0400261 DeviceID: "olt",
262 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
263 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
264 },
265 }
266
267 //UPSTREAM NEXT TABLE BASED
268
269 // openflow port 0 means absence of a port - go/protobuf interpretation
270 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400271 {
khenaidoo89b0e942018-10-21 21:11:33 -0400272 DeviceID: "onu1",
273 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
274 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
275 },
khenaidood20a5852018-10-22 22:09:55 -0400276 {
khenaidoo89b0e942018-10-21 21:11:33 -0400277 DeviceID: "olt",
278 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
279 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
280 },
281 }
282 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400283 {
khenaidoo89b0e942018-10-21 21:11:33 -0400284 DeviceID: "onu2",
285 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
286 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
287 },
khenaidood20a5852018-10-22 22:09:55 -0400288 {
khenaidoo89b0e942018-10-21 21:11:33 -0400289 DeviceID: "olt",
290 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
291 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
292 },
293 }
294 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400295 {
khenaidoo89b0e942018-10-21 21:11:33 -0400296 DeviceID: "onu3",
297 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
298 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
299 },
khenaidood20a5852018-10-22 22:09:55 -0400300 {
khenaidoo89b0e942018-10-21 21:11:33 -0400301 DeviceID: "olt",
302 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
303 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
304 },
305 }
306 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400307 {
khenaidoo89b0e942018-10-21 21:11:33 -0400308 DeviceID: "onu4",
309 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
310 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
311 },
khenaidood20a5852018-10-22 22:09:55 -0400312 {
khenaidoo89b0e942018-10-21 21:11:33 -0400313 DeviceID: "olt",
314 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
315 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
316 },
317 }
318
319 // DOWNSTREAM NEXT TABLE BASED
320
321 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400322 {
khenaidoo89b0e942018-10-21 21:11:33 -0400323 DeviceID: "olt",
324 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
325 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
326 },
khenaidood20a5852018-10-22 22:09:55 -0400327 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400328 }
329
330 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400331 {}, // 1st hop is wildcard
332 {
khenaidoo89b0e942018-10-21 21:11:33 -0400333 DeviceID: "olt",
334 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
335 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
336 },
337 }
338
339 // DEFAULT RULES
340
341 tfd.defaultRules = fu.NewDeviceRules()
342 fg := fu.NewFlowsAndGroups()
343 var fa *fu.FlowArgs
344 fa = &fu.FlowArgs{
345 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400346 fu.InPort(2),
347 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400348 },
349 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400350 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
351 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400352 },
353 }
khenaidoo68c930b2019-05-13 11:46:51 -0400354 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400355 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
356
357 fg = fu.NewFlowsAndGroups()
358 fa = &fu.FlowArgs{
359 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400360 fu.InPort(2),
361 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400362 },
363 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400364 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
365 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400366 },
367 }
khenaidoo68c930b2019-05-13 11:46:51 -0400368 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400369 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
370
371 fg = fu.NewFlowsAndGroups()
372 fa = &fu.FlowArgs{
373 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400374 fu.InPort(2),
375 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400376 },
377 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400378 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
379 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400380 },
381 }
khenaidoo68c930b2019-05-13 11:46:51 -0400382 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400383 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
384
385 fg = fu.NewFlowsAndGroups()
386 fa = &fu.FlowArgs{
387 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400388 fu.InPort(2),
389 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400390 },
391 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400392 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
393 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400394 },
395 }
khenaidoo68c930b2019-05-13 11:46:51 -0400396 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400397 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
398
399 //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 -0400400 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400401 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
402 tfd.deviceGraph.RootPorts[10] = 10
403
404 tfd.fd = NewFlowDecomposer(tfd.dMgr)
405
406 return &tfd
407}
408
409func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
410 return tfd.dMgr.GetDevice(deviceId)
411}
412
413func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
414 return ""
415}
416
khenaidoo19d7b632018-10-30 10:49:50 -0400417func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
418 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400419}
420
421func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
422 return tfd.deviceGraph
423}
424
425func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
426 return tfd.defaultRules
427}
428
429func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
430 lPorts := make([]uint32, 0)
431 var exclPort uint32
432 if len(excludePort) == 1 {
433 exclPort = excludePort[0]
434 }
khenaidood20a5852018-10-22 22:09:55 -0400435 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400436 if portno != exclPort {
437 lPorts = append(lPorts, portno)
438 }
439 }
440 return lPorts
441}
442
khenaidoo19d7b632018-10-30 10:49:50 -0400443func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400444 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400445 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400446 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400447 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400448 portLink.Egress = 10
449 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400450 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400451 }
khenaidoo19d7b632018-10-30 10:49:50 -0400452 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400453 portLink.Ingress = 0
454 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400455 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400456 }
457 for key, val := range tfd.routes {
458 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
459 return val
460 }
461 }
462 return nil
463}
464
465func TestEapolReRouteRuleDecomposition(t *testing.T) {
466
467 var fa *fu.FlowArgs
468 fa = &fu.FlowArgs{
469 KV: fu.OfpFlowModArgs{"priority": 1000},
470 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400471 fu.InPort(1),
472 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
473 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400474 },
475 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400476 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
477 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400478 },
479 }
480
khenaidoo68c930b2019-05-13 11:46:51 -0400481 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400482 groups := ofp.FlowGroups{}
483 tfd := newTestFlowDecomposer(newTestDeviceManager())
484
khenaidoo3306c992019-05-24 16:57:35 -0400485 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400486 onu1FlowAndGroup := deviceRules.Rules["onu1"]
487 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400488 assert.Nil(t, onu1FlowAndGroup)
khenaidoo89b0e942018-10-21 21:11:33 -0400489 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
490 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
491
492 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400493 KV: fu.OfpFlowModArgs{"priority": 1000},
494 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400495 fu.InPort(1),
496 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
497 fu.TunnelId(uint64(1)),
498 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400499 },
500 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400501 fu.PushVlan(0x8100),
502 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
503 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400504 },
505 }
khenaidoo68c930b2019-05-13 11:46:51 -0400506 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400507 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400508 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
509
510 fa = &fu.FlowArgs{
511 KV: fu.OfpFlowModArgs{"priority": 1000},
512 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400513 fu.InPort(2),
514 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
515 fu.VlanPcp(0),
516 fu.Metadata_ofp(1),
517 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400518 },
519 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400520 fu.PopVlan(),
521 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400522 },
523 }
khenaidoo68c930b2019-05-13 11:46:51 -0400524 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400525 derivedFlow = oltFlowAndGroup.GetFlow(1)
526 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
527}
528
529func TestDhcpReRouteRuleDecomposition(t *testing.T) {
530
531 var fa *fu.FlowArgs
532 fa = &fu.FlowArgs{
533 KV: fu.OfpFlowModArgs{"priority": 1000},
534 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400535 fu.InPort(1),
536 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
537 fu.EthType(0x0800),
538 fu.Ipv4Dst(0xffffffff),
539 fu.IpProto(17),
540 fu.UdpSrc(68),
541 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400542 },
543 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400544 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400545 },
546 }
547
khenaidoo68c930b2019-05-13 11:46:51 -0400548 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400549 groups := ofp.FlowGroups{}
550 tfd := newTestFlowDecomposer(newTestDeviceManager())
551
khenaidoo3306c992019-05-24 16:57:35 -0400552 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400553 onu1FlowAndGroup := deviceRules.Rules["onu1"]
554 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400555 assert.Nil(t, onu1FlowAndGroup)
khenaidoo89b0e942018-10-21 21:11:33 -0400556 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
557 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
558
559 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400560 KV: fu.OfpFlowModArgs{"priority": 1000},
561 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400562 fu.InPort(1),
563 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
564 fu.TunnelId(uint64(1)),
565 fu.EthType(0x0800),
566 fu.Ipv4Dst(0xffffffff),
567 fu.IpProto(17),
568 fu.UdpSrc(68),
569 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400570 },
571 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400572 fu.PushVlan(0x8100),
573 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
574 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400575 },
576 }
khenaidoo68c930b2019-05-13 11:46:51 -0400577 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400578 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400579 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
580
581 fa = &fu.FlowArgs{
582 KV: fu.OfpFlowModArgs{"priority": 1000},
583 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400584 fu.InPort(2),
585 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
586 fu.VlanPcp(0),
587 fu.Metadata_ofp(1),
588 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400589 },
590 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400591 fu.PopVlan(),
592 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400593 },
594 }
khenaidoo68c930b2019-05-13 11:46:51 -0400595 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400596 derivedFlow = oltFlowAndGroup.GetFlow(1)
597 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
598}
599
khenaidood20a5852018-10-22 22:09:55 -0400600func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
601
602 var fa *fu.FlowArgs
603 fa = &fu.FlowArgs{
604 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
605 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400606 fu.InPort(1),
607 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
608 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400609 },
610 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400611 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400612 },
613 }
614
615 var fa2 *fu.FlowArgs
616 fa2 = &fu.FlowArgs{
617 KV: fu.OfpFlowModArgs{"priority": 500},
618 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400619 fu.InPort(1),
620 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
621 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400622 },
623 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400624 fu.PushVlan(0x8100),
625 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
626 fu.SetField(fu.VlanPcp(0)),
627 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400628 },
629 }
630
khenaidoo68c930b2019-05-13 11:46:51 -0400631 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400632 groups := ofp.FlowGroups{}
633 tfd := newTestFlowDecomposer(newTestDeviceManager())
634
khenaidoo3306c992019-05-24 16:57:35 -0400635 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400636 onu1FlowAndGroup := deviceRules.Rules["onu1"]
637 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400638 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400639 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
640 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
641 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
642
643 fa = &fu.FlowArgs{
644 KV: fu.OfpFlowModArgs{"priority": 500},
645 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400646 fu.InPort(2),
647 fu.TunnelId(uint64(1)),
648 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
649 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400650 },
651 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400652 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
653 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400654 },
655 }
khenaidoo68c930b2019-05-13 11:46:51 -0400656 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400657 derivedFlow := onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400658 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
659
660 fa = &fu.FlowArgs{
661 KV: fu.OfpFlowModArgs{"priority": 500},
662 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400663 fu.InPort(1),
664 fu.TunnelId(uint64(1)),
665 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
666 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400667 },
668 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400669 fu.PushVlan(0x8100),
670 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
671 fu.SetField(fu.VlanPcp(0)),
672 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400673 },
674 }
khenaidoo68c930b2019-05-13 11:46:51 -0400675 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400676 derivedFlow = oltFlowAndGroup.GetFlow(0)
677 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
678}
679
680func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
681 var fa1 *fu.FlowArgs
682 fa1 = &fu.FlowArgs{
683 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
684 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400685 fu.InPort(10),
686 fu.Metadata_ofp((1000 << 32) | 1),
687 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400688 },
689 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400690 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400691 },
692 }
693
694 var fa2 *fu.FlowArgs
695 fa2 = &fu.FlowArgs{
696 KV: fu.OfpFlowModArgs{"priority": 500},
697 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400698 fu.InPort(10),
699 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
700 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400701 },
702 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400703 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
704 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400705 },
706 }
707
khenaidoo68c930b2019-05-13 11:46:51 -0400708 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa1), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400709 groups := ofp.FlowGroups{}
710 tfd := newTestFlowDecomposer(newTestDeviceManager())
711
khenaidoo3306c992019-05-24 16:57:35 -0400712 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400713 onu1FlowAndGroup := deviceRules.Rules["onu1"]
714 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400715 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400716 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
717 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
718 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
719
720 fa1 = &fu.FlowArgs{
721 KV: fu.OfpFlowModArgs{"priority": 500},
722 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400723 fu.InPort(2),
724 fu.Metadata_ofp(1000),
725 fu.TunnelId(uint64(1)),
726 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400727 },
728 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400729 fu.PopVlan(),
730 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400731 },
732 }
khenaidoo68c930b2019-05-13 11:46:51 -0400733 expectedOltFlow := fu.MkFlowStat(fa1)
khenaidood20a5852018-10-22 22:09:55 -0400734 derivedFlow := oltFlowAndGroup.GetFlow(0)
735 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
736
737 fa1 = &fu.FlowArgs{
738 KV: fu.OfpFlowModArgs{"priority": 500},
739 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400740 fu.InPort(1),
741 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
742 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400743 },
744 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400745 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
746 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400747 },
748 }
khenaidoo68c930b2019-05-13 11:46:51 -0400749 expectedOnu1Flow := fu.MkFlowStat(fa1)
khenaidoo3306c992019-05-24 16:57:35 -0400750 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400751 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
752}
753
754func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
755 var fa *fu.FlowArgs
756 fa = &fu.FlowArgs{
757 KV: fu.OfpFlowModArgs{"priority": 500},
758 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400759 fu.InPort(10),
760 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
761 fu.VlanPcp(0),
762 fu.EthType(0x800),
763 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400764 },
765 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400766 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400767 },
768 }
769
770 var ga *fu.GroupArgs
771 ga = &fu.GroupArgs{
772 GroupId: 10,
773 Buckets: []*ofp.OfpBucket{
774 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400775 fu.PopVlan(),
776 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400777 },
778 },
779 },
780 }
781
khenaidoo68c930b2019-05-13 11:46:51 -0400782 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
783 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{fu.MkGroupStat(ga)}}
khenaidood20a5852018-10-22 22:09:55 -0400784 tfd := newTestFlowDecomposer(newTestDeviceManager())
785
khenaidoo3306c992019-05-24 16:57:35 -0400786 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400787 onu1FlowAndGroup := deviceRules.Rules["onu1"]
788 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400789 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400790 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
791 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
792 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
793
794 fa = &fu.FlowArgs{
795 KV: fu.OfpFlowModArgs{"priority": 500},
796 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400797 fu.InPort(2),
798 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
799 fu.VlanPcp(0),
800 fu.EthType(0x800),
801 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400802 },
803 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400804 fu.PopVlan(),
805 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400806 },
807 }
khenaidoo68c930b2019-05-13 11:46:51 -0400808 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400809 derivedFlow := oltFlowAndGroup.GetFlow(0)
810 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
811
812 fa = &fu.FlowArgs{
813 KV: fu.OfpFlowModArgs{"priority": 500},
814 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400815 fu.InPort(1),
816 fu.EthType(0x800),
817 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400818 },
819 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400820 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400821 },
822 }
khenaidoo68c930b2019-05-13 11:46:51 -0400823 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400824 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400825 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
826}