blob: 6464c5d40aef832ee326d67a1857db52397e2fbc [file] [log] [blame]
khenaidoo89b0e942018-10-21 21:11:33 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package flow_decomposition
17
18import (
19 "errors"
20 "github.com/opencord/voltha-go/common/log"
khenaidoo89b0e942018-10-21 21:11:33 -040021 "github.com/opencord/voltha-go/rw_core/graph"
22 fu "github.com/opencord/voltha-go/rw_core/utils"
khenaidoo2c6a0992019-04-29 13:46:56 -040023 ofp "github.com/opencord/voltha-protos/go/openflow_13"
24 "github.com/opencord/voltha-protos/go/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040025 "github.com/stretchr/testify/assert"
26
27 "testing"
28)
29
khenaidoo89b0e942018-10-21 21:11:33 -040030func init() {
khenaidood20a5852018-10-22 22:09:55 -040031 log.AddPackage(log.JSON, log.WarnLevel, nil)
khenaidoo910204f2019-04-08 17:56:40 -040032 log.UpdateAllLoggers(log.Fields{"instanceId": "flow-decomposition"})
khenaidood20a5852018-10-22 22:09:55 -040033 log.SetAllLogLevel(log.WarnLevel)
khenaidoo89b0e942018-10-21 21:11:33 -040034}
35
36type testDeviceManager struct {
37 devices map[string]*voltha.Device
38}
39
40func newTestDeviceManager() *testDeviceManager {
41 var tdm testDeviceManager
42 tdm.devices = make(map[string]*voltha.Device)
43 tdm.devices["olt"] = &voltha.Device{
44 Id: "olt",
45 Root: true,
46 ParentId: "logical_device",
47 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040048 {PortNo: 1, Label: "pon"},
49 {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040050 },
51 }
52 tdm.devices["onu1"] = &voltha.Device{
53 Id: "onu1",
54 Root: false,
55 ParentId: "olt",
56 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040057 {PortNo: 1, Label: "pon"},
58 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040059 },
60 }
61 tdm.devices["onu2"] = &voltha.Device{
62 Id: "onu2",
63 Root: false,
64 ParentId: "olt",
65 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040066 {PortNo: 1, Label: "pon"},
67 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040068 },
69 }
70 tdm.devices["onu3"] = &voltha.Device{
71 Id: "onu3",
72 Root: false,
73 ParentId: "olt",
74 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040075 {PortNo: 1, Label: "pon"},
76 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040077 },
78 }
79 tdm.devices["onu4"] = &voltha.Device{
80 Id: "onu4",
81 Root: false,
82 ParentId: "olt",
83 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040084 {PortNo: 1, Label: "pon"},
85 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040086 },
87 }
88 return &tdm
89}
90
91func (tdm *testDeviceManager) GetDevice(deviceId string) (*voltha.Device, error) {
92 if d, ok := tdm.devices[deviceId]; ok {
93 return d, nil
94 }
khenaidood20a5852018-10-22 22:09:55 -040095 return nil, errors.New("ABSENT.")
khenaidoo89b0e942018-10-21 21:11:33 -040096}
khenaidoo19d7b632018-10-30 10:49:50 -040097func (tdm *testDeviceManager) IsRootDevice(deviceId string) (bool, error) {
98 if d, ok := tdm.devices[deviceId]; ok {
99 return d.Root, nil
100 }
101 return false, errors.New("ABSENT.")
102}
khenaidoo89b0e942018-10-21 21:11:33 -0400103
khenaidoo0a822f92019-05-08 15:15:57 -0400104func (tdm *testDeviceManager) NotifyInvalidTransition(pcDevice *voltha.Device) error {
105 return nil
106}
107
108func (tdm *testDeviceManager) SetAdminStateToEnable(cDevice *voltha.Device) error {
109 return nil
110}
111
112func (tdm *testDeviceManager) CreateLogicalDevice(cDevice *voltha.Device) error {
113 return nil
114}
115
116func (tdm *testDeviceManager) SetupUNILogicalPorts(cDevice *voltha.Device) error {
117 return nil
118}
119
120func (tdm *testDeviceManager) DisableAllChildDevices(cDevice *voltha.Device) error {
121 return nil
122}
123
124func (tdm *testDeviceManager) DeleteLogicalDevice(cDevice *voltha.Device) error {
125 return nil
126}
127
128func (tdm *testDeviceManager) DeleteLogicalPorts(cDevice *voltha.Device) error {
129 return nil
130}
131
132func (tdm *testDeviceManager) DeleteAllChildDevices(cDevice *voltha.Device) error {
133 return nil
134}
135
136func (tdm *testDeviceManager) RunPostDeviceDelete(cDevice *voltha.Device) error {
137 return nil
138}
139
khenaidoo89b0e942018-10-21 21:11:33 -0400140type testFlowDecomposer struct {
141 dMgr *testDeviceManager
142 logicalPorts map[uint32]*voltha.LogicalPort
143 routes map[graph.OFPortLink][]graph.RouteHop
144 defaultRules *fu.DeviceRules
145 deviceGraph *graph.DeviceGraph
146 fd *FlowDecomposer
147}
148
149func newTestFlowDecomposer(deviceMgr *testDeviceManager) *testFlowDecomposer {
150 var tfd testFlowDecomposer
151 tfd.dMgr = deviceMgr
152
153 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
154 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
155 // port
156 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
157 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
158 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
159 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
160 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
161
162 tfd.routes = make(map[graph.OFPortLink][]graph.RouteHop)
163
164 //DOWNSTREAM ROUTES
165
166 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 1}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400167 {
khenaidoo89b0e942018-10-21 21:11:33 -0400168 DeviceID: "olt",
169 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
170 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
171 },
khenaidood20a5852018-10-22 22:09:55 -0400172 {
khenaidoo89b0e942018-10-21 21:11:33 -0400173 DeviceID: "onu1",
174 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
175 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
176 },
177 }
178
179 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 2}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400180 {
khenaidoo89b0e942018-10-21 21:11:33 -0400181 DeviceID: "olt",
182 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
183 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
184 },
khenaidood20a5852018-10-22 22:09:55 -0400185 {
khenaidoo89b0e942018-10-21 21:11:33 -0400186 DeviceID: "onu2",
187 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
188 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
189 },
190 }
191 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 3}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400192 {
khenaidoo89b0e942018-10-21 21:11:33 -0400193 DeviceID: "olt",
194 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
195 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
196 },
khenaidood20a5852018-10-22 22:09:55 -0400197 {
khenaidoo89b0e942018-10-21 21:11:33 -0400198 DeviceID: "onu3",
199 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
200 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
201 },
202 }
203 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 4}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400204 {
khenaidoo89b0e942018-10-21 21:11:33 -0400205 DeviceID: "olt",
206 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
207 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
208 },
khenaidood20a5852018-10-22 22:09:55 -0400209 {
khenaidoo89b0e942018-10-21 21:11:33 -0400210 DeviceID: "onu4",
211 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
212 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
213 },
214 }
215
216 //UPSTREAM DATA PLANE
217
218 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400219 {
khenaidoo89b0e942018-10-21 21:11:33 -0400220 DeviceID: "onu1",
221 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
222 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
223 },
khenaidood20a5852018-10-22 22:09:55 -0400224 {
khenaidoo89b0e942018-10-21 21:11:33 -0400225 DeviceID: "olt",
226 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
227 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
228 },
229 }
230 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400231 {
khenaidoo89b0e942018-10-21 21:11:33 -0400232 DeviceID: "onu2",
233 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
234 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
235 },
khenaidood20a5852018-10-22 22:09:55 -0400236 {
khenaidoo89b0e942018-10-21 21:11:33 -0400237 DeviceID: "olt",
238 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
239 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
240 },
241 }
242 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400243 {
khenaidoo89b0e942018-10-21 21:11:33 -0400244 DeviceID: "onu3",
245 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
246 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
247 },
khenaidood20a5852018-10-22 22:09:55 -0400248 {
khenaidoo89b0e942018-10-21 21:11:33 -0400249 DeviceID: "olt",
250 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
251 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
252 },
253 }
254 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400255 {
khenaidoo89b0e942018-10-21 21:11:33 -0400256 DeviceID: "onu4",
257 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
258 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
259 },
khenaidood20a5852018-10-22 22:09:55 -0400260 {
khenaidoo89b0e942018-10-21 21:11:33 -0400261 DeviceID: "olt",
262 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
263 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
264 },
265 }
266
267 //UPSTREAM NEXT TABLE BASED
268
269 // openflow port 0 means absence of a port - go/protobuf interpretation
270 tfd.routes[graph.OFPortLink{Ingress: 1, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400271 {
khenaidoo89b0e942018-10-21 21:11:33 -0400272 DeviceID: "onu1",
273 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
274 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
275 },
khenaidood20a5852018-10-22 22:09:55 -0400276 {
khenaidoo89b0e942018-10-21 21:11:33 -0400277 DeviceID: "olt",
278 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
279 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
280 },
281 }
282 tfd.routes[graph.OFPortLink{Ingress: 2, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400283 {
khenaidoo89b0e942018-10-21 21:11:33 -0400284 DeviceID: "onu2",
285 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
286 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
287 },
khenaidood20a5852018-10-22 22:09:55 -0400288 {
khenaidoo89b0e942018-10-21 21:11:33 -0400289 DeviceID: "olt",
290 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
291 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
292 },
293 }
294 tfd.routes[graph.OFPortLink{Ingress: 3, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400295 {
khenaidoo89b0e942018-10-21 21:11:33 -0400296 DeviceID: "onu3",
297 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
298 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
299 },
khenaidood20a5852018-10-22 22:09:55 -0400300 {
khenaidoo89b0e942018-10-21 21:11:33 -0400301 DeviceID: "olt",
302 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
303 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
304 },
305 }
306 tfd.routes[graph.OFPortLink{Ingress: 4, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400307 {
khenaidoo89b0e942018-10-21 21:11:33 -0400308 DeviceID: "onu4",
309 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
310 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
311 },
khenaidood20a5852018-10-22 22:09:55 -0400312 {
khenaidoo89b0e942018-10-21 21:11:33 -0400313 DeviceID: "olt",
314 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
315 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
316 },
317 }
318
319 // DOWNSTREAM NEXT TABLE BASED
320
321 tfd.routes[graph.OFPortLink{Ingress: 10, Egress: 0}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400322 {
khenaidoo89b0e942018-10-21 21:11:33 -0400323 DeviceID: "olt",
324 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
325 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
326 },
khenaidood20a5852018-10-22 22:09:55 -0400327 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400328 }
329
330 tfd.routes[graph.OFPortLink{Ingress: 0, Egress: 10}] = []graph.RouteHop{
khenaidood20a5852018-10-22 22:09:55 -0400331 {}, // 1st hop is wildcard
332 {
khenaidoo89b0e942018-10-21 21:11:33 -0400333 DeviceID: "olt",
334 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
335 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
336 },
337 }
338
339 // DEFAULT RULES
340
341 tfd.defaultRules = fu.NewDeviceRules()
342 fg := fu.NewFlowsAndGroups()
343 var fa *fu.FlowArgs
344 fa = &fu.FlowArgs{
345 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400346 fu.InPort(2),
347 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400348 },
349 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400350 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
351 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400352 },
353 }
khenaidoo68c930b2019-05-13 11:46:51 -0400354 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400355 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
356
357 fg = fu.NewFlowsAndGroups()
358 fa = &fu.FlowArgs{
359 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400360 fu.InPort(2),
361 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400362 },
363 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400364 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
365 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400366 },
367 }
khenaidoo68c930b2019-05-13 11:46:51 -0400368 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400369 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
370
371 fg = fu.NewFlowsAndGroups()
372 fa = &fu.FlowArgs{
373 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400374 fu.InPort(2),
375 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400376 },
377 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400378 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
379 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400380 },
381 }
khenaidoo68c930b2019-05-13 11:46:51 -0400382 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400383 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
384
385 fg = fu.NewFlowsAndGroups()
386 fa = &fu.FlowArgs{
387 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400388 fu.InPort(2),
389 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400390 },
391 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400392 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
393 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400394 },
395 }
khenaidoo68c930b2019-05-13 11:46:51 -0400396 fg.AddFlow(fu.MkFlowStat(fa))
khenaidoo89b0e942018-10-21 21:11:33 -0400397 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
398
399 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
khenaidoo910204f2019-04-08 17:56:40 -0400400 tfd.deviceGraph = graph.NewDeviceGraph("ldid", tfd.getDeviceHelper)
khenaidoo89b0e942018-10-21 21:11:33 -0400401 tfd.deviceGraph.RootPorts = make(map[uint32]uint32)
402 tfd.deviceGraph.RootPorts[10] = 10
403
404 tfd.fd = NewFlowDecomposer(tfd.dMgr)
405
406 return &tfd
407}
408
409func (tfd *testFlowDecomposer) getDeviceHelper(deviceId string) (*voltha.Device, error) {
410 return tfd.dMgr.GetDevice(deviceId)
411}
412
413func (tfd *testFlowDecomposer) GetDeviceLogicalId() string {
414 return ""
415}
416
khenaidoo19d7b632018-10-30 10:49:50 -0400417func (tfd *testFlowDecomposer) GetLogicalDevice() (*voltha.LogicalDevice, error) {
418 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400419}
420
421func (tfd *testFlowDecomposer) GetDeviceGraph() *graph.DeviceGraph {
422 return tfd.deviceGraph
423}
424
425func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
426 return tfd.defaultRules
427}
428
429func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
430 lPorts := make([]uint32, 0)
431 var exclPort uint32
432 if len(excludePort) == 1 {
433 exclPort = excludePort[0]
434 }
khenaidood20a5852018-10-22 22:09:55 -0400435 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400436 if portno != exclPort {
437 lPorts = append(lPorts, portno)
438 }
439 }
440 return lPorts
441}
442
khenaidoo19d7b632018-10-30 10:49:50 -0400443func (tfd *testFlowDecomposer) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400444 var portLink graph.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400445 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400446 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400447 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400448 portLink.Egress = 10
449 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400450 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400451 }
khenaidoo19d7b632018-10-30 10:49:50 -0400452 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400453 portLink.Ingress = 0
454 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400455 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400456 }
457 for key, val := range tfd.routes {
458 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
459 return val
460 }
461 }
462 return nil
463}
464
465func TestEapolReRouteRuleDecomposition(t *testing.T) {
466
467 var fa *fu.FlowArgs
468 fa = &fu.FlowArgs{
469 KV: fu.OfpFlowModArgs{"priority": 1000},
470 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400471 fu.InPort(1),
472 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
473 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400474 },
475 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400476 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
477 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400478 },
479 }
480
khenaidoo68c930b2019-05-13 11:46:51 -0400481 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400482 groups := ofp.FlowGroups{}
483 tfd := newTestFlowDecomposer(newTestDeviceManager())
484
khenaidoo2c6a0992019-04-29 13:46:56 -0400485 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400486 onu1FlowAndGroup := deviceRules.Rules["onu1"]
487 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400488 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
489 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
490 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
491 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
492
493 fa = &fu.FlowArgs{
494 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400495 fu.InPort(2),
496 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400497 },
498 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400499 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
500 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400501 },
502 }
khenaidoo68c930b2019-05-13 11:46:51 -0400503 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400504 derivedFlow := onu1FlowAndGroup.GetFlow(0)
505 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
506
507 fa = &fu.FlowArgs{
508 KV: fu.OfpFlowModArgs{"priority": 1000},
509 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400510 fu.InPort(1),
511 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
512 fu.TunnelId(uint64(1)),
513 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400514 },
515 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400516 fu.PushVlan(0x8100),
517 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
518 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400519 },
520 }
khenaidoo68c930b2019-05-13 11:46:51 -0400521 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400522 derivedFlow = oltFlowAndGroup.GetFlow(0)
523 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
524
525 fa = &fu.FlowArgs{
526 KV: fu.OfpFlowModArgs{"priority": 1000},
527 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400528 fu.InPort(2),
529 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
530 fu.VlanPcp(0),
531 fu.Metadata_ofp(1),
532 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400533 },
534 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400535 fu.PopVlan(),
536 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400537 },
538 }
khenaidoo68c930b2019-05-13 11:46:51 -0400539 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400540 derivedFlow = oltFlowAndGroup.GetFlow(1)
541 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
542}
543
544func TestDhcpReRouteRuleDecomposition(t *testing.T) {
545
546 var fa *fu.FlowArgs
547 fa = &fu.FlowArgs{
548 KV: fu.OfpFlowModArgs{"priority": 1000},
549 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400550 fu.InPort(1),
551 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
552 fu.EthType(0x0800),
553 fu.Ipv4Dst(0xffffffff),
554 fu.IpProto(17),
555 fu.UdpSrc(68),
556 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400557 },
558 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400559 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400560 },
561 }
562
khenaidoo68c930b2019-05-13 11:46:51 -0400563 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
khenaidoo89b0e942018-10-21 21:11:33 -0400564 groups := ofp.FlowGroups{}
565 tfd := newTestFlowDecomposer(newTestDeviceManager())
566
khenaidoo2c6a0992019-04-29 13:46:56 -0400567 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400568 onu1FlowAndGroup := deviceRules.Rules["onu1"]
569 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo89b0e942018-10-21 21:11:33 -0400570 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
571 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
572 assert.Equal(t, 2, oltFlowAndGroup.Flows.Len())
573 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
574
575 fa = &fu.FlowArgs{
576 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400577 fu.InPort(2),
578 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400579 },
580 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400581 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
582 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400583 },
584 }
khenaidoo68c930b2019-05-13 11:46:51 -0400585 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400586 derivedFlow := onu1FlowAndGroup.GetFlow(0)
587 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
588
589 fa = &fu.FlowArgs{
590 KV: fu.OfpFlowModArgs{"priority": 1000},
591 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400592 fu.InPort(1),
593 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1),
594 fu.TunnelId(uint64(1)),
595 fu.EthType(0x0800),
596 fu.Ipv4Dst(0xffffffff),
597 fu.IpProto(17),
598 fu.UdpSrc(68),
599 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400600 },
601 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400602 fu.PushVlan(0x8100),
603 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
604 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400605 },
606 }
khenaidoo68c930b2019-05-13 11:46:51 -0400607 expectedOltFlow := fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400608 derivedFlow = oltFlowAndGroup.GetFlow(0)
609 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
610
611 fa = &fu.FlowArgs{
612 KV: fu.OfpFlowModArgs{"priority": 1000},
613 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400614 fu.InPort(2),
615 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000),
616 fu.VlanPcp(0),
617 fu.Metadata_ofp(1),
618 fu.TunnelId(uint64(1)),
khenaidoo89b0e942018-10-21 21:11:33 -0400619 },
620 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400621 fu.PopVlan(),
622 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400623 },
624 }
khenaidoo68c930b2019-05-13 11:46:51 -0400625 expectedOltFlow = fu.MkFlowStat(fa)
khenaidoo89b0e942018-10-21 21:11:33 -0400626 derivedFlow = oltFlowAndGroup.GetFlow(1)
627 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
628}
629
khenaidood20a5852018-10-22 22:09:55 -0400630func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
631
632 var fa *fu.FlowArgs
633 fa = &fu.FlowArgs{
634 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
635 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400636 fu.InPort(1),
637 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
638 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400639 },
640 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400641 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400642 },
643 }
644
645 var fa2 *fu.FlowArgs
646 fa2 = &fu.FlowArgs{
647 KV: fu.OfpFlowModArgs{"priority": 500},
648 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400649 fu.InPort(1),
650 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
651 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400652 },
653 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400654 fu.PushVlan(0x8100),
655 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
656 fu.SetField(fu.VlanPcp(0)),
657 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400658 },
659 }
660
khenaidoo68c930b2019-05-13 11:46:51 -0400661 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400662 groups := ofp.FlowGroups{}
663 tfd := newTestFlowDecomposer(newTestDeviceManager())
664
khenaidoo2c6a0992019-04-29 13:46:56 -0400665 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400666 onu1FlowAndGroup := deviceRules.Rules["onu1"]
667 oltFlowAndGroup := deviceRules.Rules["olt"]
668 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
669 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
670 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
671 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
672
673 fa = &fu.FlowArgs{
674 KV: fu.OfpFlowModArgs{"priority": 500},
675 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400676 fu.InPort(2),
677 fu.TunnelId(uint64(1)),
678 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
679 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400680 },
681 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400682 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
683 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400684 },
685 }
khenaidoo68c930b2019-05-13 11:46:51 -0400686 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400687 derivedFlow := onu1FlowAndGroup.GetFlow(1)
688 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
689
690 fa = &fu.FlowArgs{
691 KV: fu.OfpFlowModArgs{"priority": 500},
692 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400693 fu.InPort(1),
694 fu.TunnelId(uint64(1)),
695 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
696 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400697 },
698 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400699 fu.PushVlan(0x8100),
700 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
701 fu.SetField(fu.VlanPcp(0)),
702 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400703 },
704 }
khenaidoo68c930b2019-05-13 11:46:51 -0400705 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400706 derivedFlow = oltFlowAndGroup.GetFlow(0)
707 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
708}
709
710func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
711 var fa1 *fu.FlowArgs
712 fa1 = &fu.FlowArgs{
713 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
714 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400715 fu.InPort(10),
716 fu.Metadata_ofp((1000 << 32) | 1),
717 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400718 },
719 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400720 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400721 },
722 }
723
724 var fa2 *fu.FlowArgs
725 fa2 = &fu.FlowArgs{
726 KV: fu.OfpFlowModArgs{"priority": 500},
727 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400728 fu.InPort(10),
729 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
730 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400731 },
732 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400733 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
734 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400735 },
736 }
737
khenaidoo68c930b2019-05-13 11:46:51 -0400738 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa1), fu.MkFlowStat(fa2)}}
khenaidood20a5852018-10-22 22:09:55 -0400739 groups := ofp.FlowGroups{}
740 tfd := newTestFlowDecomposer(newTestDeviceManager())
741
khenaidoo2c6a0992019-04-29 13:46:56 -0400742 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400743 onu1FlowAndGroup := deviceRules.Rules["onu1"]
744 oltFlowAndGroup := deviceRules.Rules["olt"]
745 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
746 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
747 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
748 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
749
750 fa1 = &fu.FlowArgs{
751 KV: fu.OfpFlowModArgs{"priority": 500},
752 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400753 fu.InPort(2),
754 fu.Metadata_ofp(1000),
755 fu.TunnelId(uint64(1)),
756 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400757 },
758 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400759 fu.PopVlan(),
760 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400761 },
762 }
khenaidoo68c930b2019-05-13 11:46:51 -0400763 expectedOltFlow := fu.MkFlowStat(fa1)
khenaidood20a5852018-10-22 22:09:55 -0400764 derivedFlow := oltFlowAndGroup.GetFlow(0)
765 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
766
767 fa1 = &fu.FlowArgs{
768 KV: fu.OfpFlowModArgs{"priority": 500},
769 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400770 fu.InPort(1),
771 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
772 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400773 },
774 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400775 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
776 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400777 },
778 }
khenaidoo68c930b2019-05-13 11:46:51 -0400779 expectedOnu1Flow := fu.MkFlowStat(fa1)
khenaidood20a5852018-10-22 22:09:55 -0400780 derivedFlow = onu1FlowAndGroup.GetFlow(1)
781 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
782}
783
784func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
785 var fa *fu.FlowArgs
786 fa = &fu.FlowArgs{
787 KV: fu.OfpFlowModArgs{"priority": 500},
788 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400789 fu.InPort(10),
790 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
791 fu.VlanPcp(0),
792 fu.EthType(0x800),
793 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400794 },
795 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400796 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400797 },
798 }
799
800 var ga *fu.GroupArgs
801 ga = &fu.GroupArgs{
802 GroupId: 10,
803 Buckets: []*ofp.OfpBucket{
804 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400805 fu.PopVlan(),
806 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400807 },
808 },
809 },
810 }
811
khenaidoo68c930b2019-05-13 11:46:51 -0400812 flows := ofp.Flows{Items: []*ofp.OfpFlowStats{fu.MkFlowStat(fa)}}
813 groups := ofp.FlowGroups{Items: []*ofp.OfpGroupEntry{fu.MkGroupStat(ga)}}
khenaidood20a5852018-10-22 22:09:55 -0400814 tfd := newTestFlowDecomposer(newTestDeviceManager())
815
khenaidoo2c6a0992019-04-29 13:46:56 -0400816 deviceRules := tfd.fd.DecomposeRules(tfd, flows, groups, true)
khenaidood20a5852018-10-22 22:09:55 -0400817 onu1FlowAndGroup := deviceRules.Rules["onu1"]
818 oltFlowAndGroup := deviceRules.Rules["olt"]
819 assert.Equal(t, 2, onu1FlowAndGroup.Flows.Len())
820 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
821 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
822 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
823
824 fa = &fu.FlowArgs{
825 KV: fu.OfpFlowModArgs{"priority": 500},
826 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400827 fu.InPort(2),
828 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
829 fu.VlanPcp(0),
830 fu.EthType(0x800),
831 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400832 },
833 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400834 fu.PopVlan(),
835 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400836 },
837 }
khenaidoo68c930b2019-05-13 11:46:51 -0400838 expectedOltFlow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400839 derivedFlow := oltFlowAndGroup.GetFlow(0)
840 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
841
842 fa = &fu.FlowArgs{
843 KV: fu.OfpFlowModArgs{"priority": 500},
844 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400845 fu.InPort(1),
846 fu.EthType(0x800),
847 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400848 },
849 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400850 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400851 },
852 }
khenaidoo68c930b2019-05-13 11:46:51 -0400853 expectedOnu1Flow := fu.MkFlowStat(fa)
khenaidood20a5852018-10-22 22:09:55 -0400854 derivedFlow = onu1FlowAndGroup.GetFlow(1)
855 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
856}