blob: c3bbff7f7f19a3f54393cd2ad283bbca2559dead [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 */
npujar1d86a522019-11-14 17:11:16 +053016package flowdecomposition
khenaidoo89b0e942018-10-21 21:11:33 -040017
18import (
npujar467fe752020-01-16 20:17:45 +053019 "context"
khenaidoo89b0e942018-10-21 21:11:33 -040020 "errors"
Kent Hagerman433a31a2020-05-20 19:04:48 -040021 "testing"
22
khenaidooab1f7bd2019-11-14 14:00:27 -050023 "github.com/opencord/voltha-go/rw_core/mocks"
khenaidoo820197c2020-02-13 16:35:33 -050024 "github.com/opencord/voltha-go/rw_core/route"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080025 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080026 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
27 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040028 "github.com/stretchr/testify/assert"
khenaidoo820197c2020-02-13 16:35:33 -050029 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
khenaidoo89b0e942018-10-21 21:11:33 -040031)
32
khenaidoo89b0e942018-10-21 21:11:33 -040033type testDeviceManager struct {
khenaidooab1f7bd2019-11-14 14:00:27 -050034 mocks.DeviceManager
khenaidoo89b0e942018-10-21 21:11:33 -040035 devices map[string]*voltha.Device
36}
37
38func newTestDeviceManager() *testDeviceManager {
39 var tdm testDeviceManager
40 tdm.devices = make(map[string]*voltha.Device)
41 tdm.devices["olt"] = &voltha.Device{
42 Id: "olt",
43 Root: true,
44 ParentId: "logical_device",
45 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040046 {PortNo: 1, Label: "pon"},
47 {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040048 },
49 }
50 tdm.devices["onu1"] = &voltha.Device{
51 Id: "onu1",
52 Root: false,
53 ParentId: "olt",
54 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040055 {PortNo: 1, Label: "pon"},
56 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040057 },
58 }
59 tdm.devices["onu2"] = &voltha.Device{
60 Id: "onu2",
61 Root: false,
62 ParentId: "olt",
63 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040064 {PortNo: 1, Label: "pon"},
65 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040066 },
67 }
68 tdm.devices["onu3"] = &voltha.Device{
69 Id: "onu3",
70 Root: false,
71 ParentId: "olt",
72 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040073 {PortNo: 1, Label: "pon"},
74 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040075 },
76 }
77 tdm.devices["onu4"] = &voltha.Device{
78 Id: "onu4",
79 Root: false,
80 ParentId: "olt",
81 Ports: []*voltha.Port{
khenaidood20a5852018-10-22 22:09:55 -040082 {PortNo: 1, Label: "pon"},
83 {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040084 },
85 }
86 return &tdm
87}
88
Kent Hagerman45a13e42020-04-13 12:23:50 -040089func (tdm *testDeviceManager) GetDevice(ctx context.Context, deviceID *voltha.ID) (*voltha.Device, error) {
90 if d, ok := tdm.devices[deviceID.Id]; ok {
khenaidoo89b0e942018-10-21 21:11:33 -040091 return d, nil
92 }
npujar1d86a522019-11-14 17:11:16 +053093 return nil, errors.New("ABSENT")
khenaidoo89b0e942018-10-21 21:11:33 -040094}
npujar1d86a522019-11-14 17:11:16 +053095func (tdm *testDeviceManager) IsRootDevice(deviceID string) (bool, error) {
96 if d, ok := tdm.devices[deviceID]; ok {
khenaidoo19d7b632018-10-30 10:49:50 -040097 return d.Root, nil
98 }
npujar1d86a522019-11-14 17:11:16 +053099 return false, errors.New("ABSENT")
khenaidoo19d7b632018-10-30 10:49:50 -0400100}
khenaidoo89b0e942018-10-21 21:11:33 -0400101
102type testFlowDecomposer struct {
Esin Karaman09959ae2019-11-29 13:59:58 +0000103 dMgr *testDeviceManager
104 logicalPorts map[uint32]*voltha.LogicalPort
khenaidoo820197c2020-02-13 16:35:33 -0500105 routes map[route.OFPortLink][]route.Hop
Esin Karaman09959ae2019-11-29 13:59:58 +0000106 defaultRules *fu.DeviceRules
khenaidoo820197c2020-02-13 16:35:33 -0500107 deviceRoutes *route.DeviceRoutes
Esin Karaman09959ae2019-11-29 13:59:58 +0000108 fd *FlowDecomposer
109 logicalPortsNo map[uint32]bool
khenaidoo89b0e942018-10-21 21:11:33 -0400110}
111
Scott Bakerfdea1e32020-02-21 15:35:41 -0800112func newTestFlowDecomposer(t *testing.T, deviceMgr *testDeviceManager) *testFlowDecomposer {
khenaidoo89b0e942018-10-21 21:11:33 -0400113 var tfd testFlowDecomposer
114 tfd.dMgr = deviceMgr
115
116 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
Esin Karaman09959ae2019-11-29 13:59:58 +0000117 tfd.logicalPortsNo = make(map[uint32]bool)
khenaidoo89b0e942018-10-21 21:11:33 -0400118 // 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}
Esin Karaman09959ae2019-11-29 13:59:58 +0000121 tfd.logicalPorts[65536] = &voltha.LogicalPort{Id: "65536", DeviceId: "olt", DevicePortNo: 65536}
khenaidoo89b0e942018-10-21 21:11:33 -0400122 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
123 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
124 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
125 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
126
Esin Karaman09959ae2019-11-29 13:59:58 +0000127 tfd.logicalPortsNo[10] = false
128 tfd.logicalPortsNo[65536] = true // nni
129
khenaidoo820197c2020-02-13 16:35:33 -0500130 tfd.routes = make(map[route.OFPortLink][]route.Hop)
khenaidoo89b0e942018-10-21 21:11:33 -0400131
132 //DOWNSTREAM ROUTES
133
khenaidoo820197c2020-02-13 16:35:33 -0500134 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 1}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400135 {
khenaidoo89b0e942018-10-21 21:11:33 -0400136 DeviceID: "olt",
137 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
138 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
139 },
khenaidood20a5852018-10-22 22:09:55 -0400140 {
khenaidoo89b0e942018-10-21 21:11:33 -0400141 DeviceID: "onu1",
142 Ingress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
143 Egress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
144 },
145 }
146
khenaidoo820197c2020-02-13 16:35:33 -0500147 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 2}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400148 {
khenaidoo89b0e942018-10-21 21:11:33 -0400149 DeviceID: "olt",
150 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
151 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
152 },
khenaidood20a5852018-10-22 22:09:55 -0400153 {
khenaidoo89b0e942018-10-21 21:11:33 -0400154 DeviceID: "onu2",
155 Ingress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
156 Egress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
157 },
158 }
khenaidoo820197c2020-02-13 16:35:33 -0500159 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 3}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400160 {
khenaidoo89b0e942018-10-21 21:11:33 -0400161 DeviceID: "olt",
162 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
163 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
164 },
khenaidood20a5852018-10-22 22:09:55 -0400165 {
khenaidoo89b0e942018-10-21 21:11:33 -0400166 DeviceID: "onu3",
167 Ingress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
168 Egress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
169 },
170 }
khenaidoo820197c2020-02-13 16:35:33 -0500171 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 4}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400172 {
khenaidoo89b0e942018-10-21 21:11:33 -0400173 DeviceID: "olt",
174 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
175 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
176 },
khenaidood20a5852018-10-22 22:09:55 -0400177 {
khenaidoo89b0e942018-10-21 21:11:33 -0400178 DeviceID: "onu4",
179 Ingress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
180 Egress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
181 },
182 }
khenaidoo820197c2020-02-13 16:35:33 -0500183 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 10}] = []route.Hop{
Humera Kouser4ff89012019-08-25 19:01:51 -0400184 {
185 DeviceID: "olt",
186 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
187 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
188 },
189 {
190 DeviceID: "olt",
191 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
192 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
193 },
194 }
khenaidoo89b0e942018-10-21 21:11:33 -0400195
196 //UPSTREAM DATA PLANE
197
khenaidoo820197c2020-02-13 16:35:33 -0500198 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400199 {
khenaidoo89b0e942018-10-21 21:11:33 -0400200 DeviceID: "onu1",
201 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
202 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
203 },
khenaidood20a5852018-10-22 22:09:55 -0400204 {
khenaidoo89b0e942018-10-21 21:11:33 -0400205 DeviceID: "olt",
206 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
207 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
208 },
209 }
khenaidoo820197c2020-02-13 16:35:33 -0500210 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400211 {
khenaidoo89b0e942018-10-21 21:11:33 -0400212 DeviceID: "onu2",
213 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
214 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
215 },
khenaidood20a5852018-10-22 22:09:55 -0400216 {
khenaidoo89b0e942018-10-21 21:11:33 -0400217 DeviceID: "olt",
218 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
219 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
220 },
221 }
khenaidoo820197c2020-02-13 16:35:33 -0500222 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400223 {
khenaidoo89b0e942018-10-21 21:11:33 -0400224 DeviceID: "onu3",
225 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
226 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
227 },
khenaidood20a5852018-10-22 22:09:55 -0400228 {
khenaidoo89b0e942018-10-21 21:11:33 -0400229 DeviceID: "olt",
230 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
231 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
232 },
233 }
khenaidoo820197c2020-02-13 16:35:33 -0500234 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400235 {
khenaidoo89b0e942018-10-21 21:11:33 -0400236 DeviceID: "onu4",
237 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
238 Egress: tfd.dMgr.devices["onu4"].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
247 //UPSTREAM NEXT TABLE BASED
248
249 // openflow port 0 means absence of a port - go/protobuf interpretation
khenaidoo820197c2020-02-13 16:35:33 -0500250 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400251 {
khenaidoo89b0e942018-10-21 21:11:33 -0400252 DeviceID: "onu1",
253 Ingress: tfd.dMgr.devices["onu1"].Ports[1].PortNo,
254 Egress: tfd.dMgr.devices["onu1"].Ports[0].PortNo,
255 },
khenaidood20a5852018-10-22 22:09:55 -0400256 {
khenaidoo89b0e942018-10-21 21:11:33 -0400257 DeviceID: "olt",
258 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
259 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
260 },
261 }
khenaidoo820197c2020-02-13 16:35:33 -0500262 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400263 {
khenaidoo89b0e942018-10-21 21:11:33 -0400264 DeviceID: "onu2",
265 Ingress: tfd.dMgr.devices["onu2"].Ports[1].PortNo,
266 Egress: tfd.dMgr.devices["onu2"].Ports[0].PortNo,
267 },
khenaidood20a5852018-10-22 22:09:55 -0400268 {
khenaidoo89b0e942018-10-21 21:11:33 -0400269 DeviceID: "olt",
270 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
271 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
272 },
273 }
khenaidoo820197c2020-02-13 16:35:33 -0500274 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400275 {
khenaidoo89b0e942018-10-21 21:11:33 -0400276 DeviceID: "onu3",
277 Ingress: tfd.dMgr.devices["onu3"].Ports[1].PortNo,
278 Egress: tfd.dMgr.devices["onu3"].Ports[0].PortNo,
279 },
khenaidood20a5852018-10-22 22:09:55 -0400280 {
khenaidoo89b0e942018-10-21 21:11:33 -0400281 DeviceID: "olt",
282 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
283 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
284 },
285 }
khenaidoo820197c2020-02-13 16:35:33 -0500286 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400287 {
khenaidoo89b0e942018-10-21 21:11:33 -0400288 DeviceID: "onu4",
289 Ingress: tfd.dMgr.devices["onu4"].Ports[1].PortNo,
290 Egress: tfd.dMgr.devices["onu4"].Ports[0].PortNo,
291 },
khenaidood20a5852018-10-22 22:09:55 -0400292 {
khenaidoo89b0e942018-10-21 21:11:33 -0400293 DeviceID: "olt",
294 Ingress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
295 Egress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
296 },
297 }
298
299 // DOWNSTREAM NEXT TABLE BASED
300
khenaidoo820197c2020-02-13 16:35:33 -0500301 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400302 {
khenaidoo89b0e942018-10-21 21:11:33 -0400303 DeviceID: "olt",
304 Ingress: tfd.dMgr.devices["olt"].Ports[1].PortNo,
305 Egress: tfd.dMgr.devices["olt"].Ports[0].PortNo,
306 },
khenaidood20a5852018-10-22 22:09:55 -0400307 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400308 }
309
khenaidoo820197c2020-02-13 16:35:33 -0500310 tfd.routes[route.OFPortLink{Ingress: 0, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400311 {}, // 1st hop is wildcard
312 {
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 // DEFAULT RULES
320
321 tfd.defaultRules = fu.NewDeviceRules()
322 fg := fu.NewFlowsAndGroups()
npujar1d86a522019-11-14 17:11:16 +0530323 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400324 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400325 fu.InPort(2),
326 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400327 },
328 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400329 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
330 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400331 },
332 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800333 fs, err := fu.MkFlowStat(fa)
334 assert.Nil(t, err)
335 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400336 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
337
338 fg = fu.NewFlowsAndGroups()
339 fa = &fu.FlowArgs{
340 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400341 fu.InPort(2),
342 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400343 },
344 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400345 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
346 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400347 },
348 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800349 fs, err = fu.MkFlowStat(fa)
350 assert.Nil(t, err)
351 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400352 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
353
354 fg = fu.NewFlowsAndGroups()
355 fa = &fu.FlowArgs{
356 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400357 fu.InPort(2),
358 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400359 },
360 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400361 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
362 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400363 },
364 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800365 fs, err = fu.MkFlowStat(fa)
366 assert.Nil(t, err)
367 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400368 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
369
370 fg = fu.NewFlowsAndGroups()
371 fa = &fu.FlowArgs{
372 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400373 fu.InPort(2),
374 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400375 },
376 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400377 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
378 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400379 },
380 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800381 fs, err = fu.MkFlowStat(fa)
382 assert.Nil(t, err)
383 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400384 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
385
386 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
khenaidoo820197c2020-02-13 16:35:33 -0500387 tfd.deviceRoutes = route.NewDeviceRoutes("ldid", tfd.getDeviceHelper)
388 tfd.deviceRoutes.RootPorts = make(map[uint32]uint32)
389 tfd.deviceRoutes.RootPorts[10] = 10
khenaidoo89b0e942018-10-21 21:11:33 -0400390
391 tfd.fd = NewFlowDecomposer(tfd.dMgr)
392
393 return &tfd
394}
395
npujar467fe752020-01-16 20:17:45 +0530396func (tfd *testFlowDecomposer) getDeviceHelper(ctx context.Context, deviceID string) (*voltha.Device, error) {
Kent Hagerman45a13e42020-04-13 12:23:50 -0400397 return tfd.dMgr.GetDevice(ctx, &voltha.ID{Id: deviceID})
khenaidoo89b0e942018-10-21 21:11:33 -0400398}
399
npujar1d86a522019-11-14 17:11:16 +0530400func (tfd *testFlowDecomposer) GetDeviceLogicalID() string {
khenaidoo89b0e942018-10-21 21:11:33 -0400401 return ""
402}
403
khenaidoo442e7c72020-03-10 16:13:48 -0400404func (tfd *testFlowDecomposer) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
405 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400406}
407
khenaidoo820197c2020-02-13 16:35:33 -0500408func (tfd *testFlowDecomposer) GetDeviceRoutes() *route.DeviceRoutes {
409 return tfd.deviceRoutes
khenaidoo89b0e942018-10-21 21:11:33 -0400410}
411
412func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
413 return tfd.defaultRules
414}
415
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400416func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort uint32) map[uint32]struct{} {
417 lPorts := make(map[uint32]struct{})
418 for portNo := range tfd.logicalPorts {
419 if portNo != excludePort {
420 lPorts[portNo] = struct{}{}
khenaidoo89b0e942018-10-21 21:11:33 -0400421 }
422 }
423 return lPorts
424}
425
khenaidoo820197c2020-02-13 16:35:33 -0500426func (tfd *testFlowDecomposer) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
427 var portLink route.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400428 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400429 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400430 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400431 portLink.Egress = 10
432 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400433 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400434 }
khenaidoo19d7b632018-10-30 10:49:50 -0400435 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400436 portLink.Ingress = 0
437 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400438 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400439 }
440 for key, val := range tfd.routes {
441 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -0500442 return val, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400443 }
444 }
khenaidoo820197c2020-02-13 16:35:33 -0500445 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400446}
447
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400448func (tfd *testFlowDecomposer) GetNNIPorts() map[uint32]struct{} {
449 nniPorts := make(map[uint32]struct{})
Esin Karaman09959ae2019-11-29 13:59:58 +0000450 for portNo, nni := range tfd.logicalPortsNo {
451 if nni {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400452 nniPorts[portNo] = struct{}{}
Esin Karaman09959ae2019-11-29 13:59:58 +0000453 }
454 }
455 return nniPorts
456}
457
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400458func TestEapolReRouteRuleVlanDecomposition(t *testing.T) {
459
npujar1d86a522019-11-14 17:11:16 +0530460 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400461 KV: fu.OfpFlowModArgs{"priority": 1000},
462 MatchFields: []*ofp.OfpOxmOfbField{
463 fu.InPort(1),
464 fu.VlanVid(50),
465 fu.EthType(0x888e),
466 },
467 Actions: []*ofp.OfpAction{
468 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
469 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
470 },
471 }
472
Scott Bakerfdea1e32020-02-21 15:35:41 -0800473 fs, err := fu.MkFlowStat(fa)
474 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400475 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800476 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400477
Kent Hagerman433a31a2020-05-20 19:04:48 -0400478 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500479 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400480 onu1FlowAndGroup := deviceRules.Rules["onu1"]
481 oltFlowAndGroup := deviceRules.Rules["olt"]
482 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
483 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
484 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
485
npujar1d86a522019-11-14 17:11:16 +0530486 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400487 KV: fu.OfpFlowModArgs{"priority": 1000},
488 MatchFields: []*ofp.OfpOxmOfbField{
489 fu.InPort(1),
490 fu.TunnelId(uint64(1)),
491 fu.VlanVid(50),
492 fu.EthType(0x888e),
493 },
494 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400495 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
496 },
497 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800498 expectedOltFlow, err := fu.MkFlowStat(faParent)
499 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400500 derivedFlow := oltFlowAndGroup.GetFlow(0)
501 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
502
npujar1d86a522019-11-14 17:11:16 +0530503 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400504 KV: fu.OfpFlowModArgs{"priority": 1000},
505 MatchFields: []*ofp.OfpOxmOfbField{
506 fu.InPort(2),
507 fu.TunnelId(uint64(1)),
508 fu.EthType(0x888e),
509 },
510 Actions: []*ofp.OfpAction{
511 fu.PushVlan(0x8100),
512 fu.SetField(fu.VlanVid(50)),
513 fu.Output(1),
514 },
515 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800516 expectedOnuFlow, err := fu.MkFlowStat(faChild)
517 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400518 derivedFlow = onu1FlowAndGroup.GetFlow(0)
519 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
520}
521
522func TestEapolReRouteRuleZeroVlanDecomposition(t *testing.T) {
523
npujar1d86a522019-11-14 17:11:16 +0530524 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400525 KV: fu.OfpFlowModArgs{"priority": 1000},
526 MatchFields: []*ofp.OfpOxmOfbField{
527 fu.InPort(1),
528 fu.VlanVid(0),
529 fu.EthType(0x888e),
530 },
531 Actions: []*ofp.OfpAction{
532 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
533 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
534 },
535 }
536
Scott Bakerfdea1e32020-02-21 15:35:41 -0800537 fs, err := fu.MkFlowStat(fa)
538 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400539 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800540 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400541
Kent Hagerman433a31a2020-05-20 19:04:48 -0400542 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500543 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400544 onu1FlowAndGroup := deviceRules.Rules["onu1"]
545 oltFlowAndGroup := deviceRules.Rules["olt"]
546 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
547 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
548 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
549
npujar1d86a522019-11-14 17:11:16 +0530550 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400551 KV: fu.OfpFlowModArgs{"priority": 1000},
552 MatchFields: []*ofp.OfpOxmOfbField{
553 fu.InPort(1),
554 fu.TunnelId(uint64(1)),
555 fu.VlanVid(0),
556 fu.EthType(0x888e),
557 },
558 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400559 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
560 },
561 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800562 expectedOltFlow, err := fu.MkFlowStat(faParent)
563 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400564 derivedFlow := oltFlowAndGroup.GetFlow(0)
565 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
566
npujar1d86a522019-11-14 17:11:16 +0530567 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400568 KV: fu.OfpFlowModArgs{"priority": 1000},
569 MatchFields: []*ofp.OfpOxmOfbField{
570 fu.InPort(2),
571 fu.TunnelId(uint64(1)),
572 fu.EthType(0x888e),
573 },
574 Actions: []*ofp.OfpAction{
575 fu.PushVlan(0x8100),
576 fu.SetField(fu.VlanVid(0)),
577 fu.Output(1),
578 },
579 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800580 expectedOnuFlow, err := fu.MkFlowStat(faChild)
581 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400582 derivedFlow = onu1FlowAndGroup.GetFlow(0)
583 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
584}
585
586func TestEapolReRouteRuleNoVlanDecomposition(t *testing.T) {
khenaidoo89b0e942018-10-21 21:11:33 -0400587
npujar1d86a522019-11-14 17:11:16 +0530588 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400589 KV: fu.OfpFlowModArgs{"priority": 1000},
590 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400591 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400592 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400593 },
594 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400595 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
596 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400597 },
598 }
599
Scott Bakerfdea1e32020-02-21 15:35:41 -0800600 fs, err := fu.MkFlowStat(fa)
601 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400602 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800603 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400604
Kent Hagerman433a31a2020-05-20 19:04:48 -0400605 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500606 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400607 onu1FlowAndGroup := deviceRules.Rules["onu1"]
608 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400609 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400610 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400611 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
612
npujar1d86a522019-11-14 17:11:16 +0530613 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400614 KV: fu.OfpFlowModArgs{"priority": 1000},
615 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400616 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400617 fu.TunnelId(uint64(1)),
618 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400619 },
620 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400621 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400622 },
623 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800624 expectedOltFlow, err := fu.MkFlowStat(faParent)
625 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400626 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400627 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400628
npujar1d86a522019-11-14 17:11:16 +0530629 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400630 KV: fu.OfpFlowModArgs{"priority": 1000},
631 MatchFields: []*ofp.OfpOxmOfbField{
632 fu.InPort(2),
633 fu.TunnelId(uint64(1)),
634 fu.EthType(0x888e),
635 },
636 Actions: []*ofp.OfpAction{
637 fu.Output(1),
638 },
639 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800640 expectedOnuFlow, err := fu.MkFlowStat(faChild)
641 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400642 derivedFlow = onu1FlowAndGroup.GetFlow(0)
643 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400644}
645
646func TestDhcpReRouteRuleDecomposition(t *testing.T) {
647
npujar1d86a522019-11-14 17:11:16 +0530648 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400649 KV: fu.OfpFlowModArgs{"priority": 1000},
650 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400651 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400652 fu.EthType(0x0800),
653 fu.Ipv4Dst(0xffffffff),
654 fu.IpProto(17),
655 fu.UdpSrc(68),
656 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400657 },
658 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400659 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400660 },
661 }
662
Scott Bakerfdea1e32020-02-21 15:35:41 -0800663 fs, err := fu.MkFlowStat(fa)
664 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400665 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800666 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400667
Kent Hagerman433a31a2020-05-20 19:04:48 -0400668 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500669 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400670 onu1FlowAndGroup := deviceRules.Rules["onu1"]
671 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400672 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
673 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400674 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400675 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
676
npujar1d86a522019-11-14 17:11:16 +0530677 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400678 KV: fu.OfpFlowModArgs{"priority": 1000},
679 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400680 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400681 fu.TunnelId(uint64(1)),
682 fu.EthType(0x0800),
683 fu.Ipv4Dst(0xffffffff),
684 fu.IpProto(17),
685 fu.UdpSrc(68),
686 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400687 },
688 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400689 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400690 },
691 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800692 expectedOltFlow, err := fu.MkFlowStat(faParent)
693 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400694 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400695 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400696
npujar1d86a522019-11-14 17:11:16 +0530697 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400698 KV: fu.OfpFlowModArgs{"priority": 1000},
699 MatchFields: []*ofp.OfpOxmOfbField{
700 fu.InPort(2),
701 fu.TunnelId(uint64(1)),
702 fu.EthType(0x0800),
703 fu.Ipv4Dst(0xffffffff),
704 fu.IpProto(17),
705 fu.UdpSrc(68),
706 fu.UdpDst(67),
707 },
708 Actions: []*ofp.OfpAction{
709 fu.Output(1),
710 },
711 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800712 expectedOnuFlow, err := fu.MkFlowStat(faChild)
713 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400714 derivedFlow = onu1FlowAndGroup.GetFlow(0)
715 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400716}
717
Humera Kouser4ff89012019-08-25 19:01:51 -0400718func TestLldpReRouteRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530719 fa := &fu.FlowArgs{
Humera Kouser4ff89012019-08-25 19:01:51 -0400720 KV: fu.OfpFlowModArgs{"priority": 1000},
721 MatchFields: []*ofp.OfpOxmOfbField{
722 fu.InPort(10),
723 fu.EthType(0x88CC),
724 },
725 Actions: []*ofp.OfpAction{
726 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
727 },
728 }
729
Scott Bakerfdea1e32020-02-21 15:35:41 -0800730 fs, err := fu.MkFlowStat(fa)
731 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400732 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800733 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Kent Hagerman433a31a2020-05-20 19:04:48 -0400734 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500735 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400736 onu1FlowAndGroup := deviceRules.Rules["onu1"]
737 oltFlowAndGroup := deviceRules.Rules["olt"]
738 assert.Nil(t, onu1FlowAndGroup)
739 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
740 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
741
742 fa = &fu.FlowArgs{
743 KV: fu.OfpFlowModArgs{"priority": 1000},
744 MatchFields: []*ofp.OfpOxmOfbField{
745 fu.InPort(2),
746 fu.EthType(0x88CC),
747 },
748 Actions: []*ofp.OfpAction{
749 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
750 },
751 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800752 expectedOltFlow, err := fu.MkFlowStat(fa)
753 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400754 derivedFlow := oltFlowAndGroup.GetFlow(0)
755 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
756}
757
khenaidood20a5852018-10-22 22:09:55 -0400758func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530759 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400760 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400761 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400762 fu.InPort(1),
763 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
764 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400765 },
766 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400767 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400768 },
769 }
770
npujar1d86a522019-11-14 17:11:16 +0530771 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400772 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400773 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400774 fu.InPort(1),
775 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
776 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400777 },
778 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400779 fu.PushVlan(0x8100),
780 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
781 fu.SetField(fu.VlanPcp(0)),
782 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400783 },
784 }
785
Scott Bakerfdea1e32020-02-21 15:35:41 -0800786 fs, err := fu.MkFlowStat(fa)
787 assert.Nil(t, err)
788 fs2, err := fu.MkFlowStat(fa2)
789 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400790
791 fs.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400792 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
793 Data: &ofp.OfpInstruction_GotoTable{
794 GotoTable: &ofp.OfpInstructionGotoTable{
795 TableId: 1,
796 },
797 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400798 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400799
Scott Bakerfdea1e32020-02-21 15:35:41 -0800800 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400801
Kent Hagerman433a31a2020-05-20 19:04:48 -0400802 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500803 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400804 onu1FlowAndGroup := deviceRules.Rules["onu1"]
805 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400806 assert.NotNil(t, onu1FlowAndGroup)
807 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400808 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400809 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
810 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
811 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
812
813 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400814 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400815 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400816 fu.InPort(2),
817 fu.TunnelId(uint64(1)),
818 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
819 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400820 },
821 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400822 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
823 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400824 },
825 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400826
khenaidoo3306c992019-05-24 16:57:35 -0400827 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400828 // Form the expected flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800829 expectedOnu1Flow, err := fu.MkFlowStat(fa)
830 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400831 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
832 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
833 Data: &ofp.OfpInstruction_Actions{
834 Actions: &ofp.OfpInstructionActions{
835 Actions: []*ofp.OfpAction{{
836 Type: 0,
837 Action: &ofp.OfpAction_Output{
838 Output: &ofp.OfpActionOutput{
839 Port: 1,
840 MaxLen: 65509,
841 },
842 }}}}}}}
843
844 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400845 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
846
847 fa = &fu.FlowArgs{
848 KV: fu.OfpFlowModArgs{"priority": 500},
849 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400850 fu.InPort(1),
851 fu.TunnelId(uint64(1)),
852 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
853 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400854 },
855 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400856 fu.PushVlan(0x8100),
857 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
858 fu.SetField(fu.VlanPcp(0)),
859 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400860 },
861 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800862 expectedOltFlow, err := fu.MkFlowStat(fa)
863 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400864 derivedFlow = oltFlowAndGroup.GetFlow(0)
865 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
866}
867
868func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000869 logger.Debugf("Starting Test Unicast Downstream")
npujar1d86a522019-11-14 17:11:16 +0530870 fa1 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400871 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400872 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400873 fu.InPort(10),
874 fu.Metadata_ofp((1000 << 32) | 1),
875 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400876 },
877 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400878 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400879 },
880 }
881
npujar1d86a522019-11-14 17:11:16 +0530882 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400883 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400884 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400885 fu.InPort(10),
886 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
887 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400888 },
889 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400890 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
891 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400892 },
893 }
894
Scott Bakerfdea1e32020-02-21 15:35:41 -0800895 fs1, err := fu.MkFlowStat(fa1)
896 assert.Nil(t, err)
897 fs2, err := fu.MkFlowStat(fa2)
898 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400899 fs1.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400900 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
901 Data: &ofp.OfpInstruction_GotoTable{
902 GotoTable: &ofp.OfpInstructionGotoTable{
903 TableId: 1,
904 },
905 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400906 flows := map[uint64]*ofp.OfpFlowStats{fs1.Id: fs1, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400907
Scott Bakerfdea1e32020-02-21 15:35:41 -0800908 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400909
Kent Hagerman433a31a2020-05-20 19:04:48 -0400910 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500911 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400912 onu1FlowAndGroup := deviceRules.Rules["onu1"]
913 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400914 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400915 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
916 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
917 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
918
919 fa1 = &fu.FlowArgs{
920 KV: fu.OfpFlowModArgs{"priority": 500},
921 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400922 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400923 fu.TunnelId(uint64(10)),
924 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400925 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400926 },
927 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400928 fu.PopVlan(),
929 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400930 },
931 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400932
khenaidood20a5852018-10-22 22:09:55 -0400933 derivedFlow := oltFlowAndGroup.GetFlow(0)
Scott Bakerfdea1e32020-02-21 15:35:41 -0800934 expectedOltFlow, err := fu.MkFlowStat(fa1)
935 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400936 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
937 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
938 Data: &ofp.OfpInstruction_Actions{
939 Actions: &ofp.OfpInstructionActions{
940 Actions: []*ofp.OfpAction{{
941 Type: 0,
942 Action: &ofp.OfpAction_Output{
943 Output: &ofp.OfpActionOutput{
944 Port: 1,
945 MaxLen: 65509,
946 },
947 }}}}}}}
948 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400949 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
950
951 fa1 = &fu.FlowArgs{
952 KV: fu.OfpFlowModArgs{"priority": 500},
953 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400954 fu.InPort(1),
955 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
956 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400957 },
958 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400959 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
960 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400961 },
962 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800963 expectedOnu1Flow, err := fu.MkFlowStat(fa1)
964 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400965 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400966 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
967}
968
969func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530970 fa := &fu.FlowArgs{
khenaidood20a5852018-10-22 22:09:55 -0400971 KV: fu.OfpFlowModArgs{"priority": 500},
972 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400973 fu.InPort(10),
974 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
975 fu.VlanPcp(0),
976 fu.EthType(0x800),
977 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400978 },
979 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400980 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400981 },
982 }
983
npujar1d86a522019-11-14 17:11:16 +0530984 ga := &fu.GroupArgs{
khenaidood20a5852018-10-22 22:09:55 -0400985 GroupId: 10,
986 Buckets: []*ofp.OfpBucket{
987 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400988 fu.PopVlan(),
989 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400990 },
991 },
992 },
993 }
994
Scott Bakerfdea1e32020-02-21 15:35:41 -0800995 fs, err := fu.MkFlowStat(fa)
996 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400997 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
998 groups := map[uint32]*ofp.OfpGroupEntry{ga.GroupId: fu.MkGroupStat(ga)}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800999 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -04001000
khenaidoo820197c2020-02-13 16:35:33 -05001001 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, groups)
1002 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001003 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidood20a5852018-10-22 22:09:55 -04001004 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1005 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1006
1007 fa = &fu.FlowArgs{
1008 KV: fu.OfpFlowModArgs{"priority": 500},
1009 MatchFields: []*ofp.OfpOxmOfbField{
Esin Karaman09959ae2019-11-29 13:59:58 +00001010 fu.InPort(10),
khenaidoo68c930b2019-05-13 11:46:51 -04001011 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1012 fu.VlanPcp(0),
1013 fu.EthType(0x800),
1014 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001015 },
1016 Actions: []*ofp.OfpAction{
Esin Karaman09959ae2019-11-29 13:59:58 +00001017 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001018 },
1019 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001020 expectedOltFlow, err := fu.MkFlowStat(fa)
1021 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001022 derivedFlow := oltFlowAndGroup.GetFlow(0)
1023 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidood20a5852018-10-22 22:09:55 -04001024}