blob: e9c6fd094533030467e6c2502b68e1d17b12212e [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
Kent Hagerman6031aad2020-07-29 16:36:33 -040023 "github.com/opencord/voltha-go/rw_core/core/device/state"
khenaidoo820197c2020-02-13 16:35:33 -050024 "github.com/opencord/voltha-go/rw_core/route"
Maninderdfadc982020-10-28 14:04:33 +053025 fu "github.com/opencord/voltha-lib-go/v4/pkg/flows"
26 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
27 "github.com/opencord/voltha-protos/v4/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 {
Kent Hagerman6031aad2020-07-29 16:36:33 -040034 state.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
Kent Hagerman6031aad2020-07-29 16:36:33 -0400400 tfd.fd = NewFlowDecomposer(func(ctx context.Context, deviceID string) (*voltha.Device, error) {
401 return tfd.dMgr.GetDevice(ctx, &voltha.ID{Id: deviceID})
402 })
khenaidoo89b0e942018-10-21 21:11:33 -0400403
404 return &tfd
405}
406
npujar1d86a522019-11-14 17:11:16 +0530407func (tfd *testFlowDecomposer) GetDeviceLogicalID() string {
khenaidoo89b0e942018-10-21 21:11:33 -0400408 return ""
409}
410
khenaidoo442e7c72020-03-10 16:13:48 -0400411func (tfd *testFlowDecomposer) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
412 return nil, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400413}
414
khenaidoo820197c2020-02-13 16:35:33 -0500415func (tfd *testFlowDecomposer) GetDeviceRoutes() *route.DeviceRoutes {
416 return tfd.deviceRoutes
khenaidoo89b0e942018-10-21 21:11:33 -0400417}
418
419func (tfd *testFlowDecomposer) GetAllDefaultRules() *fu.DeviceRules {
420 return tfd.defaultRules
421}
422
Rohan Agrawal31f21802020-06-12 05:38:46 +0000423func (tfd *testFlowDecomposer) GetWildcardInputPorts(ctx context.Context, excludePort uint32) map[uint32]struct{} {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400424 lPorts := make(map[uint32]struct{})
425 for portNo := range tfd.logicalPorts {
426 if portNo != excludePort {
427 lPorts[portNo] = struct{}{}
khenaidoo89b0e942018-10-21 21:11:33 -0400428 }
429 }
430 return lPorts
431}
432
khenaidoo820197c2020-02-13 16:35:33 -0500433func (tfd *testFlowDecomposer) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
434 var portLink route.OFPortLink
khenaidoo19d7b632018-10-30 10:49:50 -0400435 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400436 portLink.Egress = 0
khenaidoo19d7b632018-10-30 10:49:50 -0400437 } else if egressPortNo&0x7fffffff == uint32(ofp.OfpPortNo_OFPP_CONTROLLER) {
khenaidoo89b0e942018-10-21 21:11:33 -0400438 portLink.Egress = 10
439 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400440 portLink.Egress = egressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400441 }
khenaidoo19d7b632018-10-30 10:49:50 -0400442 if ingressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400443 portLink.Ingress = 0
444 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400445 portLink.Ingress = ingressPortNo
khenaidoo89b0e942018-10-21 21:11:33 -0400446 }
447 for key, val := range tfd.routes {
448 if key.Ingress == portLink.Ingress && key.Egress == portLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -0500449 return val, nil
khenaidoo89b0e942018-10-21 21:11:33 -0400450 }
451 }
khenaidoo820197c2020-02-13 16:35:33 -0500452 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400453}
454
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400455func (tfd *testFlowDecomposer) GetNNIPorts() map[uint32]struct{} {
456 nniPorts := make(map[uint32]struct{})
Esin Karaman09959ae2019-11-29 13:59:58 +0000457 for portNo, nni := range tfd.logicalPortsNo {
458 if nni {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400459 nniPorts[portNo] = struct{}{}
Esin Karaman09959ae2019-11-29 13:59:58 +0000460 }
461 }
462 return nniPorts
463}
464
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400465func TestEapolReRouteRuleVlanDecomposition(t *testing.T) {
466
npujar1d86a522019-11-14 17:11:16 +0530467 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400468 KV: fu.OfpFlowModArgs{"priority": 1000},
469 MatchFields: []*ofp.OfpOxmOfbField{
470 fu.InPort(1),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700471 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400472 fu.EthType(0x888e),
473 },
474 Actions: []*ofp.OfpAction{
475 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
476 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
477 },
478 }
479
Scott Bakerfdea1e32020-02-21 15:35:41 -0800480 fs, err := fu.MkFlowStat(fa)
481 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400482 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800483 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400484
Kent Hagerman433a31a2020-05-20 19:04:48 -0400485 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500486 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400487 onu1FlowAndGroup := deviceRules.Rules["onu1"]
488 oltFlowAndGroup := deviceRules.Rules["olt"]
489 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
490 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
491 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
492
npujar1d86a522019-11-14 17:11:16 +0530493 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400494 KV: fu.OfpFlowModArgs{"priority": 1000},
495 MatchFields: []*ofp.OfpOxmOfbField{
496 fu.InPort(1),
497 fu.TunnelId(uint64(1)),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700498 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400499 fu.EthType(0x888e),
500 },
501 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400502 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
503 },
504 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800505 expectedOltFlow, err := fu.MkFlowStat(faParent)
506 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400507 derivedFlow := oltFlowAndGroup.GetFlow(0)
508 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
509
npujar1d86a522019-11-14 17:11:16 +0530510 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400511 KV: fu.OfpFlowModArgs{"priority": 1000},
512 MatchFields: []*ofp.OfpOxmOfbField{
513 fu.InPort(2),
514 fu.TunnelId(uint64(1)),
515 fu.EthType(0x888e),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700516 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 50),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400517 },
518 Actions: []*ofp.OfpAction{
519 fu.PushVlan(0x8100),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700520 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400521 fu.Output(1),
522 },
523 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800524 expectedOnuFlow, err := fu.MkFlowStat(faChild)
525 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400526 derivedFlow = onu1FlowAndGroup.GetFlow(0)
527 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
528}
529
530func TestEapolReRouteRuleZeroVlanDecomposition(t *testing.T) {
531
npujar1d86a522019-11-14 17:11:16 +0530532 fa := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400533 KV: fu.OfpFlowModArgs{"priority": 1000},
534 MatchFields: []*ofp.OfpOxmOfbField{
535 fu.InPort(1),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700536 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400537 fu.EthType(0x888e),
538 },
539 Actions: []*ofp.OfpAction{
540 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
541 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
542 },
543 }
544
Scott Bakerfdea1e32020-02-21 15:35:41 -0800545 fs, err := fu.MkFlowStat(fa)
546 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400547 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800548 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400549
Kent Hagerman433a31a2020-05-20 19:04:48 -0400550 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500551 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400552 onu1FlowAndGroup := deviceRules.Rules["onu1"]
553 oltFlowAndGroup := deviceRules.Rules["olt"]
554 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
555 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
556 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
557
npujar1d86a522019-11-14 17:11:16 +0530558 faParent := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400559 KV: fu.OfpFlowModArgs{"priority": 1000},
560 MatchFields: []*ofp.OfpOxmOfbField{
561 fu.InPort(1),
562 fu.TunnelId(uint64(1)),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700563 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400564 fu.EthType(0x888e),
565 },
566 Actions: []*ofp.OfpAction{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400567 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
568 },
569 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800570 expectedOltFlow, err := fu.MkFlowStat(faParent)
571 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400572 derivedFlow := oltFlowAndGroup.GetFlow(0)
573 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
574
npujar1d86a522019-11-14 17:11:16 +0530575 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400576 KV: fu.OfpFlowModArgs{"priority": 1000},
577 MatchFields: []*ofp.OfpOxmOfbField{
578 fu.InPort(2),
579 fu.TunnelId(uint64(1)),
580 fu.EthType(0x888e),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700581 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400582 },
583 Actions: []*ofp.OfpAction{
584 fu.PushVlan(0x8100),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700585 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400586 fu.Output(1),
587 },
588 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800589 expectedOnuFlow, err := fu.MkFlowStat(faChild)
590 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400591 derivedFlow = onu1FlowAndGroup.GetFlow(0)
592 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
593}
594
595func TestEapolReRouteRuleNoVlanDecomposition(t *testing.T) {
khenaidoo89b0e942018-10-21 21:11:33 -0400596
npujar1d86a522019-11-14 17:11:16 +0530597 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400598 KV: fu.OfpFlowModArgs{"priority": 1000},
599 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400600 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400601 fu.EthType(0x888e),
khenaidoo89b0e942018-10-21 21:11:33 -0400602 },
603 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400604 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
605 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400606 },
607 }
608
Scott Bakerfdea1e32020-02-21 15:35:41 -0800609 fs, err := fu.MkFlowStat(fa)
610 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400611 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800612 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400613
Kent Hagerman433a31a2020-05-20 19:04:48 -0400614 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500615 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400616 onu1FlowAndGroup := deviceRules.Rules["onu1"]
617 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400618 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400619 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400620 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
621
npujar1d86a522019-11-14 17:11:16 +0530622 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400623 KV: fu.OfpFlowModArgs{"priority": 1000},
624 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400625 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400626 fu.TunnelId(uint64(1)),
627 fu.EthType(0x888e),
Girish Gowdra9a50f032020-09-16 13:21:10 -0700628 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
khenaidoo89b0e942018-10-21 21:11:33 -0400629 },
630 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400631 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400632 },
633 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800634 expectedOltFlow, err := fu.MkFlowStat(faParent)
635 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400636 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400637 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400638
npujar1d86a522019-11-14 17:11:16 +0530639 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400640 KV: fu.OfpFlowModArgs{"priority": 1000},
641 MatchFields: []*ofp.OfpOxmOfbField{
642 fu.InPort(2),
643 fu.TunnelId(uint64(1)),
644 fu.EthType(0x888e),
645 },
646 Actions: []*ofp.OfpAction{
Girish Gowdra9a50f032020-09-16 13:21:10 -0700647 fu.PushVlan(0x8100),
648 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400649 fu.Output(1),
650 },
651 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800652 expectedOnuFlow, err := fu.MkFlowStat(faChild)
653 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400654 derivedFlow = onu1FlowAndGroup.GetFlow(0)
655 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400656}
657
658func TestDhcpReRouteRuleDecomposition(t *testing.T) {
659
npujar1d86a522019-11-14 17:11:16 +0530660 fa := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400661 KV: fu.OfpFlowModArgs{"priority": 1000},
662 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400663 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400664 fu.EthType(0x0800),
665 fu.Ipv4Dst(0xffffffff),
666 fu.IpProto(17),
667 fu.UdpSrc(68),
668 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400669 },
670 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400671 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400672 },
673 }
674
Scott Bakerfdea1e32020-02-21 15:35:41 -0800675 fs, err := fu.MkFlowStat(fa)
676 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400677 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800678 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidoo89b0e942018-10-21 21:11:33 -0400679
Kent Hagerman433a31a2020-05-20 19:04:48 -0400680 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500681 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400682 onu1FlowAndGroup := deviceRules.Rules["onu1"]
683 oltFlowAndGroup := deviceRules.Rules["olt"]
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400684 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
685 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400686 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
khenaidoo89b0e942018-10-21 21:11:33 -0400687 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
688
npujar1d86a522019-11-14 17:11:16 +0530689 faParent := &fu.FlowArgs{
khenaidoo89b0e942018-10-21 21:11:33 -0400690 KV: fu.OfpFlowModArgs{"priority": 1000},
691 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400692 fu.InPort(1),
khenaidoo68c930b2019-05-13 11:46:51 -0400693 fu.TunnelId(uint64(1)),
694 fu.EthType(0x0800),
695 fu.Ipv4Dst(0xffffffff),
696 fu.IpProto(17),
697 fu.UdpSrc(68),
698 fu.UdpDst(67),
khenaidoo89b0e942018-10-21 21:11:33 -0400699 },
700 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400701 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
khenaidoo89b0e942018-10-21 21:11:33 -0400702 },
703 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800704 expectedOltFlow, err := fu.MkFlowStat(faParent)
705 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400706 derivedFlow := oltFlowAndGroup.GetFlow(0)
khenaidoo89b0e942018-10-21 21:11:33 -0400707 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400708
npujar1d86a522019-11-14 17:11:16 +0530709 faChild := &fu.FlowArgs{
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400710 KV: fu.OfpFlowModArgs{"priority": 1000},
711 MatchFields: []*ofp.OfpOxmOfbField{
712 fu.InPort(2),
713 fu.TunnelId(uint64(1)),
714 fu.EthType(0x0800),
715 fu.Ipv4Dst(0xffffffff),
716 fu.IpProto(17),
717 fu.UdpSrc(68),
718 fu.UdpDst(67),
719 },
720 Actions: []*ofp.OfpAction{
721 fu.Output(1),
722 },
723 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800724 expectedOnuFlow, err := fu.MkFlowStat(faChild)
725 assert.Nil(t, err)
Matt Jeanneretb423bad2019-10-10 20:42:19 -0400726 derivedFlow = onu1FlowAndGroup.GetFlow(0)
727 assert.Equal(t, expectedOnuFlow.String(), derivedFlow.String())
khenaidoo89b0e942018-10-21 21:11:33 -0400728}
729
Humera Kouser4ff89012019-08-25 19:01:51 -0400730func TestLldpReRouteRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530731 fa := &fu.FlowArgs{
Humera Kouser4ff89012019-08-25 19:01:51 -0400732 KV: fu.OfpFlowModArgs{"priority": 1000},
733 MatchFields: []*ofp.OfpOxmOfbField{
734 fu.InPort(10),
735 fu.EthType(0x88CC),
736 },
737 Actions: []*ofp.OfpAction{
738 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
739 },
740 }
741
Scott Bakerfdea1e32020-02-21 15:35:41 -0800742 fs, err := fu.MkFlowStat(fa)
743 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400744 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
Scott Bakerfdea1e32020-02-21 15:35:41 -0800745 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
Kent Hagerman433a31a2020-05-20 19:04:48 -0400746 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500747 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400748 onu1FlowAndGroup := deviceRules.Rules["onu1"]
749 oltFlowAndGroup := deviceRules.Rules["olt"]
750 assert.Nil(t, onu1FlowAndGroup)
751 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
752 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
753
754 fa = &fu.FlowArgs{
755 KV: fu.OfpFlowModArgs{"priority": 1000},
756 MatchFields: []*ofp.OfpOxmOfbField{
757 fu.InPort(2),
758 fu.EthType(0x88CC),
759 },
760 Actions: []*ofp.OfpAction{
761 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
762 },
763 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800764 expectedOltFlow, err := fu.MkFlowStat(fa)
765 assert.Nil(t, err)
Humera Kouser4ff89012019-08-25 19:01:51 -0400766 derivedFlow := oltFlowAndGroup.GetFlow(0)
767 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
768}
769
khenaidood20a5852018-10-22 22:09:55 -0400770func TestUnicastUpstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530771 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400772 KV: fu.OfpFlowModArgs{"priority": 5000, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400773 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400774 fu.InPort(1),
775 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
776 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400777 },
778 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400779 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
khenaidood20a5852018-10-22 22:09:55 -0400780 },
781 }
782
npujar1d86a522019-11-14 17:11:16 +0530783 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400784 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400785 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400786 fu.InPort(1),
787 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
788 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400789 },
790 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400791 fu.PushVlan(0x8100),
792 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
793 fu.SetField(fu.VlanPcp(0)),
794 fu.Output(10),
khenaidood20a5852018-10-22 22:09:55 -0400795 },
796 }
797
Scott Bakerfdea1e32020-02-21 15:35:41 -0800798 fs, err := fu.MkFlowStat(fa)
799 assert.Nil(t, err)
800 fs2, err := fu.MkFlowStat(fa2)
801 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400802
803 fs.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400804 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
805 Data: &ofp.OfpInstruction_GotoTable{
806 GotoTable: &ofp.OfpInstructionGotoTable{
807 TableId: 1,
808 },
809 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400810 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400811
Scott Bakerfdea1e32020-02-21 15:35:41 -0800812 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400813
Kent Hagerman433a31a2020-05-20 19:04:48 -0400814 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500815 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400816 onu1FlowAndGroup := deviceRules.Rules["onu1"]
817 oltFlowAndGroup := deviceRules.Rules["olt"]
Manikkaraj kb1a10922019-07-29 12:10:34 -0400818 assert.NotNil(t, onu1FlowAndGroup)
819 assert.NotNil(t, onu1FlowAndGroup.Flows)
khenaidoo3306c992019-05-24 16:57:35 -0400820 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400821 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
822 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
823 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
824
825 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400826 KV: fu.OfpFlowModArgs{"priority": 5000},
khenaidood20a5852018-10-22 22:09:55 -0400827 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400828 fu.InPort(2),
829 fu.TunnelId(uint64(1)),
830 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
831 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400832 },
833 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400834 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101)),
835 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400836 },
837 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400838
khenaidoo3306c992019-05-24 16:57:35 -0400839 derivedFlow := onu1FlowAndGroup.GetFlow(0)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400840 // Form the expected flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800841 expectedOnu1Flow, err := fu.MkFlowStat(fa)
842 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400843 expectedOnu1Flow.Instructions = []*ofp.OfpInstruction{{
844 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
845 Data: &ofp.OfpInstruction_Actions{
846 Actions: &ofp.OfpInstructionActions{
847 Actions: []*ofp.OfpAction{{
848 Type: 0,
849 Action: &ofp.OfpAction_Output{
850 Output: &ofp.OfpActionOutput{
851 Port: 1,
852 MaxLen: 65509,
853 },
854 }}}}}}}
855
856 expectedOnu1Flow.Id = derivedFlow.Id // Assign same flow ID as derived flowID to match completely
khenaidood20a5852018-10-22 22:09:55 -0400857 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
858
859 fa = &fu.FlowArgs{
860 KV: fu.OfpFlowModArgs{"priority": 500},
861 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400862 fu.InPort(1),
863 fu.TunnelId(uint64(1)),
864 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
865 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400866 },
867 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400868 fu.PushVlan(0x8100),
869 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 1000)),
870 fu.SetField(fu.VlanPcp(0)),
871 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400872 },
873 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800874 expectedOltFlow, err := fu.MkFlowStat(fa)
875 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400876 derivedFlow = oltFlowAndGroup.GetFlow(0)
877 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
878}
879
880func TestUnicastDownstreamRuleDecomposition(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000881 ctx := context.Background()
882 logger.Debugf(ctx, "Starting Test Unicast Downstream")
npujar1d86a522019-11-14 17:11:16 +0530883 fa1 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400884 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 0},
khenaidood20a5852018-10-22 22:09:55 -0400885 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400886 fu.InPort(10),
887 fu.Metadata_ofp((1000 << 32) | 1),
888 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400889 },
890 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400891 fu.PopVlan(),
khenaidood20a5852018-10-22 22:09:55 -0400892 },
893 }
894
npujar1d86a522019-11-14 17:11:16 +0530895 fa2 := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400896 KV: fu.OfpFlowModArgs{"priority": 500, "table_id": 1},
khenaidood20a5852018-10-22 22:09:55 -0400897 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400898 fu.InPort(10),
899 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
900 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400901 },
902 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400903 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
904 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400905 },
906 }
907
Scott Bakerfdea1e32020-02-21 15:35:41 -0800908 fs1, err := fu.MkFlowStat(fa1)
909 assert.Nil(t, err)
910 fs2, err := fu.MkFlowStat(fa2)
911 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400912 fs1.Instructions = []*ofp.OfpInstruction{{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400913 Type: uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE),
914 Data: &ofp.OfpInstruction_GotoTable{
915 GotoTable: &ofp.OfpInstructionGotoTable{
916 TableId: 1,
917 },
918 }}}
Kent Hagerman433a31a2020-05-20 19:04:48 -0400919 flows := map[uint64]*ofp.OfpFlowStats{fs1.Id: fs1, fs2.Id: fs2}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400920
Scott Bakerfdea1e32020-02-21 15:35:41 -0800921 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -0400922
Kent Hagerman433a31a2020-05-20 19:04:48 -0400923 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, nil)
khenaidoo820197c2020-02-13 16:35:33 -0500924 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -0400925 onu1FlowAndGroup := deviceRules.Rules["onu1"]
926 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidoo3306c992019-05-24 16:57:35 -0400927 assert.Equal(t, 1, onu1FlowAndGroup.Flows.Len())
khenaidood20a5852018-10-22 22:09:55 -0400928 assert.Equal(t, 0, onu1FlowAndGroup.Groups.Len())
929 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
930 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
931
932 fa1 = &fu.FlowArgs{
933 KV: fu.OfpFlowModArgs{"priority": 500},
934 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400935 fu.InPort(2),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400936 fu.TunnelId(uint64(10)),
937 fu.Metadata_ofp(4294967296001),
khenaidoo68c930b2019-05-13 11:46:51 -0400938 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400939 },
940 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400941 fu.PopVlan(),
942 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -0400943 },
944 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400945
khenaidood20a5852018-10-22 22:09:55 -0400946 derivedFlow := oltFlowAndGroup.GetFlow(0)
Scott Bakerfdea1e32020-02-21 15:35:41 -0800947 expectedOltFlow, err := fu.MkFlowStat(fa1)
948 assert.Nil(t, err)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400949 expectedOltFlow.Instructions = []*ofp.OfpInstruction{{
950 Type: uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS),
951 Data: &ofp.OfpInstruction_Actions{
952 Actions: &ofp.OfpInstructionActions{
953 Actions: []*ofp.OfpAction{{
954 Type: 0,
955 Action: &ofp.OfpAction_Output{
956 Output: &ofp.OfpActionOutput{
957 Port: 1,
958 MaxLen: 65509,
959 },
960 }}}}}}}
961 expectedOltFlow.Id = derivedFlow.Id
khenaidood20a5852018-10-22 22:09:55 -0400962 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
963
964 fa1 = &fu.FlowArgs{
965 KV: fu.OfpFlowModArgs{"priority": 500},
966 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400967 fu.InPort(1),
968 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 101),
969 fu.VlanPcp(0),
khenaidood20a5852018-10-22 22:09:55 -0400970 },
971 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400972 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
973 fu.Output(2),
khenaidood20a5852018-10-22 22:09:55 -0400974 },
975 }
Scott Bakerfdea1e32020-02-21 15:35:41 -0800976 expectedOnu1Flow, err := fu.MkFlowStat(fa1)
977 assert.Nil(t, err)
khenaidoo3306c992019-05-24 16:57:35 -0400978 derivedFlow = onu1FlowAndGroup.GetFlow(0)
khenaidood20a5852018-10-22 22:09:55 -0400979 assert.Equal(t, expectedOnu1Flow.String(), derivedFlow.String())
980}
981
982func TestMulticastDownstreamRuleDecomposition(t *testing.T) {
npujar1d86a522019-11-14 17:11:16 +0530983 fa := &fu.FlowArgs{
khenaidood20a5852018-10-22 22:09:55 -0400984 KV: fu.OfpFlowModArgs{"priority": 500},
985 MatchFields: []*ofp.OfpOxmOfbField{
khenaidoo68c930b2019-05-13 11:46:51 -0400986 fu.InPort(10),
987 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
988 fu.VlanPcp(0),
989 fu.EthType(0x800),
990 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -0400991 },
992 Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -0400993 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -0400994 },
995 }
996
npujar1d86a522019-11-14 17:11:16 +0530997 ga := &fu.GroupArgs{
khenaidood20a5852018-10-22 22:09:55 -0400998 GroupId: 10,
999 Buckets: []*ofp.OfpBucket{
1000 {Actions: []*ofp.OfpAction{
khenaidoo68c930b2019-05-13 11:46:51 -04001001 fu.PopVlan(),
1002 fu.Output(1),
khenaidood20a5852018-10-22 22:09:55 -04001003 },
1004 },
1005 },
1006 }
1007
Scott Bakerfdea1e32020-02-21 15:35:41 -08001008 fs, err := fu.MkFlowStat(fa)
1009 assert.Nil(t, err)
Kent Hagerman433a31a2020-05-20 19:04:48 -04001010 flows := map[uint64]*ofp.OfpFlowStats{fs.Id: fs}
1011 groups := map[uint32]*ofp.OfpGroupEntry{ga.GroupId: fu.MkGroupStat(ga)}
Scott Bakerfdea1e32020-02-21 15:35:41 -08001012 tfd := newTestFlowDecomposer(t, newTestDeviceManager())
khenaidood20a5852018-10-22 22:09:55 -04001013
khenaidoo820197c2020-02-13 16:35:33 -05001014 deviceRules, err := tfd.fd.DecomposeRules(context.Background(), tfd, flows, groups)
1015 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001016 oltFlowAndGroup := deviceRules.Rules["olt"]
khenaidood20a5852018-10-22 22:09:55 -04001017 assert.Equal(t, 1, oltFlowAndGroup.Flows.Len())
1018 assert.Equal(t, 0, oltFlowAndGroup.Groups.Len())
1019
1020 fa = &fu.FlowArgs{
1021 KV: fu.OfpFlowModArgs{"priority": 500},
1022 MatchFields: []*ofp.OfpOxmOfbField{
Esin Karaman09959ae2019-11-29 13:59:58 +00001023 fu.InPort(10),
khenaidoo68c930b2019-05-13 11:46:51 -04001024 fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 170),
1025 fu.VlanPcp(0),
1026 fu.EthType(0x800),
1027 fu.Ipv4Dst(0xe00a0a0a),
khenaidood20a5852018-10-22 22:09:55 -04001028 },
1029 Actions: []*ofp.OfpAction{
Esin Karaman09959ae2019-11-29 13:59:58 +00001030 fu.Group(10),
khenaidood20a5852018-10-22 22:09:55 -04001031 },
1032 }
Scott Bakerfdea1e32020-02-21 15:35:41 -08001033 expectedOltFlow, err := fu.MkFlowStat(fa)
1034 assert.Nil(t, err)
khenaidood20a5852018-10-22 22:09:55 -04001035 derivedFlow := oltFlowAndGroup.GetFlow(0)
1036 assert.Equal(t, expectedOltFlow.String(), derivedFlow.String())
khenaidood20a5852018-10-22 22:09:55 -04001037}