blob: a0a2e3b70b1a1f608a15b7089c60feb18208d583 [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"
William Kurkiandaa6bb22019-03-07 12:26:28 -050021 ofp "github.com/opencord/voltha-protos/go/openflow_13"
22 "github.com/opencord/voltha-protos/go/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040023 "github.com/opencord/voltha-go/rw_core/graph"
24 fu "github.com/opencord/voltha-go/rw_core/utils"
25 "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)
khenaidoo89b0e942018-10-21 21:11:33 -040032 log.UpdateAllLoggers(log.Fields{"instanceId": "flow-descomposition"})
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.
364 tfd.deviceGraph = graph.NewDeviceGraph(tfd.getDeviceHelper)
365 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
khenaidood20a5852018-10-22 22:09:55 -0400449 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
450 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),
476 EthType(0x888e),
477 },
478 Actions: []*ofp.OfpAction{
479 PushVlan(0x8100),
480 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400481 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400482 },
483 }
484 expectedOltFlow := MkFlowStat(fa)
485 derivedFlow = oltFlowAndGroup.GetFlow(0)
486 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
487
488 fa = &fu.FlowArgs{
489 KV: fu.OfpFlowModArgs{"priority": 1000},
490 MatchFields: []*ofp.OfpOxmOfbField{
491 InPort(2),
492 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
493 VlanPcp(0),
494 Metadata_ofp(1),
495 },
496 Actions: []*ofp.OfpAction{
497 PopVlan(),
498 Output(1),
499 },
500 }
501 expectedOltFlow = MkFlowStat(fa)
502 derivedFlow = oltFlowAndGroup.GetFlow(1)
503 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
504}
505
506func TestDhcpReRouteRuleDecomposition(t *testing.T) {
507
508 var fa *fu.FlowArgs
509 fa = &fu.FlowArgs{
510 KV: fu.OfpFlowModArgs{"priority": 1000},
511 MatchFields: []*ofp.OfpOxmOfbField{
512 InPort(1),
513 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
514 EthType(0x0800),
515 Ipv4Dst(0xffffffff),
516 IpProto(17),
517 UdpSrc(68),
518 UdpDst(67),
519 },
520 Actions: []*ofp.OfpAction{
521 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
522 },
523 }
524
525 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
526 groups := ofp.FlowGroups{}
527 tfd := newTestFlowDecomposer(newTestDeviceManager())
528
khenaidood20a5852018-10-22 22:09:55 -0400529 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
530 onu1FlowAndGroup := deviceRules.Rules["onu1"]
531 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400532 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
533 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
534 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
535 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
536
537 fa = &fu.FlowArgs{
538 MatchFields: []*ofp.OfpOxmOfbField{
539 InPort(2),
540 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
541 },
542 Actions: []*ofp.OfpAction{
543 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
544 Output(1),
545 },
546 }
547 expectedOnu1Flow := MkFlowStat(fa)
548 derivedFlow := onu1FlowAndGroup.GetFlow(0)
549 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
550
551 fa = &fu.FlowArgs{
552 KV: fu.OfpFlowModArgs{"priority": 1000},
553 MatchFields: []*ofp.OfpOxmOfbField{
554 InPort(1),
555 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
556 EthType(0x0800),
557 Ipv4Dst(0xffffffff),
558 IpProto(17),
559 UdpSrc(68),
560 UdpDst(67),
561 },
562 Actions: []*ofp.OfpAction{
563 PushVlan(0x8100),
564 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
khenaidoo19d7b632018-10-30 10:49:50 -0400565 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400566 },
567 }
568 expectedOltFlow := MkFlowStat(fa)
569 derivedFlow = oltFlowAndGroup.GetFlow(0)
570 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
571
572 fa = &fu.FlowArgs{
573 KV: fu.OfpFlowModArgs{"priority": 1000},
574 MatchFields: []*ofp.OfpOxmOfbField{
575 InPort(2),
576 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
577 VlanPcp(0),
578 Metadata_ofp(1),
579 },
580 Actions: []*ofp.OfpAction{
581 PopVlan(),
582 Output(1),
583 },
584 }
585 expectedOltFlow = MkFlowStat(fa)
586 derivedFlow = oltFlowAndGroup.GetFlow(1)
587 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
588}
589
khenaidood20a5852018-10-22 22:09:55 -0400590func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
591
592 var fa *fu.FlowArgs
593 fa = &fu.FlowArgs{
594 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
595 MatchFields: []*ofp.OfpOxmOfbField{
596 InPort(1),
597 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
598 VlanPcp(0),
599 },
600 Actions: []*ofp.OfpAction{
601 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
602 },
603 }
604
605 var fa2 *fu.FlowArgs
606 fa2 = &fu.FlowArgs{
607 KV: fu.OfpFlowModArgs{"priority": 500},
608 MatchFields: []*ofp.OfpOxmOfbField{
609 InPort(1),
610 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
611 VlanPcp(0),
612 },
613 Actions: []*ofp.OfpAction{
614 PushVlan(0x8100),
615 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
616 SetField(VlanPcp(0)),
617 Output(10),
618 },
619 }
620
621 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa), MkFlowStat(fa2)}}
622 groups := ofp.FlowGroups{}
623 tfd := newTestFlowDecomposer(newTestDeviceManager())
624
625 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
626 onu1FlowAndGroup := deviceRules.Rules["onu1"]
627 oltFlowAndGroup := deviceRules.Rules["olt"]
628 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
629 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
630 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
631 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
632
633 fa = &fu.FlowArgs{
634 KV: fu.OfpFlowModArgs{"priority": 500},
635 MatchFields: []*ofp.OfpOxmOfbField{
636 InPort(2),
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 Output(1),
643 },
644 }
645 expectedOnu1Flow := MkFlowStat(fa)
646 derivedFlow := onu1FlowAndGroup.GetFlow(1)
647 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
648
649 fa = &fu.FlowArgs{
650 KV: fu.OfpFlowModArgs{"priority": 500},
651 MatchFields: []*ofp.OfpOxmOfbField{
652 InPort(1),
653 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
654 VlanPcp(0),
655 },
656 Actions: []*ofp.OfpAction{
657 PushVlan(0x8100),
658 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
659 SetField(VlanPcp(0)),
660 Output(2),
661 },
662 }
663 expectedOltFlow := MkFlowStat(fa)
664 derivedFlow = oltFlowAndGroup.GetFlow(0)
665 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
666}
667
668func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
669 var fa1 *fu.FlowArgs
670 fa1 = &fu.FlowArgs{
671 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
672 MatchFields: []*ofp.OfpOxmOfbField{
673 InPort(10),
674 Metadata_ofp((1000 << 32) | 1),
675 VlanPcp(0),
676 },
677 Actions: []*ofp.OfpAction{
678 PopVlan(),
679 },
680 }
681
682 var fa2 *fu.FlowArgs
683 fa2 = &fu.FlowArgs{
684 KV: fu.OfpFlowModArgs{"priority": 500},
685 MatchFields: []*ofp.OfpOxmOfbField{
686 InPort(10),
687 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
688 VlanPcp(0),
689 },
690 Actions: []*ofp.OfpAction{
691 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
692 Output(1),
693 },
694 }
695
696 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa1), MkFlowStat(fa2)}}
697 groups := ofp.FlowGroups{}
698 tfd := newTestFlowDecomposer(newTestDeviceManager())
699
700 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
701 onu1FlowAndGroup := deviceRules.Rules["onu1"]
702 oltFlowAndGroup := deviceRules.Rules["olt"]
703 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
704 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
705 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
706 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
707
708 fa1 = &fu.FlowArgs{
709 KV: fu.OfpFlowModArgs{"priority": 500},
710 MatchFields: []*ofp.OfpOxmOfbField{
711 InPort(2),
712 Metadata_ofp(1000),
713 VlanPcp(0),
714 },
715 Actions: []*ofp.OfpAction{
716 PopVlan(),
717 Output(1),
718 },
719 }
720 expectedOltFlow := MkFlowStat(fa1)
721 derivedFlow := oltFlowAndGroup.GetFlow(0)
722 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
723
724 fa1 = &fu.FlowArgs{
725 KV: fu.OfpFlowModArgs{"priority": 500},
726 MatchFields: []*ofp.OfpOxmOfbField{
727 InPort(1),
728 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
729 VlanPcp(0),
730 },
731 Actions: []*ofp.OfpAction{
732 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
733 Output(2),
734 },
735 }
736 expectedOnu1Flow := MkFlowStat(fa1)
737 derivedFlow = onu1FlowAndGroup.GetFlow(1)
738 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
739}
740
741func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
742 var fa *fu.FlowArgs
743 fa = &fu.FlowArgs{
744 KV: fu.OfpFlowModArgs{"priority": 500},
745 MatchFields: []*ofp.OfpOxmOfbField{
746 InPort(10),
747 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
748 VlanPcp(0),
749 EthType(0x800),
750 Ipv4Dst(0xe00a0a0a),
751 },
752 Actions: []*ofp.OfpAction{
753 Group(10),
754 },
755 }
756
757 var ga *fu.GroupArgs
758 ga = &fu.GroupArgs{
759 GroupId: 10,
760 Buckets: []*ofp.OfpBucket{
761 {Actions: []*ofp.OfpAction{
762 PopVlan(),
763 Output(1),
764 },
765 },
766 },
767 }
768
769 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
770 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{MkGroupStat(ga)}}
771 tfd := newTestFlowDecomposer(newTestDeviceManager())
772
773 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
774 onu1FlowAndGroup := deviceRules.Rules["onu1"]
775 oltFlowAndGroup := deviceRules.Rules["olt"]
776 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
777 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
778 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
779 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
780
781 fa = &fu.FlowArgs{
782 KV: fu.OfpFlowModArgs{"priority": 500},
783 MatchFields: []*ofp.OfpOxmOfbField{
784 InPort(2),
785 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
786 VlanPcp(0),
787 EthType(0x800),
788 Ipv4Dst(0xe00a0a0a),
789 },
790 Actions: []*ofp.OfpAction{
791 PopVlan(),
792 Output(1),
793 },
794 }
795 expectedOltFlow := MkFlowStat(fa)
796 derivedFlow := oltFlowAndGroup.GetFlow(0)
797 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
798
799 fa = &fu.FlowArgs{
800 KV: fu.OfpFlowModArgs{"priority": 500},
801 MatchFields: []*ofp.OfpOxmOfbField{
802 InPort(1),
803 EthType(0x800),
804 Ipv4Dst(0xe00a0a0a),
805 },
806 Actions: []*ofp.OfpAction{
807 Output(2),
808 },
809 }
810 expectedOnu1Flow := MkFlowStat(fa)
811 derivedFlow = onu1FlowAndGroup.GetFlow(1)
812 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
813}