blob: ea560e24202bcaebdde3c029201e73dbfef3bbfc [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
Kent Hagerman2a07b862020-06-19 15:23:07 -040035 devices map[string]*voltha.Device
36 devicePorts map[string]map[uint32]*voltha.Port
khenaidoo89b0e942018-10-21 21:11:33 -040037}
38
39func newTestDeviceManager() *testDeviceManager {
40 var tdm testDeviceManager
41 tdm.devices = make(map[string]*voltha.Device)
Kent Hagerman2a07b862020-06-19 15:23:07 -040042 tdm.devicePorts = make(map[string]map[uint32]*voltha.Port)
khenaidoo89b0e942018-10-21 21:11:33 -040043 tdm.devices["olt"] = &voltha.Device{
44 Id: "olt",
45 Root: true,
46 ParentId: "logical_device",
Kent Hagerman2a07b862020-06-19 15:23:07 -040047 }
48 tdm.devicePorts["olt"] = map[uint32]*voltha.Port{
49 1: {PortNo: 1, Label: "pon"},
50 2: {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040051 }
52 tdm.devices["onu1"] = &voltha.Device{
53 Id: "onu1",
54 Root: false,
55 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040056 }
57 tdm.devicePorts["onu1"] = map[uint32]*voltha.Port{
58 1: {PortNo: 1, Label: "pon"},
59 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040060 }
61 tdm.devices["onu2"] = &voltha.Device{
62 Id: "onu2",
63 Root: false,
64 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040065 }
66 tdm.devicePorts["onu2"] = map[uint32]*voltha.Port{
67 1: {PortNo: 1, Label: "pon"},
68 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040069 }
70 tdm.devices["onu3"] = &voltha.Device{
71 Id: "onu3",
72 Root: false,
73 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040074 }
75 tdm.devicePorts["onu3"] = map[uint32]*voltha.Port{
76 1: {PortNo: 1, Label: "pon"},
77 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040078 }
79 tdm.devices["onu4"] = &voltha.Device{
80 Id: "onu4",
81 Root: false,
82 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040083 }
84 tdm.devicePorts["onu4"] = map[uint32]*voltha.Port{
85 1: {PortNo: 1, Label: "pon"},
86 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040087 }
88 return &tdm
89}
90
Kent Hagerman45a13e42020-04-13 12:23:50 -040091func (tdm *testDeviceManager) GetDevice(ctx context.Context, deviceID *voltha.ID) (*voltha.Device, error) {
92 if d, ok := tdm.devices[deviceID.Id]; ok {
khenaidoo89b0e942018-10-21 21:11:33 -040093 return d, nil
94 }
npujar1d86a522019-11-14 17:11:16 +053095 return nil, errors.New("ABSENT")
khenaidoo89b0e942018-10-21 21:11:33 -040096}
Kent Hagerman2a07b862020-06-19 15:23:07 -040097func (tdm *testDeviceManager) listDevicePorts(ctx context.Context, deviceID string) (map[uint32]*voltha.Port, error) {
98 ports, have := tdm.devicePorts[deviceID]
99 if !have {
100 return nil, errors.New("ABSENT")
101 }
102 return ports, nil
103}
npujar1d86a522019-11-14 17:11:16 +0530104func (tdm *testDeviceManager) IsRootDevice(deviceID string) (bool, error) {
105 if d, ok := tdm.devices[deviceID]; ok {
khenaidoo19d7b632018-10-30 10:49:50 -0400106 return d.Root, nil
107 }
npujar1d86a522019-11-14 17:11:16 +0530108 return false, errors.New("ABSENT")
khenaidoo19d7b632018-10-30 10:49:50 -0400109}
khenaidoo89b0e942018-10-21 21:11:33 -0400110
111type testFlowDecomposer struct {
Esin Karaman09959ae2019-11-29 13:59:58 +0000112 dMgr *testDeviceManager
113 logicalPorts map[uint32]*voltha.LogicalPort
khenaidoo820197c2020-02-13 16:35:33 -0500114 routes map[route.OFPortLink][]route.Hop
Esin Karaman09959ae2019-11-29 13:59:58 +0000115 defaultRules *fu.DeviceRules
khenaidoo820197c2020-02-13 16:35:33 -0500116 deviceRoutes *route.DeviceRoutes
Esin Karaman09959ae2019-11-29 13:59:58 +0000117 fd *FlowDecomposer
118 logicalPortsNo map[uint32]bool
khenaidoo89b0e942018-10-21 21:11:33 -0400119}
120
Scott Bakerfdea1e32020-02-21 15:35:41 -0800121func newTestFlowDecomposer(t *testing.T, deviceMgr *testDeviceManager) *testFlowDecomposer {
khenaidoo89b0e942018-10-21 21:11:33 -0400122 var tfd testFlowDecomposer
123 tfd.dMgr = deviceMgr
124
125 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
Esin Karaman09959ae2019-11-29 13:59:58 +0000126 tfd.logicalPortsNo = make(map[uint32]bool)
khenaidoo89b0e942018-10-21 21:11:33 -0400127 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
128 // port
129 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
Esin Karaman09959ae2019-11-29 13:59:58 +0000130 tfd.logicalPorts[65536] = &voltha.LogicalPort{Id: "65536", DeviceId: "olt", DevicePortNo: 65536}
khenaidoo89b0e942018-10-21 21:11:33 -0400131 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
132 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
133 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
134 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
135
Esin Karaman09959ae2019-11-29 13:59:58 +0000136 tfd.logicalPortsNo[10] = false
137 tfd.logicalPortsNo[65536] = true // nni
138
khenaidoo820197c2020-02-13 16:35:33 -0500139 tfd.routes = make(map[route.OFPortLink][]route.Hop)
khenaidoo89b0e942018-10-21 21:11:33 -0400140
141 //DOWNSTREAM ROUTES
142
khenaidoo820197c2020-02-13 16:35:33 -0500143 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 1}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400144 {
khenaidoo89b0e942018-10-21 21:11:33 -0400145 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400146 Ingress: 2,
147 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400148 },
khenaidood20a5852018-10-22 22:09:55 -0400149 {
khenaidoo89b0e942018-10-21 21:11:33 -0400150 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400151 Ingress: 1,
152 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400153 },
154 }
155
khenaidoo820197c2020-02-13 16:35:33 -0500156 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 2}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400157 {
khenaidoo89b0e942018-10-21 21:11:33 -0400158 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400159 Ingress: 2,
160 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400161 },
khenaidood20a5852018-10-22 22:09:55 -0400162 {
khenaidoo89b0e942018-10-21 21:11:33 -0400163 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400164 Ingress: 1,
165 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400166 },
167 }
khenaidoo820197c2020-02-13 16:35:33 -0500168 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 3}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400169 {
khenaidoo89b0e942018-10-21 21:11:33 -0400170 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400171 Ingress: 2,
172 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400173 },
khenaidood20a5852018-10-22 22:09:55 -0400174 {
khenaidoo89b0e942018-10-21 21:11:33 -0400175 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400176 Ingress: 1,
177 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400178 },
179 }
khenaidoo820197c2020-02-13 16:35:33 -0500180 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 4}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400181 {
khenaidoo89b0e942018-10-21 21:11:33 -0400182 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400183 Ingress: 2,
184 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400185 },
khenaidood20a5852018-10-22 22:09:55 -0400186 {
khenaidoo89b0e942018-10-21 21:11:33 -0400187 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400188 Ingress: 1,
189 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400190 },
191 }
khenaidoo820197c2020-02-13 16:35:33 -0500192 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 10}] = []route.Hop{
Humera Kouser4ff89012019-08-25 19:01:51 -0400193 {
194 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400195 Ingress: 2,
196 Egress: 2,
Humera Kouser4ff89012019-08-25 19:01:51 -0400197 },
198 {
199 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400200 Ingress: 2,
201 Egress: 2,
Humera Kouser4ff89012019-08-25 19:01:51 -0400202 },
203 }
khenaidoo89b0e942018-10-21 21:11:33 -0400204
205 //UPSTREAM DATA PLANE
206
khenaidoo820197c2020-02-13 16:35:33 -0500207 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400208 {
khenaidoo89b0e942018-10-21 21:11:33 -0400209 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400210 Ingress: 2,
211 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400212 },
khenaidood20a5852018-10-22 22:09:55 -0400213 {
khenaidoo89b0e942018-10-21 21:11:33 -0400214 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400215 Ingress: 1,
216 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400217 },
218 }
khenaidoo820197c2020-02-13 16:35:33 -0500219 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400220 {
khenaidoo89b0e942018-10-21 21:11:33 -0400221 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400222 Ingress: 2,
223 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400224 },
khenaidood20a5852018-10-22 22:09:55 -0400225 {
khenaidoo89b0e942018-10-21 21:11:33 -0400226 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400227 Ingress: 1,
228 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400229 },
230 }
khenaidoo820197c2020-02-13 16:35:33 -0500231 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400232 {
khenaidoo89b0e942018-10-21 21:11:33 -0400233 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400234 Ingress: 2,
235 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400236 },
khenaidood20a5852018-10-22 22:09:55 -0400237 {
khenaidoo89b0e942018-10-21 21:11:33 -0400238 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400239 Ingress: 1,
240 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400241 },
242 }
khenaidoo820197c2020-02-13 16:35:33 -0500243 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400244 {
khenaidoo89b0e942018-10-21 21:11:33 -0400245 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400246 Ingress: 2,
247 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400248 },
khenaidood20a5852018-10-22 22:09:55 -0400249 {
khenaidoo89b0e942018-10-21 21:11:33 -0400250 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400251 Ingress: 1,
252 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400253 },
254 }
255
256 //UPSTREAM NEXT TABLE BASED
257
258 // openflow port 0 means absence of a port - go/protobuf interpretation
khenaidoo820197c2020-02-13 16:35:33 -0500259 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400260 {
khenaidoo89b0e942018-10-21 21:11:33 -0400261 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400262 Ingress: 2,
263 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400264 },
khenaidood20a5852018-10-22 22:09:55 -0400265 {
khenaidoo89b0e942018-10-21 21:11:33 -0400266 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400267 Ingress: 1,
268 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400269 },
270 }
khenaidoo820197c2020-02-13 16:35:33 -0500271 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400272 {
khenaidoo89b0e942018-10-21 21:11:33 -0400273 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400274 Ingress: 2,
275 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400276 },
khenaidood20a5852018-10-22 22:09:55 -0400277 {
khenaidoo89b0e942018-10-21 21:11:33 -0400278 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400279 Ingress: 1,
280 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400281 },
282 }
khenaidoo820197c2020-02-13 16:35:33 -0500283 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400284 {
khenaidoo89b0e942018-10-21 21:11:33 -0400285 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400286 Ingress: 2,
287 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400288 },
khenaidood20a5852018-10-22 22:09:55 -0400289 {
khenaidoo89b0e942018-10-21 21:11:33 -0400290 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400291 Ingress: 1,
292 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400293 },
294 }
khenaidoo820197c2020-02-13 16:35:33 -0500295 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400296 {
khenaidoo89b0e942018-10-21 21:11:33 -0400297 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400298 Ingress: 2,
299 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400300 },
khenaidood20a5852018-10-22 22:09:55 -0400301 {
khenaidoo89b0e942018-10-21 21:11:33 -0400302 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400303 Ingress: 1,
304 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400305 },
306 }
307
308 // DOWNSTREAM NEXT TABLE BASED
309
khenaidoo820197c2020-02-13 16:35:33 -0500310 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400311 {
khenaidoo89b0e942018-10-21 21:11:33 -0400312 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400313 Ingress: 2,
314 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400315 },
khenaidood20a5852018-10-22 22:09:55 -0400316 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400317 }
318
khenaidoo820197c2020-02-13 16:35:33 -0500319 tfd.routes[route.OFPortLink{Ingress: 0, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400320 {}, // 1st hop is wildcard
321 {
khenaidoo89b0e942018-10-21 21:11:33 -0400322 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400323 Ingress: 1,
324 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400325 },
326 }
327
328 // DEFAULT RULES
329
330 tfd.defaultRules = fu.NewDeviceRules()
331 fg := fu.NewFlowsAndGroups()
npujar1d86a522019-11-14 17:11:16 +0530332 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400333 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400334 fu.InPort(2),
335 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400336 },
337 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400338 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
339 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400340 },
341 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800342 fs, err := fu.MkFlowStat(fa)
343 assert.Nil(t, err)
344 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400345 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
346
347 fg = fu.NewFlowsAndGroups()
348 fa = &fu.FlowArgs{
349 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400350 fu.InPort(2),
351 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400352 },
353 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400354 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
355 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400356 },
357 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800358 fs, err = fu.MkFlowStat(fa)
359 assert.Nil(t, err)
360 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400361 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
362
363 fg = fu.NewFlowsAndGroups()
364 fa = &fu.FlowArgs{
365 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400366 fu.InPort(2),
367 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400368 },
369 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400370 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
371 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400372 },
373 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800374 fs, err = fu.MkFlowStat(fa)
375 assert.Nil(t, err)
376 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400377 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
378
379 fg = fu.NewFlowsAndGroups()
380 fa = &fu.FlowArgs{
381 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400382 fu.InPort(2),
383 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
khenaidoo89b0e942018-10-21 21:11:33 -0400384 },
385 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400386 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
387 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400388 },
389 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800390 fs, err = fu.MkFlowStat(fa)
391 assert.Nil(t, err)
392 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400393 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
394
395 //Set up the device graph - flow decomposer uses it only to verify whether a port is a root port.
Kent Hagerman2a07b862020-06-19 15:23:07 -0400396 tfd.deviceRoutes = route.NewDeviceRoutes("ldid", "olt", tfd.dMgr.listDevicePorts)
khenaidoo820197c2020-02-13 16:35:33 -0500397 tfd.deviceRoutes.RootPorts = make(map[uint32]uint32)
398 tfd.deviceRoutes.RootPorts[10] = 10
khenaidoo89b0e942018-10-21 21:11:33 -0400399
400 tfd.fd = NewFlowDecomposer(tfd.dMgr)
401
402 return &tfd
403}
404
npujar1d86a522019-11-14 17:11:16 +0530405func (tfd *testFlowDecomposer) GetDeviceLogicalID() string {
khenaidoo89b0e942018-10-21 21:11:33 -0400406 return ""
407}
408
khenaidoo442e7c72020-03-10 16:13:48 -0400409func (tfd *testFlowDecomposer) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
410 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400411}
412
khenaidoo820197c2020-02-13 16:35:33 -0500413func (tfd *testFlowDecomposer) GetDeviceRoutes() *route.DeviceRoutes {
414 return tfd.deviceRoutes
khenaidoo89b0e942018-10-21 21:11:33 -0400415}
416
417func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
418 return tfd.defaultRules
419}
420
Rohan Agrawal31f21802020-06-12 05:38:46 +0000421func (tfd *testFlowDecomposer) GetWildcardInputPorts(ctx context.Context, excludePort uint32) map[uint32]struct{} {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400422 lPorts := make(map[uint32]struct{})
423 for portNo := range tfd.logicalPorts {
424 if portNo != excludePort {
425 lPorts[portNo] = struct{}{}
khenaidoo89b0e942018-10-21 21:11:33 -0400426 }
427 }
428 return lPorts
429}
430
khenaidoo820197c2020-02-13 16:35:33 -0500431func (tfd *testFlowDecomposer) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
432 var portLink route.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400433 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400434 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400435 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400436 portLink.Egress = 10
437 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400438 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400439 }
khenaidoo19d7b632018-10-30 10:49:50 -0400440 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400441 portLink.Ingress = 0
442 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400443 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400444 }
445 for key, val := range tfd.routes {
446 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -0500447 return val, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400448 }
449 }
khenaidoo820197c2020-02-13 16:35:33 -0500450 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400451}
452
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400453func (tfd *testFlowDecomposer) GetNNIPorts() map[uint32]struct{} {
454 nniPorts := make(map[uint32]struct{})
Esin Karaman09959ae2019-11-29 13:59:58 +0000455 for portNo, nni := range tfd.logicalPortsNo {
456 if nni {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400457 nniPorts[portNo] = struct{}{}
Esin Karaman09959ae2019-11-29 13:59:58 +0000458 }
459 }
460 return nniPorts
461}
462
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400463func TestEapolReRouteRuleVlanDecomposition(t *testing.T) {
464
npujar1d86a522019-11-14 17:11:16 +0530465 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400466 KV: fu.OfpFlowModArgs{"priority": 1000},
467 MatchFields: []*ofp.OfpOxmOfbField{
468 fu.InPort(1),
469 fu.VlanVid(50),
470 fu.EthType(0x888e),
471 },
472 Actions: []*ofp.OfpAction{
473 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
474 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
475 },
476 }
477
Scott Bakerfdea1e32020-02-21 15:35:41 -0800478 fs, err := fu.MkFlowStat(fa)
479 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400480 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800481 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400482
Kent Hagerman433a31a2020-05-20 19:04:48 -0400483 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500484 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400485 onu1FlowAndGroup := deviceRules.Rules["onu1"]
486 oltFlowAndGroup := deviceRules.Rules["olt"]
487 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
488 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
489 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
490
npujar1d86a522019-11-14 17:11:16 +0530491 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400492 KV: fu.OfpFlowModArgs{"priority": 1000},
493 MatchFields: []*ofp.OfpOxmOfbField{
494 fu.InPort(1),
495 fu.TunnelId(uint64(1)),
496 fu.VlanVid(50),
497 fu.EthType(0x888e),
498 },
499 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400500 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
501 },
502 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800503 expectedOltFlow, err := fu.MkFlowStat(faParent)
504 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400505 derivedFlow := oltFlowAndGroup.GetFlow(0)
506 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
507
npujar1d86a522019-11-14 17:11:16 +0530508 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400509 KV: fu.OfpFlowModArgs{"priority": 1000},
510 MatchFields: []*ofp.OfpOxmOfbField{
511 fu.InPort(2),
512 fu.TunnelId(uint64(1)),
513 fu.EthType(0x888e),
514 },
515 Actions: []*ofp.OfpAction{
516 fu.PushVlan(0x8100),
517 fu.SetField(fu.VlanVid(50)),
518 fu.Output(1),
519 },
520 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800521 expectedOnuFlow, err := fu.MkFlowStat(faChild)
522 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400523 derivedFlow = onu1FlowAndGroup.GetFlow(0)
524 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
525}
526
527func TestEapolReRouteRuleZeroVlanDecomposition(t *testing.T) {
528
npujar1d86a522019-11-14 17:11:16 +0530529 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400530 KV: fu.OfpFlowModArgs{"priority": 1000},
531 MatchFields: []*ofp.OfpOxmOfbField{
532 fu.InPort(1),
533 fu.VlanVid(0),
534 fu.EthType(0x888e),
535 },
536 Actions: []*ofp.OfpAction{
537 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
538 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
539 },
540 }
541
Scott Bakerfdea1e32020-02-21 15:35:41 -0800542 fs, err := fu.MkFlowStat(fa)
543 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400544 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800545 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400546
Kent Hagerman433a31a2020-05-20 19:04:48 -0400547 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500548 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400549 onu1FlowAndGroup := deviceRules.Rules["onu1"]
550 oltFlowAndGroup := deviceRules.Rules["olt"]
551 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
552 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
553 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
554
npujar1d86a522019-11-14 17:11:16 +0530555 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400556 KV: fu.OfpFlowModArgs{"priority": 1000},
557 MatchFields: []*ofp.OfpOxmOfbField{
558 fu.InPort(1),
559 fu.TunnelId(uint64(1)),
560 fu.VlanVid(0),
561 fu.EthType(0x888e),
562 },
563 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400564 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
565 },
566 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800567 expectedOltFlow, err := fu.MkFlowStat(faParent)
568 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400569 derivedFlow := oltFlowAndGroup.GetFlow(0)
570 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
571
npujar1d86a522019-11-14 17:11:16 +0530572 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400573 KV: fu.OfpFlowModArgs{"priority": 1000},
574 MatchFields: []*ofp.OfpOxmOfbField{
575 fu.InPort(2),
576 fu.TunnelId(uint64(1)),
577 fu.EthType(0x888e),
578 },
579 Actions: []*ofp.OfpAction{
580 fu.PushVlan(0x8100),
581 fu.SetField(fu.VlanVid(0)),
582 fu.Output(1),
583 },
584 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800585 expectedOnuFlow, err := fu.MkFlowStat(faChild)
586 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400587 derivedFlow = onu1FlowAndGroup.GetFlow(0)
588 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
589}
590
591func TestEapolReRouteRuleNoVlanDecomposition(t *testing.T) {
khenaidoo89b0e942018-10-21 21:11:33 -0400592
npujar1d86a522019-11-14 17:11:16 +0530593 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400594 KV: fu.OfpFlowModArgs{"priority": 1000},
595 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400596 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400597 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400598 },
599 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400600 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
601 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400602 },
603 }
604
Scott Bakerfdea1e32020-02-21 15:35:41 -0800605 fs, err := fu.MkFlowStat(fa)
606 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400607 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800608 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400609
Kent Hagerman433a31a2020-05-20 19:04:48 -0400610 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500611 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400612 onu1FlowAndGroup := deviceRules.Rules["onu1"]
613 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400614 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400615 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400616 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
617
npujar1d86a522019-11-14 17:11:16 +0530618 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400619 KV: fu.OfpFlowModArgs{"priority": 1000},
620 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400621 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400622 fu.TunnelId(uint64(1)),
623 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400624 },
625 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400626 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400627 },
628 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800629 expectedOltFlow, err := fu.MkFlowStat(faParent)
630 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400631 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400632 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400633
npujar1d86a522019-11-14 17:11:16 +0530634 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400635 KV: fu.OfpFlowModArgs{"priority": 1000},
636 MatchFields: []*ofp.OfpOxmOfbField{
637 fu.InPort(2),
638 fu.TunnelId(uint64(1)),
639 fu.EthType(0x888e),
640 },
641 Actions: []*ofp.OfpAction{
642 fu.Output(1),
643 },
644 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800645 expectedOnuFlow, err := fu.MkFlowStat(faChild)
646 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400647 derivedFlow = onu1FlowAndGroup.GetFlow(0)
648 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400649}
650
651func TestDhcpReRouteRuleDecomposition(t *testing.T) {
652
npujar1d86a522019-11-14 17:11:16 +0530653 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400654 KV: fu.OfpFlowModArgs{"priority": 1000},
655 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400656 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400657 fu.EthType(0x0800),
658 fu.Ipv4Dst(0xffffffff),
659 fu.IpProto(17),
660 fu.UdpSrc(68),
661 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400662 },
663 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400664 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400665 },
666 }
667
Scott Bakerfdea1e32020-02-21 15:35:41 -0800668 fs, err := fu.MkFlowStat(fa)
669 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400670 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800671 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400672
Kent Hagerman433a31a2020-05-20 19:04:48 -0400673 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500674 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400675 onu1FlowAndGroup := deviceRules.Rules["onu1"]
676 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400677 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
678 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400679 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400680 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
681
npujar1d86a522019-11-14 17:11:16 +0530682 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400683 KV: fu.OfpFlowModArgs{"priority": 1000},
684 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400685 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400686 fu.TunnelId(uint64(1)),
687 fu.EthType(0x0800),
688 fu.Ipv4Dst(0xffffffff),
689 fu.IpProto(17),
690 fu.UdpSrc(68),
691 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400692 },
693 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400694 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400695 },
696 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800697 expectedOltFlow, err := fu.MkFlowStat(faParent)
698 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400699 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400700 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400701
npujar1d86a522019-11-14 17:11:16 +0530702 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400703 KV: fu.OfpFlowModArgs{"priority": 1000},
704 MatchFields: []*ofp.OfpOxmOfbField{
705 fu.InPort(2),
706 fu.TunnelId(uint64(1)),
707 fu.EthType(0x0800),
708 fu.Ipv4Dst(0xffffffff),
709 fu.IpProto(17),
710 fu.UdpSrc(68),
711 fu.UdpDst(67),
712 },
713 Actions: []*ofp.OfpAction{
714 fu.Output(1),
715 },
716 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800717 expectedOnuFlow, err := fu.MkFlowStat(faChild)
718 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400719 derivedFlow = onu1FlowAndGroup.GetFlow(0)
720 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400721}
722
Humera Kouser4ff89012019-08-25 19:01:51 -0400723func TestLldpReRouteRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530724 fa := &fu.FlowArgs{
Humera Kouser4ff89012019-08-25 19:01:51 -0400725 KV: fu.OfpFlowModArgs{"priority": 1000},
726 MatchFields: []*ofp.OfpOxmOfbField{
727 fu.InPort(10),
728 fu.EthType(0x88CC),
729 },
730 Actions: []*ofp.OfpAction{
731 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
732 },
733 }
734
Scott Bakerfdea1e32020-02-21 15:35:41 -0800735 fs, err := fu.MkFlowStat(fa)
736 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400737 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800738 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Kent Hagerman433a31a2020-05-20 19:04:48 -0400739 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500740 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400741 onu1FlowAndGroup := deviceRules.Rules["onu1"]
742 oltFlowAndGroup := deviceRules.Rules["olt"]
743 assert.Nil(t, onu1FlowAndGroup)
744 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
745 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
746
747 fa = &fu.FlowArgs{
748 KV: fu.OfpFlowModArgs{"priority": 1000},
749 MatchFields: []*ofp.OfpOxmOfbField{
750 fu.InPort(2),
751 fu.EthType(0x88CC),
752 },
753 Actions: []*ofp.OfpAction{
754 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
755 },
756 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800757 expectedOltFlow, err := fu.MkFlowStat(fa)
758 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400759 derivedFlow := oltFlowAndGroup.GetFlow(0)
760 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
761}
762
khenaidood20a5852018-10-22 22:09:55 -0400763func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530764 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400765 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400766 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400767 fu.InPort(1),
768 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
769 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400770 },
771 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400772 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400773 },
774 }
775
npujar1d86a522019-11-14 17:11:16 +0530776 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400777 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400778 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400779 fu.InPort(1),
780 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
781 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400782 },
783 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400784 fu.PushVlan(0x8100),
785 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
786 fu.SetField(fu.VlanPcp(0)),
787 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400788 },
789 }
790
Scott Bakerfdea1e32020-02-21 15:35:41 -0800791 fs, err := fu.MkFlowStat(fa)
792 assert.Nil(t, err)
793 fs2, err := fu.MkFlowStat(fa2)
794 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400795
796 fs.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400797 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
798 Data: &ofp.OfpInstruction_GotoTable{
799 GotoTable: &ofp.OfpInstructionGotoTable{
800 TableId: 1,
801 },
802 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400803 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400804
Scott Bakerfdea1e32020-02-21 15:35:41 -0800805 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400806
Kent Hagerman433a31a2020-05-20 19:04:48 -0400807 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500808 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400809 onu1FlowAndGroup := deviceRules.Rules["onu1"]
810 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400811 assert.NotNil(t, onu1FlowAndGroup)
812 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400813 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400814 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
815 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
816 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
817
818 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400819 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400820 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400821 fu.InPort(2),
822 fu.TunnelId(uint64(1)),
823 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
824 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400825 },
826 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400827 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
828 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400829 },
830 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400831
khenaidoo3306c992019-05-24 16:57:35 -0400832 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400833 // Form the expected flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800834 expectedOnu1Flow, err := fu.MkFlowStat(fa)
835 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400836 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
837 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
838 Data: &ofp.OfpInstruction_Actions{
839 Actions: &ofp.OfpInstructionActions{
840 Actions: []*ofp.OfpAction{{
841 Type: 0,
842 Action: &ofp.OfpAction_Output{
843 Output: &ofp.OfpActionOutput{
844 Port: 1,
845 MaxLen: 65509,
846 },
847 }}}}}}}
848
849 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400850 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
851
852 fa = &fu.FlowArgs{
853 KV: fu.OfpFlowModArgs{"priority": 500},
854 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400855 fu.InPort(1),
856 fu.TunnelId(uint64(1)),
857 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
858 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400859 },
860 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400861 fu.PushVlan(0x8100),
862 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
863 fu.SetField(fu.VlanPcp(0)),
864 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400865 },
866 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800867 expectedOltFlow, err := fu.MkFlowStat(fa)
868 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400869 derivedFlow = oltFlowAndGroup.GetFlow(0)
870 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
871}
872
873func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000874 ctx := context.Background()
875 logger.Debugf(ctx, "Starting Test Unicast Downstream")
npujar1d86a522019-11-14 17:11:16 +0530876 fa1 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400877 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400878 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400879 fu.InPort(10),
880 fu.Metadata_ofp((1000 << 32) | 1),
881 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400882 },
883 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400884 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400885 },
886 }
887
npujar1d86a522019-11-14 17:11:16 +0530888 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400889 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400890 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400891 fu.InPort(10),
892 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
893 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400894 },
895 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400896 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
897 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400898 },
899 }
900
Scott Bakerfdea1e32020-02-21 15:35:41 -0800901 fs1, err := fu.MkFlowStat(fa1)
902 assert.Nil(t, err)
903 fs2, err := fu.MkFlowStat(fa2)
904 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400905 fs1.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400906 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
907 Data: &ofp.OfpInstruction_GotoTable{
908 GotoTable: &ofp.OfpInstructionGotoTable{
909 TableId: 1,
910 },
911 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400912 flows := map[uint64]*ofp.OfpFlowStats{fs1.Id: fs1, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400913
Scott Bakerfdea1e32020-02-21 15:35:41 -0800914 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400915
Kent Hagerman433a31a2020-05-20 19:04:48 -0400916 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500917 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400918 onu1FlowAndGroup := deviceRules.Rules["onu1"]
919 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400920 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400921 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
922 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
923 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
924
925 fa1 = &fu.FlowArgs{
926 KV: fu.OfpFlowModArgs{"priority": 500},
927 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400928 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400929 fu.TunnelId(uint64(10)),
930 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400931 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400932 },
933 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400934 fu.PopVlan(),
935 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400936 },
937 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400938
khenaidood20a5852018-10-22 22:09:55 -0400939 derivedFlow := oltFlowAndGroup.GetFlow(0)
Scott Bakerfdea1e32020-02-21 15:35:41 -0800940 expectedOltFlow, err := fu.MkFlowStat(fa1)
941 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400942 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
943 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
944 Data: &ofp.OfpInstruction_Actions{
945 Actions: &ofp.OfpInstructionActions{
946 Actions: []*ofp.OfpAction{{
947 Type: 0,
948 Action: &ofp.OfpAction_Output{
949 Output: &ofp.OfpActionOutput{
950 Port: 1,
951 MaxLen: 65509,
952 },
953 }}}}}}}
954 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400955 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
956
957 fa1 = &fu.FlowArgs{
958 KV: fu.OfpFlowModArgs{"priority": 500},
959 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400960 fu.InPort(1),
961 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
962 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400963 },
964 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400965 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
966 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400967 },
968 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800969 expectedOnu1Flow, err := fu.MkFlowStat(fa1)
970 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400971 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400972 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
973}
974
975func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530976 fa := &fu.FlowArgs{
khenaidood20a5852018-10-22 22:09:55 -0400977 KV: fu.OfpFlowModArgs{"priority": 500},
978 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400979 fu.InPort(10),
980 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
981 fu.VlanPcp(0),
982 fu.EthType(0x800),
983 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400984 },
985 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400986 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400987 },
988 }
989
npujar1d86a522019-11-14 17:11:16 +0530990 ga := &fu.GroupArgs{
khenaidood20a5852018-10-22 22:09:55 -0400991 GroupId: 10,
992 Buckets: []*ofp.OfpBucket{
993 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400994 fu.PopVlan(),
995 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400996 },
997 },
998 },
999 }
1000
Scott Bakerfdea1e32020-02-21 15:35:41 -08001001 fs, err := fu.MkFlowStat(fa)
1002 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -04001003 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
1004 groups := map[uint32]*ofp.OfpGroupEntry{ga.GroupId: fu.MkGroupStat(ga)}
Scott Bakerfdea1e32020-02-21 15:35:41 -08001005 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -04001006
khenaidoo820197c2020-02-13 16:35:33 -05001007 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, groups)
1008 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001009 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidood20a5852018-10-22 22:09:55 -04001010 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1011 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1012
1013 fa = &fu.FlowArgs{
1014 KV: fu.OfpFlowModArgs{"priority": 500},
1015 MatchFields: []*ofp.OfpOxmOfbField{
Esin Karaman09959ae2019-11-29 13:59:58 +00001016 fu.InPort(10),
khenaidoo68c930b2019-05-13 11:46:51 -04001017 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1018 fu.VlanPcp(0),
1019 fu.EthType(0x800),
1020 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001021 },
1022 Actions: []*ofp.OfpAction{
Esin Karaman09959ae2019-11-29 13:59:58 +00001023 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001024 },
1025 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001026 expectedOltFlow, err := fu.MkFlowStat(fa)
1027 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001028 derivedFlow := oltFlowAndGroup.GetFlow(0)
1029 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidood20a5852018-10-22 22:09:55 -04001030}