blob: c8f920f76a1b85e7026007e6d83e231c337622e1 [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 Scandolo4a036262020-08-17 15:56:13 -070033func createMockOlt(numPon int, numOnu 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
75 for k, s := range services {
76 service := s.(*Service)
77 service.HwAddress = net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(pon.ID), byte(onuId), byte(k)}
78 service.Onu = &onu
79 onu.Services = append(onu.Services, service)
80 }
81
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080082 onu.SerialNumber = NewSN(olt.ID, pon.ID, onu.ID)
Matteo Scandolo27428702019-10-11 16:21:16 -070083 pon.Onus = append(pon.Onus, &onu)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070084 }
Matteo Scandolo27428702019-10-11 16:21:16 -070085 olt.Pons = append(olt.Pons, &pon)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070086 }
87 return olt
88}
89
Matteo Scandolo4a036262020-08-17 15:56:13 -070090// check the creation of an OLT with a single Service
91func TestCreateOLT(t *testing.T) {
92
93 common.Services = []common.ServiceYaml{
94 {Name: "hsia", CTag: 900, CTagAllocation: common.TagAllocationUnique.String(), STag: 900, STagAllocation: common.TagAllocationShared.String(), NeedsEapol: true, NeedsDchp: true, NeedsIgmp: true},
95 }
96
97 common.Config = &common.GlobalConfig{
98 Olt: common.OltConfig{
99 ID: 1,
100 PonPorts: 2,
101 OnusPonPort: 2,
102 },
103 }
104
105 olt := CreateOLT(*common.Config, common.Services, true)
106
107 assert.Equal(t, len(olt.Pons), int(common.Config.Olt.PonPorts))
108
109 // count the ONUs
110 onus := 0
111 for _, p := range olt.Pons {
112 onus = onus + len(p.Onus)
113 }
114
115 assert.Equal(t, onus, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort))
116
117 // count the services
118 services := 0
119 for _, p := range olt.Pons {
120 for _, o := range p.Onus {
121 services = services + len(o.Services)
122 }
123 }
124
125 assert.Equal(t, services, int(common.Config.Olt.PonPorts)*int(common.Config.Olt.OnusPonPort)*len(common.Services))
126
127 s1 := olt.Pons[0].Onus[0].Services[0].(*Service)
128
129 assert.Equal(t, s1.Name, "hsia")
130 assert.Equal(t, s1.CTag, 900)
131 assert.Equal(t, s1.STag, 900)
132 assert.Equal(t, s1.HwAddress.String(), "2e:60:01:00:01:00")
133 assert.Equal(t, olt.Pons[0].Onus[0].ID, uint32(1))
134
135 s2 := olt.Pons[0].Onus[1].Services[0].(*Service)
136 assert.Equal(t, s2.CTag, 901)
137 assert.Equal(t, s2.STag, 900)
138 assert.Equal(t, s2.HwAddress.String(), "2e:60:01:00:02:00")
139 assert.Equal(t, olt.Pons[0].Onus[1].ID, uint32(2))
140
141 s3 := olt.Pons[1].Onus[0].Services[0].(*Service)
142 assert.Equal(t, s3.CTag, 902)
143 assert.Equal(t, s3.STag, 900)
144 assert.Equal(t, s3.HwAddress.String(), "2e:60:01:01:01:00")
145 assert.Equal(t, olt.Pons[1].Onus[0].ID, uint32(1))
146
147 s4 := olt.Pons[1].Onus[1].Services[0].(*Service)
148 assert.Equal(t, s4.CTag, 903)
149 assert.Equal(t, s4.STag, 900)
150 assert.Equal(t, s4.HwAddress.String(), "2e:60:01:01:02:00")
151 assert.Equal(t, olt.Pons[1].Onus[1].ID, uint32(2))
152}
153
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700154func Test_Olt_FindOnuBySn_Success(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700155
156 numPon := 4
157 numOnu := 4
158
Matteo Scandolo4a036262020-08-17 15:56:13 -0700159 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700160
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700161 onu, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700162
163 assert.Equal(t, err, nil)
164 assert.Equal(t, onu.Sn(), "BBSM00000303")
165 assert.Equal(t, onu.ID, uint32(3))
166 assert.Equal(t, onu.PonPortID, uint32(3))
167}
168
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700169func Test_Olt_FindOnuBySn_Error(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700170
171 numPon := 1
172 numOnu := 4
173
Matteo Scandolo4a036262020-08-17 15:56:13 -0700174 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700175
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700176 _, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700177
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700178 assert.Equal(t, err.Error(), "cannot-find-onu-by-serial-number-BBSM00000303")
179}
180
181func Test_Olt_FindOnuByMacAddress_Success(t *testing.T) {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700182 numPon := 4
183 numOnu := 4
184
Matteo Scandolo4a036262020-08-17 15:56:13 -0700185 services := []ServiceIf{
186 &Service{Name: "hsia"},
187 &Service{Name: "voip"},
188 &Service{Name: "vod"},
189 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700190
Matteo Scandolo4a036262020-08-17 15:56:13 -0700191 olt := createMockOlt(numPon, numOnu, services)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700192
Matteo Scandolo4a036262020-08-17 15:56:13 -0700193 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(3), byte(6), byte(1)}
194 s, err := olt.FindServiceByMacAddress(mac)
195
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700196 assert.NoError(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700197
198 service := s.(*Service)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700199
200 assert.Equal(t, err, nil)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700201 assert.Equal(t, service.Onu.Sn(), "BBSM00000306")
202 assert.Equal(t, service.Onu.ID, uint32(6))
203 assert.Equal(t, service.Onu.PonPortID, uint32(3))
204
205 assert.Equal(t, service.Name, "voip")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700206}
207
208func Test_Olt_FindOnuByMacAddress_Error(t *testing.T) {
209
210 numPon := 1
211 numOnu := 4
212
Matteo Scandolo4a036262020-08-17 15:56:13 -0700213 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700214
215 mac := net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(3), byte(3)}
216
Matteo Scandolo4a036262020-08-17 15:56:13 -0700217 _, err := olt.FindServiceByMacAddress(mac)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700218
Matteo Scandolo4a036262020-08-17 15:56:13 -0700219 assert.Equal(t, err.Error(), "cannot-find-service-by-mac-address-2e:60:70:13:03:03")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700220}
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700221
222func Test_Olt_GetOnuByFlowId(t *testing.T) {
223 numPon := 4
224 numOnu := 4
225
Matteo Scandolo4a036262020-08-17 15:56:13 -0700226 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700227
228 // Add the flows to onus (to be found)
229 onu1, _ := olt.FindOnuBySn("BBSM00000303")
230 flow1 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530231 FlowId: 64,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700232 Classifier: &openolt.Classifier{},
233 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800234 msg1 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700235 OnuID: onu1.ID,
236 PonPortID: onu1.PonPortID,
237 Flow: &flow1,
238 }
239 onu1.handleFlowAdd(msg1)
240
241 onu2, _ := olt.FindOnuBySn("BBSM00000103")
242 flow2 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530243 FlowId: 72,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700244 Classifier: &openolt.Classifier{},
245 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800246 msg2 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700247 OnuID: onu2.ID,
248 PonPortID: onu2.PonPortID,
249 Flow: &flow2,
250 }
251 onu2.handleFlowAdd(msg2)
252
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700253 found, err := olt.GetOnuByFlowId(flow1.FlowId)
254
255 assert.Equal(t, err, nil)
256 assert.Equal(t, found.Sn(), onu1.Sn())
Shrey Baid688b4242020-07-10 20:40:10 +0530257}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800258
259func Test_Olt_storeGemPortId(t *testing.T) {
260
261 const (
262 pon = 1
263 onu = 1
264 uni = 16
265 gem1 = 1024
266 gem2 = 1025
267 )
268
269 numPon := 2
270 numOnu := 2
271
272 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
273
274 // add a first flow on the ONU
275 flow1 := &openolt.Flow{
276 AccessIntfId: pon,
277 OnuId: onu,
278 PortNo: uni,
279 FlowId: 1,
280 GemportId: gem1,
281 }
282
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700283 olt.storeGemPortIdByFlow(flow1)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800284 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
285 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing it
286
287 // add a second flow on the ONU (same gem)
288 flow2 := &openolt.Flow{
289 AccessIntfId: pon,
290 OnuId: onu,
291 PortNo: uni,
292 FlowId: 2,
293 GemportId: gem1,
294 }
295
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700296 olt.storeGemPortIdByFlow(flow2)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800297 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
298 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // and two flows referencing it
299
300 // add a third flow on the ONU (different gem)
301 flow3 := &openolt.Flow{
302 AccessIntfId: pon,
303 OnuId: onu,
304 PortNo: uni,
305 FlowId: 2,
306 GemportId: 1025,
307 }
308
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700309 olt.storeGemPortIdByFlow(flow3)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800310 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports
311 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // two flows referencing the first one
312 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing the second one
313}
314
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700315func Test_Olt_storeGemPortIdReplicatedFlow(t *testing.T) {
316 const (
317 pon = 1
318 onu = 1
319 uni = 16
320 gem1 = 1024
321 gem2 = 1025
322 )
323
324 numPon := 2
325 numOnu := 2
326
327 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
328
329 // add a flow that needs replication
330 pbitToGemPortMap := make(map[uint32]uint32)
331 pbitToGemPortMap[0] = gem1
332 pbitToGemPortMap[1] = gem2
333 flow1 := &openolt.Flow{
334 AccessIntfId: pon,
335 OnuId: onu,
336 PortNo: uni,
337 FlowId: 1,
338 GemportId: 0,
339 ReplicateFlow: true,
340 PbitToGemport: pbitToGemPortMap,
341 }
342
343 olt.storeGemPortIdByFlow(flow1)
344 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports in the flow
345 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing them
346 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing them
347}
348
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800349func Test_Olt_freeGemPortId(t *testing.T) {
350 const (
351 pon = 1
352 onu = 1
353 uni = 16
354 gem1 = 1024
355 gem2 = 1025
356 flow1 = 1
357 flow2 = 2
358 flow3 = 3
359 )
360
361 numPon := 2
362 numOnu := 2
363
364 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
365
366 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
367 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
368 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
369 olt.GemPortIDs[pon][onu][uni][gem1][flow2] = true
370 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
371 olt.GemPortIDs[pon][onu][uni][gem2][flow3] = true
372
373 // remove one flow on the first gem, check that the gem is still allocated as there is still a flow referencing it
374 // NOTE that the flow remove only carries the flow ID, no other information
375 flowGem1 := &openolt.Flow{
376 FlowId: flow1,
377 }
378
379 olt.freeGemPortId(flowGem1)
380 // we still have two unis in the map
381 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2)
382
383 // we should now have a single gem referenced on this UNI
384 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1, "gemport-not-removed")
385
386 // the gem should still reference flow 2
387 assert.Equal(t, olt.GemPortIDs[pon][onu][uni][gem1][flow2], true)
388 // but should not reference flow1
389 _, flow1Exists := olt.GemPortIDs[pon][onu][uni][gem1][flow1]
390 assert.Equal(t, flow1Exists, false)
391
392 // this is the only flow remaining on this gem, the gem should be removed
393 flowGem2 := &openolt.Flow{
394 FlowId: flow2,
395 }
396 olt.freeGemPortId(flowGem2)
397
398 // we should now have a single gem referenced on this UNI
399 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1, "gemport-not-removed")
400
401 // and it should be gem2
402 _, gem1exists := olt.GemPortIDs[pon][onu][uni][gem1]
403 assert.Equal(t, gem1exists, false)
404 _, gem2exists := olt.GemPortIDs[pon][onu][uni][gem2]
405 assert.Equal(t, gem2exists, true)
406}
407
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700408func Test_Olt_freeGemPortIdReplicatedflow(t *testing.T) {
409 const (
410 pon = 1
411 onu = 1
412 uni = 16
413 gem1 = 1024
414 gem2 = 1025
415 flow1 = 1
416 )
417
418 numPon := 2
419 numOnu := 2
420
421 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
422
423 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
424 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
425 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
426 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
427 olt.GemPortIDs[pon][onu][uni][gem2][flow1] = true
428
429 // this flow was a replicated flow, remove all the gems that are referenced by that flow
430 flowMultiGem := &openolt.Flow{
431 FlowId: flow1,
432 }
433
434 olt.freeGemPortId(flowMultiGem)
435
436 // this flow removes all the gems, so no UNI should be left
437 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 0)
438}
439
Matteo Scandolo21195d62021-04-07 14:31:23 -0700440// testing that we can validate flows while we are adding them
441func Benchmark_validateAndAddFlows(b *testing.B) {
442 const (
443 pon = 0
444 start = 0
445 end = 512
446 )
447
448 for r := 0; r < b.N; r++ {
449 olt := createMockOlt(1, 512, []ServiceIf{})
450
451 wg := sync.WaitGroup{}
452
453 // concurrently adding 1K gems
454 for i := start; i < end; i++ {
455 wg.Add(1)
456 flow := &openolt.Flow{
457 AccessIntfId: pon,
458 OnuId: int32(i),
459 PortNo: uint32(i),
460 GemportId: int32(i),
461 FlowId: uint64(i),
462 }
463 go func(wg *sync.WaitGroup) {
464 olt.storeGemPortIdByFlow(flow)
465 olt.storeAllocId(flow)
466 wg.Done()
467 }(&wg)
468 }
469
470 // at the same time validate flows
471 for i := start; i < end; i++ {
472 wg.Add(1)
473 flow := &openolt.Flow{
474 AccessIntfId: pon,
475 OnuId: int32(i),
476 PortNo: uint32(i),
477 GemportId: 1,
478 FlowId: uint64(i),
479 }
480 go func(wg *sync.WaitGroup) {
481 _ = olt.validateFlow(flow)
482 wg.Done()
483 }(&wg)
484 }
485
486 wg.Wait()
487 // NOTE this tests only fails if there is concurrent access to the map
488 }
489}
490
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800491func Test_Olt_validateFlow(t *testing.T) {
492
493 const (
494 pon0 = 0
495 pon1 = 1
496 onu0 = 0
497 onu1 = 1
498 uniPort = 0
499 usedGemIdPon0 = 1024
500 usedGemIdPon1 = 1025
501 usedAllocIdPon0 = 1
502 usedAllocIdPon1 = 2
503 flowId = 1
504 )
505
506 numPon := 2
507 numOnu := 2
508
509 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
510
511 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
512 olt.GemPortIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
513
514 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0] = make(map[uint64]bool)
515 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0][flowId] = true
516 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1] = make(map[uint64]bool)
517 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1][flowId] = true
518
519 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
520 olt.AllocIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
521 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
522 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
523 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1] = make(map[uint64]bool)
524 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1][flowId] = true
525
526 // a GemPortID can be referenced across multiple flows on the same ONU
527 validGemFlow := &openolt.Flow{
528 AccessIntfId: pon0,
529 OnuId: onu0,
530 GemportId: usedGemIdPon0,
531 }
532
533 err := olt.validateFlow(validGemFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700534 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800535
536 // a GemPortID can NOT be referenced across different ONUs on the same PON
537 invalidGemFlow := &openolt.Flow{
538 AccessIntfId: pon0,
539 OnuId: onu1,
540 GemportId: usedGemIdPon0,
541 }
542 err = olt.validateFlow(invalidGemFlow)
543 assert.Error(t, err, "gem-1024-already-in-use-on-uni-0-onu-0")
544
545 // if a flow reference the same GEM on a different PON it's a valid flow
546 invalidGemDifferentPonFlow := &openolt.Flow{
547 AccessIntfId: pon1,
548 OnuId: onu1,
549 GemportId: usedGemIdPon0,
550 }
551 err = olt.validateFlow(invalidGemDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700552 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800553
554 // an allocId can be referenced across multiple flows on the same ONU
555 validAllocFlow := &openolt.Flow{
556 AccessIntfId: pon0,
557 OnuId: onu0,
558 AllocId: usedAllocIdPon0,
559 }
560 err = olt.validateFlow(validAllocFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700561 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800562
563 // an allocId can NOT be referenced across different ONUs on the same PON
564 invalidAllocFlow := &openolt.Flow{
565 AccessIntfId: pon0,
566 OnuId: onu1,
567 AllocId: usedAllocIdPon0,
568 }
569 err = olt.validateFlow(invalidAllocFlow)
570 assert.Error(t, err, "allocId-1-already-in-use-on-uni-0-onu-0")
571
572 // if a flow reference the same AllocId on a different PON it's a valid flow
573 invalidAllocDifferentPonFlow := &openolt.Flow{
574 AccessIntfId: pon1,
575 OnuId: onu1,
576 AllocId: usedAllocIdPon0,
577 }
578 err = olt.validateFlow(invalidAllocDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700579 assert.NoError(t, err)
580}
581
582func Test_Olt_validateReplicatedFlow(t *testing.T) {
583
584 const (
585 pon0 = 0
586 onu0 = 0
587 onu1 = 1
588 uniPort = 0
589 usedGemId1 = 1024
590 usedGemId2 = 1025
591 usedAllocIdPon0 = 1
592 flowId = 1
593 )
594
595 numPon := 1
596 numOnu := 1
597
598 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
599
600 // both the gemports referenced in this flow are already allocated
601 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
602 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1] = make(map[uint64]bool)
603 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1][flowId] = true
604 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2] = make(map[uint64]bool)
605 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2][flowId] = true
606
607 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
608 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
609 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
610
611 pbitToGemPortMap := make(map[uint32]uint32)
612 pbitToGemPortMap[0] = usedGemId1
613 pbitToGemPortMap[1] = usedGemId2
614
615 // this flow should fail vlidation as the gems are already allocated to Onu0
616 invalidGemFlow := &openolt.Flow{
617 AccessIntfId: pon0,
618 OnuId: onu1,
619 PortNo: uniPort,
620 GemportId: 0,
621 ReplicateFlow: true,
622 PbitToGemport: pbitToGemPortMap,
623 }
624
625 err := olt.validateFlow(invalidGemFlow)
626 assert.NotNil(t, err)
627
628 // PbitToGemport is a map, so any of the two gemPorts can fail first and determine the error message
629 foundError := false
630 switch err.Error() {
631 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId2, uniPort, onu0, invalidGemFlow.FlowId):
632 foundError = true
633 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId1, uniPort, onu0, invalidGemFlow.FlowId):
634 foundError = true
635
636 }
637 assert.True(t, foundError)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800638}
Matteo Scandolob5913142021-03-19 16:10:18 -0700639
640func Test_Olt_OmciMsgOut(t *testing.T) {
641 numPon := 4
642 numOnu := 4
643
644 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
645
646 // a malformed packet should return an error
647 msg := &openolt.OmciMsg{
648 IntfId: 1,
649 OnuId: 1,
650 Pkt: []byte{},
651 }
652 ctx := context.TODO()
653 _, err := olt.OmciMsgOut(ctx, msg)
654 assert.Error(t, err, "olt-received-malformed-omci-packet")
655
656 // a correct packet for a non exiting ONU should throw an error
657 msg = &openolt.OmciMsg{
658 IntfId: 10,
659 OnuId: 25,
660 Pkt: makeOmciSetRequest(t),
661 }
662 _, err = olt.OmciMsgOut(ctx, msg)
663 assert.Error(t, err, "Cannot find PonPort with id 10 in OLT 0")
664
665 // a correct packet for a disabled ONU should be dropped
666 // note that an error is not returned, this is valid in BBsim
667 const (
668 ponId = 1
669 onuId = 1
670 )
671 pon, _ := olt.GetPonById(ponId)
672 onu, _ := pon.GetOnuById(onuId)
673 onu.InternalState.SetState(OnuStateDisabled)
674 msg = &openolt.OmciMsg{
675 IntfId: ponId,
676 OnuId: onuId,
677 Pkt: makeOmciSetRequest(t),
678 }
679 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700680 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700681 assert.Equal(t, len(onu.Channel), 0) // check that no messages have been sent
682
683 // test that the ONU receives a valid packet
684 onu.InternalState.SetState(OnuStateEnabled)
685 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700686 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700687 assert.Equal(t, len(onu.Channel), 1) // check that one message have been sent
688
689}