blob: 6c7d7fa41fb769f853fc268a32812a7e3abe3570 [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
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}
97
98type testFlowDecomposer struct {
99 dMgr *testDeviceManager
100 logicalPorts map[uint32]*voltha.LogicalPort
101 routes map[graph.OFPortLink][]graph.RouteHop
102 defaultRules *fu.DeviceRules
103 deviceGraph *graph.DeviceGraph
104 fd *FlowDecomposer
105}
106
107func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
108 var tfd testFlowDecomposer
109 tfd.dMgr = deviceMgr
110
111 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
112 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
113 // port
114 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
115 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
116 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
117 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
118 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
119
120 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
121
122 //DOWNSTREAM ROUTES
123
124 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400125 {
khenaidoo89b0e942018-10-21 21:11:33 -0400126 DeviceID: "olt",
127 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
128 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
129 },
khenaidood20a5852018-10-22 22:09:55 -0400130 {
khenaidoo89b0e942018-10-21 21:11:33 -0400131 DeviceID: "onu1",
132 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
133 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
134 },
135 }
136
137 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400138 {
khenaidoo89b0e942018-10-21 21:11:33 -0400139 DeviceID: "olt",
140 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
141 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
142 },
khenaidood20a5852018-10-22 22:09:55 -0400143 {
khenaidoo89b0e942018-10-21 21:11:33 -0400144 DeviceID: "onu2",
145 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
146 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
147 },
148 }
149 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400150 {
khenaidoo89b0e942018-10-21 21:11:33 -0400151 DeviceID: "olt",
152 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
153 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
154 },
khenaidood20a5852018-10-22 22:09:55 -0400155 {
khenaidoo89b0e942018-10-21 21:11:33 -0400156 DeviceID: "onu3",
157 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
158 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
159 },
160 }
161 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400162 {
khenaidoo89b0e942018-10-21 21:11:33 -0400163 DeviceID: "olt",
164 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
165 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
166 },
khenaidood20a5852018-10-22 22:09:55 -0400167 {
khenaidoo89b0e942018-10-21 21:11:33 -0400168 DeviceID: "onu4",
169 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
170 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
171 },
172 }
173
174 //UPSTREAM DATA PLANE
175
176 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400177 {
khenaidoo89b0e942018-10-21 21:11:33 -0400178 DeviceID: "onu1",
179 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
180 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
181 },
khenaidood20a5852018-10-22 22:09:55 -0400182 {
khenaidoo89b0e942018-10-21 21:11:33 -0400183 DeviceID: "olt",
184 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
185 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
186 },
187 }
188 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400189 {
khenaidoo89b0e942018-10-21 21:11:33 -0400190 DeviceID: "onu2",
191 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
192 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
193 },
khenaidood20a5852018-10-22 22:09:55 -0400194 {
khenaidoo89b0e942018-10-21 21:11:33 -0400195 DeviceID: "olt",
196 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
197 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
198 },
199 }
200 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400201 {
khenaidoo89b0e942018-10-21 21:11:33 -0400202 DeviceID: "onu3",
203 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
204 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
205 },
khenaidood20a5852018-10-22 22:09:55 -0400206 {
khenaidoo89b0e942018-10-21 21:11:33 -0400207 DeviceID: "olt",
208 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
209 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
210 },
211 }
212 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400213 {
khenaidoo89b0e942018-10-21 21:11:33 -0400214 DeviceID: "onu4",
215 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
216 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
217 },
khenaidood20a5852018-10-22 22:09:55 -0400218 {
khenaidoo89b0e942018-10-21 21:11:33 -0400219 DeviceID: "olt",
220 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
221 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
222 },
223 }
224
225 //UPSTREAM NEXT TABLE BASED
226
227 // openflow port 0 means absence of a port - go/protobuf interpretation
228 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400229 {
khenaidoo89b0e942018-10-21 21:11:33 -0400230 DeviceID: "onu1",
231 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
232 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
233 },
khenaidood20a5852018-10-22 22:09:55 -0400234 {
khenaidoo89b0e942018-10-21 21:11:33 -0400235 DeviceID: "olt",
236 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
237 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
238 },
239 }
240 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400241 {
khenaidoo89b0e942018-10-21 21:11:33 -0400242 DeviceID: "onu2",
243 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
244 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
245 },
khenaidood20a5852018-10-22 22:09:55 -0400246 {
khenaidoo89b0e942018-10-21 21:11:33 -0400247 DeviceID: "olt",
248 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
249 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
250 },
251 }
252 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400253 {
khenaidoo89b0e942018-10-21 21:11:33 -0400254 DeviceID: "onu3",
255 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
256 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
257 },
khenaidood20a5852018-10-22 22:09:55 -0400258 {
khenaidoo89b0e942018-10-21 21:11:33 -0400259 DeviceID: "olt",
260 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
261 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
262 },
263 }
264 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400265 {
khenaidoo89b0e942018-10-21 21:11:33 -0400266 DeviceID: "onu4",
267 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
268 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
269 },
khenaidood20a5852018-10-22 22:09:55 -0400270 {
khenaidoo89b0e942018-10-21 21:11:33 -0400271 DeviceID: "olt",
272 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
273 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
274 },
275 }
276
277 // DOWNSTREAM NEXT TABLE BASED
278
279 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400280 {
khenaidoo89b0e942018-10-21 21:11:33 -0400281 DeviceID: "olt",
282 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
283 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
284 },
khenaidood20a5852018-10-22 22:09:55 -0400285 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400286 }
287
288 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400289 {}, // 1st hop is wildcard
290 {
khenaidoo89b0e942018-10-21 21:11:33 -0400291 DeviceID: "olt",
292 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
293 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
294 },
295 }
296
297 // DEFAULT RULES
298
299 tfd.defaultRules = fu.NewDeviceRules()
300 fg := fu.NewFlowsAndGroups()
301 var fa *fu.FlowArgs
302 fa = &fu.FlowArgs{
303 MatchFields: []*ofp.OfpOxmOfbField{
304 InPort(2),
305 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
306 },
307 Actions: []*ofp.OfpAction{
308 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
309 Output(1),
310 },
311 }
312 fg.AddFlow(MkFlowStat(fa))
313 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
314
315 fg = fu.NewFlowsAndGroups()
316 fa = &fu.FlowArgs{
317 MatchFields: []*ofp.OfpOxmOfbField{
318 InPort(2),
319 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
320 },
321 Actions: []*ofp.OfpAction{
322 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
323 Output(1),
324 },
325 }
326 fg.AddFlow(MkFlowStat(fa))
327 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
328
329 fg = fu.NewFlowsAndGroups()
330 fa = &fu.FlowArgs{
331 MatchFields: []*ofp.OfpOxmOfbField{
332 InPort(2),
333 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
334 },
335 Actions: []*ofp.OfpAction{
336 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
337 Output(1),
338 },
339 }
340 fg.AddFlow(MkFlowStat(fa))
341 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
342
343 fg = fu.NewFlowsAndGroups()
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) | 104)),
351 Output(1),
352 },
353 }
354 fg.AddFlow(MkFlowStat(fa))
355 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
356
357 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
358 tfd.deviceGraph = graph.NewDeviceGraph(tfd.getDeviceHelper)
359 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
360 tfd.deviceGraph.RootPorts[10] = 10
361
362 tfd.fd = NewFlowDecomposer(tfd.dMgr)
363
364 return &tfd
365}
366
367func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
368 return tfd.dMgr.GetDevice(deviceId)
369}
370
371func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
372 return ""
373}
374
375func (tfd *testFlowDecomposer) GetLogicalDevice() *voltha.LogicalDevice {
376 return nil
377}
378
379func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
380 return tfd.deviceGraph
381}
382
383func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
384 return tfd.defaultRules
385}
386
387func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
388 lPorts := make([]uint32, 0)
389 var exclPort uint32
390 if len(excludePort) == 1 {
391 exclPort = excludePort[0]
392 }
khenaidood20a5852018-10-22 22:09:55 -0400393 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400394 if portno != exclPort {
395 lPorts = append(lPorts, portno)
396 }
397 }
398 return lPorts
399}
400
401func (tfd *testFlowDecomposer) GetRoute(ingressPortNo *uint32, egressPortNo *uint32) []graph.RouteHop {
402 var portLink graph.OFPortLink
403 if egressPortNo == nil {
404 portLink.Egress = 0
405 } else if *egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
406 portLink.Egress = 10
407 } else {
408 portLink.Egress = *egressPortNo
409 }
410 if ingressPortNo == nil {
411 portLink.Ingress = 0
412 } else {
413 portLink.Ingress = *ingressPortNo
414 }
415 for key, val := range tfd.routes {
416 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
417 return val
418 }
419 }
420 return nil
421}
422
423func TestEapolReRouteRuleDecomposition(t *testing.T) {
424
425 var fa *fu.FlowArgs
426 fa = &fu.FlowArgs{
427 KV: fu.OfpFlowModArgs{"priority": 1000},
428 MatchFields: []*ofp.OfpOxmOfbField{
429 InPort(1),
430 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
431 EthType(0x888e),
432 },
433 Actions: []*ofp.OfpAction{
434 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
435 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
436 },
437 }
438
439 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
440 groups := ofp.FlowGroups{}
441 tfd := newTestFlowDecomposer(newTestDeviceManager())
442
khenaidood20a5852018-10-22 22:09:55 -0400443 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
444 onu1FlowAndGroup := deviceRules.Rules["onu1"]
445 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400446 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
447 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
448 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
449 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
450
451 fa = &fu.FlowArgs{
452 MatchFields: []*ofp.OfpOxmOfbField{
453 InPort(2),
454 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
455 },
456 Actions: []*ofp.OfpAction{
457 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
458 Output(1),
459 },
460 }
461 expectedOnu1Flow := MkFlowStat(fa)
462 derivedFlow := onu1FlowAndGroup.GetFlow(0)
463 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
464
465 fa = &fu.FlowArgs{
466 KV: fu.OfpFlowModArgs{"priority": 1000},
467 MatchFields: []*ofp.OfpOxmOfbField{
468 InPort(1),
469 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
470 EthType(0x888e),
471 },
472 Actions: []*ofp.OfpAction{
473 PushVlan(0x8100),
474 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
475 Output(2),
476 },
477 }
478 expectedOltFlow := MkFlowStat(fa)
479 derivedFlow = oltFlowAndGroup.GetFlow(0)
480 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
481
482 fa = &fu.FlowArgs{
483 KV: fu.OfpFlowModArgs{"priority": 1000},
484 MatchFields: []*ofp.OfpOxmOfbField{
485 InPort(2),
486 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
487 VlanPcp(0),
488 Metadata_ofp(1),
489 },
490 Actions: []*ofp.OfpAction{
491 PopVlan(),
492 Output(1),
493 },
494 }
495 expectedOltFlow = MkFlowStat(fa)
496 derivedFlow = oltFlowAndGroup.GetFlow(1)
497 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
498}
499
500func TestDhcpReRouteRuleDecomposition(t *testing.T) {
501
502 var fa *fu.FlowArgs
503 fa = &fu.FlowArgs{
504 KV: fu.OfpFlowModArgs{"priority": 1000},
505 MatchFields: []*ofp.OfpOxmOfbField{
506 InPort(1),
507 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
508 EthType(0x0800),
509 Ipv4Dst(0xffffffff),
510 IpProto(17),
511 UdpSrc(68),
512 UdpDst(67),
513 },
514 Actions: []*ofp.OfpAction{
515 Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
516 },
517 }
518
519 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
520 groups := ofp.FlowGroups{}
521 tfd := newTestFlowDecomposer(newTestDeviceManager())
522
khenaidood20a5852018-10-22 22:09:55 -0400523 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
524 onu1FlowAndGroup := deviceRules.Rules["onu1"]
525 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400526 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
527 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
528 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
529 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
530
531 fa = &fu.FlowArgs{
532 MatchFields: []*ofp.OfpOxmOfbField{
533 InPort(2),
534 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
535 },
536 Actions: []*ofp.OfpAction{
537 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
538 Output(1),
539 },
540 }
541 expectedOnu1Flow := MkFlowStat(fa)
542 derivedFlow := onu1FlowAndGroup.GetFlow(0)
543 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
544
545 fa = &fu.FlowArgs{
546 KV: fu.OfpFlowModArgs{"priority": 1000},
547 MatchFields: []*ofp.OfpOxmOfbField{
548 InPort(1),
549 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
550 EthType(0x0800),
551 Ipv4Dst(0xffffffff),
552 IpProto(17),
553 UdpSrc(68),
554 UdpDst(67),
555 },
556 Actions: []*ofp.OfpAction{
557 PushVlan(0x8100),
558 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
559 Output(2),
560 },
561 }
562 expectedOltFlow := MkFlowStat(fa)
563 derivedFlow = oltFlowAndGroup.GetFlow(0)
564 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
565
566 fa = &fu.FlowArgs{
567 KV: fu.OfpFlowModArgs{"priority": 1000},
568 MatchFields: []*ofp.OfpOxmOfbField{
569 InPort(2),
570 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
571 VlanPcp(0),
572 Metadata_ofp(1),
573 },
574 Actions: []*ofp.OfpAction{
575 PopVlan(),
576 Output(1),
577 },
578 }
579 expectedOltFlow = MkFlowStat(fa)
580 derivedFlow = oltFlowAndGroup.GetFlow(1)
581 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
582}
583
khenaidood20a5852018-10-22 22:09:55 -0400584func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
585
586 var fa *fu.FlowArgs
587 fa = &fu.FlowArgs{
588 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
589 MatchFields: []*ofp.OfpOxmOfbField{
590 InPort(1),
591 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
592 VlanPcp(0),
593 },
594 Actions: []*ofp.OfpAction{
595 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
596 },
597 }
598
599 var fa2 *fu.FlowArgs
600 fa2 = &fu.FlowArgs{
601 KV: fu.OfpFlowModArgs{"priority": 500},
602 MatchFields: []*ofp.OfpOxmOfbField{
603 InPort(1),
604 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
605 VlanPcp(0),
606 },
607 Actions: []*ofp.OfpAction{
608 PushVlan(0x8100),
609 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
610 SetField(VlanPcp(0)),
611 Output(10),
612 },
613 }
614
615 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa), MkFlowStat(fa2)}}
616 groups := ofp.FlowGroups{}
617 tfd := newTestFlowDecomposer(newTestDeviceManager())
618
619 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
620 onu1FlowAndGroup := deviceRules.Rules["onu1"]
621 oltFlowAndGroup := deviceRules.Rules["olt"]
622 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
623 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
624 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
625 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
626
627 fa = &fu.FlowArgs{
628 KV: fu.OfpFlowModArgs{"priority": 500},
629 MatchFields: []*ofp.OfpOxmOfbField{
630 InPort(2),
631 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
632 VlanPcp(0),
633 },
634 Actions: []*ofp.OfpAction{
635 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
636 Output(1),
637 },
638 }
639 expectedOnu1Flow := MkFlowStat(fa)
640 derivedFlow := onu1FlowAndGroup.GetFlow(1)
641 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
642
643 fa = &fu.FlowArgs{
644 KV: fu.OfpFlowModArgs{"priority": 500},
645 MatchFields: []*ofp.OfpOxmOfbField{
646 InPort(1),
647 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
648 VlanPcp(0),
649 },
650 Actions: []*ofp.OfpAction{
651 PushVlan(0x8100),
652 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
653 SetField(VlanPcp(0)),
654 Output(2),
655 },
656 }
657 expectedOltFlow := MkFlowStat(fa)
658 derivedFlow = oltFlowAndGroup.GetFlow(0)
659 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
660}
661
662func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
663 var fa1 *fu.FlowArgs
664 fa1 = &fu.FlowArgs{
665 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
666 MatchFields: []*ofp.OfpOxmOfbField{
667 InPort(10),
668 Metadata_ofp((1000 << 32) | 1),
669 VlanPcp(0),
670 },
671 Actions: []*ofp.OfpAction{
672 PopVlan(),
673 },
674 }
675
676 var fa2 *fu.FlowArgs
677 fa2 = &fu.FlowArgs{
678 KV: fu.OfpFlowModArgs{"priority": 500},
679 MatchFields: []*ofp.OfpOxmOfbField{
680 InPort(10),
681 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
682 VlanPcp(0),
683 },
684 Actions: []*ofp.OfpAction{
685 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
686 Output(1),
687 },
688 }
689
690 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa1), MkFlowStat(fa2)}}
691 groups := ofp.FlowGroups{}
692 tfd := newTestFlowDecomposer(newTestDeviceManager())
693
694 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
695 onu1FlowAndGroup := deviceRules.Rules["onu1"]
696 oltFlowAndGroup := deviceRules.Rules["olt"]
697 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
698 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
699 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
700 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
701
702 fa1 = &fu.FlowArgs{
703 KV: fu.OfpFlowModArgs{"priority": 500},
704 MatchFields: []*ofp.OfpOxmOfbField{
705 InPort(2),
706 Metadata_ofp(1000),
707 VlanPcp(0),
708 },
709 Actions: []*ofp.OfpAction{
710 PopVlan(),
711 Output(1),
712 },
713 }
714 expectedOltFlow := MkFlowStat(fa1)
715 derivedFlow := oltFlowAndGroup.GetFlow(0)
716 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
717
718 fa1 = &fu.FlowArgs{
719 KV: fu.OfpFlowModArgs{"priority": 500},
720 MatchFields: []*ofp.OfpOxmOfbField{
721 InPort(1),
722 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
723 VlanPcp(0),
724 },
725 Actions: []*ofp.OfpAction{
726 SetField(VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
727 Output(2),
728 },
729 }
730 expectedOnu1Flow := MkFlowStat(fa1)
731 derivedFlow = onu1FlowAndGroup.GetFlow(1)
732 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
733}
734
735func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
736 var fa *fu.FlowArgs
737 fa = &fu.FlowArgs{
738 KV: fu.OfpFlowModArgs{"priority": 500},
739 MatchFields: []*ofp.OfpOxmOfbField{
740 InPort(10),
741 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
742 VlanPcp(0),
743 EthType(0x800),
744 Ipv4Dst(0xe00a0a0a),
745 },
746 Actions: []*ofp.OfpAction{
747 Group(10),
748 },
749 }
750
751 var ga *fu.GroupArgs
752 ga = &fu.GroupArgs{
753 GroupId: 10,
754 Buckets: []*ofp.OfpBucket{
755 {Actions: []*ofp.OfpAction{
756 PopVlan(),
757 Output(1),
758 },
759 },
760 },
761 }
762
763 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{MkFlowStat(fa)}}
764 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{MkGroupStat(ga)}}
765 tfd := newTestFlowDecomposer(newTestDeviceManager())
766
767 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups)
768 onu1FlowAndGroup := deviceRules.Rules["onu1"]
769 oltFlowAndGroup := deviceRules.Rules["olt"]
770 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
771 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
772 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
773 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
774
775 fa = &fu.FlowArgs{
776 KV: fu.OfpFlowModArgs{"priority": 500},
777 MatchFields: []*ofp.OfpOxmOfbField{
778 InPort(2),
779 VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
780 VlanPcp(0),
781 EthType(0x800),
782 Ipv4Dst(0xe00a0a0a),
783 },
784 Actions: []*ofp.OfpAction{
785 PopVlan(),
786 Output(1),
787 },
788 }
789 expectedOltFlow := MkFlowStat(fa)
790 derivedFlow := oltFlowAndGroup.GetFlow(0)
791 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
792
793 fa = &fu.FlowArgs{
794 KV: fu.OfpFlowModArgs{"priority": 500},
795 MatchFields: []*ofp.OfpOxmOfbField{
796 InPort(1),
797 EthType(0x800),
798 Ipv4Dst(0xe00a0a0a),
799 },
800 Actions: []*ofp.OfpAction{
801 Output(2),
802 },
803 }
804 expectedOnu1Flow := MkFlowStat(fa)
805 derivedFlow = onu1FlowAndGroup.GetFlow(1)
806 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
807}