blob: 5e1dbe7e85e9d5d1ecb451c56e5c9d2d30d23fc7 [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 }
Humera Kouser4ff89012019-08-25 19:01:51 -0400228 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 10}] = []graph.RouteHop{
229 {
230 DeviceID: "olt",
231 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
232 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
233 },
234 {
235 DeviceID: "olt",
236 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
237 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
238 },
239 }
khenaidoo89b0e942018-10-21 21:11:33 -0400240
241 //UPSTREAM DATA PLANE
242
243 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400244 {
khenaidoo89b0e942018-10-21 21:11:33 -0400245 DeviceID: "onu1",
246 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
247 Egress: tfd.dMgr.devices["onu1"].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: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400256 {
khenaidoo89b0e942018-10-21 21:11:33 -0400257 DeviceID: "onu2",
258 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
259 Egress: tfd.dMgr.devices["onu2"].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: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400268 {
khenaidoo89b0e942018-10-21 21:11:33 -0400269 DeviceID: "onu3",
270 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
271 Egress: tfd.dMgr.devices["onu3"].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 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400280 {
khenaidoo89b0e942018-10-21 21:11:33 -0400281 DeviceID: "onu4",
282 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
283 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
284 },
khenaidood20a5852018-10-22 22:09:55 -0400285 {
khenaidoo89b0e942018-10-21 21:11:33 -0400286 DeviceID: "olt",
287 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
288 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
289 },
290 }
291
292 //UPSTREAM NEXT TABLE BASED
293
294 // openflow port 0 means absence of a port - go/protobuf interpretation
295 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400296 {
khenaidoo89b0e942018-10-21 21:11:33 -0400297 DeviceID: "onu1",
298 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
299 Egress: tfd.dMgr.devices["onu1"].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: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400308 {
khenaidoo89b0e942018-10-21 21:11:33 -0400309 DeviceID: "onu2",
310 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
311 Egress: tfd.dMgr.devices["onu2"].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: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400320 {
khenaidoo89b0e942018-10-21 21:11:33 -0400321 DeviceID: "onu3",
322 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
323 Egress: tfd.dMgr.devices["onu3"].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 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400332 {
khenaidoo89b0e942018-10-21 21:11:33 -0400333 DeviceID: "onu4",
334 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
335 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
336 },
khenaidood20a5852018-10-22 22:09:55 -0400337 {
khenaidoo89b0e942018-10-21 21:11:33 -0400338 DeviceID: "olt",
339 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
340 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
341 },
342 }
343
344 // DOWNSTREAM NEXT TABLE BASED
345
346 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400347 {
khenaidoo89b0e942018-10-21 21:11:33 -0400348 DeviceID: "olt",
349 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
350 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
351 },
khenaidood20a5852018-10-22 22:09:55 -0400352 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400353 }
354
355 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400356 {}, // 1st hop is wildcard
357 {
khenaidoo89b0e942018-10-21 21:11:33 -0400358 DeviceID: "olt",
359 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
360 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
361 },
362 }
363
364 // DEFAULT RULES
365
366 tfd.defaultRules = fu.NewDeviceRules()
367 fg := fu.NewFlowsAndGroups()
368 var fa *fu.FlowArgs
369 fa = &fu.FlowArgs{
370 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400371 fu.InPort(2),
372 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400373 },
374 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400375 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
376 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400377 },
378 }
khenaidoo68c930b2019-05-13 11:46:51 -0400379 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400380 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
381
382 fg = fu.NewFlowsAndGroups()
383 fa = &fu.FlowArgs{
384 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400385 fu.InPort(2),
386 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400387 },
388 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400389 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
390 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400391 },
392 }
khenaidoo68c930b2019-05-13 11:46:51 -0400393 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400394 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
395
396 fg = fu.NewFlowsAndGroups()
397 fa = &fu.FlowArgs{
398 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400399 fu.InPort(2),
400 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400401 },
402 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400403 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
404 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400405 },
406 }
khenaidoo68c930b2019-05-13 11:46:51 -0400407 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400408 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
409
410 fg = fu.NewFlowsAndGroups()
411 fa = &fu.FlowArgs{
412 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400413 fu.InPort(2),
414 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400415 },
416 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400417 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
418 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400419 },
420 }
khenaidoo68c930b2019-05-13 11:46:51 -0400421 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400422 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
423
424 //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 -0400425 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400426 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
427 tfd.deviceGraph.RootPorts[10] = 10
428
429 tfd.fd = NewFlowDecomposer(tfd.dMgr)
430
431 return &tfd
432}
433
434func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
435 return tfd.dMgr.GetDevice(deviceId)
436}
437
438func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
439 return ""
440}
441
khenaidoo19d7b632018-10-30 10:49:50 -0400442func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
443 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400444}
445
446func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
447 return tfd.deviceGraph
448}
449
450func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
451 return tfd.defaultRules
452}
453
454func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
455 lPorts := make([]uint32, 0)
456 var exclPort uint32
457 if len(excludePort) == 1 {
458 exclPort = excludePort[0]
459 }
khenaidood20a5852018-10-22 22:09:55 -0400460 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400461 if portno != exclPort {
462 lPorts = append(lPorts, portno)
463 }
464 }
465 return lPorts
466}
467
khenaidoo19d7b632018-10-30 10:49:50 -0400468func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400469 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400470 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400471 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400472 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400473 portLink.Egress = 10
474 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400475 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400476 }
khenaidoo19d7b632018-10-30 10:49:50 -0400477 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400478 portLink.Ingress = 0
479 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400480 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400481 }
482 for key, val := range tfd.routes {
483 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
484 return val
485 }
486 }
487 return nil
488}
489
490func TestEapolReRouteRuleDecomposition(t *testing.T) {
491
492 var fa *fu.FlowArgs
493 fa = &fu.FlowArgs{
494 KV: fu.OfpFlowModArgs{"priority": 1000},
495 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400496 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400497 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400498 },
499 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400500 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
501 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400502 },
503 }
504
khenaidoo68c930b2019-05-13 11:46:51 -0400505 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400506 groups := ofp.FlowGroups{}
507 tfd := newTestFlowDecomposer(newTestDeviceManager())
508
khenaidoo3306c992019-05-24 16:57:35 -0400509 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400510 onu1FlowAndGroup := deviceRules.Rules["onu1"]
511 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400512 assert.Nil(t, onu1FlowAndGroup)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400513 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400514 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
515
516 fa = &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400517 KV: fu.OfpFlowModArgs{"priority": 1000},
518 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400519 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400520 fu.TunnelId(uint64(1)),
521 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400522 },
523 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400524 fu.PushVlan(0x8100),
525 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
526 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400527 },
528 }
khenaidoo68c930b2019-05-13 11:46:51 -0400529 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400530 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400531 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400532}
533
534func TestDhcpReRouteRuleDecomposition(t *testing.T) {
535
536 var fa *fu.FlowArgs
537 fa = &fu.FlowArgs{
538 KV: fu.OfpFlowModArgs{"priority": 1000},
539 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400540 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400541 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)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400560 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400561 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),
khenaidoo68c930b2019-05-13 11:46:51 -0400567 fu.TunnelId(uint64(1)),
568 fu.EthType(0x0800),
569 fu.Ipv4Dst(0xffffffff),
570 fu.IpProto(17),
571 fu.UdpSrc(68),
572 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400573 },
574 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400575 fu.PushVlan(0x8100),
576 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
577 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400578 },
579 }
khenaidoo68c930b2019-05-13 11:46:51 -0400580 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400581 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400582 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400583}
584
Humera Kouser4ff89012019-08-25 19:01:51 -0400585func TestLldpReRouteRuleDecomposition(t *testing.T) {
586 var fa *fu.FlowArgs
587 fa = &fu.FlowArgs{
588 KV: fu.OfpFlowModArgs{"priority": 1000},
589 MatchFields: []*ofp.OfpOxmOfbField{
590 fu.InPort(10),
591 fu.EthType(0x88CC),
592 },
593 Actions: []*ofp.OfpAction{
594 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
595 },
596 }
597
598 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
599 groups := ofp.FlowGroups{}
600 tfd := newTestFlowDecomposer(newTestDeviceManager())
601 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
602 onu1FlowAndGroup := deviceRules.Rules["onu1"]
603 oltFlowAndGroup := deviceRules.Rules["olt"]
604 assert.Nil(t, onu1FlowAndGroup)
605 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
606 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
607
608 fa = &fu.FlowArgs{
609 KV: fu.OfpFlowModArgs{"priority": 1000},
610 MatchFields: []*ofp.OfpOxmOfbField{
611 fu.InPort(2),
612 fu.EthType(0x88CC),
613 },
614 Actions: []*ofp.OfpAction{
615 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
616 },
617 }
618 expectedOltFlow := fu.MkFlowStat(fa)
619 derivedFlow := oltFlowAndGroup.GetFlow(0)
620 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
621}
622
khenaidood20a5852018-10-22 22:09:55 -0400623func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
khenaidood20a5852018-10-22 22:09:55 -0400624 var fa *fu.FlowArgs
625 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400626 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400627 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400628 fu.InPort(1),
629 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
630 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400631 },
632 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400633 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400634 },
635 }
636
637 var fa2 *fu.FlowArgs
638 fa2 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400639 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400640 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400641 fu.InPort(1),
642 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
643 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400644 },
645 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400646 fu.PushVlan(0x8100),
647 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
648 fu.SetField(fu.VlanPcp(0)),
649 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400650 },
651 }
652
khenaidoo68c930b2019-05-13 11:46:51 -0400653 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa), fu.MkFlowStat(fa2)}}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400654 flows.Items[0].Instructions = []*ofp.OfpInstruction{{
655 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
656 Data: &ofp.OfpInstruction_GotoTable{
657 GotoTable: &ofp.OfpInstructionGotoTable{
658 TableId: 1,
659 },
660 }}}
661
khenaidood20a5852018-10-22 22:09:55 -0400662 groups := ofp.FlowGroups{}
663 tfd := newTestFlowDecomposer(newTestDeviceManager())
664
khenaidoo3306c992019-05-24 16:57:35 -0400665 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400666 onu1FlowAndGroup := deviceRules.Rules["onu1"]
667 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400668 assert.NotNil(t, onu1FlowAndGroup)
669 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400670 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400671 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
672 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
673 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
674
675 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400676 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400677 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400678 fu.InPort(2),
679 fu.TunnelId(uint64(1)),
680 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
681 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400682 },
683 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400684 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
685 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400686 },
687 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400688
khenaidoo3306c992019-05-24 16:57:35 -0400689 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400690 // Form the expected flow
691 expectedOnu1Flow := fu.MkFlowStat(fa)
692 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
693 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
694 Data: &ofp.OfpInstruction_Actions{
695 Actions: &ofp.OfpInstructionActions{
696 Actions: []*ofp.OfpAction{{
697 Type: 0,
698 Action: &ofp.OfpAction_Output{
699 Output: &ofp.OfpActionOutput{
700 Port: 1,
701 MaxLen: 65509,
702 },
703 }}}}}}}
704
705 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400706 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
707
708 fa = &fu.FlowArgs{
709 KV: fu.OfpFlowModArgs{"priority": 500},
710 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400711 fu.InPort(1),
712 fu.TunnelId(uint64(1)),
713 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
714 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400715 },
716 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400717 fu.PushVlan(0x8100),
718 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
719 fu.SetField(fu.VlanPcp(0)),
720 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400721 },
722 }
khenaidoo68c930b2019-05-13 11:46:51 -0400723 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400724 derivedFlow = oltFlowAndGroup.GetFlow(0)
725 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
726}
727
728func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400729 log.Debugf("Starting Test Unicast Downstream")
khenaidood20a5852018-10-22 22:09:55 -0400730 var fa1 *fu.FlowArgs
731 fa1 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400732 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400733 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400734 fu.InPort(10),
735 fu.Metadata_ofp((1000 << 32) | 1),
736 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400737 },
738 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400739 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400740 },
741 }
742
743 var fa2 *fu.FlowArgs
744 fa2 = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400745 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400746 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400747 fu.InPort(10),
748 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
749 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400750 },
751 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400752 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
753 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400754 },
755 }
756
khenaidoo68c930b2019-05-13 11:46:51 -0400757 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa1), fu.MkFlowStat(fa2)}}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400758 flows.Items[0].Instructions = []*ofp.OfpInstruction{{
759 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
760 Data: &ofp.OfpInstruction_GotoTable{
761 GotoTable: &ofp.OfpInstructionGotoTable{
762 TableId: 1,
763 },
764 }}}
765
khenaidood20a5852018-10-22 22:09:55 -0400766 groups := ofp.FlowGroups{}
767 tfd := newTestFlowDecomposer(newTestDeviceManager())
768
khenaidoo3306c992019-05-24 16:57:35 -0400769 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400770
khenaidood20a5852018-10-22 22:09:55 -0400771 onu1FlowAndGroup := deviceRules.Rules["onu1"]
772 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400773 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400774 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
775 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
776 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
777
778 fa1 = &fu.FlowArgs{
779 KV: fu.OfpFlowModArgs{"priority": 500},
780 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400781 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400782 fu.TunnelId(uint64(10)),
783 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400784 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400785 },
786 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400787 fu.PopVlan(),
788 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400789 },
790 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400791
khenaidood20a5852018-10-22 22:09:55 -0400792 derivedFlow := oltFlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400793 expectedOltFlow := fu.MkFlowStat(fa1)
794 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
795 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
796 Data: &ofp.OfpInstruction_Actions{
797 Actions: &ofp.OfpInstructionActions{
798 Actions: []*ofp.OfpAction{{
799 Type: 0,
800 Action: &ofp.OfpAction_Output{
801 Output: &ofp.OfpActionOutput{
802 Port: 1,
803 MaxLen: 65509,
804 },
805 }}}}}}}
806 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400807 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
808
809 fa1 = &fu.FlowArgs{
810 KV: fu.OfpFlowModArgs{"priority": 500},
811 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400812 fu.InPort(1),
813 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
814 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400815 },
816 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400817 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
818 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400819 },
820 }
khenaidoo68c930b2019-05-13 11:46:51 -0400821 expectedOnu1Flow := fu.MkFlowStat(fa1)
khenaidoo3306c992019-05-24 16:57:35 -0400822 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400823 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
824}
825
826func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
827 var fa *fu.FlowArgs
828 fa = &fu.FlowArgs{
829 KV: fu.OfpFlowModArgs{"priority": 500},
830 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400831 fu.InPort(10),
832 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
833 fu.VlanPcp(0),
834 fu.EthType(0x800),
835 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400836 },
837 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400838 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400839 },
840 }
841
842 var ga *fu.GroupArgs
843 ga = &fu.GroupArgs{
844 GroupId: 10,
845 Buckets: []*ofp.OfpBucket{
846 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400847 fu.PopVlan(),
848 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400849 },
850 },
851 },
852 }
853
khenaidoo68c930b2019-05-13 11:46:51 -0400854 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
855 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{fu.MkGroupStat(ga)}}
khenaidood20a5852018-10-22 22:09:55 -0400856 tfd := newTestFlowDecomposer(newTestDeviceManager())
857
khenaidoo3306c992019-05-24 16:57:35 -0400858 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
khenaidood20a5852018-10-22 22:09:55 -0400859 onu1FlowAndGroup := deviceRules.Rules["onu1"]
860 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400861 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400862 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
863 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
864 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
865
866 fa = &fu.FlowArgs{
867 KV: fu.OfpFlowModArgs{"priority": 500},
868 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400869 fu.InPort(2),
870 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
871 fu.VlanPcp(0),
872 fu.EthType(0x800),
873 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400874 },
875 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400876 fu.PopVlan(),
877 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400878 },
879 }
khenaidoo68c930b2019-05-13 11:46:51 -0400880 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400881 derivedFlow := oltFlowAndGroup.GetFlow(0)
882 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
883
884 fa = &fu.FlowArgs{
885 KV: fu.OfpFlowModArgs{"priority": 500},
886 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400887 fu.InPort(1),
888 fu.EthType(0x800),
889 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400890 },
891 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400892 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400893 },
894 }
khenaidoo68c930b2019-05-13 11:46:51 -0400895 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo3306c992019-05-24 16:57:35 -0400896 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400897 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
898}