blob: f4632cda4fff4f583ccf2ab11cb1a8ea86b4c1bf [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() {
Manikkaraj kb1a10922019-07-29 12:10:34 -040031 // Setup default logger - applies for packages that do not have specific logger set
32 if _, err := log.SetDefaultLogger(log.JSON, 0, log.Fields{"instanceId": 1}); err != nil {
33 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
34 }
35
36 // Update all loggers (provisioned via init) with a common field
37 if err := log.UpdateAllLoggers(log.Fields{"instanceId": 1}); err != nil {
38 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
39 }
40
41 // Update all loggers to log level specified as input parameter
42 log.SetAllLogLevel(0)
khenaidoo89b0e942018-10-21 21:11:33 -040043}
44
45type testDeviceManager struct {
46 devices map[string]*voltha.Device
47}
48
49func newTestDeviceManager() *testDeviceManager {
50 var tdm testDeviceManager
51 tdm.devices = make(map[string]*voltha.Device)
52 tdm.devices["olt"] = &voltha.Device{
53 Id: "olt",
54 Root: true,
55 ParentId: "logical_device",
56 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040057 {PortNo: 1, Label: "pon"},
58 {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040059 },
60 }
61 tdm.devices["onu1"] = &voltha.Device{
62 Id: "onu1",
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["onu2"] = &voltha.Device{
71 Id: "onu2",
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["onu3"] = &voltha.Device{
80 Id: "onu3",
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 tdm.devices["onu4"] = &voltha.Device{
89 Id: "onu4",
90 Root: false,
91 ParentId: "olt",
92 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040093 {PortNo: 1, Label: "pon"},
94 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040095 },
96 }
97 return &tdm
98}
99
100func (tdm *testDeviceManager) GetDevice(deviceId string) (*voltha.Device, error) {
101 if d, ok := tdm.devices[deviceId]; ok {
102 return d, nil
103 }
khenaidood20a5852018-10-22 22:09:55 -0400104 return nil, errors.New("ABSENT.")
khenaidoo89b0e942018-10-21 21:11:33 -0400105}
khenaidoo19d7b632018-10-30 10:49:50 -0400106func (tdm *testDeviceManager) IsRootDevice(deviceId string) (bool, error) {
107 if d, ok := tdm.devices[deviceId]; ok {
108 return d.Root, nil
109 }
110 return false, errors.New("ABSENT.")
111}
khenaidoo89b0e942018-10-21 21:11:33 -0400112
khenaidoo0a822f92019-05-08 15:15:57 -0400113func (tdm *testDeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
114 return nil
115}
116
117func (tdm *testDeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
118 return nil
119}
120
121func (tdm *testDeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
122 return nil
123}
124
125func (tdm *testDeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
126 return nil
127}
128
129func (tdm *testDeviceManager) DisableAllChildDevices(cDevice *voltha.Device) error {
130 return nil
131}
132
133func (tdm *testDeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
134 return nil
135}
136
137func (tdm *testDeviceManager) DeleteLogicalPorts(cDevice *voltha.Device) error {
138 return nil
139}
140
141func (tdm *testDeviceManager) DeleteAllChildDevices(cDevice *voltha.Device) error {
142 return nil
143}
144
145func (tdm *testDeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
146 return nil
147}
148
khenaidoo59ef7be2019-06-21 12:40:28 -0400149func (tdm *testDeviceManager) MarkChildDevicesAsUnReachable(cDevice *voltha.Device) error {
150 return nil
151}
152
khenaidoo89b0e942018-10-21 21:11:33 -0400153type testFlowDecomposer struct {
154 dMgr *testDeviceManager
155 logicalPorts map[uint32]*voltha.LogicalPort
156 routes map[graph.OFPortLink][]graph.RouteHop
157 defaultRules *fu.DeviceRules
158 deviceGraph *graph.DeviceGraph
159 fd *FlowDecomposer
160}
161
162func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
163 var tfd testFlowDecomposer
164 tfd.dMgr = deviceMgr
165
166 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
167 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
168 // port
169 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
170 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
171 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
172 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
173 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
174
175 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
176
177 //DOWNSTREAM ROUTES
178
179 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []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: "onu1",
187 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
188 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
189 },
190 }
191
192 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400193 {
khenaidoo89b0e942018-10-21 21:11:33 -0400194 DeviceID: "olt",
195 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
196 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
197 },
khenaidood20a5852018-10-22 22:09:55 -0400198 {
khenaidoo89b0e942018-10-21 21:11:33 -0400199 DeviceID: "onu2",
200 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
201 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
202 },
203 }
204 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400205 {
khenaidoo89b0e942018-10-21 21:11:33 -0400206 DeviceID: "olt",
207 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
208 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
209 },
khenaidood20a5852018-10-22 22:09:55 -0400210 {
khenaidoo89b0e942018-10-21 21:11:33 -0400211 DeviceID: "onu3",
212 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
213 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
214 },
215 }
216 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400217 {
khenaidoo89b0e942018-10-21 21:11:33 -0400218 DeviceID: "olt",
219 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
220 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
221 },
khenaidood20a5852018-10-22 22:09:55 -0400222 {
khenaidoo89b0e942018-10-21 21:11:33 -0400223 DeviceID: "onu4",
224 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
225 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
226 },
227 }
228
229 //UPSTREAM DATA PLANE
230
231 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400232 {
khenaidoo89b0e942018-10-21 21:11:33 -0400233 DeviceID: "onu1",
234 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
235 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
236 },
khenaidood20a5852018-10-22 22:09:55 -0400237 {
khenaidoo89b0e942018-10-21 21:11:33 -0400238 DeviceID: "olt",
239 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
240 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
241 },
242 }
243 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400244 {
khenaidoo89b0e942018-10-21 21:11:33 -0400245 DeviceID: "onu2",
246 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
247 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
248 },
khenaidood20a5852018-10-22 22:09:55 -0400249 {
khenaidoo89b0e942018-10-21 21:11:33 -0400250 DeviceID: "olt",
251 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
252 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
253 },
254 }
255 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400256 {
khenaidoo89b0e942018-10-21 21:11:33 -0400257 DeviceID: "onu3",
258 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
259 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
260 },
khenaidood20a5852018-10-22 22:09:55 -0400261 {
khenaidoo89b0e942018-10-21 21:11:33 -0400262 DeviceID: "olt",
263 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
264 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
265 },
266 }
267 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400268 {
khenaidoo89b0e942018-10-21 21:11:33 -0400269 DeviceID: "onu4",
270 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
271 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
272 },
khenaidood20a5852018-10-22 22:09:55 -0400273 {
khenaidoo89b0e942018-10-21 21:11:33 -0400274 DeviceID: "olt",
275 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
276 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
277 },
278 }
279
280 //UPSTREAM NEXT TABLE BASED
281
282 // openflow port 0 means absence of a port - go/protobuf interpretation
283 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400284 {
khenaidoo89b0e942018-10-21 21:11:33 -0400285 DeviceID: "onu1",
286 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
287 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
288 },
khenaidood20a5852018-10-22 22:09:55 -0400289 {
khenaidoo89b0e942018-10-21 21:11:33 -0400290 DeviceID: "olt",
291 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
292 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
293 },
294 }
295 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400296 {
khenaidoo89b0e942018-10-21 21:11:33 -0400297 DeviceID: "onu2",
298 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
299 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
300 },
khenaidood20a5852018-10-22 22:09:55 -0400301 {
khenaidoo89b0e942018-10-21 21:11:33 -0400302 DeviceID: "olt",
303 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
304 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
305 },
306 }
307 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400308 {
khenaidoo89b0e942018-10-21 21:11:33 -0400309 DeviceID: "onu3",
310 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
311 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
312 },
khenaidood20a5852018-10-22 22:09:55 -0400313 {
khenaidoo89b0e942018-10-21 21:11:33 -0400314 DeviceID: "olt",
315 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
316 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
317 },
318 }
319 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400320 {
khenaidoo89b0e942018-10-21 21:11:33 -0400321 DeviceID: "onu4",
322 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
323 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
324 },
khenaidood20a5852018-10-22 22:09:55 -0400325 {
khenaidoo89b0e942018-10-21 21:11:33 -0400326 DeviceID: "olt",
327 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
328 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
329 },
330 }
331
332 // DOWNSTREAM NEXT TABLE BASED
333
334 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400335 {
khenaidoo89b0e942018-10-21 21:11:33 -0400336 DeviceID: "olt",
337 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
338 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
339 },
khenaidood20a5852018-10-22 22:09:55 -0400340 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400341 }
342
343 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400344 {}, // 1st hop is wildcard
345 {
khenaidoo89b0e942018-10-21 21:11:33 -0400346 DeviceID: "olt",
347 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
348 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
349 },
350 }
351
352 // DEFAULT RULES
353
354 tfd.defaultRules = fu.NewDeviceRules()
355 fg := fu.NewFlowsAndGroups()
356 var fa *fu.FlowArgs
357 fa = &fu.FlowArgs{
358 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400359 fu.InPort(2),
360 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400361 },
362 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400363 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
364 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400365 },
366 }
khenaidoo68c930b2019-05-13 11:46:51 -0400367 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400368 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
369
370 fg = fu.NewFlowsAndGroups()
371 fa = &fu.FlowArgs{
372 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400373 fu.InPort(2),
374 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400375 },
376 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400377 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
378 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400379 },
380 }
khenaidoo68c930b2019-05-13 11:46:51 -0400381 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400382 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
383
384 fg = fu.NewFlowsAndGroups()
385 fa = &fu.FlowArgs{
386 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400387 fu.InPort(2),
388 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400389 },
390 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400391 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
392 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400393 },
394 }
khenaidoo68c930b2019-05-13 11:46:51 -0400395 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400396 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
397
398 fg = fu.NewFlowsAndGroups()
399 fa = &fu.FlowArgs{
400 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400401 fu.InPort(2),
402 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400403 },
404 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400405 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
406 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400407 },
408 }
khenaidoo68c930b2019-05-13 11:46:51 -0400409 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400410 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
411
412 //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 -0400413 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400414 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
415 tfd.deviceGraph.RootPorts[10] = 10
416
417 tfd.fd = NewFlowDecomposer(tfd.dMgr)
418
419 return &tfd
420}
421
422func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
423 return tfd.dMgr.GetDevice(deviceId)
424}
425
426func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
427 return ""
428}
429
khenaidoo19d7b632018-10-30 10:49:50 -0400430func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
431 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400432}
433
434func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
435 return tfd.deviceGraph
436}
437
438func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
439 return tfd.defaultRules
440}
441
442func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
443 lPorts := make([]uint32, 0)
444 var exclPort uint32
445 if len(excludePort) == 1 {
446 exclPort = excludePort[0]
447 }
khenaidood20a5852018-10-22 22:09:55 -0400448 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400449 if portno != exclPort {
450 lPorts = append(lPorts, portno)
451 }
452 }
453 return lPorts
454}
455
khenaidoo19d7b632018-10-30 10:49:50 -0400456func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400457 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400458 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400459 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400460 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400461 portLink.Egress = 10
462 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400463 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400464 }
khenaidoo19d7b632018-10-30 10:49:50 -0400465 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400466 portLink.Ingress = 0
467 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400468 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400469 }
470 for key, val := range tfd.routes {
471 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
472 return val
473 }
474 }
475 return nil
476}
477
478func TestEapolReRouteRuleDecomposition(t *testing.T) {
479
480 var fa *fu.FlowArgs
481 fa = &fu.FlowArgs{
482 KV: fu.OfpFlowModArgs{"priority": 1000},
483 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400484 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400485 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400486 },
487 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400488 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
489 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400490 },
491 }
492
khenaidoo68c930b2019-05-13 11:46:51 -0400493 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400494 groups := ofp.FlowGroups{}
495 tfd := newTestFlowDecomposer(newTestDeviceManager())
496
khenaidoo3306c992019-05-24 16:57:35 -0400497 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400498 onu1FlowAndGroup := deviceRules.Rules["onu1"]
499 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400500 assert.Nil(t, onu1FlowAndGroup)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400501 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400502 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
503
504 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400505 KV: fu.OfpFlowModArgs{"priority": 1000},
506 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400507 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400508 fu.TunnelId(uint64(1)),
509 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400510 },
511 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400512 fu.PushVlan(0x8100),
513 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
514 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400515 },
516 }
khenaidoo68c930b2019-05-13 11:46:51 -0400517 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400518 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400519 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400520}
521
522func TestDhcpReRouteRuleDecomposition(t *testing.T) {
523
524 var fa *fu.FlowArgs
525 fa = &fu.FlowArgs{
526 KV: fu.OfpFlowModArgs{"priority": 1000},
527 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400528 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400529 fu.EthType(0x0800),
530 fu.Ipv4Dst(0xffffffff),
531 fu.IpProto(17),
532 fu.UdpSrc(68),
533 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400534 },
535 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400536 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400537 },
538 }
539
khenaidoo68c930b2019-05-13 11:46:51 -0400540 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400541 groups := ofp.FlowGroups{}
542 tfd := newTestFlowDecomposer(newTestDeviceManager())
543
khenaidoo3306c992019-05-24 16:57:35 -0400544 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400545 onu1FlowAndGroup := deviceRules.Rules["onu1"]
546 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400547 assert.Nil(t, onu1FlowAndGroup)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400548 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400549 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
550
551 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400552 KV: fu.OfpFlowModArgs{"priority": 1000},
553 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400554 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400555 fu.TunnelId(uint64(1)),
556 fu.EthType(0x0800),
557 fu.Ipv4Dst(0xffffffff),
558 fu.IpProto(17),
559 fu.UdpSrc(68),
560 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400561 },
562 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400563 fu.PushVlan(0x8100),
564 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
565 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400566 },
567 }
khenaidoo68c930b2019-05-13 11:46:51 -0400568 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400569 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400570 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400571}
572
khenaidood20a5852018-10-22 22:09:55 -0400573func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
khenaidood20a5852018-10-22 22:09:55 -0400574 var fa *fu.FlowArgs
575 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400576 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400577 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400578 fu.InPort(1),
579 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
580 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400581 },
582 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400583 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400584 },
585 }
586
587 var fa2 *fu.FlowArgs
588 fa2 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400589 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400590 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400591 fu.InPort(1),
592 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
593 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400594 },
595 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400596 fu.PushVlan(0x8100),
597 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
598 fu.SetField(fu.VlanPcp(0)),
599 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400600 },
601 }
602
khenaidoo68c930b2019-05-13 11:46:51 -0400603 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa), fu.MkFlowStat(fa2)}}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400604 flows.Items[0].Instructions = []*ofp.OfpInstruction{{
605 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
606 Data: &ofp.OfpInstruction_GotoTable{
607 GotoTable: &ofp.OfpInstructionGotoTable{
608 TableId: 1,
609 },
610 }}}
611
khenaidood20a5852018-10-22 22:09:55 -0400612 groups := ofp.FlowGroups{}
613 tfd := newTestFlowDecomposer(newTestDeviceManager())
614
khenaidoo3306c992019-05-24 16:57:35 -0400615 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400616 onu1FlowAndGroup := deviceRules.Rules["onu1"]
617 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400618 assert.NotNil(t, onu1FlowAndGroup)
619 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400620 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400621 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
622 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
623 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
624
625 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400626 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400627 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400628 fu.InPort(2),
629 fu.TunnelId(uint64(1)),
630 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
631 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400632 },
633 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400634 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
635 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400636 },
637 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400638
khenaidoo3306c992019-05-24 16:57:35 -0400639 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400640 // Form the expected flow
641 expectedOnu1Flow := fu.MkFlowStat(fa)
642 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
643 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
644 Data: &ofp.OfpInstruction_Actions{
645 Actions: &ofp.OfpInstructionActions{
646 Actions: []*ofp.OfpAction{{
647 Type: 0,
648 Action: &ofp.OfpAction_Output{
649 Output: &ofp.OfpActionOutput{
650 Port: 1,
651 MaxLen: 65509,
652 },
653 }}}}}}}
654
655 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400656 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
657
658 fa = &fu.FlowArgs{
659 KV: fu.OfpFlowModArgs{"priority": 500},
660 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400661 fu.InPort(1),
662 fu.TunnelId(uint64(1)),
663 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
664 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400665 },
666 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400667 fu.PushVlan(0x8100),
668 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
669 fu.SetField(fu.VlanPcp(0)),
670 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400671 },
672 }
khenaidoo68c930b2019-05-13 11:46:51 -0400673 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400674 derivedFlow = oltFlowAndGroup.GetFlow(0)
675 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
676}
677
678func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400679 log.Debugf("Starting Test Unicast Downstream")
khenaidood20a5852018-10-22 22:09:55 -0400680 var fa1 *fu.FlowArgs
681 fa1 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400682 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400683 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400684 fu.InPort(10),
685 fu.Metadata_ofp((1000 << 32) | 1),
686 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400687 },
688 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400689 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400690 },
691 }
692
693 var fa2 *fu.FlowArgs
694 fa2 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400695 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400696 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400697 fu.InPort(10),
698 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
699 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400700 },
701 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400702 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
703 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400704 },
705 }
706
khenaidoo68c930b2019-05-13 11:46:51 -0400707 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa1), fu.MkFlowStat(fa2)}}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400708 flows.Items[0].Instructions = []*ofp.OfpInstruction{{
709 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
710 Data: &ofp.OfpInstruction_GotoTable{
711 GotoTable: &ofp.OfpInstructionGotoTable{
712 TableId: 1,
713 },
714 }}}
715
khenaidood20a5852018-10-22 22:09:55 -0400716 groups := ofp.FlowGroups{}
717 tfd := newTestFlowDecomposer(newTestDeviceManager())
718
khenaidoo3306c992019-05-24 16:57:35 -0400719 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400720
khenaidood20a5852018-10-22 22:09:55 -0400721 onu1FlowAndGroup := deviceRules.Rules["onu1"]
722 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400723 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400724 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
725 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
726 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
727
728 fa1 = &fu.FlowArgs{
729 KV: fu.OfpFlowModArgs{"priority": 500},
730 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400731 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400732 fu.TunnelId(uint64(10)),
733 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400734 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400735 },
736 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400737 fu.PopVlan(),
738 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400739 },
740 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400741
khenaidood20a5852018-10-22 22:09:55 -0400742 derivedFlow := oltFlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400743 expectedOltFlow := fu.MkFlowStat(fa1)
744 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
745 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
746 Data: &ofp.OfpInstruction_Actions{
747 Actions: &ofp.OfpInstructionActions{
748 Actions: []*ofp.OfpAction{{
749 Type: 0,
750 Action: &ofp.OfpAction_Output{
751 Output: &ofp.OfpActionOutput{
752 Port: 1,
753 MaxLen: 65509,
754 },
755 }}}}}}}
756 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400757 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
758
759 fa1 = &fu.FlowArgs{
760 KV: fu.OfpFlowModArgs{"priority": 500},
761 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400762 fu.InPort(1),
763 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
764 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400765 },
766 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400767 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
768 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400769 },
770 }
khenaidoo68c930b2019-05-13 11:46:51 -0400771 expectedOnu1Flow := fu.MkFlowStat(fa1)
khenaidoo3306c992019-05-24 16:57:35 -0400772 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400773 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
774}
775
776func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
777 var fa *fu.FlowArgs
778 fa = &fu.FlowArgs{
779 KV: fu.OfpFlowModArgs{"priority": 500},
780 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400781 fu.InPort(10),
782 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
783 fu.VlanPcp(0),
784 fu.EthType(0x800),
785 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400786 },
787 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400788 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400789 },
790 }
791
792 var ga *fu.GroupArgs
793 ga = &fu.GroupArgs{
794 GroupId: 10,
795 Buckets: []*ofp.OfpBucket{
796 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400797 fu.PopVlan(),
798 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400799 },
800 },
801 },
802 }
803
khenaidoo68c930b2019-05-13 11:46:51 -0400804 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
805 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{fu.MkGroupStat(ga)}}
khenaidood20a5852018-10-22 22:09:55 -0400806 tfd := newTestFlowDecomposer(newTestDeviceManager())
807
khenaidoo3306c992019-05-24 16:57:35 -0400808 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400809 onu1FlowAndGroup := deviceRules.Rules["onu1"]
810 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400811 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400812 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
813 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
814 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
815
816 fa = &fu.FlowArgs{
817 KV: fu.OfpFlowModArgs{"priority": 500},
818 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400819 fu.InPort(2),
820 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
821 fu.VlanPcp(0),
822 fu.EthType(0x800),
823 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400824 },
825 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400826 fu.PopVlan(),
827 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400828 },
829 }
khenaidoo68c930b2019-05-13 11:46:51 -0400830 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400831 derivedFlow := oltFlowAndGroup.GetFlow(0)
832 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
833
834 fa = &fu.FlowArgs{
835 KV: fu.OfpFlowModArgs{"priority": 500},
836 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400837 fu.InPort(1),
838 fu.EthType(0x800),
839 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400840 },
841 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400842 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400843 },
844 }
khenaidoo68c930b2019-05-13 11:46:51 -0400845 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400846 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400847 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
848}