blob: 4c6ca8ce96d62c780a957fd48f7f34532222cbaa [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
416func (tfd *testFlowDecomposer) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
417 lPorts := make([]uint32, 0)
418 var exclPort uint32
419 if len(excludePort) == 1 {
420 exclPort = excludePort[0]
421 }
khenaidood20a5852018-10-22 22:09:55 -0400422 for portno := range tfd.logicalPorts {
khenaidoo89b0e942018-10-21 21:11:33 -0400423 if portno != exclPort {
424 lPorts = append(lPorts, portno)
425 }
426 }
427 return lPorts
428}
429
khenaidoo820197c2020-02-13 16:35:33 -0500430func (tfd *testFlowDecomposer) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
431 var portLink route.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400432 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400433 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400434 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400435 portLink.Egress = 10
436 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400437 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400438 }
khenaidoo19d7b632018-10-30 10:49:50 -0400439 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400440 portLink.Ingress = 0
441 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400442 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400443 }
444 for key, val := range tfd.routes {
445 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -0500446 return val, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400447 }
448 }
khenaidoo820197c2020-02-13 16:35:33 -0500449 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400450}
451
Esin Karaman09959ae2019-11-29 13:59:58 +0000452func (tfd *testFlowDecomposer) GetNNIPorts() []uint32 {
453 nniPorts := make([]uint32, 0)
454 for portNo, nni := range tfd.logicalPortsNo {
455 if nni {
456 nniPorts = append(nniPorts, portNo)
457 }
458 }
459 return nniPorts
460}
461
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400462func TestEapolReRouteRuleVlanDecomposition(t *testing.T) {
463
npujar1d86a522019-11-14 17:11:16 +0530464 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400465 KV: fu.OfpFlowModArgs{"priority": 1000},
466 MatchFields: []*ofp.OfpOxmOfbField{
467 fu.InPort(1),
468 fu.VlanVid(50),
469 fu.EthType(0x888e),
470 },
471 Actions: []*ofp.OfpAction{
472 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
473 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
474 },
475 }
476
Scott Bakerfdea1e32020-02-21 15:35:41 -0800477 fs, err := fu.MkFlowStat(fa)
478 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400479 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800480 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400481
Kent Hagerman433a31a2020-05-20 19:04:48 -0400482 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500483 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400484 onu1FlowAndGroup := deviceRules.Rules["onu1"]
485 oltFlowAndGroup := deviceRules.Rules["olt"]
486 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
487 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
488 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
489
npujar1d86a522019-11-14 17:11:16 +0530490 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400491 KV: fu.OfpFlowModArgs{"priority": 1000},
492 MatchFields: []*ofp.OfpOxmOfbField{
493 fu.InPort(1),
494 fu.TunnelId(uint64(1)),
495 fu.VlanVid(50),
496 fu.EthType(0x888e),
497 },
498 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400499 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
500 },
501 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800502 expectedOltFlow, err := fu.MkFlowStat(faParent)
503 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400504 derivedFlow := oltFlowAndGroup.GetFlow(0)
505 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
506
npujar1d86a522019-11-14 17:11:16 +0530507 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400508 KV: fu.OfpFlowModArgs{"priority": 1000},
509 MatchFields: []*ofp.OfpOxmOfbField{
510 fu.InPort(2),
511 fu.TunnelId(uint64(1)),
512 fu.EthType(0x888e),
513 },
514 Actions: []*ofp.OfpAction{
515 fu.PushVlan(0x8100),
516 fu.SetField(fu.VlanVid(50)),
517 fu.Output(1),
518 },
519 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800520 expectedOnuFlow, err := fu.MkFlowStat(faChild)
521 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400522 derivedFlow = onu1FlowAndGroup.GetFlow(0)
523 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
524}
525
526func TestEapolReRouteRuleZeroVlanDecomposition(t *testing.T) {
527
npujar1d86a522019-11-14 17:11:16 +0530528 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400529 KV: fu.OfpFlowModArgs{"priority": 1000},
530 MatchFields: []*ofp.OfpOxmOfbField{
531 fu.InPort(1),
532 fu.VlanVid(0),
533 fu.EthType(0x888e),
534 },
535 Actions: []*ofp.OfpAction{
536 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
537 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
538 },
539 }
540
Scott Bakerfdea1e32020-02-21 15:35:41 -0800541 fs, err := fu.MkFlowStat(fa)
542 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400543 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800544 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400545
Kent Hagerman433a31a2020-05-20 19:04:48 -0400546 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500547 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400548 onu1FlowAndGroup := deviceRules.Rules["onu1"]
549 oltFlowAndGroup := deviceRules.Rules["olt"]
550 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
551 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
552 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
553
npujar1d86a522019-11-14 17:11:16 +0530554 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400555 KV: fu.OfpFlowModArgs{"priority": 1000},
556 MatchFields: []*ofp.OfpOxmOfbField{
557 fu.InPort(1),
558 fu.TunnelId(uint64(1)),
559 fu.VlanVid(0),
560 fu.EthType(0x888e),
561 },
562 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400563 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
564 },
565 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800566 expectedOltFlow, err := fu.MkFlowStat(faParent)
567 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400568 derivedFlow := oltFlowAndGroup.GetFlow(0)
569 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
570
npujar1d86a522019-11-14 17:11:16 +0530571 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400572 KV: fu.OfpFlowModArgs{"priority": 1000},
573 MatchFields: []*ofp.OfpOxmOfbField{
574 fu.InPort(2),
575 fu.TunnelId(uint64(1)),
576 fu.EthType(0x888e),
577 },
578 Actions: []*ofp.OfpAction{
579 fu.PushVlan(0x8100),
580 fu.SetField(fu.VlanVid(0)),
581 fu.Output(1),
582 },
583 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800584 expectedOnuFlow, err := fu.MkFlowStat(faChild)
585 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400586 derivedFlow = onu1FlowAndGroup.GetFlow(0)
587 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
588}
589
590func TestEapolReRouteRuleNoVlanDecomposition(t *testing.T) {
khenaidoo89b0e942018-10-21 21:11:33 -0400591
npujar1d86a522019-11-14 17:11:16 +0530592 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400593 KV: fu.OfpFlowModArgs{"priority": 1000},
594 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400595 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400596 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400597 },
598 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400599 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
600 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400601 },
602 }
603
Scott Bakerfdea1e32020-02-21 15:35:41 -0800604 fs, err := fu.MkFlowStat(fa)
605 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400606 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800607 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400608
Kent Hagerman433a31a2020-05-20 19:04:48 -0400609 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500610 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400611 onu1FlowAndGroup := deviceRules.Rules["onu1"]
612 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400613 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400614 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400615 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
616
npujar1d86a522019-11-14 17:11:16 +0530617 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400618 KV: fu.OfpFlowModArgs{"priority": 1000},
619 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400620 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400621 fu.TunnelId(uint64(1)),
622 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400623 },
624 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400625 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400626 },
627 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800628 expectedOltFlow, err := fu.MkFlowStat(faParent)
629 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400630 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400631 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400632
npujar1d86a522019-11-14 17:11:16 +0530633 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400634 KV: fu.OfpFlowModArgs{"priority": 1000},
635 MatchFields: []*ofp.OfpOxmOfbField{
636 fu.InPort(2),
637 fu.TunnelId(uint64(1)),
638 fu.EthType(0x888e),
639 },
640 Actions: []*ofp.OfpAction{
641 fu.Output(1),
642 },
643 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800644 expectedOnuFlow, err := fu.MkFlowStat(faChild)
645 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400646 derivedFlow = onu1FlowAndGroup.GetFlow(0)
647 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400648}
649
650func TestDhcpReRouteRuleDecomposition(t *testing.T) {
651
npujar1d86a522019-11-14 17:11:16 +0530652 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400653 KV: fu.OfpFlowModArgs{"priority": 1000},
654 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400655 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400656 fu.EthType(0x0800),
657 fu.Ipv4Dst(0xffffffff),
658 fu.IpProto(17),
659 fu.UdpSrc(68),
660 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400661 },
662 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400663 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400664 },
665 }
666
Scott Bakerfdea1e32020-02-21 15:35:41 -0800667 fs, err := fu.MkFlowStat(fa)
668 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400669 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800670 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400671
Kent Hagerman433a31a2020-05-20 19:04:48 -0400672 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500673 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400674 onu1FlowAndGroup := deviceRules.Rules["onu1"]
675 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400676 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
677 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400678 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400679 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
680
npujar1d86a522019-11-14 17:11:16 +0530681 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400682 KV: fu.OfpFlowModArgs{"priority": 1000},
683 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400684 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400685 fu.TunnelId(uint64(1)),
686 fu.EthType(0x0800),
687 fu.Ipv4Dst(0xffffffff),
688 fu.IpProto(17),
689 fu.UdpSrc(68),
690 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400691 },
692 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400693 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400694 },
695 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800696 expectedOltFlow, err := fu.MkFlowStat(faParent)
697 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400698 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400699 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400700
npujar1d86a522019-11-14 17:11:16 +0530701 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400702 KV: fu.OfpFlowModArgs{"priority": 1000},
703 MatchFields: []*ofp.OfpOxmOfbField{
704 fu.InPort(2),
705 fu.TunnelId(uint64(1)),
706 fu.EthType(0x0800),
707 fu.Ipv4Dst(0xffffffff),
708 fu.IpProto(17),
709 fu.UdpSrc(68),
710 fu.UdpDst(67),
711 },
712 Actions: []*ofp.OfpAction{
713 fu.Output(1),
714 },
715 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800716 expectedOnuFlow, err := fu.MkFlowStat(faChild)
717 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400718 derivedFlow = onu1FlowAndGroup.GetFlow(0)
719 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400720}
721
Humera Kouser4ff89012019-08-25 19:01:51 -0400722func TestLldpReRouteRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530723 fa := &fu.FlowArgs{
Humera Kouser4ff89012019-08-25 19:01:51 -0400724 KV: fu.OfpFlowModArgs{"priority": 1000},
725 MatchFields: []*ofp.OfpOxmOfbField{
726 fu.InPort(10),
727 fu.EthType(0x88CC),
728 },
729 Actions: []*ofp.OfpAction{
730 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
731 },
732 }
733
Scott Bakerfdea1e32020-02-21 15:35:41 -0800734 fs, err := fu.MkFlowStat(fa)
735 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400736 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800737 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Kent Hagerman433a31a2020-05-20 19:04:48 -0400738 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500739 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400740 onu1FlowAndGroup := deviceRules.Rules["onu1"]
741 oltFlowAndGroup := deviceRules.Rules["olt"]
742 assert.Nil(t, onu1FlowAndGroup)
743 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
744 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
745
746 fa = &fu.FlowArgs{
747 KV: fu.OfpFlowModArgs{"priority": 1000},
748 MatchFields: []*ofp.OfpOxmOfbField{
749 fu.InPort(2),
750 fu.EthType(0x88CC),
751 },
752 Actions: []*ofp.OfpAction{
753 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
754 },
755 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800756 expectedOltFlow, err := fu.MkFlowStat(fa)
757 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400758 derivedFlow := oltFlowAndGroup.GetFlow(0)
759 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
760}
761
khenaidood20a5852018-10-22 22:09:55 -0400762func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530763 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400764 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400765 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400766 fu.InPort(1),
767 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
768 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400769 },
770 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400771 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400772 },
773 }
774
npujar1d86a522019-11-14 17:11:16 +0530775 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400776 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400777 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400778 fu.InPort(1),
779 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
780 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400781 },
782 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400783 fu.PushVlan(0x8100),
784 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
785 fu.SetField(fu.VlanPcp(0)),
786 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400787 },
788 }
789
Scott Bakerfdea1e32020-02-21 15:35:41 -0800790 fs, err := fu.MkFlowStat(fa)
791 assert.Nil(t, err)
792 fs2, err := fu.MkFlowStat(fa2)
793 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400794
795 fs.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400796 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
797 Data: &ofp.OfpInstruction_GotoTable{
798 GotoTable: &ofp.OfpInstructionGotoTable{
799 TableId: 1,
800 },
801 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400802 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400803
Scott Bakerfdea1e32020-02-21 15:35:41 -0800804 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400805
Kent Hagerman433a31a2020-05-20 19:04:48 -0400806 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500807 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400808 onu1FlowAndGroup := deviceRules.Rules["onu1"]
809 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400810 assert.NotNil(t, onu1FlowAndGroup)
811 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400812 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400813 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
814 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
815 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
816
817 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400818 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400819 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400820 fu.InPort(2),
821 fu.TunnelId(uint64(1)),
822 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
823 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400824 },
825 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400826 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
827 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400828 },
829 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400830
khenaidoo3306c992019-05-24 16:57:35 -0400831 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400832 // Form the expected flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800833 expectedOnu1Flow, err := fu.MkFlowStat(fa)
834 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400835 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
836 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
837 Data: &ofp.OfpInstruction_Actions{
838 Actions: &ofp.OfpInstructionActions{
839 Actions: []*ofp.OfpAction{{
840 Type: 0,
841 Action: &ofp.OfpAction_Output{
842 Output: &ofp.OfpActionOutput{
843 Port: 1,
844 MaxLen: 65509,
845 },
846 }}}}}}}
847
848 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400849 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
850
851 fa = &fu.FlowArgs{
852 KV: fu.OfpFlowModArgs{"priority": 500},
853 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400854 fu.InPort(1),
855 fu.TunnelId(uint64(1)),
856 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
857 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400858 },
859 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400860 fu.PushVlan(0x8100),
861 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
862 fu.SetField(fu.VlanPcp(0)),
863 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400864 },
865 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800866 expectedOltFlow, err := fu.MkFlowStat(fa)
867 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400868 derivedFlow = oltFlowAndGroup.GetFlow(0)
869 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
870}
871
872func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000873 logger.Debugf("Starting Test Unicast Downstream")
npujar1d86a522019-11-14 17:11:16 +0530874 fa1 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400875 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400876 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400877 fu.InPort(10),
878 fu.Metadata_ofp((1000 << 32) | 1),
879 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400880 },
881 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400882 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400883 },
884 }
885
npujar1d86a522019-11-14 17:11:16 +0530886 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400887 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400888 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400889 fu.InPort(10),
890 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
891 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400892 },
893 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400894 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
895 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400896 },
897 }
898
Scott Bakerfdea1e32020-02-21 15:35:41 -0800899 fs1, err := fu.MkFlowStat(fa1)
900 assert.Nil(t, err)
901 fs2, err := fu.MkFlowStat(fa2)
902 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400903 fs1.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400904 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
905 Data: &ofp.OfpInstruction_GotoTable{
906 GotoTable: &ofp.OfpInstructionGotoTable{
907 TableId: 1,
908 },
909 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400910 flows := map[uint64]*ofp.OfpFlowStats{fs1.Id: fs1, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400911
Scott Bakerfdea1e32020-02-21 15:35:41 -0800912 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400913
Kent Hagerman433a31a2020-05-20 19:04:48 -0400914 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500915 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400916 onu1FlowAndGroup := deviceRules.Rules["onu1"]
917 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400918 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400919 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
920 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
921 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
922
923 fa1 = &fu.FlowArgs{
924 KV: fu.OfpFlowModArgs{"priority": 500},
925 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400926 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400927 fu.TunnelId(uint64(10)),
928 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400929 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400930 },
931 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400932 fu.PopVlan(),
933 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400934 },
935 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400936
khenaidood20a5852018-10-22 22:09:55 -0400937 derivedFlow := oltFlowAndGroup.GetFlow(0)
Scott Bakerfdea1e32020-02-21 15:35:41 -0800938 expectedOltFlow, err := fu.MkFlowStat(fa1)
939 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400940 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
941 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
942 Data: &ofp.OfpInstruction_Actions{
943 Actions: &ofp.OfpInstructionActions{
944 Actions: []*ofp.OfpAction{{
945 Type: 0,
946 Action: &ofp.OfpAction_Output{
947 Output: &ofp.OfpActionOutput{
948 Port: 1,
949 MaxLen: 65509,
950 },
951 }}}}}}}
952 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400953 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
954
955 fa1 = &fu.FlowArgs{
956 KV: fu.OfpFlowModArgs{"priority": 500},
957 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400958 fu.InPort(1),
959 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
960 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400961 },
962 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400963 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
964 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400965 },
966 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800967 expectedOnu1Flow, err := fu.MkFlowStat(fa1)
968 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400969 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400970 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
971}
972
973func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530974 fa := &fu.FlowArgs{
khenaidood20a5852018-10-22 22:09:55 -0400975 KV: fu.OfpFlowModArgs{"priority": 500},
976 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400977 fu.InPort(10),
978 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
979 fu.VlanPcp(0),
980 fu.EthType(0x800),
981 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400982 },
983 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400984 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400985 },
986 }
987
npujar1d86a522019-11-14 17:11:16 +0530988 ga := &fu.GroupArgs{
khenaidood20a5852018-10-22 22:09:55 -0400989 GroupId: 10,
990 Buckets: []*ofp.OfpBucket{
991 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400992 fu.PopVlan(),
993 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400994 },
995 },
996 },
997 }
998
Scott Bakerfdea1e32020-02-21 15:35:41 -0800999 fs, err := fu.MkFlowStat(fa)
1000 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -04001001 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
1002 groups := map[uint32]*ofp.OfpGroupEntry{ga.GroupId: fu.MkGroupStat(ga)}
Scott Bakerfdea1e32020-02-21 15:35:41 -08001003 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -04001004
khenaidoo820197c2020-02-13 16:35:33 -05001005 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, groups)
1006 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001007 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidood20a5852018-10-22 22:09:55 -04001008 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1009 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1010
1011 fa = &fu.FlowArgs{
1012 KV: fu.OfpFlowModArgs{"priority": 500},
1013 MatchFields: []*ofp.OfpOxmOfbField{
Esin Karaman09959ae2019-11-29 13:59:58 +00001014 fu.InPort(10),
khenaidoo68c930b2019-05-13 11:46:51 -04001015 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1016 fu.VlanPcp(0),
1017 fu.EthType(0x800),
1018 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001019 },
1020 Actions: []*ofp.OfpAction{
Esin Karaman09959ae2019-11-29 13:59:58 +00001021 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001022 },
1023 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001024 expectedOltFlow, err := fu.MkFlowStat(fa)
1025 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001026 derivedFlow := oltFlowAndGroup.GetFlow(0)
1027 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidood20a5852018-10-22 22:09:55 -04001028}