blob: 8274c83cdb016a26a430897f603e1a19293e55e4 [file] [log] [blame]
khenaidoo89b0e942018-10-21 21:11:33 -04001/*
Joey Armstrong5f51f2e2023-01-17 17:06:26 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
khenaidoo89b0e942018-10-21 21:11:33 -04003 *
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"
Andrea Campanella832cff62021-11-05 17:05:18 +010021 "fmt"
Kent Hagerman433a31a2020-05-20 19:04:48 -040022 "testing"
23
Kent Hagerman6031aad2020-07-29 16:36:33 -040024 "github.com/opencord/voltha-go/rw_core/core/device/state"
khenaidoo820197c2020-02-13 16:35:33 -050025 "github.com/opencord/voltha-go/rw_core/route"
khenaidood948f772021-08-11 17:49:24 -040026 fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
27 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
28 "github.com/opencord/voltha-protos/v5/go/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040029 "github.com/stretchr/testify/assert"
khenaidoo89b0e942018-10-21 21:11:33 -040030)
31
khenaidoo89b0e942018-10-21 21:11:33 -040032type testDeviceManager struct {
Kent Hagerman6031aad2020-07-29 16:36:33 -040033 state.DeviceManager
Kent Hagerman2a07b862020-06-19 15:23:07 -040034 devices map[string]*voltha.Device
35 devicePorts map[string]map[uint32]*voltha.Port
khenaidoo89b0e942018-10-21 21:11:33 -040036}
37
38func newTestDeviceManager() *testDeviceManager {
39 var tdm testDeviceManager
40 tdm.devices = make(map[string]*voltha.Device)
Kent Hagerman2a07b862020-06-19 15:23:07 -040041 tdm.devicePorts = make(map[string]map[uint32]*voltha.Port)
khenaidoo89b0e942018-10-21 21:11:33 -040042 tdm.devices["olt"] = &voltha.Device{
43 Id: "olt",
44 Root: true,
45 ParentId: "logical_device",
Kent Hagerman2a07b862020-06-19 15:23:07 -040046 }
47 tdm.devicePorts["olt"] = map[uint32]*voltha.Port{
48 1: {PortNo: 1, Label: "pon"},
49 2: {PortNo: 2, Label: "nni"},
khenaidoo89b0e942018-10-21 21:11:33 -040050 }
51 tdm.devices["onu1"] = &voltha.Device{
52 Id: "onu1",
53 Root: false,
54 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040055 }
56 tdm.devicePorts["onu1"] = map[uint32]*voltha.Port{
57 1: {PortNo: 1, Label: "pon"},
58 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040059 }
60 tdm.devices["onu2"] = &voltha.Device{
61 Id: "onu2",
62 Root: false,
63 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040064 }
65 tdm.devicePorts["onu2"] = map[uint32]*voltha.Port{
66 1: {PortNo: 1, Label: "pon"},
67 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040068 }
69 tdm.devices["onu3"] = &voltha.Device{
70 Id: "onu3",
71 Root: false,
72 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040073 }
74 tdm.devicePorts["onu3"] = map[uint32]*voltha.Port{
75 1: {PortNo: 1, Label: "pon"},
76 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040077 }
78 tdm.devices["onu4"] = &voltha.Device{
79 Id: "onu4",
80 Root: false,
81 ParentId: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -040082 }
83 tdm.devicePorts["onu4"] = map[uint32]*voltha.Port{
84 1: {PortNo: 1, Label: "pon"},
85 2: {PortNo: 2, Label: "uni"},
khenaidoo89b0e942018-10-21 21:11:33 -040086 }
87 return &tdm
88}
89
Kent Hagerman45a13e42020-04-13 12:23:50 -040090func (tdm *testDeviceManager) GetDevice(ctx context.Context, deviceID *voltha.ID) (*voltha.Device, error) {
91 if d, ok := tdm.devices[deviceID.Id]; ok {
khenaidoo89b0e942018-10-21 21:11:33 -040092 return d, nil
93 }
npujar1d86a522019-11-14 17:11:16 +053094 return nil, errors.New("ABSENT")
khenaidoo89b0e942018-10-21 21:11:33 -040095}
Kent Hagerman2a07b862020-06-19 15:23:07 -040096func (tdm *testDeviceManager) listDevicePorts(ctx context.Context, deviceID string) (map[uint32]*voltha.Port, error) {
97 ports, have := tdm.devicePorts[deviceID]
98 if !have {
99 return nil, errors.New("ABSENT")
100 }
101 return ports, nil
102}
npujar1d86a522019-11-14 17:11:16 +0530103func (tdm *testDeviceManager) IsRootDevice(deviceID string) (bool, error) {
104 if d, ok := tdm.devices[deviceID]; ok {
khenaidoo19d7b632018-10-30 10:49:50 -0400105 return d.Root, nil
106 }
npujar1d86a522019-11-14 17:11:16 +0530107 return false, errors.New("ABSENT")
khenaidoo19d7b632018-10-30 10:49:50 -0400108}
khenaidoo89b0e942018-10-21 21:11:33 -0400109
110type testFlowDecomposer struct {
Esin Karaman09959ae2019-11-29 13:59:58 +0000111 dMgr *testDeviceManager
112 logicalPorts map[uint32]*voltha.LogicalPort
khenaidoo820197c2020-02-13 16:35:33 -0500113 routes map[route.OFPortLink][]route.Hop
Esin Karaman09959ae2019-11-29 13:59:58 +0000114 defaultRules *fu.DeviceRules
khenaidoo820197c2020-02-13 16:35:33 -0500115 deviceRoutes *route.DeviceRoutes
Esin Karaman09959ae2019-11-29 13:59:58 +0000116 fd *FlowDecomposer
117 logicalPortsNo map[uint32]bool
khenaidoo89b0e942018-10-21 21:11:33 -0400118}
119
Scott Bakerfdea1e32020-02-21 15:35:41 -0800120func newTestFlowDecomposer(t *testing.T, deviceMgr *testDeviceManager) *testFlowDecomposer {
khenaidoo89b0e942018-10-21 21:11:33 -0400121 var tfd testFlowDecomposer
122 tfd.dMgr = deviceMgr
123
124 tfd.logicalPorts = make(map[uint32]*voltha.LogicalPort)
Esin Karaman09959ae2019-11-29 13:59:58 +0000125 tfd.logicalPortsNo = make(map[uint32]bool)
khenaidoo89b0e942018-10-21 21:11:33 -0400126 // Go protobuf interpreted absence of a port as 0, so we can't use port #0 as an openflow
127 // port
128 tfd.logicalPorts[10] = &voltha.LogicalPort{Id: "10", DeviceId: "olt", DevicePortNo: 2}
Esin Karaman09959ae2019-11-29 13:59:58 +0000129 tfd.logicalPorts[65536] = &voltha.LogicalPort{Id: "65536", DeviceId: "olt", DevicePortNo: 65536}
khenaidoo89b0e942018-10-21 21:11:33 -0400130 tfd.logicalPorts[1] = &voltha.LogicalPort{Id: "1", DeviceId: "onu1", DevicePortNo: 2}
131 tfd.logicalPorts[2] = &voltha.LogicalPort{Id: "2", DeviceId: "onu2", DevicePortNo: 2}
132 tfd.logicalPorts[3] = &voltha.LogicalPort{Id: "3", DeviceId: "onu3", DevicePortNo: 2}
133 tfd.logicalPorts[4] = &voltha.LogicalPort{Id: "4", DeviceId: "onu4", DevicePortNo: 2}
134
Esin Karaman09959ae2019-11-29 13:59:58 +0000135 tfd.logicalPortsNo[10] = false
136 tfd.logicalPortsNo[65536] = true // nni
137
khenaidoo820197c2020-02-13 16:35:33 -0500138 tfd.routes = make(map[route.OFPortLink][]route.Hop)
khenaidoo89b0e942018-10-21 21:11:33 -0400139
140 //DOWNSTREAM ROUTES
141
khenaidoo820197c2020-02-13 16:35:33 -0500142 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 1}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400143 {
khenaidoo89b0e942018-10-21 21:11:33 -0400144 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400145 Ingress: 2,
146 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400147 },
khenaidood20a5852018-10-22 22:09:55 -0400148 {
khenaidoo89b0e942018-10-21 21:11:33 -0400149 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400150 Ingress: 1,
151 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400152 },
153 }
154
khenaidoo820197c2020-02-13 16:35:33 -0500155 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 2}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400156 {
khenaidoo89b0e942018-10-21 21:11:33 -0400157 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400158 Ingress: 2,
159 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400160 },
khenaidood20a5852018-10-22 22:09:55 -0400161 {
khenaidoo89b0e942018-10-21 21:11:33 -0400162 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400163 Ingress: 1,
164 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400165 },
166 }
khenaidoo820197c2020-02-13 16:35:33 -0500167 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 3}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400168 {
khenaidoo89b0e942018-10-21 21:11:33 -0400169 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400170 Ingress: 2,
171 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400172 },
khenaidood20a5852018-10-22 22:09:55 -0400173 {
khenaidoo89b0e942018-10-21 21:11:33 -0400174 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400175 Ingress: 1,
176 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400177 },
178 }
khenaidoo820197c2020-02-13 16:35:33 -0500179 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 4}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400180 {
khenaidoo89b0e942018-10-21 21:11:33 -0400181 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400182 Ingress: 2,
183 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400184 },
khenaidood20a5852018-10-22 22:09:55 -0400185 {
khenaidoo89b0e942018-10-21 21:11:33 -0400186 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400187 Ingress: 1,
188 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400189 },
190 }
khenaidoo820197c2020-02-13 16:35:33 -0500191 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 10}] = []route.Hop{
Humera Kouser4ff89012019-08-25 19:01:51 -0400192 {
193 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400194 Ingress: 2,
195 Egress: 2,
Humera Kouser4ff89012019-08-25 19:01:51 -0400196 },
197 {
198 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400199 Ingress: 2,
200 Egress: 2,
Humera Kouser4ff89012019-08-25 19:01:51 -0400201 },
202 }
khenaidoo89b0e942018-10-21 21:11:33 -0400203
204 //UPSTREAM DATA PLANE
205
khenaidoo820197c2020-02-13 16:35:33 -0500206 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400207 {
khenaidoo89b0e942018-10-21 21:11:33 -0400208 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400209 Ingress: 2,
210 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400211 },
khenaidood20a5852018-10-22 22:09:55 -0400212 {
khenaidoo89b0e942018-10-21 21:11:33 -0400213 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400214 Ingress: 1,
215 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400216 },
217 }
khenaidoo820197c2020-02-13 16:35:33 -0500218 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400219 {
khenaidoo89b0e942018-10-21 21:11:33 -0400220 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400221 Ingress: 2,
222 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400223 },
khenaidood20a5852018-10-22 22:09:55 -0400224 {
khenaidoo89b0e942018-10-21 21:11:33 -0400225 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400226 Ingress: 1,
227 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400228 },
229 }
khenaidoo820197c2020-02-13 16:35:33 -0500230 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400231 {
khenaidoo89b0e942018-10-21 21:11:33 -0400232 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400233 Ingress: 2,
234 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400235 },
khenaidood20a5852018-10-22 22:09:55 -0400236 {
khenaidoo89b0e942018-10-21 21:11:33 -0400237 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400238 Ingress: 1,
239 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400240 },
241 }
khenaidoo820197c2020-02-13 16:35:33 -0500242 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400243 {
khenaidoo89b0e942018-10-21 21:11:33 -0400244 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400245 Ingress: 2,
246 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400247 },
khenaidood20a5852018-10-22 22:09:55 -0400248 {
khenaidoo89b0e942018-10-21 21:11:33 -0400249 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400250 Ingress: 1,
251 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400252 },
253 }
254
255 //UPSTREAM NEXT TABLE BASED
256
257 // openflow port 0 means absence of a port - go/protobuf interpretation
khenaidoo820197c2020-02-13 16:35:33 -0500258 tfd.routes[route.OFPortLink{Ingress: 1, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400259 {
khenaidoo89b0e942018-10-21 21:11:33 -0400260 DeviceID: "onu1",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400261 Ingress: 2,
262 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400263 },
khenaidood20a5852018-10-22 22:09:55 -0400264 {
khenaidoo89b0e942018-10-21 21:11:33 -0400265 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400266 Ingress: 1,
267 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400268 },
269 }
khenaidoo820197c2020-02-13 16:35:33 -0500270 tfd.routes[route.OFPortLink{Ingress: 2, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400271 {
khenaidoo89b0e942018-10-21 21:11:33 -0400272 DeviceID: "onu2",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400273 Ingress: 2,
274 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400275 },
khenaidood20a5852018-10-22 22:09:55 -0400276 {
khenaidoo89b0e942018-10-21 21:11:33 -0400277 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400278 Ingress: 1,
279 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400280 },
281 }
khenaidoo820197c2020-02-13 16:35:33 -0500282 tfd.routes[route.OFPortLink{Ingress: 3, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400283 {
khenaidoo89b0e942018-10-21 21:11:33 -0400284 DeviceID: "onu3",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400285 Ingress: 2,
286 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400287 },
khenaidood20a5852018-10-22 22:09:55 -0400288 {
khenaidoo89b0e942018-10-21 21:11:33 -0400289 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400290 Ingress: 1,
291 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400292 },
293 }
khenaidoo820197c2020-02-13 16:35:33 -0500294 tfd.routes[route.OFPortLink{Ingress: 4, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400295 {
khenaidoo89b0e942018-10-21 21:11:33 -0400296 DeviceID: "onu4",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400297 Ingress: 2,
298 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400299 },
khenaidood20a5852018-10-22 22:09:55 -0400300 {
khenaidoo89b0e942018-10-21 21:11:33 -0400301 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400302 Ingress: 1,
303 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400304 },
305 }
306
307 // DOWNSTREAM NEXT TABLE BASED
308
khenaidoo820197c2020-02-13 16:35:33 -0500309 tfd.routes[route.OFPortLink{Ingress: 10, Egress: 0}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400310 {
khenaidoo89b0e942018-10-21 21:11:33 -0400311 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400312 Ingress: 2,
313 Egress: 1,
khenaidoo89b0e942018-10-21 21:11:33 -0400314 },
khenaidood20a5852018-10-22 22:09:55 -0400315 {}, // 2nd hop is not known yet
khenaidoo89b0e942018-10-21 21:11:33 -0400316 }
317
khenaidoo820197c2020-02-13 16:35:33 -0500318 tfd.routes[route.OFPortLink{Ingress: 0, Egress: 10}] = []route.Hop{
khenaidood20a5852018-10-22 22:09:55 -0400319 {}, // 1st hop is wildcard
320 {
khenaidoo89b0e942018-10-21 21:11:33 -0400321 DeviceID: "olt",
Kent Hagerman2a07b862020-06-19 15:23:07 -0400322 Ingress: 1,
323 Egress: 2,
khenaidoo89b0e942018-10-21 21:11:33 -0400324 },
325 }
326
327 // DEFAULT RULES
328
329 tfd.defaultRules = fu.NewDeviceRules()
330 fg := fu.NewFlowsAndGroups()
npujar1d86a522019-11-14 17:11:16 +0530331 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400332 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400333 fu.InPort(2),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300334 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo89b0e942018-10-21 21:11:33 -0400335 },
336 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400337 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
338 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400339 },
340 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800341 fs, err := fu.MkFlowStat(fa)
342 assert.Nil(t, err)
343 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400344 tfd.defaultRules.AddFlowsAndGroup("onu1", fg)
345
346 fg = fu.NewFlowsAndGroups()
347 fa = &fu.FlowArgs{
348 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400349 fu.InPort(2),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300350 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo89b0e942018-10-21 21:11:33 -0400351 },
352 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400353 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 102)),
354 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400355 },
356 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800357 fs, err = fu.MkFlowStat(fa)
358 assert.Nil(t, err)
359 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400360 tfd.defaultRules.AddFlowsAndGroup("onu2", fg)
361
362 fg = fu.NewFlowsAndGroups()
363 fa = &fu.FlowArgs{
364 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400365 fu.InPort(2),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300366 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo89b0e942018-10-21 21:11:33 -0400367 },
368 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400369 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 103)),
370 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400371 },
372 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800373 fs, err = fu.MkFlowStat(fa)
374 assert.Nil(t, err)
375 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400376 tfd.defaultRules.AddFlowsAndGroup("onu3", fg)
377
378 fg = fu.NewFlowsAndGroups()
379 fa = &fu.FlowArgs{
380 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400381 fu.InPort(2),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300382 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo89b0e942018-10-21 21:11:33 -0400383 },
384 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400385 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 104)),
386 fu.Output(1),
khenaidoo89b0e942018-10-21 21:11:33 -0400387 },
388 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800389 fs, err = fu.MkFlowStat(fa)
390 assert.Nil(t, err)
391 fg.AddFlow(fs)
khenaidoo89b0e942018-10-21 21:11:33 -0400392 tfd.defaultRules.AddFlowsAndGroup("onu4", fg)
393
394 //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 -0400395 tfd.deviceRoutes = route.NewDeviceRoutes("ldid", "olt", tfd.dMgr.listDevicePorts)
khenaidoo820197c2020-02-13 16:35:33 -0500396 tfd.deviceRoutes.RootPorts = make(map[uint32]uint32)
397 tfd.deviceRoutes.RootPorts[10] = 10
khenaidoo89b0e942018-10-21 21:11:33 -0400398
Kent Hagerman6031aad2020-07-29 16:36:33 -0400399 tfd.fd = NewFlowDecomposer(func(ctx context.Context, deviceID string) (*voltha.Device, error) {
400 return tfd.dMgr.GetDevice(ctx, &voltha.ID{Id: deviceID})
401 })
khenaidoo89b0e942018-10-21 21:11:33 -0400402
403 return &tfd
404}
405
npujar1d86a522019-11-14 17:11:16 +0530406func (tfd *testFlowDecomposer) GetDeviceLogicalID() string {
khenaidoo89b0e942018-10-21 21:11:33 -0400407 return ""
408}
409
khenaidoo442e7c72020-03-10 16:13:48 -0400410func (tfd *testFlowDecomposer) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
411 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400412}
413
khenaidoo820197c2020-02-13 16:35:33 -0500414func (tfd *testFlowDecomposer) GetDeviceRoutes() *route.DeviceRoutes {
415 return tfd.deviceRoutes
khenaidoo89b0e942018-10-21 21:11:33 -0400416}
417
418func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
419 return tfd.defaultRules
420}
421
Rohan Agrawal31f21802020-06-12 05:38:46 +0000422func (tfd *testFlowDecomposer) GetWildcardInputPorts(ctx context.Context, excludePort uint32) map[uint32]struct{} {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400423 lPorts := make(map[uint32]struct{})
424 for portNo := range tfd.logicalPorts {
425 if portNo != excludePort {
426 lPorts[portNo] = struct{}{}
khenaidoo89b0e942018-10-21 21:11:33 -0400427 }
428 }
429 return lPorts
430}
431
khenaidoo820197c2020-02-13 16:35:33 -0500432func (tfd *testFlowDecomposer) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
433 var portLink route.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400434 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400435 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400436 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400437 portLink.Egress = 10
438 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400439 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400440 }
khenaidoo19d7b632018-10-30 10:49:50 -0400441 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400442 portLink.Ingress = 0
443 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400444 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400445 }
446 for key, val := range tfd.routes {
447 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -0500448 return val, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400449 }
450 }
Andrea Campanella832cff62021-11-05 17:05:18 +0100451 return nil, fmt.Errorf("no route from:%d to:%d %w", ingressPortNo, egressPortNo, route.ErrNoRoute)
khenaidoo89b0e942018-10-21 21:11:33 -0400452}
453
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400454func (tfd *testFlowDecomposer) GetNNIPorts() map[uint32]struct{} {
455 nniPorts := make(map[uint32]struct{})
Esin Karaman09959ae2019-11-29 13:59:58 +0000456 for portNo, nni := range tfd.logicalPortsNo {
457 if nni {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400458 nniPorts[portNo] = struct{}{}
Esin Karaman09959ae2019-11-29 13:59:58 +0000459 }
460 }
461 return nniPorts
462}
463
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400464func TestEapolReRouteRuleVlanDecomposition(t *testing.T) {
465
npujar1d86a522019-11-14 17:11:16 +0530466 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400467 KV: fu.OfpFlowModArgs{"priority": 1000},
468 MatchFields: []*ofp.OfpOxmOfbField{
469 fu.InPort(1),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700470 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400471 fu.EthType(0x888e),
472 },
473 Actions: []*ofp.OfpAction{
474 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
475 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
476 },
477 }
478
Scott Bakerfdea1e32020-02-21 15:35:41 -0800479 fs, err := fu.MkFlowStat(fa)
480 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400481 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800482 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400483
Kent Hagerman433a31a2020-05-20 19:04:48 -0400484 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500485 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400486 onu1FlowAndGroup := deviceRules.Rules["onu1"]
487 oltFlowAndGroup := deviceRules.Rules["olt"]
488 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
489 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
490 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
491
npujar1d86a522019-11-14 17:11:16 +0530492 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400493 KV: fu.OfpFlowModArgs{"priority": 1000},
494 MatchFields: []*ofp.OfpOxmOfbField{
495 fu.InPort(1),
496 fu.TunnelId(uint64(1)),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700497 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400498 fu.EthType(0x888e),
499 },
500 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400501 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
502 },
503 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800504 expectedOltFlow, err := fu.MkFlowStat(faParent)
505 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400506 derivedFlow := oltFlowAndGroup.GetFlow(0)
507 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
508
npujar1d86a522019-11-14 17:11:16 +0530509 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400510 KV: fu.OfpFlowModArgs{"priority": 1000},
511 MatchFields: []*ofp.OfpOxmOfbField{
512 fu.InPort(2),
513 fu.TunnelId(uint64(1)),
514 fu.EthType(0x888e),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700515 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400516 },
517 Actions: []*ofp.OfpAction{
518 fu.PushVlan(0x8100),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700519 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400520 fu.Output(1),
521 },
522 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800523 expectedOnuFlow, err := fu.MkFlowStat(faChild)
524 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400525 derivedFlow = onu1FlowAndGroup.GetFlow(0)
526 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
527}
528
529func TestEapolReRouteRuleZeroVlanDecomposition(t *testing.T) {
530
npujar1d86a522019-11-14 17:11:16 +0530531 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400532 KV: fu.OfpFlowModArgs{"priority": 1000},
533 MatchFields: []*ofp.OfpOxmOfbField{
534 fu.InPort(1),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300535 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400536 fu.EthType(0x888e),
537 },
538 Actions: []*ofp.OfpAction{
539 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
540 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
541 },
542 }
543
Scott Bakerfdea1e32020-02-21 15:35:41 -0800544 fs, err := fu.MkFlowStat(fa)
545 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400546 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800547 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400548
Kent Hagerman433a31a2020-05-20 19:04:48 -0400549 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500550 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400551 onu1FlowAndGroup := deviceRules.Rules["onu1"]
552 oltFlowAndGroup := deviceRules.Rules["olt"]
553 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
554 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
555 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
556
npujar1d86a522019-11-14 17:11:16 +0530557 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400558 KV: fu.OfpFlowModArgs{"priority": 1000},
559 MatchFields: []*ofp.OfpOxmOfbField{
560 fu.InPort(1),
561 fu.TunnelId(uint64(1)),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700562 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400563 fu.EthType(0x888e),
564 },
565 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400566 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
567 },
568 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800569 expectedOltFlow, err := fu.MkFlowStat(faParent)
570 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400571 derivedFlow := oltFlowAndGroup.GetFlow(0)
572 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
573
npujar1d86a522019-11-14 17:11:16 +0530574 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400575 KV: fu.OfpFlowModArgs{"priority": 1000},
576 MatchFields: []*ofp.OfpOxmOfbField{
577 fu.InPort(2),
578 fu.TunnelId(uint64(1)),
579 fu.EthType(0x888e),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300580 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400581 },
582 Actions: []*ofp.OfpAction{
583 fu.PushVlan(0x8100),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700584 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400585 fu.Output(1),
586 },
587 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800588 expectedOnuFlow, err := fu.MkFlowStat(faChild)
589 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400590 derivedFlow = onu1FlowAndGroup.GetFlow(0)
591 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
592}
593
594func TestEapolReRouteRuleNoVlanDecomposition(t *testing.T) {
khenaidoo89b0e942018-10-21 21:11:33 -0400595
npujar1d86a522019-11-14 17:11:16 +0530596 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400597 KV: fu.OfpFlowModArgs{"priority": 1000},
598 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400599 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400600 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400601 },
602 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400603 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
604 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400605 },
606 }
607
Scott Bakerfdea1e32020-02-21 15:35:41 -0800608 fs, err := fu.MkFlowStat(fa)
609 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400610 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800611 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400612
Kent Hagerman433a31a2020-05-20 19:04:48 -0400613 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500614 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400615 onu1FlowAndGroup := deviceRules.Rules["onu1"]
616 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400617 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400618 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400619 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
620
npujar1d86a522019-11-14 17:11:16 +0530621 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400622 KV: fu.OfpFlowModArgs{"priority": 1000},
623 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400624 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400625 fu.TunnelId(uint64(1)),
626 fu.EthType(0x888e),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700627 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
khenaidoo89b0e942018-10-21 21:11:33 -0400628 },
629 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400630 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400631 },
632 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800633 expectedOltFlow, err := fu.MkFlowStat(faParent)
634 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400635 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400636 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400637
npujar1d86a522019-11-14 17:11:16 +0530638 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400639 KV: fu.OfpFlowModArgs{"priority": 1000},
640 MatchFields: []*ofp.OfpOxmOfbField{
641 fu.InPort(2),
642 fu.TunnelId(uint64(1)),
643 fu.EthType(0x888e),
644 },
645 Actions: []*ofp.OfpAction{
Girish Gowdra9a50f032020-09-16 13:21:10 -0700646 fu.PushVlan(0x8100),
647 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400648 fu.Output(1),
649 },
650 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800651 expectedOnuFlow, err := fu.MkFlowStat(faChild)
652 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400653 derivedFlow = onu1FlowAndGroup.GetFlow(0)
654 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400655}
656
Marcos Aurelio Carrero (Furukawa)a61a72c2021-01-28 13:48:20 -0300657func TestPppoedReRouteRuleVlanDecomposition(t *testing.T) {
658
659 fa := &fu.FlowArgs{
660 KV: fu.OfpFlowModArgs{"priority": 1000},
661 MatchFields: []*ofp.OfpOxmOfbField{
662 fu.InPort(1),
663 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
664 fu.EthType(0x8863),
665 },
666 Actions: []*ofp.OfpAction{
667 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
668 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
669 },
670 }
671
672 fs, err := fu.MkFlowStat(fa)
673 assert.Nil(t, err)
674 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
675 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
676
677 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
678 assert.Nil(t, err)
679 onu1FlowAndGroup := deviceRules.Rules["onu1"]
680 oltFlowAndGroup := deviceRules.Rules["olt"]
681 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
682 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
683 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
684
685 faParent := &fu.FlowArgs{
686 KV: fu.OfpFlowModArgs{"priority": 1000},
687 MatchFields: []*ofp.OfpOxmOfbField{
688 fu.InPort(1),
689 fu.TunnelId(uint64(1)),
690 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
691 fu.EthType(0x8863),
692 },
693 Actions: []*ofp.OfpAction{
694 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
695 },
696 }
697 expectedOltFlow, err := fu.MkFlowStat(faParent)
698 assert.Nil(t, err)
699 derivedFlow := oltFlowAndGroup.GetFlow(0)
700 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
701
702 faChild := &fu.FlowArgs{
703 KV: fu.OfpFlowModArgs{"priority": 1000},
704 MatchFields: []*ofp.OfpOxmOfbField{
705 fu.InPort(2),
706 fu.TunnelId(uint64(1)),
707 fu.EthType(0x8863),
708 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
709 },
710 Actions: []*ofp.OfpAction{
711 fu.PushVlan(0x8100),
712 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
713 fu.Output(1),
714 },
715 }
716 expectedOnuFlow, err := fu.MkFlowStat(faChild)
717 assert.Nil(t, err)
718 derivedFlow = onu1FlowAndGroup.GetFlow(0)
719 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
720}
721
khenaidoo89b0e942018-10-21 21:11:33 -0400722func TestDhcpReRouteRuleDecomposition(t *testing.T) {
723
npujar1d86a522019-11-14 17:11:16 +0530724 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400725 KV: fu.OfpFlowModArgs{"priority": 1000},
726 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400727 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400728 fu.EthType(0x0800),
729 fu.Ipv4Dst(0xffffffff),
730 fu.IpProto(17),
731 fu.UdpSrc(68),
732 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400733 },
734 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400735 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400736 },
737 }
738
Scott Bakerfdea1e32020-02-21 15:35:41 -0800739 fs, err := fu.MkFlowStat(fa)
740 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400741 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800742 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400743
Kent Hagerman433a31a2020-05-20 19:04:48 -0400744 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500745 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400746 onu1FlowAndGroup := deviceRules.Rules["onu1"]
747 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400748 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
749 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400750 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400751 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
752
npujar1d86a522019-11-14 17:11:16 +0530753 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400754 KV: fu.OfpFlowModArgs{"priority": 1000},
755 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400756 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400757 fu.TunnelId(uint64(1)),
758 fu.EthType(0x0800),
759 fu.Ipv4Dst(0xffffffff),
760 fu.IpProto(17),
761 fu.UdpSrc(68),
762 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400763 },
764 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400765 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400766 },
767 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800768 expectedOltFlow, err := fu.MkFlowStat(faParent)
769 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400770 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400771 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400772
npujar1d86a522019-11-14 17:11:16 +0530773 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400774 KV: fu.OfpFlowModArgs{"priority": 1000},
775 MatchFields: []*ofp.OfpOxmOfbField{
776 fu.InPort(2),
777 fu.TunnelId(uint64(1)),
778 fu.EthType(0x0800),
779 fu.Ipv4Dst(0xffffffff),
780 fu.IpProto(17),
781 fu.UdpSrc(68),
782 fu.UdpDst(67),
783 },
784 Actions: []*ofp.OfpAction{
785 fu.Output(1),
786 },
787 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800788 expectedOnuFlow, err := fu.MkFlowStat(faChild)
789 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400790 derivedFlow = onu1FlowAndGroup.GetFlow(0)
791 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400792}
793
Humera Kouser4ff89012019-08-25 19:01:51 -0400794func TestLldpReRouteRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530795 fa := &fu.FlowArgs{
Humera Kouser4ff89012019-08-25 19:01:51 -0400796 KV: fu.OfpFlowModArgs{"priority": 1000},
797 MatchFields: []*ofp.OfpOxmOfbField{
798 fu.InPort(10),
799 fu.EthType(0x88CC),
800 },
801 Actions: []*ofp.OfpAction{
802 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
803 },
804 }
805
Scott Bakerfdea1e32020-02-21 15:35:41 -0800806 fs, err := fu.MkFlowStat(fa)
807 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400808 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800809 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Kent Hagerman433a31a2020-05-20 19:04:48 -0400810 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500811 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400812 onu1FlowAndGroup := deviceRules.Rules["onu1"]
813 oltFlowAndGroup := deviceRules.Rules["olt"]
814 assert.Nil(t, onu1FlowAndGroup)
815 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
816 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
817
818 fa = &fu.FlowArgs{
819 KV: fu.OfpFlowModArgs{"priority": 1000},
820 MatchFields: []*ofp.OfpOxmOfbField{
821 fu.InPort(2),
822 fu.EthType(0x88CC),
823 },
824 Actions: []*ofp.OfpAction{
825 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
826 },
827 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800828 expectedOltFlow, err := fu.MkFlowStat(fa)
829 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400830 derivedFlow := oltFlowAndGroup.GetFlow(0)
831 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
832}
833
khenaidood20a5852018-10-22 22:09:55 -0400834func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530835 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400836 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400837 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400838 fu.InPort(1),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300839 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo68c930b2019-05-13 11:46:51 -0400840 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400841 },
842 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400843 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400844 },
845 }
846
npujar1d86a522019-11-14 17:11:16 +0530847 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400848 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400849 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400850 fu.InPort(1),
851 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
852 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400853 },
854 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400855 fu.PushVlan(0x8100),
856 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
857 fu.SetField(fu.VlanPcp(0)),
858 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400859 },
860 }
861
Scott Bakerfdea1e32020-02-21 15:35:41 -0800862 fs, err := fu.MkFlowStat(fa)
863 assert.Nil(t, err)
864 fs2, err := fu.MkFlowStat(fa2)
865 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400866
867 fs.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400868 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
869 Data: &ofp.OfpInstruction_GotoTable{
870 GotoTable: &ofp.OfpInstructionGotoTable{
871 TableId: 1,
872 },
873 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400874 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400875
Scott Bakerfdea1e32020-02-21 15:35:41 -0800876 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400877
Kent Hagerman433a31a2020-05-20 19:04:48 -0400878 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500879 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400880 onu1FlowAndGroup := deviceRules.Rules["onu1"]
881 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400882 assert.NotNil(t, onu1FlowAndGroup)
883 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400884 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400885 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
886 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
887 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
888
889 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400890 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400891 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400892 fu.InPort(2),
893 fu.TunnelId(uint64(1)),
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300894 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT)),
khenaidoo68c930b2019-05-13 11:46:51 -0400895 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400896 },
897 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400898 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
899 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400900 },
901 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400902
khenaidoo3306c992019-05-24 16:57:35 -0400903 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400904 // Form the expected flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800905 expectedOnu1Flow, err := fu.MkFlowStat(fa)
906 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400907 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
908 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
909 Data: &ofp.OfpInstruction_Actions{
910 Actions: &ofp.OfpInstructionActions{
911 Actions: []*ofp.OfpAction{{
912 Type: 0,
913 Action: &ofp.OfpAction_Output{
914 Output: &ofp.OfpActionOutput{
915 Port: 1,
916 MaxLen: 65509,
917 },
918 }}}}}}}
919
920 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400921 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
922
923 fa = &fu.FlowArgs{
924 KV: fu.OfpFlowModArgs{"priority": 500},
925 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400926 fu.InPort(1),
927 fu.TunnelId(uint64(1)),
928 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
929 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400930 },
931 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400932 fu.PushVlan(0x8100),
933 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
934 fu.SetField(fu.VlanPcp(0)),
935 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400936 },
937 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800938 expectedOltFlow, err := fu.MkFlowStat(fa)
939 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400940 derivedFlow = oltFlowAndGroup.GetFlow(0)
941 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
942}
943
944func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000945 ctx := context.Background()
946 logger.Debugf(ctx, "Starting Test Unicast Downstream")
npujar1d86a522019-11-14 17:11:16 +0530947 fa1 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400948 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400949 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400950 fu.InPort(10),
951 fu.Metadata_ofp((1000 << 32) | 1),
952 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400953 },
954 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400955 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400956 },
957 }
958
ssiddiqui21e54c32021-07-27 11:30:46 +0530959 // If table-id is provided in the flow-args, the same is also used as go-to-next table
npujar1d86a522019-11-14 17:11:16 +0530960 fa2 := &fu.FlowArgs{
ssiddiqui21e54c32021-07-27 11:30:46 +0530961 KV: fu.OfpFlowModArgs{"priority": 500 /*"table_id": 1*/},
khenaidood20a5852018-10-22 22:09:55 -0400962 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400963 fu.InPort(10),
964 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
965 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400966 },
967 Actions: []*ofp.OfpAction{
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300968 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT))),
khenaidoo68c930b2019-05-13 11:46:51 -0400969 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400970 },
971 }
972
Scott Bakerfdea1e32020-02-21 15:35:41 -0800973 fs1, err := fu.MkFlowStat(fa1)
974 assert.Nil(t, err)
975 fs2, err := fu.MkFlowStat(fa2)
976 assert.Nil(t, err)
ssiddiqui21e54c32021-07-27 11:30:46 +0530977 // Table-1, without next table
978 fs2.TableId = 1
979
Kent Hagerman433a31a2020-05-20 19:04:48 -0400980 fs1.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400981 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
982 Data: &ofp.OfpInstruction_GotoTable{
983 GotoTable: &ofp.OfpInstructionGotoTable{
984 TableId: 1,
985 },
986 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400987 flows := map[uint64]*ofp.OfpFlowStats{fs1.Id: fs1, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400988
Scott Bakerfdea1e32020-02-21 15:35:41 -0800989 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400990
Kent Hagerman433a31a2020-05-20 19:04:48 -0400991 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500992 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400993 onu1FlowAndGroup := deviceRules.Rules["onu1"]
994 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400995 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400996 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
997 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
998 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
999
1000 fa1 = &fu.FlowArgs{
1001 KV: fu.OfpFlowModArgs{"priority": 500},
1002 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -04001003 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -04001004 fu.TunnelId(uint64(10)),
1005 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -04001006 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -04001007 },
1008 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -04001009 fu.PopVlan(),
1010 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -04001011 },
1012 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001013
khenaidood20a5852018-10-22 22:09:55 -04001014 derivedFlow := oltFlowAndGroup.GetFlow(0)
Scott Bakerfdea1e32020-02-21 15:35:41 -08001015 expectedOltFlow, err := fu.MkFlowStat(fa1)
1016 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001017 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
1018 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
1019 Data: &ofp.OfpInstruction_Actions{
1020 Actions: &ofp.OfpInstructionActions{
1021 Actions: []*ofp.OfpAction{{
1022 Type: 0,
1023 Action: &ofp.OfpAction_Output{
1024 Output: &ofp.OfpActionOutput{
1025 Port: 1,
1026 MaxLen: 65509,
1027 },
1028 }}}}}}}
1029 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -04001030 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
1031
1032 fa1 = &fu.FlowArgs{
1033 KV: fu.OfpFlowModArgs{"priority": 500},
1034 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -04001035 fu.InPort(1),
1036 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
1037 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -04001038 },
1039 Actions: []*ofp.OfpAction{
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +03001040 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT))),
khenaidoo68c930b2019-05-13 11:46:51 -04001041 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -04001042 },
1043 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001044 expectedOnu1Flow, err := fu.MkFlowStat(fa1)
1045 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -04001046 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -04001047 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
1048}
1049
1050func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +05301051 fa := &fu.FlowArgs{
khenaidood20a5852018-10-22 22:09:55 -04001052 KV: fu.OfpFlowModArgs{"priority": 500},
1053 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -04001054 fu.InPort(10),
1055 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1056 fu.VlanPcp(0),
1057 fu.EthType(0x800),
1058 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001059 },
1060 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -04001061 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001062 },
1063 }
1064
npujar1d86a522019-11-14 17:11:16 +05301065 ga := &fu.GroupArgs{
khenaidood20a5852018-10-22 22:09:55 -04001066 GroupId: 10,
1067 Buckets: []*ofp.OfpBucket{
1068 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -04001069 fu.PopVlan(),
1070 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -04001071 },
1072 },
1073 },
1074 }
1075
Scott Bakerfdea1e32020-02-21 15:35:41 -08001076 fs, err := fu.MkFlowStat(fa)
1077 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -04001078 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
1079 groups := map[uint32]*ofp.OfpGroupEntry{ga.GroupId: fu.MkGroupStat(ga)}
Scott Bakerfdea1e32020-02-21 15:35:41 -08001080 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -04001081
khenaidoo820197c2020-02-13 16:35:33 -05001082 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, groups)
1083 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001084 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidood20a5852018-10-22 22:09:55 -04001085 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1086 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1087
1088 fa = &fu.FlowArgs{
1089 KV: fu.OfpFlowModArgs{"priority": 500},
1090 MatchFields: []*ofp.OfpOxmOfbField{
Esin Karaman09959ae2019-11-29 13:59:58 +00001091 fu.InPort(10),
khenaidoo68c930b2019-05-13 11:46:51 -04001092 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1093 fu.VlanPcp(0),
1094 fu.EthType(0x800),
1095 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001096 },
1097 Actions: []*ofp.OfpAction{
Esin Karaman09959ae2019-11-29 13:59:58 +00001098 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001099 },
1100 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001101 expectedOltFlow, err := fu.MkFlowStat(fa)
1102 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001103 derivedFlow := oltFlowAndGroup.GetFlow(0)
1104 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidood20a5852018-10-22 22:09:55 -04001105}
ssiddiqui21e54c32021-07-27 11:30:46 +05301106
1107func TestMplsUpstreamFlowDecomposition(t *testing.T) {
1108 // Note: Olt-Nni=10
1109 // Onu1-Uni=1
1110
1111 /*
1112 ADDED, bytes=0, packets=0, table=0, priority=1000, selector=[IN_PORT:UNI, VLAN_VID:ANY], treatment=[immediate=[],
1113 transition=TABLE:1, meter=METER:1, metadata=METADATA:4100010000/0]
1114 */
1115
1116 // Here, 'table_id=1' is present to add go-to-table action
1117 faOnu := &fu.FlowArgs{
1118 KV: fu.OfpFlowModArgs{"priority": 1000, "table_id": 1, "meter_id": 1, "write_metadata": 4100100000},
1119 MatchFields: []*ofp.OfpOxmOfbField{
1120 fu.InPort(1), // Onu Uni
1121 fu.VlanVid(4096),
1122 },
1123 Actions: []*ofp.OfpAction{},
1124 }
1125 fsOnu, err := fu.MkFlowStat(faOnu)
1126 assert.NoError(t, err)
1127 assert.NotNil(t, fsOnu)
1128 // Update table-id
1129 fsOnu.TableId = 0
1130
1131 /*
1132 ADDED, bytes=0, packets=0, table=1, priority=1000, selector=[IN_PORT:32, VLAN_VID:ANY], treatment=[immediate=[VLAN_PUSH:vlan,
1133 VLAN_ID:2, MPLS_PUSH:mpls_unicast, MPLS_LABEL:YYY,MPLS_BOS:true, MPLS_PUSH:mpls_unicast ,MPLS_LABEL:XXX, MPLS_BOS:false,
1134 EXTENSION:of:0000000000000227/VolthaPushL2Header{​​​​​​​}​​​​​​​, ETH_SRC:OLT_MAC, ETH_DST:LEAF_MAC, TTL:64, OUTPUT:65536],
1135 meter=METER:1, metadata=METADATA:4100000000/0]
1136 */
1137 faOlt := &fu.FlowArgs{
1138 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1, "write_metadata": 4100000000},
1139 MatchFields: []*ofp.OfpOxmOfbField{
1140 fu.InPort(1), // Onu-Uni
1141 fu.VlanVid(4096),
1142 },
1143 Actions: []*ofp.OfpAction{
1144 fu.PushVlan(0x8100),
1145 fu.SetField(fu.VlanVid(2)),
1146 fu.SetField(fu.EthSrc(1111)),
1147 fu.SetField(fu.EthDst(2222)),
1148 fu.PushVlan(0x8847),
1149 fu.SetField(fu.MplsLabel(100)),
1150 fu.SetField(fu.MplsBos(1)),
1151 fu.PushVlan(0x8847),
1152 fu.SetField(fu.MplsLabel(200)),
1153 fu.MplsTtl(64),
1154 fu.Output(10), // Olt-Nni
1155 },
1156 }
1157
1158 fsOlt, err := fu.MkFlowStat(faOlt)
1159 assert.NoError(t, err)
1160 assert.NotNil(t, fsOlt)
1161 // Update table-id
1162 // table-id is skipped in flow-args above as that would also add the go-to-table action
1163 fsOlt.TableId = 1
1164
1165 flows := map[uint64]*ofp.OfpFlowStats{fsOnu.Id: fsOnu, fsOlt.Id: fsOlt}
1166
1167 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
1168
1169 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
1170 assert.Nil(t, err)
1171 onuFlowAndGroup := deviceRules.Rules["onu1"]
1172 oltFlowAndGroup := deviceRules.Rules["olt"]
1173 assert.NotNil(t, onuFlowAndGroup)
1174 assert.NotNil(t, onuFlowAndGroup.Flows)
1175 assert.Equal(t, 1, onuFlowAndGroup.Flows.Len())
1176 assert.Equal(t, 0, onuFlowAndGroup.Groups.Len())
1177 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1178 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1179
1180 // Form expected ONU flow args
1181 expectedOnufa := &fu.FlowArgs{
1182 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1, "write_metadata": 4100100000},
1183 MatchFields: []*ofp.OfpOxmOfbField{
1184 fu.InPort(2), // Onu Uni
1185 fu.TunnelId(uint64(1)),
1186 fu.VlanVid(4096),
1187 },
1188 Actions: []*ofp.OfpAction{
1189 fu.Output(1),
1190 },
1191 }
1192
1193 // Form the expected ONU flow
1194 expectedOnuFlow, err := fu.MkFlowStat(expectedOnufa)
1195 assert.Nil(t, err)
1196 assert.NotNil(t, expectedOnuFlow)
1197 expectedOnuFlow.TableId = 0
1198
1199 derivedOnuFlow := onuFlowAndGroup.GetFlow(0)
1200 expectedOnuFlow.Id = derivedOnuFlow.Id // Assign same flow ID as derived flowID to match completely
1201 assert.Equal(t, expectedOnuFlow.String(), derivedOnuFlow.String())
1202
1203 expectedOltfa := &fu.FlowArgs{
1204 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1, "write_metadata": 4100000000},
1205 MatchFields: []*ofp.OfpOxmOfbField{
1206 fu.InPort(1), // Onu-Uni
1207 fu.TunnelId(uint64(1)),
1208 fu.VlanVid(4096),
1209 },
1210 Actions: []*ofp.OfpAction{
1211 fu.PushVlan(0x8100),
1212 fu.SetField(fu.VlanVid(2)),
1213 fu.SetField(fu.EthSrc(1111)),
1214 fu.SetField(fu.EthDst(2222)),
1215 fu.PushVlan(0x8847),
1216 fu.SetField(fu.MplsLabel(100)),
1217 fu.SetField(fu.MplsBos(1)),
1218 fu.PushVlan(0x8847),
1219 fu.SetField(fu.MplsLabel(200)),
1220 fu.MplsTtl(64),
1221 fu.Output(2), // Olt-Nni
1222 },
1223 }
1224
1225 expectedOltFlow, err := fu.MkFlowStat(expectedOltfa)
1226 assert.NoError(t, err)
1227 assert.NotNil(t, expectedOltFlow)
1228
1229 derivedOltFlow := oltFlowAndGroup.GetFlow(0)
1230 expectedOltFlow.Id = derivedOltFlow.Id
1231 assert.Equal(t, expectedOltFlow.String(), derivedOltFlow.String())
1232}
1233
1234func TestMplsDownstreamFlowDecomposition(t *testing.T) {
1235 faOltSingleMplsLable := &fu.FlowArgs{
1236 KV: fu.OfpFlowModArgs{"priority": 1000, "table_id": 1},
1237 MatchFields: []*ofp.OfpOxmOfbField{
1238 fu.InPort(10),
1239 fu.Metadata_ofp((1000 << 32) | 1),
1240 fu.EthType(0x8847),
1241 fu.MplsBos(1),
1242 fu.EthSrc(2222),
1243 },
1244 Actions: []*ofp.OfpAction{
1245 {Type: ofp.OfpActionType_OFPAT_DEC_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: 62}}},
1246 fu.PopMpls(0x8847),
1247 },
1248 }
1249 fsOltSingleMplsLabel, err := fu.MkFlowStat(faOltSingleMplsLable)
1250 assert.NoError(t, err)
1251 assert.NotNil(t, fsOltSingleMplsLabel)
1252 fsOltSingleMplsLabel.TableId = 0
1253
1254 flows := map[uint64]*ofp.OfpFlowStats{fsOltSingleMplsLabel.Id: fsOltSingleMplsLabel}
1255
1256 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
1257
1258 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
1259 assert.Nil(t, err)
1260 assert.NotNil(t, deviceRules)
1261 oltFlowAndGroup := deviceRules.Rules["olt"]
1262 assert.NotNil(t, oltFlowAndGroup)
1263
1264 derivedFlow := oltFlowAndGroup.GetFlow(0)
1265 assert.NotNil(t, derivedFlow)
1266
1267 // Formulate expected
1268 expectedFa := &fu.FlowArgs{
1269 KV: fu.OfpFlowModArgs{"priority": 1000},
1270 MatchFields: []*ofp.OfpOxmOfbField{
1271 fu.InPort(2),
1272 fu.TunnelId(10),
1273 fu.Metadata_ofp((1000 << 32) | 1),
1274 fu.EthType(0x8847),
1275 fu.MplsBos(1),
1276 fu.EthSrc(2222),
1277 },
1278 Actions: []*ofp.OfpAction{
1279 {Type: ofp.OfpActionType_OFPAT_DEC_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: 62}}},
1280 fu.PopMpls(0x8847),
1281 fu.Output(1),
1282 },
1283 }
1284 expectedFs, err := fu.MkFlowStat(expectedFa)
1285 assert.NoError(t, err)
1286 expectedFs.Id = derivedFlow.Id
1287
1288 assert.Equal(t, expectedFs.String(), derivedFlow.String())
1289
1290 // Formulate Mpls double label
1291 faOltDoubleMplsLabel := &fu.FlowArgs{
1292 KV: fu.OfpFlowModArgs{"priority": 1000, "table_id": 1},
1293 MatchFields: []*ofp.OfpOxmOfbField{
1294 fu.InPort(10),
1295 fu.EthType(0x8847),
1296 fu.EthSrc(2222),
1297 },
1298 Actions: []*ofp.OfpAction{
1299 {Type: ofp.OfpActionType_OFPAT_DEC_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: 62}}},
1300 fu.PopMpls(0x8847),
1301 fu.PopMpls(0x8847),
1302 },
1303 }
1304 fsOltDoubleMplsLabel, err := fu.MkFlowStat(faOltDoubleMplsLabel)
1305 assert.NoError(t, err)
1306 assert.NotNil(t, fsOltDoubleMplsLabel)
1307
1308 flows2 := map[uint64]*ofp.OfpFlowStats{fsOltDoubleMplsLabel.Id: fsOltDoubleMplsLabel}
1309 assert.NotNil(t, flows2)
1310
1311 deviceRules, err = tfd.fd.DecomposeRules(context.Background(), tfd, flows2, nil)
1312 assert.NoError(t, err)
1313 assert.NotNil(t, deviceRules)
1314 oltFlowAndGroup = deviceRules.Rules["olt"]
1315 assert.NotNil(t, oltFlowAndGroup)
1316 derivedFlow = oltFlowAndGroup.GetFlow(0)
1317 assert.NotNil(t, derivedFlow)
1318
1319 expectedFa = &fu.FlowArgs{
1320 KV: fu.OfpFlowModArgs{"priority": 1000},
1321 MatchFields: []*ofp.OfpOxmOfbField{
1322 fu.InPort(2),
1323 fu.TunnelId(10),
1324 fu.EthType(0x8847),
1325 fu.EthSrc(2222),
1326 },
1327 Actions: []*ofp.OfpAction{
1328 {Type: ofp.OfpActionType_OFPAT_DEC_MPLS_TTL, Action: &ofp.OfpAction_MplsTtl{MplsTtl: &ofp.OfpActionMplsTtl{MplsTtl: 62}}},
1329 fu.PopMpls(0x8847),
1330 fu.PopMpls(0x8847),
1331 fu.Output(1),
1332 },
1333 }
1334 expectedFs, err = fu.MkFlowStat(expectedFa)
1335 assert.NoError(t, err)
1336 assert.NotNil(t, expectedFs)
1337 expectedFs.Id = derivedFlow.Id
1338 assert.Equal(t, expectedFs.String(), derivedFlow.String())
1339
1340 //olt downstream flows (table-id=1)
1341 faOlt := &fu.FlowArgs{
1342 KV: fu.OfpFlowModArgs{"priority": 1000, "table_id": 2, "meter_id": 1},
1343 MatchFields: []*ofp.OfpOxmOfbField{
1344 fu.InPort(10),
1345 fu.VlanVid(2),
1346 },
1347 Actions: []*ofp.OfpAction{
1348 fu.PopVlan(),
1349 },
1350 }
1351 fsOlt, err := fu.MkFlowStat(faOlt)
1352 assert.NoError(t, err)
1353 assert.NotNil(t, fsOlt)
1354 fsOlt.TableId = 1
1355
1356 flows3 := map[uint64]*ofp.OfpFlowStats{fsOlt.Id: fsOlt}
1357 assert.NotNil(t, flows3)
1358 deviceRules, err = tfd.fd.DecomposeRules(context.Background(), tfd, flows3, nil)
1359 assert.NoError(t, err)
1360 assert.NotNil(t, deviceRules)
1361 oltFlowAndGroup = deviceRules.Rules["olt"]
1362 assert.NotNil(t, oltFlowAndGroup)
1363 derivedFlow = oltFlowAndGroup.GetFlow(0)
1364 assert.NotNil(t, derivedFlow)
1365
1366 faOltExpected := &fu.FlowArgs{
1367 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1},
1368 MatchFields: []*ofp.OfpOxmOfbField{
1369 fu.InPort(2),
1370 fu.TunnelId(10),
1371 fu.VlanVid(2),
1372 },
1373 Actions: []*ofp.OfpAction{
1374 fu.PopVlan(),
1375 fu.Output(1),
1376 },
1377 }
1378 fsOltExpected, err := fu.MkFlowStat(faOltExpected)
1379 assert.NoError(t, err)
1380 assert.NotNil(t, fsOltExpected)
1381 fsOltExpected.Id = derivedFlow.Id
1382 assert.Equal(t, fsOltExpected.String(), derivedFlow.String())
1383
1384 // Onu Downstream
1385 faOnu := &fu.FlowArgs{
1386 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1},
1387 MatchFields: []*ofp.OfpOxmOfbField{
1388 fu.InPort(10),
1389 fu.Metadata_ofp((1000 << 32) | 1),
1390 fu.VlanVid(4096),
1391 },
1392 Actions: []*ofp.OfpAction{
1393 fu.Output(1),
1394 },
1395 }
1396 fsOnu, err := fu.MkFlowStat(faOnu)
1397 assert.NoError(t, err)
1398 fsOnu.TableId = 2
1399
1400 flows4 := map[uint64]*ofp.OfpFlowStats{fsOnu.Id: fsOnu}
1401 assert.NotNil(t, flows4)
1402 deviceRules, err = tfd.fd.DecomposeRules(context.Background(), tfd, flows4, nil)
1403 assert.NoError(t, err)
1404 assert.NotNil(t, deviceRules)
1405 onuFlowAndGroup := deviceRules.Rules["onu1"]
1406 assert.NotNil(t, onuFlowAndGroup)
1407 derivedFlow = onuFlowAndGroup.GetFlow(0)
1408 assert.NotNil(t, derivedFlow)
1409
1410 faExpected := &fu.FlowArgs{
1411 KV: fu.OfpFlowModArgs{"priority": 1000, "meter_id": 1},
1412 MatchFields: []*ofp.OfpOxmOfbField{
1413 fu.InPort(1),
1414 fu.Metadata_ofp((1000 << 32) | 1),
1415 fu.VlanVid(4096),
1416 },
1417 Actions: []*ofp.OfpAction{
1418 fu.Output(2),
1419 },
1420 }
1421 fsExpected, err := fu.MkFlowStat(faExpected)
1422 assert.NoError(t, err)
1423 assert.NotNil(t, fsExpected)
1424 fsExpected.Id = derivedFlow.Id
1425
1426 assert.Equal(t, fsExpected.String(), derivedFlow.String())
1427}