blob: 5d914ac4d5f272b8ac3fa374d97901d5e8ac8e89 [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{
346 InPort(2),
347 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
348 },
349 Actions: []*ofp.OfpAction{
350 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
351 Output(1),
352 },
353 }
354 fg.AddFlow(MkFlowStat(fa))
355 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
356
357 fg = fu.NewFlowsAndGroups()
358 fa = &fu.FlowArgs{
359 MatchFields: []*ofp.OfpOxmOfbField{
360 InPort(2),
361 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
362 },
363 Actions: []*ofp.OfpAction{
364 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
365 Output(1),
366 },
367 }
368 fg.AddFlow(MkFlowStat(fa))
369 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
370
371 fg = fu.NewFlowsAndGroups()
372 fa = &fu.FlowArgs{
373 MatchFields: []*ofp.OfpOxmOfbField{
374 InPort(2),
375 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
376 },
377 Actions: []*ofp.OfpAction{
378 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
379 Output(1),
380 },
381 }
382 fg.AddFlow(MkFlowStat(fa))
383 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
384
385 fg = fu.NewFlowsAndGroups()
386 fa = &fu.FlowArgs{
387 MatchFields: []*ofp.OfpOxmOfbField{
388 InPort(2),
389 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
390 },
391 Actions: []*ofp.OfpAction{
392 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
393 Output(1),
394 },
395 }
396 fg.AddFlow(MkFlowStat(fa))
397 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{
471 InPort(1),
472 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
473 EthType(0x888e),
474 },
475 Actions: []*ofp.OfpAction{
476 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
477 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
478 },
479 }
480
481 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
482 groups := ofp.FlowGroups{}
483 tfd := newTestFlowDecomposer(newTestDeviceManager())
484
khenaidoo2c6a0992019-04-29 13:46:56 -0400485 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400486 onu1FlowAndGroup := deviceRules.Rules["onu1"]
487 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400488 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
489 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
490 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
491 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
492
493 fa = &fu.FlowArgs{
494 MatchFields: []*ofp.OfpOxmOfbField{
495 InPort(2),
496 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
497 },
498 Actions: []*ofp.OfpAction{
499 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
500 Output(1),
501 },
502 }
503 expectedOnu1Flow := MkFlowStat(fa)
504 derivedFlow := onu1FlowAndGroup.GetFlow(0)
505 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
506
507 fa = &fu.FlowArgs{
508 KV: fu.OfpFlowModArgs{"priority": 1000},
509 MatchFields: []*ofp.OfpOxmOfbField{
510 InPort(1),
511 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400512 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400513 EthType(0x888e),
514 },
515 Actions: []*ofp.OfpAction{
516 PushVlan(0x8100),
517 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400518 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400519 },
520 }
521 expectedOltFlow := MkFlowStat(fa)
522 derivedFlow = oltFlowAndGroup.GetFlow(0)
523 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
524
525 fa = &fu.FlowArgs{
526 KV: fu.OfpFlowModArgs{"priority": 1000},
527 MatchFields: []*ofp.OfpOxmOfbField{
528 InPort(2),
529 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
530 VlanPcp(0),
531 Metadata_ofp(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400532 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400533 },
534 Actions: []*ofp.OfpAction{
535 PopVlan(),
536 Output(1),
537 },
538 }
539 expectedOltFlow = MkFlowStat(fa)
540 derivedFlow = oltFlowAndGroup.GetFlow(1)
541 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
542}
543
544func TestDhcpReRouteRuleDecomposition(t *testing.T) {
545
546 var fa *fu.FlowArgs
547 fa = &fu.FlowArgs{
548 KV: fu.OfpFlowModArgs{"priority": 1000},
549 MatchFields: []*ofp.OfpOxmOfbField{
550 InPort(1),
551 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
552 EthType(0x0800),
553 Ipv4Dst(0xffffffff),
554 IpProto(17),
555 UdpSrc(68),
556 UdpDst(67),
557 },
558 Actions: []*ofp.OfpAction{
559 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
560 },
561 }
562
563 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
564 groups := ofp.FlowGroups{}
565 tfd := newTestFlowDecomposer(newTestDeviceManager())
566
khenaidoo2c6a0992019-04-29 13:46:56 -0400567 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400568 onu1FlowAndGroup := deviceRules.Rules["onu1"]
569 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400570 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
571 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
572 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
573 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
574
575 fa = &fu.FlowArgs{
576 MatchFields: []*ofp.OfpOxmOfbField{
577 InPort(2),
578 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
579 },
580 Actions: []*ofp.OfpAction{
581 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
582 Output(1),
583 },
584 }
585 expectedOnu1Flow := MkFlowStat(fa)
586 derivedFlow := onu1FlowAndGroup.GetFlow(0)
587 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
588
589 fa = &fu.FlowArgs{
590 KV: fu.OfpFlowModArgs{"priority": 1000},
591 MatchFields: []*ofp.OfpOxmOfbField{
592 InPort(1),
593 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400594 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400595 EthType(0x0800),
596 Ipv4Dst(0xffffffff),
597 IpProto(17),
598 UdpSrc(68),
599 UdpDst(67),
600 },
601 Actions: []*ofp.OfpAction{
602 PushVlan(0x8100),
603 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400604 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400605 },
606 }
607 expectedOltFlow := MkFlowStat(fa)
608 derivedFlow = oltFlowAndGroup.GetFlow(0)
609 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
610
611 fa = &fu.FlowArgs{
612 KV: fu.OfpFlowModArgs{"priority": 1000},
613 MatchFields: []*ofp.OfpOxmOfbField{
614 InPort(2),
615 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
616 VlanPcp(0),
617 Metadata_ofp(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400618 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400619 },
620 Actions: []*ofp.OfpAction{
621 PopVlan(),
622 Output(1),
623 },
624 }
625 expectedOltFlow = MkFlowStat(fa)
626 derivedFlow = oltFlowAndGroup.GetFlow(1)
627 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
628}
629
khenaidood20a5852018-10-22 22:09:55 -0400630func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
631
632 var fa *fu.FlowArgs
633 fa = &fu.FlowArgs{
634 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
635 MatchFields: []*ofp.OfpOxmOfbField{
636 InPort(1),
637 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
638 VlanPcp(0),
639 },
640 Actions: []*ofp.OfpAction{
641 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
642 },
643 }
644
645 var fa2 *fu.FlowArgs
646 fa2 = &fu.FlowArgs{
647 KV: fu.OfpFlowModArgs{"priority": 500},
648 MatchFields: []*ofp.OfpOxmOfbField{
649 InPort(1),
650 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
651 VlanPcp(0),
652 },
653 Actions: []*ofp.OfpAction{
654 PushVlan(0x8100),
655 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
656 SetField(VlanPcp(0)),
657 Output(10),
658 },
659 }
660
661 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa), MkFlowStat(fa2)}}
662 groups := ofp.FlowGroups{}
663 tfd := newTestFlowDecomposer(newTestDeviceManager())
664
khenaidoo2c6a0992019-04-29 13:46:56 -0400665 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400666 onu1FlowAndGroup := deviceRules.Rules["onu1"]
667 oltFlowAndGroup := deviceRules.Rules["olt"]
668 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
669 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
670 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
671 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
672
673 fa = &fu.FlowArgs{
674 KV: fu.OfpFlowModArgs{"priority": 500},
675 MatchFields: []*ofp.OfpOxmOfbField{
676 InPort(2),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400677 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400678 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
679 VlanPcp(0),
680 },
681 Actions: []*ofp.OfpAction{
682 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
683 Output(1),
684 },
685 }
686 expectedOnu1Flow := MkFlowStat(fa)
687 derivedFlow := onu1FlowAndGroup.GetFlow(1)
688 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
689
690 fa = &fu.FlowArgs{
691 KV: fu.OfpFlowModArgs{"priority": 500},
692 MatchFields: []*ofp.OfpOxmOfbField{
693 InPort(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400694 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400695 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
696 VlanPcp(0),
697 },
698 Actions: []*ofp.OfpAction{
699 PushVlan(0x8100),
700 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
701 SetField(VlanPcp(0)),
702 Output(2),
703 },
704 }
705 expectedOltFlow := MkFlowStat(fa)
706 derivedFlow = oltFlowAndGroup.GetFlow(0)
707 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
708}
709
710func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
711 var fa1 *fu.FlowArgs
712 fa1 = &fu.FlowArgs{
713 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
714 MatchFields: []*ofp.OfpOxmOfbField{
715 InPort(10),
716 Metadata_ofp((1000 << 32) | 1),
717 VlanPcp(0),
718 },
719 Actions: []*ofp.OfpAction{
720 PopVlan(),
721 },
722 }
723
724 var fa2 *fu.FlowArgs
725 fa2 = &fu.FlowArgs{
726 KV: fu.OfpFlowModArgs{"priority": 500},
727 MatchFields: []*ofp.OfpOxmOfbField{
728 InPort(10),
729 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
730 VlanPcp(0),
731 },
732 Actions: []*ofp.OfpAction{
733 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
734 Output(1),
735 },
736 }
737
738 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa1), MkFlowStat(fa2)}}
739 groups := ofp.FlowGroups{}
740 tfd := newTestFlowDecomposer(newTestDeviceManager())
741
khenaidoo2c6a0992019-04-29 13:46:56 -0400742 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400743 onu1FlowAndGroup := deviceRules.Rules["onu1"]
744 oltFlowAndGroup := deviceRules.Rules["olt"]
745 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
746 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
747 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
748 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
749
750 fa1 = &fu.FlowArgs{
751 KV: fu.OfpFlowModArgs{"priority": 500},
752 MatchFields: []*ofp.OfpOxmOfbField{
753 InPort(2),
754 Metadata_ofp(1000),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400755 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400756 VlanPcp(0),
757 },
758 Actions: []*ofp.OfpAction{
759 PopVlan(),
760 Output(1),
761 },
762 }
763 expectedOltFlow := MkFlowStat(fa1)
764 derivedFlow := oltFlowAndGroup.GetFlow(0)
765 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
766
767 fa1 = &fu.FlowArgs{
768 KV: fu.OfpFlowModArgs{"priority": 500},
769 MatchFields: []*ofp.OfpOxmOfbField{
770 InPort(1),
771 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
772 VlanPcp(0),
773 },
774 Actions: []*ofp.OfpAction{
775 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
776 Output(2),
777 },
778 }
779 expectedOnu1Flow := MkFlowStat(fa1)
780 derivedFlow = onu1FlowAndGroup.GetFlow(1)
781 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
782}
783
784func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
785 var fa *fu.FlowArgs
786 fa = &fu.FlowArgs{
787 KV: fu.OfpFlowModArgs{"priority": 500},
788 MatchFields: []*ofp.OfpOxmOfbField{
789 InPort(10),
790 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
791 VlanPcp(0),
792 EthType(0x800),
793 Ipv4Dst(0xe00a0a0a),
794 },
795 Actions: []*ofp.OfpAction{
796 Group(10),
797 },
798 }
799
800 var ga *fu.GroupArgs
801 ga = &fu.GroupArgs{
802 GroupId: 10,
803 Buckets: []*ofp.OfpBucket{
804 {Actions: []*ofp.OfpAction{
805 PopVlan(),
806 Output(1),
807 },
808 },
809 },
810 }
811
812 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
813 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{MkGroupStat(ga)}}
814 tfd := newTestFlowDecomposer(newTestDeviceManager())
815
khenaidoo2c6a0992019-04-29 13:46:56 -0400816 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400817 onu1FlowAndGroup := deviceRules.Rules["onu1"]
818 oltFlowAndGroup := deviceRules.Rules["olt"]
819 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
820 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
821 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
822 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
823
824 fa = &fu.FlowArgs{
825 KV: fu.OfpFlowModArgs{"priority": 500},
826 MatchFields: []*ofp.OfpOxmOfbField{
827 InPort(2),
828 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
829 VlanPcp(0),
830 EthType(0x800),
831 Ipv4Dst(0xe00a0a0a),
832 },
833 Actions: []*ofp.OfpAction{
834 PopVlan(),
835 Output(1),
836 },
837 }
838 expectedOltFlow := MkFlowStat(fa)
839 derivedFlow := oltFlowAndGroup.GetFlow(0)
840 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
841
842 fa = &fu.FlowArgs{
843 KV: fu.OfpFlowModArgs{"priority": 500},
844 MatchFields: []*ofp.OfpOxmOfbField{
845 InPort(1),
846 EthType(0x800),
847 Ipv4Dst(0xe00a0a0a),
848 },
849 Actions: []*ofp.OfpAction{
850 Output(2),
851 },
852 }
853 expectedOnu1Flow := MkFlowStat(fa)
854 derivedFlow = onu1FlowAndGroup.GetFlow(1)
855 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
856}