blob: 65b4e863e90f756880896cd3234c6d43e4b0c771 [file] [log] [blame]
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001/*
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 */
16
17package devices
18
19import (
Matteo Scandolob5913142021-03-19 16:10:18 -070020 "context"
Matteo Scandoloa8eca492021-03-23 09:45:16 -070021 "fmt"
Matteo Scandolob5913142021-03-19 16:10:18 -070022 "github.com/looplab/fsm"
Matteo Scandolof9d43412021-01-12 11:11:34 -080023 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolob5913142021-03-19 16:10:18 -070024 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo4a036262020-08-17 15:56:13 -070025 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo21195d62021-04-07 14:31:23 -070026 "github.com/opencord/voltha-protos/v4/go/openolt"
Matteo Scandoloa8eca492021-03-23 09:45:16 -070027 "github.com/stretchr/testify/assert"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070028 "net"
Matteo Scandolo21195d62021-04-07 14:31:23 -070029 "sync"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070030 "testing"
31)
32
Matteo Scandolo8a574812021-05-20 15:18:53 -070033func createMockOlt(numPon int, numOnu int, numUni int, services []ServiceIf) *OltDevice {
Shrey Baid688b4242020-07-10 20:40:10 +053034 olt := &OltDevice{
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +020035 ID: 0,
36 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
37 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
38 OmciResponseRate: 10,
Matteo Scandolo10f965c2019-09-24 10:40:46 -070039 }
40
41 for i := 0; i < numPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080042
43 // initialize the resource maps for every PON Ports
44 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
45 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
46
Matteo Scandolo10f965c2019-09-24 10:40:46 -070047 pon := PonPort{
48 ID: uint32(i),
49 }
50
51 for j := 0; j < numOnu; j++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080052
53 // initialize the resource maps for every ONU and the first UNI
54 olt.AllocIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
55 olt.GemPortIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
56
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070057 onuId := uint32(i + j)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070058 onu := Onu{
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070059 ID: onuId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070060 PonPort: &pon,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070061 PonPortID: pon.ID,
Matteo Scandolob5913142021-03-19 16:10:18 -070062 InternalState: fsm.NewFSM(
63 OnuStateCreated,
64 // this is fake state machine, we don't care about transition in the OLT
65 // unit tests, we'll use SetState to emulate cases
66 fsm.Events{
67 {Name: OnuTxEnable, Src: []string{}, Dst: OnuStateEnabled},
68 {Name: OnuTxDisable, Src: []string{}, Dst: OnuStateDisabled},
69 },
70 fsm.Callbacks{},
71 ),
72 Channel: make(chan bbsim.Message, 2048),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070073 }
Matteo Scandolo4a036262020-08-17 15:56:13 -070074
Mahir Gunyela1753ae2021-06-23 00:24:56 -070075 for k := 0; k < numUni; k++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -070076 uni := UniPort{
77 ID: uint32(k + 1),
78 Onu: &onu,
79 logger: uniLogger,
80 }
81 for l, s := range services {
82 service := s.(*Service)
83 service.HwAddress = net.HardwareAddr{0x2e, byte(olt.ID), byte(pon.ID), byte(onuId), byte(k), byte(l)}
84 service.UniPort = &uni
85 uni.Services = append(uni.Services, service)
86 }
87 onu.UniPorts = append(onu.UniPorts, &uni)
Matteo Scandolo4a036262020-08-17 15:56:13 -070088 }
89
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080090 onu.SerialNumber = NewSN(olt.ID, pon.ID, onu.ID)
Matteo Scandolo27428702019-10-11 16:21:16 -070091 pon.Onus = append(pon.Onus, &onu)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070092 }
Matteo Scandolo27428702019-10-11 16:21:16 -070093 olt.Pons = append(olt.Pons, &pon)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070094 }
95 return olt
96}
97
Matteo Scandolo4a036262020-08-17 15:56:13 -070098// check the creation of an OLT with a single Service
99func TestCreateOLT(t *testing.T) {
100
101 common.Services = []common.ServiceYaml{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700102 {Name: "hsia", CTag: 900, CTagAllocation: common.TagAllocationUnique.String(), STag: 900, STagAllocation: common.TagAllocationShared.String(), NeedsEapol: true, NeedsDhcp: true, NeedsIgmp: true},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103 }
104
105 common.Config = &common.GlobalConfig{
106 Olt: common.OltConfig{
107 ID: 1,
108 PonPorts: 2,
109 OnusPonPort: 2,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700110 UniPorts: 4,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700111 },
112 }
113
114 olt := CreateOLT(*common.Config, common.Services, true)
115
116 assert.Equal(t, len(olt.Pons), int(common.Config.Olt.PonPorts))
117
118 // count the ONUs
119 onus := 0
120 for _, p := range olt.Pons {
121 onus = onus + len(p.Onus)
122 }
123
124 assert.Equal(t, onus, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort))
125
Matteo Scandolo8a574812021-05-20 15:18:53 -0700126 // counte the UNIs
127 unis := 0
128 for _, p := range olt.Pons {
129 for _, o := range p.Onus {
130 unis = unis + len(o.UniPorts)
131 }
132 }
133 // NOTE when unis will be configurable this test will need to adapt
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700134 assert.Equal(t, unis, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort*common.Config.Olt.UniPorts))
Matteo Scandolo8a574812021-05-20 15:18:53 -0700135
Matteo Scandolo4a036262020-08-17 15:56:13 -0700136 // count the services
137 services := 0
138 for _, p := range olt.Pons {
139 for _, o := range p.Onus {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700140 for _, u := range o.UniPorts {
141 uni := u.(*UniPort)
142 services = services + len(uni.Services)
143 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700144 }
145 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700146 // NOTE when unis will be configurable this test will need to adapt
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700147 assert.Equal(t, services, int(common.Config.Olt.PonPorts)*int(common.Config.Olt.OnusPonPort)*int(common.Config.Olt.UniPorts)*len(common.Services))
Matteo Scandolo4a036262020-08-17 15:56:13 -0700148
Matteo Scandolo8a574812021-05-20 15:18:53 -0700149 s1 := olt.Pons[0].Onus[0].UniPorts[0].(*UniPort).Services[0].(*Service)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700150
151 assert.Equal(t, s1.Name, "hsia")
152 assert.Equal(t, s1.CTag, 900)
153 assert.Equal(t, s1.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700154 assert.Equal(t, "2e:01:00:01:00:00", s1.HwAddress.String())
Matteo Scandolo4a036262020-08-17 15:56:13 -0700155 assert.Equal(t, olt.Pons[0].Onus[0].ID, uint32(1))
156
Matteo Scandolo8a574812021-05-20 15:18:53 -0700157 // each ONU has 4 UNIs, taking up the c-tags
158 s2 := olt.Pons[0].Onus[1].UniPorts[0].(*UniPort).Services[0].(*Service)
159 assert.Equal(t, s2.CTag, 904)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700160 assert.Equal(t, s2.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700161 assert.Equal(t, s2.HwAddress.String(), "2e:01:00:02:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700162 assert.Equal(t, olt.Pons[0].Onus[1].ID, uint32(2))
163
Matteo Scandolo8a574812021-05-20 15:18:53 -0700164 s3 := olt.Pons[1].Onus[0].UniPorts[0].(*UniPort).Services[0].(*Service)
165 assert.Equal(t, s3.CTag, 908)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700166 assert.Equal(t, s3.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700167 assert.Equal(t, s3.HwAddress.String(), "2e:01:01:01:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700168 assert.Equal(t, olt.Pons[1].Onus[0].ID, uint32(1))
169
Matteo Scandolo8a574812021-05-20 15:18:53 -0700170 s4 := olt.Pons[1].Onus[1].UniPorts[0].(*UniPort).Services[0].(*Service)
171 assert.Equal(t, s4.CTag, 912)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700172 assert.Equal(t, s4.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700173 assert.Equal(t, s4.HwAddress.String(), "2e:01:01:02:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700174 assert.Equal(t, olt.Pons[1].Onus[1].ID, uint32(2))
175}
176
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700177func Test_Olt_FindOnuBySn_Success(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700178
179 numPon := 4
180 numOnu := 4
181
Matteo Scandolo8a574812021-05-20 15:18:53 -0700182 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700183
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700184 onu, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700185
186 assert.Equal(t, err, nil)
187 assert.Equal(t, onu.Sn(), "BBSM00000303")
188 assert.Equal(t, onu.ID, uint32(3))
189 assert.Equal(t, onu.PonPortID, uint32(3))
190}
191
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700192func Test_Olt_FindOnuBySn_Error(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700193
194 numPon := 1
195 numOnu := 4
196
Matteo Scandolo8a574812021-05-20 15:18:53 -0700197 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700198
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700199 _, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700200
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700201 assert.Equal(t, err.Error(), "cannot-find-onu-by-serial-number-BBSM00000303")
202}
203
204func Test_Olt_FindOnuByMacAddress_Success(t *testing.T) {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700205 numPon := 4
206 numOnu := 4
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700207 numUni := 4
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700208
Matteo Scandolo4a036262020-08-17 15:56:13 -0700209 services := []ServiceIf{
210 &Service{Name: "hsia"},
211 &Service{Name: "voip"},
212 &Service{Name: "vod"},
213 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700214
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700215 olt := createMockOlt(numPon, numOnu, numUni, services)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700216
Matteo Scandolo8a574812021-05-20 15:18:53 -0700217 mac := net.HardwareAddr{0x2e, byte(olt.ID), byte(3), byte(6), byte(3), byte(1)}
Matteo Scandolo4a036262020-08-17 15:56:13 -0700218 s, err := olt.FindServiceByMacAddress(mac)
219
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700220 assert.NoError(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700221
222 service := s.(*Service)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700223
224 assert.Equal(t, err, nil)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700225 assert.Equal(t, service.UniPort.Onu.Sn(), "BBSM00000306")
226 assert.Equal(t, service.UniPort.ID, uint32(4))
227 assert.Equal(t, service.UniPort.Onu.ID, uint32(6))
228 assert.Equal(t, service.UniPort.Onu.PonPortID, uint32(3))
Matteo Scandolo4a036262020-08-17 15:56:13 -0700229
230 assert.Equal(t, service.Name, "voip")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700231}
232
233func Test_Olt_FindOnuByMacAddress_Error(t *testing.T) {
234
235 numPon := 1
236 numOnu := 4
237
Matteo Scandolo8a574812021-05-20 15:18:53 -0700238 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700239
240 mac := net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(3), byte(3)}
241
Matteo Scandolo4a036262020-08-17 15:56:13 -0700242 _, err := olt.FindServiceByMacAddress(mac)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700243
Matteo Scandolo4a036262020-08-17 15:56:13 -0700244 assert.Equal(t, err.Error(), "cannot-find-service-by-mac-address-2e:60:70:13:03:03")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700245}
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700246
247func Test_Olt_GetOnuByFlowId(t *testing.T) {
248 numPon := 4
249 numOnu := 4
250
Matteo Scandolo8a574812021-05-20 15:18:53 -0700251 services := []ServiceIf{
252 &Service{Name: "hsia"},
253 }
254
255 olt := createMockOlt(numPon, numOnu, 1, services)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700256
257 // Add the flows to onus (to be found)
258 onu1, _ := olt.FindOnuBySn("BBSM00000303")
259 flow1 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530260 FlowId: 64,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700261 Classifier: &openolt.Classifier{},
Matteo Scandolo8a574812021-05-20 15:18:53 -0700262 UniId: 1,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700263 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800264 msg1 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700265 OnuID: onu1.ID,
266 PonPortID: onu1.PonPortID,
267 Flow: &flow1,
268 }
269 onu1.handleFlowAdd(msg1)
270
271 onu2, _ := olt.FindOnuBySn("BBSM00000103")
272 flow2 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530273 FlowId: 72,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700274 Classifier: &openolt.Classifier{},
Matteo Scandolo8a574812021-05-20 15:18:53 -0700275 UniId: 1,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700276 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800277 msg2 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700278 OnuID: onu2.ID,
279 PonPortID: onu2.PonPortID,
280 Flow: &flow2,
281 }
282 onu2.handleFlowAdd(msg2)
283
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700284 found, err := olt.GetOnuByFlowId(flow1.FlowId)
285
286 assert.Equal(t, err, nil)
287 assert.Equal(t, found.Sn(), onu1.Sn())
Shrey Baid688b4242020-07-10 20:40:10 +0530288}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800289
290func Test_Olt_storeGemPortId(t *testing.T) {
291
292 const (
293 pon = 1
294 onu = 1
295 uni = 16
296 gem1 = 1024
297 gem2 = 1025
298 )
299
300 numPon := 2
301 numOnu := 2
302
Matteo Scandolo8a574812021-05-20 15:18:53 -0700303 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800304
305 // add a first flow on the ONU
306 flow1 := &openolt.Flow{
307 AccessIntfId: pon,
308 OnuId: onu,
309 PortNo: uni,
310 FlowId: 1,
311 GemportId: gem1,
312 }
313
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700314 olt.storeGemPortIdByFlow(flow1)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800315 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
316 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing it
317
318 // add a second flow on the ONU (same gem)
319 flow2 := &openolt.Flow{
320 AccessIntfId: pon,
321 OnuId: onu,
322 PortNo: uni,
323 FlowId: 2,
324 GemportId: gem1,
325 }
326
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700327 olt.storeGemPortIdByFlow(flow2)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800328 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
329 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // and two flows referencing it
330
331 // add a third flow on the ONU (different gem)
332 flow3 := &openolt.Flow{
333 AccessIntfId: pon,
334 OnuId: onu,
335 PortNo: uni,
336 FlowId: 2,
337 GemportId: 1025,
338 }
339
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700340 olt.storeGemPortIdByFlow(flow3)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800341 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports
342 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // two flows referencing the first one
343 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing the second one
344}
345
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700346func Test_Olt_storeGemPortIdReplicatedFlow(t *testing.T) {
347 const (
348 pon = 1
349 onu = 1
350 uni = 16
351 gem1 = 1024
352 gem2 = 1025
353 )
354
355 numPon := 2
356 numOnu := 2
357
Matteo Scandolo8a574812021-05-20 15:18:53 -0700358 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700359
360 // add a flow that needs replication
361 pbitToGemPortMap := make(map[uint32]uint32)
362 pbitToGemPortMap[0] = gem1
363 pbitToGemPortMap[1] = gem2
364 flow1 := &openolt.Flow{
365 AccessIntfId: pon,
366 OnuId: onu,
367 PortNo: uni,
368 FlowId: 1,
369 GemportId: 0,
370 ReplicateFlow: true,
371 PbitToGemport: pbitToGemPortMap,
372 }
373
374 olt.storeGemPortIdByFlow(flow1)
375 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports in the flow
376 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing them
377 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing them
378}
379
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800380func Test_Olt_freeGemPortId(t *testing.T) {
381 const (
382 pon = 1
383 onu = 1
384 uni = 16
385 gem1 = 1024
386 gem2 = 1025
387 flow1 = 1
388 flow2 = 2
389 flow3 = 3
390 )
391
392 numPon := 2
393 numOnu := 2
394
Matteo Scandolo8a574812021-05-20 15:18:53 -0700395 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800396
397 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
398 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
399 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
400 olt.GemPortIDs[pon][onu][uni][gem1][flow2] = true
401 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
402 olt.GemPortIDs[pon][onu][uni][gem2][flow3] = true
403
404 // remove one flow on the first gem, check that the gem is still allocated as there is still a flow referencing it
405 // NOTE that the flow remove only carries the flow ID, no other information
406 flowGem1 := &openolt.Flow{
407 FlowId: flow1,
408 }
409
410 olt.freeGemPortId(flowGem1)
411 // we still have two unis in the map
412 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2)
413
414 // we should now have a single gem referenced on this UNI
415 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1, "gemport-not-removed")
416
417 // the gem should still reference flow 2
418 assert.Equal(t, olt.GemPortIDs[pon][onu][uni][gem1][flow2], true)
419 // but should not reference flow1
420 _, flow1Exists := olt.GemPortIDs[pon][onu][uni][gem1][flow1]
421 assert.Equal(t, flow1Exists, false)
422
423 // this is the only flow remaining on this gem, the gem should be removed
424 flowGem2 := &openolt.Flow{
425 FlowId: flow2,
426 }
427 olt.freeGemPortId(flowGem2)
428
429 // we should now have a single gem referenced on this UNI
430 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1, "gemport-not-removed")
431
432 // and it should be gem2
433 _, gem1exists := olt.GemPortIDs[pon][onu][uni][gem1]
434 assert.Equal(t, gem1exists, false)
435 _, gem2exists := olt.GemPortIDs[pon][onu][uni][gem2]
436 assert.Equal(t, gem2exists, true)
437}
438
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700439func Test_Olt_freeGemPortIdReplicatedflow(t *testing.T) {
440 const (
441 pon = 1
442 onu = 1
443 uni = 16
444 gem1 = 1024
445 gem2 = 1025
446 flow1 = 1
447 )
448
449 numPon := 2
450 numOnu := 2
451
Matteo Scandolo8a574812021-05-20 15:18:53 -0700452 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700453
454 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
455 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
456 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
457 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
458 olt.GemPortIDs[pon][onu][uni][gem2][flow1] = true
459
460 // this flow was a replicated flow, remove all the gems that are referenced by that flow
461 flowMultiGem := &openolt.Flow{
462 FlowId: flow1,
463 }
464
465 olt.freeGemPortId(flowMultiGem)
466
467 // this flow removes all the gems, so no UNI should be left
468 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 0)
469}
470
Matteo Scandolo21195d62021-04-07 14:31:23 -0700471// testing that we can validate flows while we are adding them
472func Benchmark_validateAndAddFlows(b *testing.B) {
473 const (
474 pon = 0
475 start = 0
476 end = 512
477 )
478
479 for r := 0; r < b.N; r++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700480 olt := createMockOlt(1, 512, 4, []ServiceIf{})
Matteo Scandolo21195d62021-04-07 14:31:23 -0700481
482 wg := sync.WaitGroup{}
483
484 // concurrently adding 1K gems
485 for i := start; i < end; i++ {
486 wg.Add(1)
487 flow := &openolt.Flow{
488 AccessIntfId: pon,
489 OnuId: int32(i),
490 PortNo: uint32(i),
491 GemportId: int32(i),
492 FlowId: uint64(i),
493 }
494 go func(wg *sync.WaitGroup) {
495 olt.storeGemPortIdByFlow(flow)
496 olt.storeAllocId(flow)
497 wg.Done()
498 }(&wg)
499 }
500
501 // at the same time validate flows
502 for i := start; i < end; i++ {
503 wg.Add(1)
504 flow := &openolt.Flow{
505 AccessIntfId: pon,
506 OnuId: int32(i),
507 PortNo: uint32(i),
508 GemportId: 1,
509 FlowId: uint64(i),
510 }
511 go func(wg *sync.WaitGroup) {
512 _ = olt.validateFlow(flow)
513 wg.Done()
514 }(&wg)
515 }
516
517 wg.Wait()
518 // NOTE this tests only fails if there is concurrent access to the map
519 }
520}
521
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800522func Test_Olt_validateFlow(t *testing.T) {
523
524 const (
525 pon0 = 0
526 pon1 = 1
527 onu0 = 0
528 onu1 = 1
529 uniPort = 0
530 usedGemIdPon0 = 1024
531 usedGemIdPon1 = 1025
532 usedAllocIdPon0 = 1
533 usedAllocIdPon1 = 2
534 flowId = 1
535 )
536
537 numPon := 2
538 numOnu := 2
539
Matteo Scandolo8a574812021-05-20 15:18:53 -0700540 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800541
542 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
543 olt.GemPortIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
544
545 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0] = make(map[uint64]bool)
546 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0][flowId] = true
547 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1] = make(map[uint64]bool)
548 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1][flowId] = true
549
550 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
551 olt.AllocIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
552 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
553 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
554 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1] = make(map[uint64]bool)
555 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1][flowId] = true
556
557 // a GemPortID can be referenced across multiple flows on the same ONU
558 validGemFlow := &openolt.Flow{
559 AccessIntfId: pon0,
560 OnuId: onu0,
561 GemportId: usedGemIdPon0,
562 }
563
564 err := olt.validateFlow(validGemFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700565 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800566
567 // a GemPortID can NOT be referenced across different ONUs on the same PON
568 invalidGemFlow := &openolt.Flow{
569 AccessIntfId: pon0,
570 OnuId: onu1,
571 GemportId: usedGemIdPon0,
572 }
573 err = olt.validateFlow(invalidGemFlow)
574 assert.Error(t, err, "gem-1024-already-in-use-on-uni-0-onu-0")
575
576 // if a flow reference the same GEM on a different PON it's a valid flow
577 invalidGemDifferentPonFlow := &openolt.Flow{
578 AccessIntfId: pon1,
579 OnuId: onu1,
580 GemportId: usedGemIdPon0,
581 }
582 err = olt.validateFlow(invalidGemDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700583 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800584
585 // an allocId can be referenced across multiple flows on the same ONU
586 validAllocFlow := &openolt.Flow{
587 AccessIntfId: pon0,
588 OnuId: onu0,
589 AllocId: usedAllocIdPon0,
590 }
591 err = olt.validateFlow(validAllocFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700592 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800593
594 // an allocId can NOT be referenced across different ONUs on the same PON
595 invalidAllocFlow := &openolt.Flow{
596 AccessIntfId: pon0,
597 OnuId: onu1,
598 AllocId: usedAllocIdPon0,
599 }
600 err = olt.validateFlow(invalidAllocFlow)
601 assert.Error(t, err, "allocId-1-already-in-use-on-uni-0-onu-0")
602
603 // if a flow reference the same AllocId on a different PON it's a valid flow
604 invalidAllocDifferentPonFlow := &openolt.Flow{
605 AccessIntfId: pon1,
606 OnuId: onu1,
607 AllocId: usedAllocIdPon0,
608 }
609 err = olt.validateFlow(invalidAllocDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700610 assert.NoError(t, err)
611}
612
613func Test_Olt_validateReplicatedFlow(t *testing.T) {
614
615 const (
616 pon0 = 0
617 onu0 = 0
618 onu1 = 1
619 uniPort = 0
620 usedGemId1 = 1024
621 usedGemId2 = 1025
622 usedAllocIdPon0 = 1
623 flowId = 1
624 )
625
626 numPon := 1
627 numOnu := 1
628
Matteo Scandolo8a574812021-05-20 15:18:53 -0700629 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700630
631 // both the gemports referenced in this flow are already allocated
632 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
633 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1] = make(map[uint64]bool)
634 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1][flowId] = true
635 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2] = make(map[uint64]bool)
636 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2][flowId] = true
637
638 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
639 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
640 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
641
642 pbitToGemPortMap := make(map[uint32]uint32)
643 pbitToGemPortMap[0] = usedGemId1
644 pbitToGemPortMap[1] = usedGemId2
645
646 // this flow should fail vlidation as the gems are already allocated to Onu0
647 invalidGemFlow := &openolt.Flow{
648 AccessIntfId: pon0,
649 OnuId: onu1,
650 PortNo: uniPort,
651 GemportId: 0,
652 ReplicateFlow: true,
653 PbitToGemport: pbitToGemPortMap,
654 }
655
656 err := olt.validateFlow(invalidGemFlow)
657 assert.NotNil(t, err)
658
659 // PbitToGemport is a map, so any of the two gemPorts can fail first and determine the error message
660 foundError := false
661 switch err.Error() {
662 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId2, uniPort, onu0, invalidGemFlow.FlowId):
663 foundError = true
664 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId1, uniPort, onu0, invalidGemFlow.FlowId):
665 foundError = true
666
667 }
668 assert.True(t, foundError)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800669}
Matteo Scandolob5913142021-03-19 16:10:18 -0700670
671func Test_Olt_OmciMsgOut(t *testing.T) {
672 numPon := 4
673 numOnu := 4
674
Matteo Scandolo8a574812021-05-20 15:18:53 -0700675 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolob5913142021-03-19 16:10:18 -0700676
677 // a malformed packet should return an error
678 msg := &openolt.OmciMsg{
679 IntfId: 1,
680 OnuId: 1,
681 Pkt: []byte{},
682 }
683 ctx := context.TODO()
684 _, err := olt.OmciMsgOut(ctx, msg)
685 assert.Error(t, err, "olt-received-malformed-omci-packet")
686
687 // a correct packet for a non exiting ONU should throw an error
688 msg = &openolt.OmciMsg{
689 IntfId: 10,
690 OnuId: 25,
691 Pkt: makeOmciSetRequest(t),
692 }
693 _, err = olt.OmciMsgOut(ctx, msg)
694 assert.Error(t, err, "Cannot find PonPort with id 10 in OLT 0")
695
696 // a correct packet for a disabled ONU should be dropped
697 // note that an error is not returned, this is valid in BBsim
698 const (
699 ponId = 1
700 onuId = 1
701 )
702 pon, _ := olt.GetPonById(ponId)
703 onu, _ := pon.GetOnuById(onuId)
704 onu.InternalState.SetState(OnuStateDisabled)
705 msg = &openolt.OmciMsg{
706 IntfId: ponId,
707 OnuId: onuId,
708 Pkt: makeOmciSetRequest(t),
709 }
710 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700711 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700712 assert.Equal(t, len(onu.Channel), 0) // check that no messages have been sent
713
714 // test that the ONU receives a valid packet
715 onu.InternalState.SetState(OnuStateEnabled)
716 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700717 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700718 assert.Equal(t, len(onu.Channel), 1) // check that one message have been sent
719
720}