blob: 4de6609b4e600c7f209f1847d556f6a72c46af7d [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 Scandoloa8eca492021-03-23 09:45:16 -070026 "github.com/stretchr/testify/assert"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070027 "net"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070028 "testing"
Shrey Baid688b4242020-07-10 20:40:10 +053029
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070030 "github.com/opencord/voltha-protos/v4/go/openolt"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070031)
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{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080035 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),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070038 }
39
40 for i := 0; i < numPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080041
42 // initialize the resource maps for every PON Ports
43 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
44 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
45
Matteo Scandolo10f965c2019-09-24 10:40:46 -070046 pon := PonPort{
47 ID: uint32(i),
48 }
49
50 for j := 0; j < numOnu; j++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080051
52 // initialize the resource maps for every ONU and the first UNI
53 olt.AllocIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
54 olt.GemPortIDs[uint32(i)][uint32(j)] = make(map[uint32]map[int32]map[uint64]bool)
55
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070056 onuId := uint32(i + j)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070057 onu := Onu{
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070058 ID: onuId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070059 PonPort: &pon,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070060 PonPortID: pon.ID,
Matteo Scandolob5913142021-03-19 16:10:18 -070061 InternalState: fsm.NewFSM(
62 OnuStateCreated,
63 // this is fake state machine, we don't care about transition in the OLT
64 // unit tests, we'll use SetState to emulate cases
65 fsm.Events{
66 {Name: OnuTxEnable, Src: []string{}, Dst: OnuStateEnabled},
67 {Name: OnuTxDisable, Src: []string{}, Dst: OnuStateDisabled},
68 },
69 fsm.Callbacks{},
70 ),
71 Channel: make(chan bbsim.Message, 2048),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070072 }
Matteo Scandolo4a036262020-08-17 15:56:13 -070073
74 for k, s := range services {
75 service := s.(*Service)
76 service.HwAddress = net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(pon.ID), byte(onuId), byte(k)}
77 service.Onu = &onu
78 onu.Services = append(onu.Services, service)
79 }
80
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080081 onu.SerialNumber = NewSN(olt.ID, pon.ID, onu.ID)
Matteo Scandolo27428702019-10-11 16:21:16 -070082 pon.Onus = append(pon.Onus, &onu)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070083 }
Matteo Scandolo27428702019-10-11 16:21:16 -070084 olt.Pons = append(olt.Pons, &pon)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070085 }
86 return olt
87}
88
Matteo Scandolo4a036262020-08-17 15:56:13 -070089// check the creation of an OLT with a single Service
90func TestCreateOLT(t *testing.T) {
91
92 common.Services = []common.ServiceYaml{
93 {Name: "hsia", CTag: 900, CTagAllocation: common.TagAllocationUnique.String(), STag: 900, STagAllocation: common.TagAllocationShared.String(), NeedsEapol: true, NeedsDchp: true, NeedsIgmp: true},
94 }
95
96 common.Config = &common.GlobalConfig{
97 Olt: common.OltConfig{
98 ID: 1,
99 PonPorts: 2,
100 OnusPonPort: 2,
101 },
102 }
103
104 olt := CreateOLT(*common.Config, common.Services, true)
105
106 assert.Equal(t, len(olt.Pons), int(common.Config.Olt.PonPorts))
107
108 // count the ONUs
109 onus := 0
110 for _, p := range olt.Pons {
111 onus = onus + len(p.Onus)
112 }
113
114 assert.Equal(t, onus, int(common.Config.Olt.PonPorts*common.Config.Olt.OnusPonPort))
115
116 // count the services
117 services := 0
118 for _, p := range olt.Pons {
119 for _, o := range p.Onus {
120 services = services + len(o.Services)
121 }
122 }
123
124 assert.Equal(t, services, int(common.Config.Olt.PonPorts)*int(common.Config.Olt.OnusPonPort)*len(common.Services))
125
126 s1 := olt.Pons[0].Onus[0].Services[0].(*Service)
127
128 assert.Equal(t, s1.Name, "hsia")
129 assert.Equal(t, s1.CTag, 900)
130 assert.Equal(t, s1.STag, 900)
131 assert.Equal(t, s1.HwAddress.String(), "2e:60:01:00:01:00")
132 assert.Equal(t, olt.Pons[0].Onus[0].ID, uint32(1))
133
134 s2 := olt.Pons[0].Onus[1].Services[0].(*Service)
135 assert.Equal(t, s2.CTag, 901)
136 assert.Equal(t, s2.STag, 900)
137 assert.Equal(t, s2.HwAddress.String(), "2e:60:01:00:02:00")
138 assert.Equal(t, olt.Pons[0].Onus[1].ID, uint32(2))
139
140 s3 := olt.Pons[1].Onus[0].Services[0].(*Service)
141 assert.Equal(t, s3.CTag, 902)
142 assert.Equal(t, s3.STag, 900)
143 assert.Equal(t, s3.HwAddress.String(), "2e:60:01:01:01:00")
144 assert.Equal(t, olt.Pons[1].Onus[0].ID, uint32(1))
145
146 s4 := olt.Pons[1].Onus[1].Services[0].(*Service)
147 assert.Equal(t, s4.CTag, 903)
148 assert.Equal(t, s4.STag, 900)
149 assert.Equal(t, s4.HwAddress.String(), "2e:60:01:01:02:00")
150 assert.Equal(t, olt.Pons[1].Onus[1].ID, uint32(2))
151}
152
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700153func Test_Olt_FindOnuBySn_Success(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700154
155 numPon := 4
156 numOnu := 4
157
Matteo Scandolo4a036262020-08-17 15:56:13 -0700158 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700159
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700160 onu, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700161
162 assert.Equal(t, err, nil)
163 assert.Equal(t, onu.Sn(), "BBSM00000303")
164 assert.Equal(t, onu.ID, uint32(3))
165 assert.Equal(t, onu.PonPortID, uint32(3))
166}
167
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700168func Test_Olt_FindOnuBySn_Error(t *testing.T) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700169
170 numPon := 1
171 numOnu := 4
172
Matteo Scandolo4a036262020-08-17 15:56:13 -0700173 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700174
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700175 _, err := olt.FindOnuBySn("BBSM00000303")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700176
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700177 assert.Equal(t, err.Error(), "cannot-find-onu-by-serial-number-BBSM00000303")
178}
179
180func Test_Olt_FindOnuByMacAddress_Success(t *testing.T) {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700181 numPon := 4
182 numOnu := 4
183
Matteo Scandolo4a036262020-08-17 15:56:13 -0700184 services := []ServiceIf{
185 &Service{Name: "hsia"},
186 &Service{Name: "voip"},
187 &Service{Name: "vod"},
188 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700189
Matteo Scandolo4a036262020-08-17 15:56:13 -0700190 olt := createMockOlt(numPon, numOnu, services)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700191
Matteo Scandolo4a036262020-08-17 15:56:13 -0700192 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(3), byte(6), byte(1)}
193 s, err := olt.FindServiceByMacAddress(mac)
194
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700195 assert.NoError(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700196
197 service := s.(*Service)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700198
199 assert.Equal(t, err, nil)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700200 assert.Equal(t, service.Onu.Sn(), "BBSM00000306")
201 assert.Equal(t, service.Onu.ID, uint32(6))
202 assert.Equal(t, service.Onu.PonPortID, uint32(3))
203
204 assert.Equal(t, service.Name, "voip")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700205}
206
207func Test_Olt_FindOnuByMacAddress_Error(t *testing.T) {
208
209 numPon := 1
210 numOnu := 4
211
Matteo Scandolo4a036262020-08-17 15:56:13 -0700212 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700213
214 mac := net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(3), byte(3)}
215
Matteo Scandolo4a036262020-08-17 15:56:13 -0700216 _, err := olt.FindServiceByMacAddress(mac)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700217
Matteo Scandolo4a036262020-08-17 15:56:13 -0700218 assert.Equal(t, err.Error(), "cannot-find-service-by-mac-address-2e:60:70:13:03:03")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700219}
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700220
221func Test_Olt_GetOnuByFlowId(t *testing.T) {
222 numPon := 4
223 numOnu := 4
224
Matteo Scandolo4a036262020-08-17 15:56:13 -0700225 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700226
227 // Add the flows to onus (to be found)
228 onu1, _ := olt.FindOnuBySn("BBSM00000303")
229 flow1 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530230 FlowId: 64,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700231 Classifier: &openolt.Classifier{},
232 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800233 msg1 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700234 OnuID: onu1.ID,
235 PonPortID: onu1.PonPortID,
236 Flow: &flow1,
237 }
238 onu1.handleFlowAdd(msg1)
239
240 onu2, _ := olt.FindOnuBySn("BBSM00000103")
241 flow2 := openolt.Flow{
Shrey Baid688b4242020-07-10 20:40:10 +0530242 FlowId: 72,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700243 Classifier: &openolt.Classifier{},
244 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800245 msg2 := types.OnuFlowUpdateMessage{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700246 OnuID: onu2.ID,
247 PonPortID: onu2.PonPortID,
248 Flow: &flow2,
249 }
250 onu2.handleFlowAdd(msg2)
251
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700252 found, err := olt.GetOnuByFlowId(flow1.FlowId)
253
254 assert.Equal(t, err, nil)
255 assert.Equal(t, found.Sn(), onu1.Sn())
Shrey Baid688b4242020-07-10 20:40:10 +0530256}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800257
258func Test_Olt_storeGemPortId(t *testing.T) {
259
260 const (
261 pon = 1
262 onu = 1
263 uni = 16
264 gem1 = 1024
265 gem2 = 1025
266 )
267
268 numPon := 2
269 numOnu := 2
270
271 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
272
273 // add a first flow on the ONU
274 flow1 := &openolt.Flow{
275 AccessIntfId: pon,
276 OnuId: onu,
277 PortNo: uni,
278 FlowId: 1,
279 GemportId: gem1,
280 }
281
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700282 olt.storeGemPortIdByFlow(flow1)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800283 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
284 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing it
285
286 // add a second flow on the ONU (same gem)
287 flow2 := &openolt.Flow{
288 AccessIntfId: pon,
289 OnuId: onu,
290 PortNo: uni,
291 FlowId: 2,
292 GemportId: gem1,
293 }
294
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700295 olt.storeGemPortIdByFlow(flow2)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800296 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1) // we have 1 gem port
297 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // and two flows referencing it
298
299 // add a third flow on the ONU (different gem)
300 flow3 := &openolt.Flow{
301 AccessIntfId: pon,
302 OnuId: onu,
303 PortNo: uni,
304 FlowId: 2,
305 GemportId: 1025,
306 }
307
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700308 olt.storeGemPortIdByFlow(flow3)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800309 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports
310 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 2) // two flows referencing the first one
311 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing the second one
312}
313
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700314func Test_Olt_storeGemPortIdReplicatedFlow(t *testing.T) {
315 const (
316 pon = 1
317 onu = 1
318 uni = 16
319 gem1 = 1024
320 gem2 = 1025
321 )
322
323 numPon := 2
324 numOnu := 2
325
326 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
327
328 // add a flow that needs replication
329 pbitToGemPortMap := make(map[uint32]uint32)
330 pbitToGemPortMap[0] = gem1
331 pbitToGemPortMap[1] = gem2
332 flow1 := &openolt.Flow{
333 AccessIntfId: pon,
334 OnuId: onu,
335 PortNo: uni,
336 FlowId: 1,
337 GemportId: 0,
338 ReplicateFlow: true,
339 PbitToGemport: pbitToGemPortMap,
340 }
341
342 olt.storeGemPortIdByFlow(flow1)
343 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2) // we have 2 gem ports in the flow
344 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1) // and one flow referencing them
345 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem2]), 1) // and one flow referencing them
346}
347
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800348func Test_Olt_freeGemPortId(t *testing.T) {
349 const (
350 pon = 1
351 onu = 1
352 uni = 16
353 gem1 = 1024
354 gem2 = 1025
355 flow1 = 1
356 flow2 = 2
357 flow3 = 3
358 )
359
360 numPon := 2
361 numOnu := 2
362
363 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
364
365 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
366 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
367 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
368 olt.GemPortIDs[pon][onu][uni][gem1][flow2] = true
369 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
370 olt.GemPortIDs[pon][onu][uni][gem2][flow3] = true
371
372 // remove one flow on the first gem, check that the gem is still allocated as there is still a flow referencing it
373 // NOTE that the flow remove only carries the flow ID, no other information
374 flowGem1 := &openolt.Flow{
375 FlowId: flow1,
376 }
377
378 olt.freeGemPortId(flowGem1)
379 // we still have two unis in the map
380 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 2)
381
382 // we should now have a single gem referenced on this UNI
383 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni][gem1]), 1, "gemport-not-removed")
384
385 // the gem should still reference flow 2
386 assert.Equal(t, olt.GemPortIDs[pon][onu][uni][gem1][flow2], true)
387 // but should not reference flow1
388 _, flow1Exists := olt.GemPortIDs[pon][onu][uni][gem1][flow1]
389 assert.Equal(t, flow1Exists, false)
390
391 // this is the only flow remaining on this gem, the gem should be removed
392 flowGem2 := &openolt.Flow{
393 FlowId: flow2,
394 }
395 olt.freeGemPortId(flowGem2)
396
397 // we should now have a single gem referenced on this UNI
398 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 1, "gemport-not-removed")
399
400 // and it should be gem2
401 _, gem1exists := olt.GemPortIDs[pon][onu][uni][gem1]
402 assert.Equal(t, gem1exists, false)
403 _, gem2exists := olt.GemPortIDs[pon][onu][uni][gem2]
404 assert.Equal(t, gem2exists, true)
405}
406
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700407func Test_Olt_freeGemPortIdReplicatedflow(t *testing.T) {
408 const (
409 pon = 1
410 onu = 1
411 uni = 16
412 gem1 = 1024
413 gem2 = 1025
414 flow1 = 1
415 )
416
417 numPon := 2
418 numOnu := 2
419
420 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
421
422 olt.GemPortIDs[pon][onu][uni] = make(map[int32]map[uint64]bool)
423 olt.GemPortIDs[pon][onu][uni][gem1] = make(map[uint64]bool)
424 olt.GemPortIDs[pon][onu][uni][gem1][flow1] = true
425 olt.GemPortIDs[pon][onu][uni][gem2] = make(map[uint64]bool)
426 olt.GemPortIDs[pon][onu][uni][gem2][flow1] = true
427
428 // this flow was a replicated flow, remove all the gems that are referenced by that flow
429 flowMultiGem := &openolt.Flow{
430 FlowId: flow1,
431 }
432
433 olt.freeGemPortId(flowMultiGem)
434
435 // this flow removes all the gems, so no UNI should be left
436 assert.Equal(t, len(olt.GemPortIDs[pon][onu][uni]), 0)
437}
438
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800439func Test_Olt_validateFlow(t *testing.T) {
440
441 const (
442 pon0 = 0
443 pon1 = 1
444 onu0 = 0
445 onu1 = 1
446 uniPort = 0
447 usedGemIdPon0 = 1024
448 usedGemIdPon1 = 1025
449 usedAllocIdPon0 = 1
450 usedAllocIdPon1 = 2
451 flowId = 1
452 )
453
454 numPon := 2
455 numOnu := 2
456
457 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
458
459 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
460 olt.GemPortIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
461
462 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0] = make(map[uint64]bool)
463 olt.GemPortIDs[pon0][onu0][uniPort][usedGemIdPon0][flowId] = true
464 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1] = make(map[uint64]bool)
465 olt.GemPortIDs[pon1][onu0][uniPort][usedGemIdPon1][flowId] = true
466
467 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
468 olt.AllocIDs[pon1][onu0][uniPort] = make(map[int32]map[uint64]bool)
469 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
470 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
471 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1] = make(map[uint64]bool)
472 olt.AllocIDs[pon1][onu0][uniPort][usedAllocIdPon1][flowId] = true
473
474 // a GemPortID can be referenced across multiple flows on the same ONU
475 validGemFlow := &openolt.Flow{
476 AccessIntfId: pon0,
477 OnuId: onu0,
478 GemportId: usedGemIdPon0,
479 }
480
481 err := olt.validateFlow(validGemFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700482 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800483
484 // a GemPortID can NOT be referenced across different ONUs on the same PON
485 invalidGemFlow := &openolt.Flow{
486 AccessIntfId: pon0,
487 OnuId: onu1,
488 GemportId: usedGemIdPon0,
489 }
490 err = olt.validateFlow(invalidGemFlow)
491 assert.Error(t, err, "gem-1024-already-in-use-on-uni-0-onu-0")
492
493 // if a flow reference the same GEM on a different PON it's a valid flow
494 invalidGemDifferentPonFlow := &openolt.Flow{
495 AccessIntfId: pon1,
496 OnuId: onu1,
497 GemportId: usedGemIdPon0,
498 }
499 err = olt.validateFlow(invalidGemDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700500 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800501
502 // an allocId can be referenced across multiple flows on the same ONU
503 validAllocFlow := &openolt.Flow{
504 AccessIntfId: pon0,
505 OnuId: onu0,
506 AllocId: usedAllocIdPon0,
507 }
508 err = olt.validateFlow(validAllocFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700509 assert.NoError(t, err)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800510
511 // an allocId can NOT be referenced across different ONUs on the same PON
512 invalidAllocFlow := &openolt.Flow{
513 AccessIntfId: pon0,
514 OnuId: onu1,
515 AllocId: usedAllocIdPon0,
516 }
517 err = olt.validateFlow(invalidAllocFlow)
518 assert.Error(t, err, "allocId-1-already-in-use-on-uni-0-onu-0")
519
520 // if a flow reference the same AllocId on a different PON it's a valid flow
521 invalidAllocDifferentPonFlow := &openolt.Flow{
522 AccessIntfId: pon1,
523 OnuId: onu1,
524 AllocId: usedAllocIdPon0,
525 }
526 err = olt.validateFlow(invalidAllocDifferentPonFlow)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700527 assert.NoError(t, err)
528}
529
530func Test_Olt_validateReplicatedFlow(t *testing.T) {
531
532 const (
533 pon0 = 0
534 onu0 = 0
535 onu1 = 1
536 uniPort = 0
537 usedGemId1 = 1024
538 usedGemId2 = 1025
539 usedAllocIdPon0 = 1
540 flowId = 1
541 )
542
543 numPon := 1
544 numOnu := 1
545
546 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
547
548 // both the gemports referenced in this flow are already allocated
549 olt.GemPortIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
550 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1] = make(map[uint64]bool)
551 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId1][flowId] = true
552 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2] = make(map[uint64]bool)
553 olt.GemPortIDs[pon0][onu0][uniPort][usedGemId2][flowId] = true
554
555 olt.AllocIDs[pon0][onu0][uniPort] = make(map[int32]map[uint64]bool)
556 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0] = make(map[uint64]bool)
557 olt.AllocIDs[pon0][onu0][uniPort][usedAllocIdPon0][flowId] = true
558
559 pbitToGemPortMap := make(map[uint32]uint32)
560 pbitToGemPortMap[0] = usedGemId1
561 pbitToGemPortMap[1] = usedGemId2
562
563 // this flow should fail vlidation as the gems are already allocated to Onu0
564 invalidGemFlow := &openolt.Flow{
565 AccessIntfId: pon0,
566 OnuId: onu1,
567 PortNo: uniPort,
568 GemportId: 0,
569 ReplicateFlow: true,
570 PbitToGemport: pbitToGemPortMap,
571 }
572
573 err := olt.validateFlow(invalidGemFlow)
574 assert.NotNil(t, err)
575
576 // PbitToGemport is a map, so any of the two gemPorts can fail first and determine the error message
577 foundError := false
578 switch err.Error() {
579 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId2, uniPort, onu0, invalidGemFlow.FlowId):
580 foundError = true
581 case fmt.Sprintf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", usedGemId1, uniPort, onu0, invalidGemFlow.FlowId):
582 foundError = true
583
584 }
585 assert.True(t, foundError)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800586}
Matteo Scandolob5913142021-03-19 16:10:18 -0700587
588func Test_Olt_OmciMsgOut(t *testing.T) {
589 numPon := 4
590 numOnu := 4
591
592 olt := createMockOlt(numPon, numOnu, []ServiceIf{})
593
594 // a malformed packet should return an error
595 msg := &openolt.OmciMsg{
596 IntfId: 1,
597 OnuId: 1,
598 Pkt: []byte{},
599 }
600 ctx := context.TODO()
601 _, err := olt.OmciMsgOut(ctx, msg)
602 assert.Error(t, err, "olt-received-malformed-omci-packet")
603
604 // a correct packet for a non exiting ONU should throw an error
605 msg = &openolt.OmciMsg{
606 IntfId: 10,
607 OnuId: 25,
608 Pkt: makeOmciSetRequest(t),
609 }
610 _, err = olt.OmciMsgOut(ctx, msg)
611 assert.Error(t, err, "Cannot find PonPort with id 10 in OLT 0")
612
613 // a correct packet for a disabled ONU should be dropped
614 // note that an error is not returned, this is valid in BBsim
615 const (
616 ponId = 1
617 onuId = 1
618 )
619 pon, _ := olt.GetPonById(ponId)
620 onu, _ := pon.GetOnuById(onuId)
621 onu.InternalState.SetState(OnuStateDisabled)
622 msg = &openolt.OmciMsg{
623 IntfId: ponId,
624 OnuId: onuId,
625 Pkt: makeOmciSetRequest(t),
626 }
627 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700628 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700629 assert.Equal(t, len(onu.Channel), 0) // check that no messages have been sent
630
631 // test that the ONU receives a valid packet
632 onu.InternalState.SetState(OnuStateEnabled)
633 _, err = olt.OmciMsgOut(ctx, msg)
Matteo Scandoloa8eca492021-03-23 09:45:16 -0700634 assert.NoError(t, err)
Matteo Scandolob5913142021-03-19 16:10:18 -0700635 assert.Equal(t, len(onu.Channel), 1) // check that one message have been sent
636
637}