blob: 58714da9018ad46c63c31fa0a1a6a63917405b06 [file] [log] [blame]
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001/*
Joey Armstrong14628cd2023-01-10 08:38:31 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo10f965c2019-09-24 10:40:46 -07003
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"
Elia Battistonb7bea222022-02-18 16:25:00 +010022 "net"
23 "sync"
24 "testing"
25
Matteo Scandolob5913142021-03-19 16:10:18 -070026 "github.com/looplab/fsm"
Matteo Scandolof9d43412021-01-12 11:11:34 -080027 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolob5913142021-03-19 16:10:18 -070028 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo4a036262020-08-17 15:56:13 -070029 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000030 "github.com/opencord/voltha-protos/v5/go/openolt"
Matteo Scandoloa8eca492021-03-23 09:45:16 -070031 "github.com/stretchr/testify/assert"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070032)
33
Matteo Scandolo8a574812021-05-20 15:18:53 -070034func createMockOlt(numPon int, numOnu int, numUni int, services []ServiceIf) *OltDevice {
Shrey Baid688b4242020-07-10 20:40:10 +053035 olt := &OltDevice{
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +020036 ID: 0,
37 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
38 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
39 OmciResponseRate: 10,
Matteo Scandolo10f965c2019-09-24 10:40:46 -070040 }
41
42 for i := 0; i < numPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080043
44 // initialize the resource maps for every PON Ports
45 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
46 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
47
Matteo Scandolo10f965c2019-09-24 10:40:46 -070048 pon := PonPort{
49 ID: uint32(i),
50 }
51
52 for j := 0; j < numOnu; j++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080053
54 // initialize the resource maps for every ONU and the first UNI
55 olt.AllocIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
56 olt.GemPortIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
57
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070058 onuId := uint32(i + j)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070059 onu := Onu{
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070060 ID: onuId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070061 PonPort: &pon,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070062 PonPortID: pon.ID,
Matteo Scandolob5913142021-03-19 16:10:18 -070063 InternalState: fsm.NewFSM(
64 OnuStateCreated,
65 // this is fake state machine, we don't care about transition in the OLT
66 // unit tests, we'll use SetState to emulate cases
67 fsm.Events{
68 {Name: OnuTxEnable, Src: []string{}, Dst: OnuStateEnabled},
69 {Name: OnuTxDisable, Src: []string{}, Dst: OnuStateDisabled},
70 },
71 fsm.Callbacks{},
72 ),
73 Channel: make(chan bbsim.Message, 2048),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070074 }
Matteo Scandolo4a036262020-08-17 15:56:13 -070075
Mahir Gunyela1753ae2021-06-23 00:24:56 -070076 for k := 0; k < numUni; k++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -070077 uni := UniPort{
78 ID: uint32(k + 1),
79 Onu: &onu,
80 logger: uniLogger,
81 }
82 for l, s := range services {
83 service := s.(*Service)
84 service.HwAddress = net.HardwareAddr{0x2e, byte(olt.ID), byte(pon.ID), byte(onuId), byte(k), byte(l)}
85 service.UniPort = &uni
86 uni.Services = append(uni.Services, service)
87 }
88 onu.UniPorts = append(onu.UniPorts, &uni)
Matteo Scandolo4a036262020-08-17 15:56:13 -070089 }
90
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080091 onu.SerialNumber = NewSN(olt.ID, pon.ID, onu.ID)
Matteo Scandolo27428702019-10-11 16:21:16 -070092 pon.Onus = append(pon.Onus, &onu)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070093 }
Matteo Scandolo27428702019-10-11 16:21:16 -070094 olt.Pons = append(olt.Pons, &pon)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070095 }
96 return olt
97}
98
Matteo Scandolo4a036262020-08-17 15:56:13 -070099// check the creation of an OLT with a single Service
100func TestCreateOLT(t *testing.T) {
101
102 common.Services = []common.ServiceYaml{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700103 {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 -0700104 }
105
106 common.Config = &common.GlobalConfig{
107 Olt: common.OltConfig{
108 ID: 1,
109 PonPorts: 2,
110 OnusPonPort: 2,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700111 UniPorts: 4,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112 },
113 }
114
Elia Battistonb7bea222022-02-18 16:25:00 +0100115 allocIdPerOnu := uint32(common.Config.Olt.UniPorts * uint32(len(common.Services)))
116 common.PonsConfig = &common.PonPortsConfig{
117 Number: common.Config.Olt.PonPorts,
118 Ranges: []common.PonRangeConfig{
119 {
120 PonRange: common.IdRange{StartId: 0, EndId: common.Config.Olt.PonPorts - 1},
121 Technology: common.XGSPON.String(),
122 OnuRange: common.IdRange{StartId: 1, EndId: 1 + (common.Config.Olt.OnusPonPort - 1)},
123 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1024 + (common.Config.Olt.OnusPonPort * allocIdPerOnu)},
124 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + common.Config.Olt.OnusPonPort*allocIdPerOnu*8},
125 },
126 },
127 }
128
Matteo Scandolo4a036262020-08-17 15:56:13 -0700129 olt := CreateOLT(*common.Config, common.Services, true)
130
131 assert.Equal(t, len(olt.Pons), int(common.Config.Olt.PonPorts))
132
133 // count the ONUs
134 onus := 0
135 for _, p := range olt.Pons {
136 onus = onus + len(p.Onus)
137 }
138
139 assert.Equal(t, onus, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort))
140
Matteo Scandolo8a574812021-05-20 15:18:53 -0700141 // counte the UNIs
142 unis := 0
143 for _, p := range olt.Pons {
144 for _, o := range p.Onus {
145 unis = unis + len(o.UniPorts)
146 }
147 }
148 // NOTE when unis will be configurable this test will need to adapt
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700149 assert.Equal(t, unis, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort*common.Config.Olt.UniPorts))
Matteo Scandolo8a574812021-05-20 15:18:53 -0700150
Matteo Scandolo4a036262020-08-17 15:56:13 -0700151 // count the services
152 services := 0
153 for _, p := range olt.Pons {
154 for _, o := range p.Onus {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700155 for _, u := range o.UniPorts {
156 uni := u.(*UniPort)
157 services = services + len(uni.Services)
158 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700159 }
160 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700161 // NOTE when unis will be configurable this test will need to adapt
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700162 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 -0700163
Matteo Scandolo8a574812021-05-20 15:18:53 -0700164 s1 := olt.Pons[0].Onus[0].UniPorts[0].(*UniPort).Services[0].(*Service)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700165
166 assert.Equal(t, s1.Name, "hsia")
167 assert.Equal(t, s1.CTag, 900)
168 assert.Equal(t, s1.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700169 assert.Equal(t, "2e:01:00:01:00:00", s1.HwAddress.String())
Matteo Scandolo4a036262020-08-17 15:56:13 -0700170 assert.Equal(t, olt.Pons[0].Onus[0].ID, uint32(1))
171
Matteo Scandolo8a574812021-05-20 15:18:53 -0700172 // each ONU has 4 UNIs, taking up the c-tags
173 s2 := olt.Pons[0].Onus[1].UniPorts[0].(*UniPort).Services[0].(*Service)
174 assert.Equal(t, s2.CTag, 904)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700175 assert.Equal(t, s2.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700176 assert.Equal(t, s2.HwAddress.String(), "2e:01:00:02:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700177 assert.Equal(t, olt.Pons[0].Onus[1].ID, uint32(2))
178
Matteo Scandolo8a574812021-05-20 15:18:53 -0700179 s3 := olt.Pons[1].Onus[0].UniPorts[0].(*UniPort).Services[0].(*Service)
180 assert.Equal(t, s3.CTag, 908)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700181 assert.Equal(t, s3.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700182 assert.Equal(t, s3.HwAddress.String(), "2e:01:01:01:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700183 assert.Equal(t, olt.Pons[1].Onus[0].ID, uint32(1))
184
Matteo Scandolo8a574812021-05-20 15:18:53 -0700185 s4 := olt.Pons[1].Onus[1].UniPorts[0].(*UniPort).Services[0].(*Service)
186 assert.Equal(t, s4.CTag, 912)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700187 assert.Equal(t, s4.STag, 900)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700188 assert.Equal(t, s4.HwAddress.String(), "2e:01:01:02:00:00")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700189 assert.Equal(t, olt.Pons[1].Onus[1].ID, uint32(2))
190}
191
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800192func TestGetDeviceInfo(t *testing.T) {
193
194 var onusPerPon uint32 = 4
195
196 common.Services = []common.ServiceYaml{
197 {Name: "hsia", CTag: 900, CTagAllocation: common.TagAllocationUnique.String(), STag: 900, STagAllocation: common.TagAllocationShared.String(), NeedsEapol: true, NeedsDhcp: true, NeedsIgmp: true},
198 }
199
200 common.Config = &common.GlobalConfig{
201 Olt: common.OltConfig{
202 ID: 1,
203 PonPorts: 2,
204 OnusPonPort: onusPerPon,
205 UniPorts: 4,
206 },
207 }
208
Elia Battistonb7bea222022-02-18 16:25:00 +0100209 common.PonsConfig = &common.PonPortsConfig{
210 Number: 16,
211 Ranges: []common.PonRangeConfig{
212 {
213 PonRange: common.IdRange{StartId: 0, EndId: 1},
214 Technology: common.XGSPON.String(),
215 OnuRange: common.IdRange{StartId: 1, EndId: 4},
216 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1024 + 4},
217 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
218 },
219 {
220 PonRange: common.IdRange{StartId: 2, EndId: 2},
221 Technology: common.GPON.String(),
222 OnuRange: common.IdRange{StartId: 1, EndId: 4},
223 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
224 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
225 },
226 {
227 PonRange: common.IdRange{StartId: 3, EndId: 3},
228 Technology: common.XGSPON.String(),
229 OnuRange: common.IdRange{StartId: 1, EndId: 4},
230 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
231 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
232 },
233 {
234 PonRange: common.IdRange{StartId: 4, EndId: 6},
235 Technology: common.XGSPON.String(),
236 OnuRange: common.IdRange{StartId: 1, EndId: 4},
237 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
238 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
239 },
240 {
241 PonRange: common.IdRange{StartId: 7, EndId: 8},
242 Technology: common.XGSPON.String(),
243 OnuRange: common.IdRange{StartId: 1, EndId: 4},
244 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
245 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
246 },
247 {
248 PonRange: common.IdRange{StartId: 9, EndId: 9},
249 Technology: common.GPON.String(),
250 OnuRange: common.IdRange{StartId: 1, EndId: 4},
251 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
252 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
253 },
254 {
255 PonRange: common.IdRange{StartId: 10, EndId: 10},
256 Technology: common.GPON.String(),
257 OnuRange: common.IdRange{StartId: 1, EndId: 4},
258 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
259 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
260 },
261 {
262 PonRange: common.IdRange{StartId: 11, EndId: 15},
263 Technology: common.XGSPON.String(),
264 OnuRange: common.IdRange{StartId: 1, EndId: 4},
265 AllocIdRange: common.IdRange{StartId: 1024, EndId: 1028 + 4},
266 GemportRange: common.IdRange{StartId: 1024, EndId: 1024 + 32},
267 },
268 },
269 }
270
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800271 olt := CreateOLT(*common.Config, common.Services, true)
272
273 res, err := olt.GetDeviceInfo(context.Background(), &openolt.Empty{})
274
275 assert.NoError(t, err, "GetDeviceInfo returned error")
276
Elia Battistonb7bea222022-02-18 16:25:00 +0100277 assert.Equal(t, len(res.Ranges), len(common.PonsConfig.Ranges))
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800278
Elia Battistonb7bea222022-02-18 16:25:00 +0100279 for _, resRange := range res.Ranges {
280 for _, ponId := range resRange.IntfIds {
281 conf, err := common.GetPonConfigById(ponId)
282 assert.NoError(t, err, fmt.Sprintf("Cannot get pon configuration by id %d", ponId))
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800283
Elia Battistonb7bea222022-02-18 16:25:00 +0100284 for _, pool := range resRange.Pools {
285 switch pool.Type {
286 case openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID:
287 assert.Equal(t, pool.Start, conf.OnuRange.StartId)
288 assert.Equal(t, pool.End, conf.OnuRange.EndId)
289 case openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID:
290 assert.Equal(t, pool.Start, conf.AllocIdRange.StartId)
291 assert.Equal(t, pool.End, conf.AllocIdRange.EndId)
292 case openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID:
293 assert.Equal(t, pool.Start, conf.GemportRange.StartId)
294 assert.Equal(t, pool.End, conf.GemportRange.EndId)
295 }
296 }
297 }
298 }
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800299}
300
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700301func Test_Olt_FindOnuBySn_Success(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700302
303 numPon := 4
304 numOnu := 4
305
Matteo Scandolo8a574812021-05-20 15:18:53 -0700306 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700307
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700308 onu, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700309
310 assert.Equal(t, err, nil)
311 assert.Equal(t, onu.Sn(), "BBSM00000303")
312 assert.Equal(t, onu.ID, uint32(3))
313 assert.Equal(t, onu.PonPortID, uint32(3))
314}
315
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700316func Test_Olt_FindOnuBySn_Error(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700317
318 numPon := 1
319 numOnu := 4
320
Matteo Scandolo8a574812021-05-20 15:18:53 -0700321 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700322
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700323 _, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700324
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700325 assert.Equal(t, err.Error(), "cannot-find-onu-by-serial-number-BBSM00000303")
326}
327
328func Test_Olt_FindOnuByMacAddress_Success(t *testing.T) {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700329 numPon := 4
330 numOnu := 4
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700331 numUni := 4
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700332
Matteo Scandolo4a036262020-08-17 15:56:13 -0700333 services := []ServiceIf{
334 &Service{Name: "hsia"},
335 &Service{Name: "voip"},
336 &Service{Name: "vod"},
337 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700338
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700339 olt := createMockOlt(numPon, numOnu, numUni, services)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700340
Matteo Scandolo8a574812021-05-20 15:18:53 -0700341 mac := net.HardwareAddr{0x2e, byte(olt.ID), byte(3), byte(6), byte(3), byte(1)}
Matteo Scandolo4a036262020-08-17 15:56:13 -0700342 s, err := olt.FindServiceByMacAddress(mac)
343
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700344 assert.NoError(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700345
346 service := s.(*Service)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700347
348 assert.Equal(t, err, nil)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700349 assert.Equal(t, service.UniPort.Onu.Sn(), "BBSM00000306")
350 assert.Equal(t, service.UniPort.ID, uint32(4))
351 assert.Equal(t, service.UniPort.Onu.ID, uint32(6))
352 assert.Equal(t, service.UniPort.Onu.PonPortID, uint32(3))
Matteo Scandolo4a036262020-08-17 15:56:13 -0700353
354 assert.Equal(t, service.Name, "voip")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700355}
356
357func Test_Olt_FindOnuByMacAddress_Error(t *testing.T) {
358
359 numPon := 1
360 numOnu := 4
361
Matteo Scandolo8a574812021-05-20 15:18:53 -0700362 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700363
364 mac := net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(3), byte(3)}
365
Matteo Scandolo4a036262020-08-17 15:56:13 -0700366 _, err := olt.FindServiceByMacAddress(mac)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700367
Matteo Scandolo4a036262020-08-17 15:56:13 -0700368 assert.Equal(t, err.Error(), "cannot-find-service-by-mac-address-2e:60:70:13:03:03")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700369}
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700370
371func Test_Olt_GetOnuByFlowId(t *testing.T) {
372 numPon := 4
373 numOnu := 4
374
Matteo Scandolo8a574812021-05-20 15:18:53 -0700375 services := []ServiceIf{
376 &Service{Name: "hsia"},
377 }
378
379 olt := createMockOlt(numPon, numOnu, 1, services)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700380
381 // Add the flows to onus (to be found)
382 onu1, _ := olt.FindOnuBySn("BBSM00000303")
383 flow1 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530384 FlowId: 64,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700385 Classifier: &openolt.Classifier{},
Matteo Scandolo8a574812021-05-20 15:18:53 -0700386 UniId: 1,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700387 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800388 msg1 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700389 OnuID: onu1.ID,
390 PonPortID: onu1.PonPortID,
391 Flow: &flow1,
392 }
393 onu1.handleFlowAdd(msg1)
394
395 onu2, _ := olt.FindOnuBySn("BBSM00000103")
396 flow2 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530397 FlowId: 72,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700398 Classifier: &openolt.Classifier{},
Matteo Scandolo8a574812021-05-20 15:18:53 -0700399 UniId: 1,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700400 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800401 msg2 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700402 OnuID: onu2.ID,
403 PonPortID: onu2.PonPortID,
404 Flow: &flow2,
405 }
406 onu2.handleFlowAdd(msg2)
407
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700408 found, err := olt.GetOnuByFlowId(flow1.FlowId)
409
410 assert.Equal(t, err, nil)
411 assert.Equal(t, found.Sn(), onu1.Sn())
Shrey Baid688b4242020-07-10 20:40:10 +0530412}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800413
414func Test_Olt_storeGemPortId(t *testing.T) {
415
416 const (
417 pon = 1
418 onu = 1
419 uni = 16
420 gem1 = 1024
421 gem2 = 1025
422 )
423
424 numPon := 2
425 numOnu := 2
426
Matteo Scandolo8a574812021-05-20 15:18:53 -0700427 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800428
429 // add a first flow on the ONU
430 flow1 := &openolt.Flow{
431 AccessIntfId: pon,
432 OnuId: onu,
433 PortNo: uni,
434 FlowId: 1,
435 GemportId: gem1,
436 }
437
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700438 olt.storeGemPortIdByFlow(flow1)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800439 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
440 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing it
441
442 // add a second flow on the ONU (same gem)
443 flow2 := &openolt.Flow{
444 AccessIntfId: pon,
445 OnuId: onu,
446 PortNo: uni,
447 FlowId: 2,
448 GemportId: gem1,
449 }
450
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700451 olt.storeGemPortIdByFlow(flow2)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800452 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
453 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // and two flows referencing it
454
455 // add a third flow on the ONU (different gem)
456 flow3 := &openolt.Flow{
457 AccessIntfId: pon,
458 OnuId: onu,
459 PortNo: uni,
460 FlowId: 2,
461 GemportId: 1025,
462 }
463
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700464 olt.storeGemPortIdByFlow(flow3)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800465 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports
466 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // two flows referencing the first one
467 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing the second one
468}
469
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700470func Test_Olt_storeGemPortIdReplicatedFlow(t *testing.T) {
471 const (
472 pon = 1
473 onu = 1
474 uni = 16
475 gem1 = 1024
476 gem2 = 1025
477 )
478
479 numPon := 2
480 numOnu := 2
481
Matteo Scandolo8a574812021-05-20 15:18:53 -0700482 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700483
484 // add a flow that needs replication
485 pbitToGemPortMap := make(map[uint32]uint32)
486 pbitToGemPortMap[0] = gem1
487 pbitToGemPortMap[1] = gem2
488 flow1 := &openolt.Flow{
489 AccessIntfId: pon,
490 OnuId: onu,
491 PortNo: uni,
492 FlowId: 1,
493 GemportId: 0,
494 ReplicateFlow: true,
495 PbitToGemport: pbitToGemPortMap,
496 }
497
498 olt.storeGemPortIdByFlow(flow1)
499 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports in the flow
500 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing them
501 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing them
502}
503
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800504func Test_Olt_freeGemPortId(t *testing.T) {
505 const (
506 pon = 1
507 onu = 1
508 uni = 16
509 gem1 = 1024
510 gem2 = 1025
511 flow1 = 1
512 flow2 = 2
513 flow3 = 3
514 )
515
516 numPon := 2
517 numOnu := 2
518
Matteo Scandolo8a574812021-05-20 15:18:53 -0700519 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800520
521 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
522 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
523 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
524 olt.GemPortIDs[pon][onu][uni][gem1][flow2] = true
525 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
526 olt.GemPortIDs[pon][onu][uni][gem2][flow3] = true
527
528 // remove one flow on the first gem, check that the gem is still allocated as there is still a flow referencing it
529 // NOTE that the flow remove only carries the flow ID, no other information
530 flowGem1 := &openolt.Flow{
531 FlowId: flow1,
532 }
533
534 olt.freeGemPortId(flowGem1)
535 // we still have two unis in the map
536 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2)
537
538 // we should now have a single gem referenced on this UNI
539 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1, "gemport-not-removed")
540
541 // the gem should still reference flow 2
542 assert.Equal(t, olt.GemPortIDs[pon][onu][uni][gem1][flow2], true)
543 // but should not reference flow1
544 _, flow1Exists := olt.GemPortIDs[pon][onu][uni][gem1][flow1]
545 assert.Equal(t, flow1Exists, false)
546
547 // this is the only flow remaining on this gem, the gem should be removed
548 flowGem2 := &openolt.Flow{
549 FlowId: flow2,
550 }
551 olt.freeGemPortId(flowGem2)
552
553 // we should now have a single gem referenced on this UNI
554 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1, "gemport-not-removed")
555
556 // and it should be gem2
557 _, gem1exists := olt.GemPortIDs[pon][onu][uni][gem1]
558 assert.Equal(t, gem1exists, false)
559 _, gem2exists := olt.GemPortIDs[pon][onu][uni][gem2]
560 assert.Equal(t, gem2exists, true)
561}
562
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700563func Test_Olt_freeGemPortIdReplicatedflow(t *testing.T) {
564 const (
565 pon = 1
566 onu = 1
567 uni = 16
568 gem1 = 1024
569 gem2 = 1025
570 flow1 = 1
571 )
572
573 numPon := 2
574 numOnu := 2
575
Matteo Scandolo8a574812021-05-20 15:18:53 -0700576 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700577
578 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
579 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
580 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
581 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
582 olt.GemPortIDs[pon][onu][uni][gem2][flow1] = true
583
584 // this flow was a replicated flow, remove all the gems that are referenced by that flow
585 flowMultiGem := &openolt.Flow{
586 FlowId: flow1,
587 }
588
589 olt.freeGemPortId(flowMultiGem)
590
591 // this flow removes all the gems, so no UNI should be left
592 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 0)
593}
594
Matteo Scandolo21195d62021-04-07 14:31:23 -0700595// testing that we can validate flows while we are adding them
596func Benchmark_validateAndAddFlows(b *testing.B) {
597 const (
598 pon = 0
599 start = 0
600 end = 512
601 )
602
603 for r := 0; r < b.N; r++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700604 olt := createMockOlt(1, 512, 4, []ServiceIf{})
Matteo Scandolo21195d62021-04-07 14:31:23 -0700605
606 wg := sync.WaitGroup{}
607
608 // concurrently adding 1K gems
609 for i := start; i < end; i++ {
610 wg.Add(1)
611 flow := &openolt.Flow{
612 AccessIntfId: pon,
613 OnuId: int32(i),
614 PortNo: uint32(i),
615 GemportId: int32(i),
616 FlowId: uint64(i),
617 }
618 go func(wg *sync.WaitGroup) {
619 olt.storeGemPortIdByFlow(flow)
620 olt.storeAllocId(flow)
621 wg.Done()
622 }(&wg)
623 }
624
625 // at the same time validate flows
626 for i := start; i < end; i++ {
627 wg.Add(1)
628 flow := &openolt.Flow{
629 AccessIntfId: pon,
630 OnuId: int32(i),
631 PortNo: uint32(i),
632 GemportId: 1,
633 FlowId: uint64(i),
634 }
635 go func(wg *sync.WaitGroup) {
636 _ = olt.validateFlow(flow)
637 wg.Done()
638 }(&wg)
639 }
640
641 wg.Wait()
642 // NOTE this tests only fails if there is concurrent access to the map
643 }
644}
645
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800646func Test_Olt_validateFlow(t *testing.T) {
647
648 const (
649 pon0 = 0
650 pon1 = 1
651 onu0 = 0
652 onu1 = 1
653 uniPort = 0
654 usedGemIdPon0 = 1024
655 usedGemIdPon1 = 1025
656 usedAllocIdPon0 = 1
657 usedAllocIdPon1 = 2
658 flowId = 1
659 )
660
661 numPon := 2
662 numOnu := 2
663
Matteo Scandolo8a574812021-05-20 15:18:53 -0700664 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800665
666 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
667 olt.GemPortIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
668
669 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0] = make(map[uint64]bool)
670 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0][flowId] = true
671 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1] = make(map[uint64]bool)
672 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1][flowId] = true
673
674 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
675 olt.AllocIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
676 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
677 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
678 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1] = make(map[uint64]bool)
679 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1][flowId] = true
680
681 // a GemPortID can be referenced across multiple flows on the same ONU
682 validGemFlow := &openolt.Flow{
683 AccessIntfId: pon0,
684 OnuId: onu0,
685 GemportId: usedGemIdPon0,
686 }
687
688 err := olt.validateFlow(validGemFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700689 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800690
691 // a GemPortID can NOT be referenced across different ONUs on the same PON
692 invalidGemFlow := &openolt.Flow{
693 AccessIntfId: pon0,
694 OnuId: onu1,
695 GemportId: usedGemIdPon0,
696 }
697 err = olt.validateFlow(invalidGemFlow)
698 assert.Error(t, err, "gem-1024-already-in-use-on-uni-0-onu-0")
699
700 // if a flow reference the same GEM on a different PON it's a valid flow
701 invalidGemDifferentPonFlow := &openolt.Flow{
702 AccessIntfId: pon1,
703 OnuId: onu1,
704 GemportId: usedGemIdPon0,
705 }
706 err = olt.validateFlow(invalidGemDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700707 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800708
709 // an allocId can be referenced across multiple flows on the same ONU
710 validAllocFlow := &openolt.Flow{
711 AccessIntfId: pon0,
712 OnuId: onu0,
713 AllocId: usedAllocIdPon0,
714 }
715 err = olt.validateFlow(validAllocFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700716 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800717
718 // an allocId can NOT be referenced across different ONUs on the same PON
719 invalidAllocFlow := &openolt.Flow{
720 AccessIntfId: pon0,
721 OnuId: onu1,
722 AllocId: usedAllocIdPon0,
723 }
724 err = olt.validateFlow(invalidAllocFlow)
725 assert.Error(t, err, "allocId-1-already-in-use-on-uni-0-onu-0")
726
727 // if a flow reference the same AllocId on a different PON it's a valid flow
728 invalidAllocDifferentPonFlow := &openolt.Flow{
729 AccessIntfId: pon1,
730 OnuId: onu1,
731 AllocId: usedAllocIdPon0,
732 }
733 err = olt.validateFlow(invalidAllocDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700734 assert.NoError(t, err)
735}
736
737func Test_Olt_validateReplicatedFlow(t *testing.T) {
738
739 const (
740 pon0 = 0
741 onu0 = 0
742 onu1 = 1
743 uniPort = 0
744 usedGemId1 = 1024
745 usedGemId2 = 1025
746 usedAllocIdPon0 = 1
747 flowId = 1
748 )
749
750 numPon := 1
751 numOnu := 1
752
Matteo Scandolo8a574812021-05-20 15:18:53 -0700753 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700754
755 // both the gemports referenced in this flow are already allocated
756 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
757 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1] = make(map[uint64]bool)
758 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1][flowId] = true
759 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2] = make(map[uint64]bool)
760 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2][flowId] = true
761
762 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
763 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
764 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
765
766 pbitToGemPortMap := make(map[uint32]uint32)
767 pbitToGemPortMap[0] = usedGemId1
768 pbitToGemPortMap[1] = usedGemId2
769
770 // this flow should fail vlidation as the gems are already allocated to Onu0
771 invalidGemFlow := &openolt.Flow{
772 AccessIntfId: pon0,
773 OnuId: onu1,
774 PortNo: uniPort,
775 GemportId: 0,
776 ReplicateFlow: true,
777 PbitToGemport: pbitToGemPortMap,
778 }
779
780 err := olt.validateFlow(invalidGemFlow)
781 assert.NotNil(t, err)
782
783 // PbitToGemport is a map, so any of the two gemPorts can fail first and determine the error message
784 foundError := false
785 switch err.Error() {
786 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId2, uniPort, onu0, invalidGemFlow.FlowId):
787 foundError = true
788 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId1, uniPort, onu0, invalidGemFlow.FlowId):
789 foundError = true
790
791 }
792 assert.True(t, foundError)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800793}
Matteo Scandolob5913142021-03-19 16:10:18 -0700794
795func Test_Olt_OmciMsgOut(t *testing.T) {
796 numPon := 4
797 numOnu := 4
798
Matteo Scandolo8a574812021-05-20 15:18:53 -0700799 olt := createMockOlt(numPon, numOnu, 1, []ServiceIf{})
Matteo Scandolob5913142021-03-19 16:10:18 -0700800
801 // a malformed packet should return an error
802 msg := &openolt.OmciMsg{
803 IntfId: 1,
804 OnuId: 1,
805 Pkt: []byte{},
806 }
807 ctx := context.TODO()
808 _, err := olt.OmciMsgOut(ctx, msg)
809 assert.Error(t, err, "olt-received-malformed-omci-packet")
810
811 // a correct packet for a non exiting ONU should throw an error
812 msg = &openolt.OmciMsg{
813 IntfId: 10,
814 OnuId: 25,
815 Pkt: makeOmciSetRequest(t),
816 }
817 _, err = olt.OmciMsgOut(ctx, msg)
818 assert.Error(t, err, "Cannot find PonPort with id 10 in OLT 0")
819
820 // a correct packet for a disabled ONU should be dropped
821 // note that an error is not returned, this is valid in BBsim
822 const (
823 ponId = 1
824 onuId = 1
825 )
826 pon, _ := olt.GetPonById(ponId)
827 onu, _ := pon.GetOnuById(onuId)
828 onu.InternalState.SetState(OnuStateDisabled)
829 msg = &openolt.OmciMsg{
830 IntfId: ponId,
831 OnuId: onuId,
832 Pkt: makeOmciSetRequest(t),
833 }
834 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700835 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700836 assert.Equal(t, len(onu.Channel), 0) // check that no messages have been sent
837
838 // test that the ONU receives a valid packet
839 onu.InternalState.SetState(OnuStateEnabled)
840 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700841 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700842 assert.Equal(t, len(onu.Channel), 1) // check that one message have been sent
843
844}