blob: fdc2b865743cb1ce6446e8163354482c4815b441 [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
104type testFlowDecomposer struct {
105 dMgr *testDeviceManager
106 logicalPorts map[uint32]*voltha.LogicalPort
107 routes map[graph.OFPortLink][]graph.RouteHop
108 defaultRules *fu.DeviceRules
109 deviceGraph *graph.DeviceGraph
110 fd *FlowDecomposer
111}
112
113func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
114 var tfd testFlowDecomposer
115 tfd.dMgr = deviceMgr
116
117 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
118 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
119 // port
120 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
121 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
122 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
123 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
124 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
125
126 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
127
128 //DOWNSTREAM ROUTES
129
130 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400131 {
khenaidoo89b0e942018-10-21 21:11:33 -0400132 DeviceID: "olt",
133 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
134 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
135 },
khenaidood20a5852018-10-22 22:09:55 -0400136 {
khenaidoo89b0e942018-10-21 21:11:33 -0400137 DeviceID: "onu1",
138 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
139 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
140 },
141 }
142
143 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400144 {
khenaidoo89b0e942018-10-21 21:11:33 -0400145 DeviceID: "olt",
146 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
147 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
148 },
khenaidood20a5852018-10-22 22:09:55 -0400149 {
khenaidoo89b0e942018-10-21 21:11:33 -0400150 DeviceID: "onu2",
151 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
152 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
153 },
154 }
155 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400156 {
khenaidoo89b0e942018-10-21 21:11:33 -0400157 DeviceID: "olt",
158 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
159 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
160 },
khenaidood20a5852018-10-22 22:09:55 -0400161 {
khenaidoo89b0e942018-10-21 21:11:33 -0400162 DeviceID: "onu3",
163 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
164 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
165 },
166 }
167 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400168 {
khenaidoo89b0e942018-10-21 21:11:33 -0400169 DeviceID: "olt",
170 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
171 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
172 },
khenaidood20a5852018-10-22 22:09:55 -0400173 {
khenaidoo89b0e942018-10-21 21:11:33 -0400174 DeviceID: "onu4",
175 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
176 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
177 },
178 }
179
180 //UPSTREAM DATA PLANE
181
182 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400183 {
khenaidoo89b0e942018-10-21 21:11:33 -0400184 DeviceID: "onu1",
185 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
186 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
187 },
khenaidood20a5852018-10-22 22:09:55 -0400188 {
khenaidoo89b0e942018-10-21 21:11:33 -0400189 DeviceID: "olt",
190 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
191 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
192 },
193 }
194 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400195 {
khenaidoo89b0e942018-10-21 21:11:33 -0400196 DeviceID: "onu2",
197 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
198 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
199 },
khenaidood20a5852018-10-22 22:09:55 -0400200 {
khenaidoo89b0e942018-10-21 21:11:33 -0400201 DeviceID: "olt",
202 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
203 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
204 },
205 }
206 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400207 {
khenaidoo89b0e942018-10-21 21:11:33 -0400208 DeviceID: "onu3",
209 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
210 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
211 },
khenaidood20a5852018-10-22 22:09:55 -0400212 {
khenaidoo89b0e942018-10-21 21:11:33 -0400213 DeviceID: "olt",
214 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
215 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
216 },
217 }
218 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400219 {
khenaidoo89b0e942018-10-21 21:11:33 -0400220 DeviceID: "onu4",
221 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
222 Egress: tfd.dMgr.devices["onu4"].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
231 //UPSTREAM NEXT TABLE BASED
232
233 // openflow port 0 means absence of a port - go/protobuf interpretation
234 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400235 {
khenaidoo89b0e942018-10-21 21:11:33 -0400236 DeviceID: "onu1",
237 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
238 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
239 },
khenaidood20a5852018-10-22 22:09:55 -0400240 {
khenaidoo89b0e942018-10-21 21:11:33 -0400241 DeviceID: "olt",
242 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
243 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
244 },
245 }
246 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400247 {
khenaidoo89b0e942018-10-21 21:11:33 -0400248 DeviceID: "onu2",
249 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
250 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
251 },
khenaidood20a5852018-10-22 22:09:55 -0400252 {
khenaidoo89b0e942018-10-21 21:11:33 -0400253 DeviceID: "olt",
254 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
255 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
256 },
257 }
258 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400259 {
khenaidoo89b0e942018-10-21 21:11:33 -0400260 DeviceID: "onu3",
261 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
262 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
263 },
khenaidood20a5852018-10-22 22:09:55 -0400264 {
khenaidoo89b0e942018-10-21 21:11:33 -0400265 DeviceID: "olt",
266 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
267 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
268 },
269 }
270 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400271 {
khenaidoo89b0e942018-10-21 21:11:33 -0400272 DeviceID: "onu4",
273 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
274 Egress: tfd.dMgr.devices["onu4"].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
283 // DOWNSTREAM NEXT TABLE BASED
284
285 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400286 {
khenaidoo89b0e942018-10-21 21:11:33 -0400287 DeviceID: "olt",
288 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
289 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
290 },
khenaidood20a5852018-10-22 22:09:55 -0400291 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400292 }
293
294 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400295 {}, // 1st hop is wildcard
296 {
khenaidoo89b0e942018-10-21 21:11:33 -0400297 DeviceID: "olt",
298 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
299 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
300 },
301 }
302
303 // DEFAULT RULES
304
305 tfd.defaultRules = fu.NewDeviceRules()
306 fg := fu.NewFlowsAndGroups()
307 var fa *fu.FlowArgs
308 fa = &fu.FlowArgs{
309 MatchFields: []*ofp.OfpOxmOfbField{
310 InPort(2),
311 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
312 },
313 Actions: []*ofp.OfpAction{
314 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
315 Output(1),
316 },
317 }
318 fg.AddFlow(MkFlowStat(fa))
319 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
320
321 fg = fu.NewFlowsAndGroups()
322 fa = &fu.FlowArgs{
323 MatchFields: []*ofp.OfpOxmOfbField{
324 InPort(2),
325 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
326 },
327 Actions: []*ofp.OfpAction{
328 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
329 Output(1),
330 },
331 }
332 fg.AddFlow(MkFlowStat(fa))
333 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
334
335 fg = fu.NewFlowsAndGroups()
336 fa = &fu.FlowArgs{
337 MatchFields: []*ofp.OfpOxmOfbField{
338 InPort(2),
339 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
340 },
341 Actions: []*ofp.OfpAction{
342 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
343 Output(1),
344 },
345 }
346 fg.AddFlow(MkFlowStat(fa))
347 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
348
349 fg = fu.NewFlowsAndGroups()
350 fa = &fu.FlowArgs{
351 MatchFields: []*ofp.OfpOxmOfbField{
352 InPort(2),
353 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
354 },
355 Actions: []*ofp.OfpAction{
356 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
357 Output(1),
358 },
359 }
360 fg.AddFlow(MkFlowStat(fa))
361 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
362
363 //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 -0400364 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400365 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
366 tfd.deviceGraph.RootPorts[10] = 10
367
368 tfd.fd = NewFlowDecomposer(tfd.dMgr)
369
370 return &tfd
371}
372
373func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
374 return tfd.dMgr.GetDevice(deviceId)
375}
376
377func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
378 return ""
379}
380
khenaidoo19d7b632018-10-30 10:49:50 -0400381func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
382 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400383}
384
385func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
386 return tfd.deviceGraph
387}
388
389func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
390 return tfd.defaultRules
391}
392
393func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
394 lPorts := make([]uint32, 0)
395 var exclPort uint32
396 if len(excludePort) == 1 {
397 exclPort = excludePort[0]
398 }
khenaidood20a5852018-10-22 22:09:55 -0400399 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400400 if portno != exclPort {
401 lPorts = append(lPorts, portno)
402 }
403 }
404 return lPorts
405}
406
khenaidoo19d7b632018-10-30 10:49:50 -0400407func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400408 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400409 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400410 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400411 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400412 portLink.Egress = 10
413 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400414 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400415 }
khenaidoo19d7b632018-10-30 10:49:50 -0400416 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400417 portLink.Ingress = 0
418 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400419 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400420 }
421 for key, val := range tfd.routes {
422 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
423 return val
424 }
425 }
426 return nil
427}
428
429func TestEapolReRouteRuleDecomposition(t *testing.T) {
430
431 var fa *fu.FlowArgs
432 fa = &fu.FlowArgs{
433 KV: fu.OfpFlowModArgs{"priority": 1000},
434 MatchFields: []*ofp.OfpOxmOfbField{
435 InPort(1),
436 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
437 EthType(0x888e),
438 },
439 Actions: []*ofp.OfpAction{
440 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
441 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
442 },
443 }
444
445 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
446 groups := ofp.FlowGroups{}
447 tfd := newTestFlowDecomposer(newTestDeviceManager())
448
khenaidoo2c6a0992019-04-29 13:46:56 -0400449 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400450 onu1FlowAndGroup := deviceRules.Rules["onu1"]
451 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400452 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
453 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
454 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
455 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
456
457 fa = &fu.FlowArgs{
458 MatchFields: []*ofp.OfpOxmOfbField{
459 InPort(2),
460 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
461 },
462 Actions: []*ofp.OfpAction{
463 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
464 Output(1),
465 },
466 }
467 expectedOnu1Flow := MkFlowStat(fa)
468 derivedFlow := onu1FlowAndGroup.GetFlow(0)
469 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
470
471 fa = &fu.FlowArgs{
472 KV: fu.OfpFlowModArgs{"priority": 1000},
473 MatchFields: []*ofp.OfpOxmOfbField{
474 InPort(1),
475 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400476 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400477 EthType(0x888e),
478 },
479 Actions: []*ofp.OfpAction{
480 PushVlan(0x8100),
481 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400482 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400483 },
484 }
485 expectedOltFlow := MkFlowStat(fa)
486 derivedFlow = oltFlowAndGroup.GetFlow(0)
487 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
488
489 fa = &fu.FlowArgs{
490 KV: fu.OfpFlowModArgs{"priority": 1000},
491 MatchFields: []*ofp.OfpOxmOfbField{
492 InPort(2),
493 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
494 VlanPcp(0),
495 Metadata_ofp(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400496 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400497 },
498 Actions: []*ofp.OfpAction{
499 PopVlan(),
500 Output(1),
501 },
502 }
503 expectedOltFlow = MkFlowStat(fa)
504 derivedFlow = oltFlowAndGroup.GetFlow(1)
505 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
506}
507
508func TestDhcpReRouteRuleDecomposition(t *testing.T) {
509
510 var fa *fu.FlowArgs
511 fa = &fu.FlowArgs{
512 KV: fu.OfpFlowModArgs{"priority": 1000},
513 MatchFields: []*ofp.OfpOxmOfbField{
514 InPort(1),
515 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
516 EthType(0x0800),
517 Ipv4Dst(0xffffffff),
518 IpProto(17),
519 UdpSrc(68),
520 UdpDst(67),
521 },
522 Actions: []*ofp.OfpAction{
523 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
524 },
525 }
526
527 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
528 groups := ofp.FlowGroups{}
529 tfd := newTestFlowDecomposer(newTestDeviceManager())
530
khenaidoo2c6a0992019-04-29 13:46:56 -0400531 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400532 onu1FlowAndGroup := deviceRules.Rules["onu1"]
533 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400534 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
535 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
536 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
537 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
538
539 fa = &fu.FlowArgs{
540 MatchFields: []*ofp.OfpOxmOfbField{
541 InPort(2),
542 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
543 },
544 Actions: []*ofp.OfpAction{
545 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
546 Output(1),
547 },
548 }
549 expectedOnu1Flow := MkFlowStat(fa)
550 derivedFlow := onu1FlowAndGroup.GetFlow(0)
551 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
552
553 fa = &fu.FlowArgs{
554 KV: fu.OfpFlowModArgs{"priority": 1000},
555 MatchFields: []*ofp.OfpOxmOfbField{
556 InPort(1),
557 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400558 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400559 EthType(0x0800),
560 Ipv4Dst(0xffffffff),
561 IpProto(17),
562 UdpSrc(68),
563 UdpDst(67),
564 },
565 Actions: []*ofp.OfpAction{
566 PushVlan(0x8100),
567 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400568 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400569 },
570 }
571 expectedOltFlow := MkFlowStat(fa)
572 derivedFlow = oltFlowAndGroup.GetFlow(0)
573 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
574
575 fa = &fu.FlowArgs{
576 KV: fu.OfpFlowModArgs{"priority": 1000},
577 MatchFields: []*ofp.OfpOxmOfbField{
578 InPort(2),
579 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
580 VlanPcp(0),
581 Metadata_ofp(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400582 TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400583 },
584 Actions: []*ofp.OfpAction{
585 PopVlan(),
586 Output(1),
587 },
588 }
589 expectedOltFlow = MkFlowStat(fa)
590 derivedFlow = oltFlowAndGroup.GetFlow(1)
591 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
592}
593
khenaidood20a5852018-10-22 22:09:55 -0400594func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
595
596 var fa *fu.FlowArgs
597 fa = &fu.FlowArgs{
598 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
599 MatchFields: []*ofp.OfpOxmOfbField{
600 InPort(1),
601 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
602 VlanPcp(0),
603 },
604 Actions: []*ofp.OfpAction{
605 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
606 },
607 }
608
609 var fa2 *fu.FlowArgs
610 fa2 = &fu.FlowArgs{
611 KV: fu.OfpFlowModArgs{"priority": 500},
612 MatchFields: []*ofp.OfpOxmOfbField{
613 InPort(1),
614 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
615 VlanPcp(0),
616 },
617 Actions: []*ofp.OfpAction{
618 PushVlan(0x8100),
619 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
620 SetField(VlanPcp(0)),
621 Output(10),
622 },
623 }
624
625 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa), MkFlowStat(fa2)}}
626 groups := ofp.FlowGroups{}
627 tfd := newTestFlowDecomposer(newTestDeviceManager())
628
khenaidoo2c6a0992019-04-29 13:46:56 -0400629 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400630 onu1FlowAndGroup := deviceRules.Rules["onu1"]
631 oltFlowAndGroup := deviceRules.Rules["olt"]
632 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
633 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
634 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
635 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
636
637 fa = &fu.FlowArgs{
638 KV: fu.OfpFlowModArgs{"priority": 500},
639 MatchFields: []*ofp.OfpOxmOfbField{
640 InPort(2),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400641 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400642 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
643 VlanPcp(0),
644 },
645 Actions: []*ofp.OfpAction{
646 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
647 Output(1),
648 },
649 }
650 expectedOnu1Flow := MkFlowStat(fa)
651 derivedFlow := onu1FlowAndGroup.GetFlow(1)
652 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
653
654 fa = &fu.FlowArgs{
655 KV: fu.OfpFlowModArgs{"priority": 500},
656 MatchFields: []*ofp.OfpOxmOfbField{
657 InPort(1),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400658 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400659 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
660 VlanPcp(0),
661 },
662 Actions: []*ofp.OfpAction{
663 PushVlan(0x8100),
664 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
665 SetField(VlanPcp(0)),
666 Output(2),
667 },
668 }
669 expectedOltFlow := MkFlowStat(fa)
670 derivedFlow = oltFlowAndGroup.GetFlow(0)
671 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
672}
673
674func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
675 var fa1 *fu.FlowArgs
676 fa1 = &fu.FlowArgs{
677 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
678 MatchFields: []*ofp.OfpOxmOfbField{
679 InPort(10),
680 Metadata_ofp((1000 << 32) | 1),
681 VlanPcp(0),
682 },
683 Actions: []*ofp.OfpAction{
684 PopVlan(),
685 },
686 }
687
688 var fa2 *fu.FlowArgs
689 fa2 = &fu.FlowArgs{
690 KV: fu.OfpFlowModArgs{"priority": 500},
691 MatchFields: []*ofp.OfpOxmOfbField{
692 InPort(10),
693 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
694 VlanPcp(0),
695 },
696 Actions: []*ofp.OfpAction{
697 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
698 Output(1),
699 },
700 }
701
702 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa1), MkFlowStat(fa2)}}
703 groups := ofp.FlowGroups{}
704 tfd := newTestFlowDecomposer(newTestDeviceManager())
705
khenaidoo2c6a0992019-04-29 13:46:56 -0400706 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400707 onu1FlowAndGroup := deviceRules.Rules["onu1"]
708 oltFlowAndGroup := deviceRules.Rules["olt"]
709 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
710 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
711 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
712 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
713
714 fa1 = &fu.FlowArgs{
715 KV: fu.OfpFlowModArgs{"priority": 500},
716 MatchFields: []*ofp.OfpOxmOfbField{
717 InPort(2),
718 Metadata_ofp(1000),
Matt Jeanneret802bf362019-04-14 20:33:08 -0400719 TunnelId(uint64(1)),
khenaidood20a5852018-10-22 22:09:55 -0400720 VlanPcp(0),
721 },
722 Actions: []*ofp.OfpAction{
723 PopVlan(),
724 Output(1),
725 },
726 }
727 expectedOltFlow := MkFlowStat(fa1)
728 derivedFlow := oltFlowAndGroup.GetFlow(0)
729 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
730
731 fa1 = &fu.FlowArgs{
732 KV: fu.OfpFlowModArgs{"priority": 500},
733 MatchFields: []*ofp.OfpOxmOfbField{
734 InPort(1),
735 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
736 VlanPcp(0),
737 },
738 Actions: []*ofp.OfpAction{
739 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
740 Output(2),
741 },
742 }
743 expectedOnu1Flow := MkFlowStat(fa1)
744 derivedFlow = onu1FlowAndGroup.GetFlow(1)
745 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
746}
747
748func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
749 var fa *fu.FlowArgs
750 fa = &fu.FlowArgs{
751 KV: fu.OfpFlowModArgs{"priority": 500},
752 MatchFields: []*ofp.OfpOxmOfbField{
753 InPort(10),
754 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
755 VlanPcp(0),
756 EthType(0x800),
757 Ipv4Dst(0xe00a0a0a),
758 },
759 Actions: []*ofp.OfpAction{
760 Group(10),
761 },
762 }
763
764 var ga *fu.GroupArgs
765 ga = &fu.GroupArgs{
766 GroupId: 10,
767 Buckets: []*ofp.OfpBucket{
768 {Actions: []*ofp.OfpAction{
769 PopVlan(),
770 Output(1),
771 },
772 },
773 },
774 }
775
776 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
777 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{MkGroupStat(ga)}}
778 tfd := newTestFlowDecomposer(newTestDeviceManager())
779
khenaidoo2c6a0992019-04-29 13:46:56 -0400780 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400781 onu1FlowAndGroup := deviceRules.Rules["onu1"]
782 oltFlowAndGroup := deviceRules.Rules["olt"]
783 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
784 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
785 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
786 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
787
788 fa = &fu.FlowArgs{
789 KV: fu.OfpFlowModArgs{"priority": 500},
790 MatchFields: []*ofp.OfpOxmOfbField{
791 InPort(2),
792 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
793 VlanPcp(0),
794 EthType(0x800),
795 Ipv4Dst(0xe00a0a0a),
796 },
797 Actions: []*ofp.OfpAction{
798 PopVlan(),
799 Output(1),
800 },
801 }
802 expectedOltFlow := MkFlowStat(fa)
803 derivedFlow := oltFlowAndGroup.GetFlow(0)
804 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
805
806 fa = &fu.FlowArgs{
807 KV: fu.OfpFlowModArgs{"priority": 500},
808 MatchFields: []*ofp.OfpOxmOfbField{
809 InPort(1),
810 EthType(0x800),
811 Ipv4Dst(0xe00a0a0a),
812 },
813 Actions: []*ofp.OfpAction{
814 Output(2),
815 },
816 }
817 expectedOnu1Flow := MkFlowStat(fa)
818 derivedFlow = onu1FlowAndGroup.GetFlow(1)
819 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
820}