blob: b2ba77788ef7b591a1a8f0d53d5709a6ca7ba41b [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"
21 ofp "github.com/opencord/voltha-go/protos/openflow_13"
22 "github.com/opencord/voltha-go/protos/voltha"
23 "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
30const (
31 maxOnuOnPort4 int = 1
32 maxOnuOnPort5 int = 1
33)
34
35func init() {
36 log.AddPackage(log.JSON, log.DebugLevel, nil)
37 log.UpdateAllLoggers(log.Fields{"instanceId": "flow-descomposition"})
38 log.SetAllLogLevel(log.DebugLevel)
39}
40
41type testDeviceManager struct {
42 devices map[string]*voltha.Device
43}
44
45func newTestDeviceManager() *testDeviceManager {
46 var tdm testDeviceManager
47 tdm.devices = make(map[string]*voltha.Device)
48 tdm.devices["olt"] = &voltha.Device{
49 Id: "olt",
50 Root: true,
51 ParentId: "logical_device",
52 Ports: []*voltha.Port{
53 &voltha.Port{PortNo: 1, Label: "pon"},
54 &voltha.Port{PortNo: 2, Label: "nni"},
55 },
56 }
57 tdm.devices["onu1"] = &voltha.Device{
58 Id: "onu1",
59 Root: false,
60 ParentId: "olt",
61 Ports: []*voltha.Port{
62 &voltha.Port{PortNo: 1, Label: "pon"},
63 &voltha.Port{PortNo: 2, Label: "uni"},
64 },
65 }
66 tdm.devices["onu2"] = &voltha.Device{
67 Id: "onu2",
68 Root: false,
69 ParentId: "olt",
70 Ports: []*voltha.Port{
71 &voltha.Port{PortNo: 1, Label: "pon"},
72 &voltha.Port{PortNo: 2, Label: "uni"},
73 },
74 }
75 tdm.devices["onu3"] = &voltha.Device{
76 Id: "onu3",
77 Root: false,
78 ParentId: "olt",
79 Ports: []*voltha.Port{
80 &voltha.Port{PortNo: 1, Label: "pon"},
81 &voltha.Port{PortNo: 2, Label: "uni"},
82 },
83 }
84 tdm.devices["onu4"] = &voltha.Device{
85 Id: "onu4",
86 Root: false,
87 ParentId: "olt",
88 Ports: []*voltha.Port{
89 &voltha.Port{PortNo: 1, Label: "pon"},
90 &voltha.Port{PortNo: 2, Label: "uni"},
91 },
92 }
93 return &tdm
94}
95
96func (tdm *testDeviceManager) GetDevice(deviceId string) (*voltha.Device, error) {
97 if d, ok := tdm.devices[deviceId]; ok {
98 return d, nil
99 }
100 return nil, errors.New("Absent")
101}
102
103type testFlowDecomposer struct {
104 dMgr *testDeviceManager
105 logicalPorts map[uint32]*voltha.LogicalPort
106 routes map[graph.OFPortLink][]graph.RouteHop
107 defaultRules *fu.DeviceRules
108 deviceGraph *graph.DeviceGraph
109 fd *FlowDecomposer
110}
111
112func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
113 var tfd testFlowDecomposer
114 tfd.dMgr = deviceMgr
115
116 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
117 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
118 // port
119 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
120 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
121 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
122 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
123 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
124
125 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
126
127 //DOWNSTREAM ROUTES
128
129 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
130 graph.RouteHop{
131 DeviceID: "olt",
132 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
133 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
134 },
135 graph.RouteHop{
136 DeviceID: "onu1",
137 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
138 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
139 },
140 }
141
142 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
143 graph.RouteHop{
144 DeviceID: "olt",
145 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
146 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
147 },
148 graph.RouteHop{
149 DeviceID: "onu2",
150 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
151 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
152 },
153 }
154 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
155 graph.RouteHop{
156 DeviceID: "olt",
157 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
158 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
159 },
160 graph.RouteHop{
161 DeviceID: "onu3",
162 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
163 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
164 },
165 }
166 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
167 graph.RouteHop{
168 DeviceID: "olt",
169 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
170 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
171 },
172 graph.RouteHop{
173 DeviceID: "onu4",
174 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
175 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
176 },
177 }
178
179 //UPSTREAM DATA PLANE
180
181 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
182 graph.RouteHop{
183 DeviceID: "onu1",
184 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
185 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
186 },
187 graph.RouteHop{
188 DeviceID: "olt",
189 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
190 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
191 },
192 }
193 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
194 graph.RouteHop{
195 DeviceID: "onu2",
196 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
197 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
198 },
199 graph.RouteHop{
200 DeviceID: "olt",
201 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
202 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
203 },
204 }
205 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
206 graph.RouteHop{
207 DeviceID: "onu3",
208 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
209 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
210 },
211 graph.RouteHop{
212 DeviceID: "olt",
213 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
214 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
215 },
216 }
217 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
218 graph.RouteHop{
219 DeviceID: "onu4",
220 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
221 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
222 },
223 graph.RouteHop{
224 DeviceID: "olt",
225 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
226 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
227 },
228 }
229
230 //UPSTREAM NEXT TABLE BASED
231
232 // openflow port 0 means absence of a port - go/protobuf interpretation
233 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
234 graph.RouteHop{
235 DeviceID: "onu1",
236 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
237 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
238 },
239 graph.RouteHop{
240 DeviceID: "olt",
241 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
242 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
243 },
244 }
245 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
246 graph.RouteHop{
247 DeviceID: "onu2",
248 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
249 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
250 },
251 graph.RouteHop{
252 DeviceID: "olt",
253 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
254 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
255 },
256 }
257 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
258 graph.RouteHop{
259 DeviceID: "onu3",
260 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
261 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
262 },
263 graph.RouteHop{
264 DeviceID: "olt",
265 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
266 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
267 },
268 }
269 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
270 graph.RouteHop{
271 DeviceID: "onu4",
272 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
273 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
274 },
275 graph.RouteHop{
276 DeviceID: "olt",
277 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
278 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
279 },
280 }
281
282 // DOWNSTREAM NEXT TABLE BASED
283
284 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
285 graph.RouteHop{
286 DeviceID: "olt",
287 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
288 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
289 },
290 graph.RouteHop{}, // 2nd hop is not known yet
291 }
292
293 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
294 graph.RouteHop{}, // 1st hop is wildcard
295 graph.RouteHop{
296 DeviceID: "olt",
297 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
298 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
299 },
300 }
301
302 // DEFAULT RULES
303
304 tfd.defaultRules = fu.NewDeviceRules()
305 fg := fu.NewFlowsAndGroups()
306 var fa *fu.FlowArgs
307 fa = &fu.FlowArgs{
308 MatchFields: []*ofp.OfpOxmOfbField{
309 InPort(2),
310 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
311 },
312 Actions: []*ofp.OfpAction{
313 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
314 Output(1),
315 },
316 }
317 fg.AddFlow(MkFlowStat(fa))
318 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
319
320 fg = fu.NewFlowsAndGroups()
321 fa = &fu.FlowArgs{
322 MatchFields: []*ofp.OfpOxmOfbField{
323 InPort(2),
324 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
325 },
326 Actions: []*ofp.OfpAction{
327 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
328 Output(1),
329 },
330 }
331 fg.AddFlow(MkFlowStat(fa))
332 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
333
334 fg = fu.NewFlowsAndGroups()
335 fa = &fu.FlowArgs{
336 MatchFields: []*ofp.OfpOxmOfbField{
337 InPort(2),
338 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
339 },
340 Actions: []*ofp.OfpAction{
341 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
342 Output(1),
343 },
344 }
345 fg.AddFlow(MkFlowStat(fa))
346 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
347
348 fg = fu.NewFlowsAndGroups()
349 fa = &fu.FlowArgs{
350 MatchFields: []*ofp.OfpOxmOfbField{
351 InPort(2),
352 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
353 },
354 Actions: []*ofp.OfpAction{
355 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
356 Output(1),
357 },
358 }
359 fg.AddFlow(MkFlowStat(fa))
360 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
361
362 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
363 tfd.deviceGraph = graph.NewDeviceGraph(tfd.getDeviceHelper)
364 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
365 tfd.deviceGraph.RootPorts[10] = 10
366
367 tfd.fd = NewFlowDecomposer(tfd.dMgr)
368
369 return &tfd
370}
371
372func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
373 return tfd.dMgr.GetDevice(deviceId)
374}
375
376func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
377 return ""
378}
379
380func (tfd *testFlowDecomposer) GetLogicalDevice() *voltha.LogicalDevice {
381 return nil
382}
383
384func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
385 return tfd.deviceGraph
386}
387
388func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
389 return tfd.defaultRules
390}
391
392func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
393 lPorts := make([]uint32, 0)
394 var exclPort uint32
395 if len(excludePort) == 1 {
396 exclPort = excludePort[0]
397 }
398 for portno, _ := range tfd.logicalPorts {
399 if portno != exclPort {
400 lPorts = append(lPorts, portno)
401 }
402 }
403 return lPorts
404}
405
406func (tfd *testFlowDecomposer) GetRoute(ingressPortNo *uint32, egressPortNo *uint32) []graph.RouteHop {
407 var portLink graph.OFPortLink
408 if egressPortNo == nil {
409 portLink.Egress = 0
410 } else if *egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
411 portLink.Egress = 10
412 } else {
413 portLink.Egress = *egressPortNo
414 }
415 if ingressPortNo == nil {
416 portLink.Ingress = 0
417 } else {
418 portLink.Ingress = *ingressPortNo
419 }
420 for key, val := range tfd.routes {
421 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
422 return val
423 }
424 }
425 return nil
426}
427
428func TestEapolReRouteRuleDecomposition(t *testing.T) {
429
430 var fa *fu.FlowArgs
431 fa = &fu.FlowArgs{
432 KV: fu.OfpFlowModArgs{"priority": 1000},
433 MatchFields: []*ofp.OfpOxmOfbField{
434 InPort(1),
435 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
436 EthType(0x888e),
437 },
438 Actions: []*ofp.OfpAction{
439 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
440 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
441 },
442 }
443
444 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
445 groups := ofp.FlowGroups{}
446 tfd := newTestFlowDecomposer(newTestDeviceManager())
447
448 device_rules := tfd.fd.DecomposeRules(tfd, flows, groups)
449 onu1FlowAndGroup := device_rules.Rules["onu1"]
450 oltFlowAndGroup := device_rules.Rules["olt"]
451 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
452 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
453 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
454 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
455
456 fa = &fu.FlowArgs{
457 MatchFields: []*ofp.OfpOxmOfbField{
458 InPort(2),
459 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
460 },
461 Actions: []*ofp.OfpAction{
462 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
463 Output(1),
464 },
465 }
466 expectedOnu1Flow := MkFlowStat(fa)
467 derivedFlow := onu1FlowAndGroup.GetFlow(0)
468 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
469
470 fa = &fu.FlowArgs{
471 KV: fu.OfpFlowModArgs{"priority": 1000},
472 MatchFields: []*ofp.OfpOxmOfbField{
473 InPort(1),
474 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
475 EthType(0x888e),
476 },
477 Actions: []*ofp.OfpAction{
478 PushVlan(0x8100),
479 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
480 Output(2),
481 },
482 }
483 expectedOltFlow := MkFlowStat(fa)
484 derivedFlow = oltFlowAndGroup.GetFlow(0)
485 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
486
487 fa = &fu.FlowArgs{
488 KV: fu.OfpFlowModArgs{"priority": 1000},
489 MatchFields: []*ofp.OfpOxmOfbField{
490 InPort(2),
491 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
492 VlanPcp(0),
493 Metadata_ofp(1),
494 },
495 Actions: []*ofp.OfpAction{
496 PopVlan(),
497 Output(1),
498 },
499 }
500 expectedOltFlow = MkFlowStat(fa)
501 derivedFlow = oltFlowAndGroup.GetFlow(1)
502 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
503}
504
505func TestDhcpReRouteRuleDecomposition(t *testing.T) {
506
507 var fa *fu.FlowArgs
508 fa = &fu.FlowArgs{
509 KV: fu.OfpFlowModArgs{"priority": 1000},
510 MatchFields: []*ofp.OfpOxmOfbField{
511 InPort(1),
512 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
513 EthType(0x0800),
514 Ipv4Dst(0xffffffff),
515 IpProto(17),
516 UdpSrc(68),
517 UdpDst(67),
518 },
519 Actions: []*ofp.OfpAction{
520 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
521 },
522 }
523
524 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
525 groups := ofp.FlowGroups{}
526 tfd := newTestFlowDecomposer(newTestDeviceManager())
527
528 device_rules := tfd.fd.DecomposeRules(tfd, flows, groups)
529 onu1FlowAndGroup := device_rules.Rules["onu1"]
530 oltFlowAndGroup := device_rules.Rules["olt"]
531 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
532 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
533 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
534 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
535
536 fa = &fu.FlowArgs{
537 MatchFields: []*ofp.OfpOxmOfbField{
538 InPort(2),
539 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
540 },
541 Actions: []*ofp.OfpAction{
542 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
543 Output(1),
544 },
545 }
546 expectedOnu1Flow := MkFlowStat(fa)
547 derivedFlow := onu1FlowAndGroup.GetFlow(0)
548 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
549
550 fa = &fu.FlowArgs{
551 KV: fu.OfpFlowModArgs{"priority": 1000},
552 MatchFields: []*ofp.OfpOxmOfbField{
553 InPort(1),
554 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
555 EthType(0x0800),
556 Ipv4Dst(0xffffffff),
557 IpProto(17),
558 UdpSrc(68),
559 UdpDst(67),
560 },
561 Actions: []*ofp.OfpAction{
562 PushVlan(0x8100),
563 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
564 Output(2),
565 },
566 }
567 expectedOltFlow := MkFlowStat(fa)
568 derivedFlow = oltFlowAndGroup.GetFlow(0)
569 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
570
571 fa = &fu.FlowArgs{
572 KV: fu.OfpFlowModArgs{"priority": 1000},
573 MatchFields: []*ofp.OfpOxmOfbField{
574 InPort(2),
575 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
576 VlanPcp(0),
577 Metadata_ofp(1),
578 },
579 Actions: []*ofp.OfpAction{
580 PopVlan(),
581 Output(1),
582 },
583 }
584 expectedOltFlow = MkFlowStat(fa)
585 derivedFlow = oltFlowAndGroup.GetFlow(1)
586 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
587}
588
589//func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
590//
591// var fa *fu.FlowArgs
592// fa = &fu.FlowArgs{
593// KV: fu.OfpFlowModArgs{"priority": 500, "table_id":1},
594// MatchFields: []*ofp.OfpOxmOfbField{
595// InPort(1),
596// VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
597// VlanPcp(0),
598// },
599// Actions: []*ofp.OfpAction{
600// SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
601// },
602// }
603//
604// var fa2 *fu.FlowArgs
605// fa2 = &fu.FlowArgs{
606// KV: fu.OfpFlowModArgs{"priority": 500},
607// MatchFields: []*ofp.OfpOxmOfbField{
608// InPort(1),
609// VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
610// VlanPcp(0),
611// },
612// Actions: []*ofp.OfpAction{
613// PushVlan(0x8100),
614// SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
615// SetField(VlanPcp(0)),
616// Output(10),
617// },
618// }
619//
620// flows := ofp.Flows{Items:[]*ofp.OfpFlowStats{MkFlowStat(fa), MkFlowStat(fa2)}}
621// groups := ofp.FlowGroups{}
622// tfd := newTestFlowDecomposer(newTestDeviceManager())
623//
624// device_rules := tfd.fd.DecomposeRules(tfd, flows, groups)
625// onu1FlowAndGroup := device_rules.Rules["onu1"]
626// oltFlowAndGroup := device_rules.Rules["olt"]
627// assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
628// assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
629// assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
630// assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
631//
632// fa = &fu.FlowArgs{
633// KV: fu.OfpFlowModArgs{"priority": 500},
634// MatchFields: []*ofp.OfpOxmOfbField{
635// InPort(2),
636// VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
637// VlanPcp(0),
638// },
639// Actions: []*ofp.OfpAction{
640// SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
641// Output(1),
642// },
643// }
644// expectedOnu1Flow := MkFlowStat(fa)
645// derivedFlow := onu1FlowAndGroup.GetFlow(1)
646// assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
647//
648// fa = &fu.FlowArgs{
649// KV: fu.OfpFlowModArgs{"priority": 500},
650// MatchFields: []*ofp.OfpOxmOfbField{
651// InPort(1),
652// VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
653// VlanPcp(0),
654// },
655// Actions: []*ofp.OfpAction{
656// PushVlan(0x8100),
657// SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
658// SetField(VlanPcp(0)),
659// Output(2),
660// },
661// }
662// expectedOltFlow := MkFlowStat(fa)
663// derivedFlow = oltFlowAndGroup.GetFlow(0)
664// assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
665//}