blob: a56b21538dde6d5cd7543358fe8fd0c06aaf1fee [file] [log] [blame]
Elia Battistone1cecb22022-03-21 10:05:25 +01001/*
2* Copyright 2022-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 core
18
19import (
20 "fmt"
21 "testing"
Elia Battiston4750d3c2022-07-14 13:24:56 +000022 "time"
Elia Battistone1cecb22022-03-21 10:05:25 +010023
Elia Battistona1333642022-07-27 12:17:24 +000024 "github.com/opencord/voltha-northbound-bbf-adapter/internal/clients"
Elia Battiston4750d3c2022-07-14 13:24:56 +000025 "github.com/opencord/voltha-protos/v5/go/openflow_13"
Elia Battistone1cecb22022-03-21 10:05:25 +010026 "github.com/opencord/voltha-protos/v5/go/voltha"
27 "github.com/stretchr/testify/assert"
Elia Battiston4750d3c2022-07-14 13:24:56 +000028 "google.golang.org/protobuf/types/known/timestamppb"
Elia Battistone1cecb22022-03-21 10:05:25 +010029)
30
31const (
32 testDeviceId = "123145abcdef"
33)
34
35func getItemWithPath(items []YangItem, path string) (value string, ok bool) {
36 for _, item := range items {
37 if item.Path == path {
38 return item.Value, true
39 }
40 }
41
42 return "", false
43}
44
45func TestDevicePath(t *testing.T) {
46 path := getDevicePath(testDeviceId)
Elia Battistona1333642022-07-27 12:17:24 +000047 assert.Equal(t, "/bbf-device-aggregation:devices/device[name='123145abcdef']", path)
48}
49
50func TestDeviceHardwarePath(t *testing.T) {
51 path := getDeviceHardwarePath(testDeviceId)
52 assert.Equal(t, "/bbf-device-aggregation:devices/device[name='123145abcdef']/data/ietf-hardware:hardware/component[name='123145abcdef']", path)
53}
54
55func TestServicePortPath(t *testing.T) {
56 path := GetServicePortPath("testService", "testPort")
57 assert.Equal(t, "/bbf-nt-service-profile:service-profiles/service-profile[name='testService']/ports/port[name='testPort']", path)
58}
59
60func TestVlansPath(t *testing.T) {
61 path := GetVlansPath("testProfile")
62 assert.Equal(t, "/bbf-l2-access-attributes:vlan-translation-profiles/vlan-translation-profile[name='testProfile']", path)
Elia Battistone1cecb22022-03-21 10:05:25 +010063}
64
65func TestTranslateDevice(t *testing.T) {
Elia Battiston4750d3c2022-07-14 13:24:56 +000066 olt := &voltha.Device{
67 Id: testDeviceId,
68 Root: true,
69 Vendor: "BBSim",
70 Model: "asfvolt16",
71 SerialNumber: "BBSIM_OLT_10",
72 HardwareVersion: "v0.0.2",
73 FirmwareVersion: "v0.0.3",
74 AdminState: voltha.AdminState_ENABLED,
75 OperStatus: voltha.OperStatus_ACTIVE,
Elia Battistone1cecb22022-03-21 10:05:25 +010076 }
77 items := translateDevice(olt)
78
Elia Battiston4750d3c2022-07-14 13:24:56 +000079 oltPath := getDevicePath(testDeviceId)
80 oltHwPath := getDeviceHardwarePath(testDeviceId)
Elia Battistone1cecb22022-03-21 10:05:25 +010081
Elia Battiston4750d3c2022-07-14 13:24:56 +000082 expected := []YangItem{
83 {
84 Path: oltPath + "/type",
85 Value: DeviceTypeOlt,
86 },
87 {
88 Path: oltHwPath + "/mfg-name",
89 Value: "BBSim",
90 },
91 {
92 Path: oltHwPath + "/model-name",
93 Value: "asfvolt16",
94 },
95 {
96 Path: oltHwPath + "/hardware-rev",
97 Value: "v0.0.2",
98 },
99 {
100 Path: oltHwPath + "/firmware-rev",
101 Value: "v0.0.3",
102 },
103 {
104 Path: oltHwPath + "/serial-num",
105 Value: "BBSIM_OLT_10",
106 },
107 {
108 Path: oltHwPath + "/state/admin-state",
109 Value: ietfAdminStateUnlocked,
110 },
111 {
112 Path: oltHwPath + "/state/oper-state",
113 Value: ietfOperStateEnabled,
114 },
115 }
116
117 assert.NotEmpty(t, items, "No OLT items")
118 for _, e := range expected {
119 val, ok := getItemWithPath(items, e.Path)
120 assert.True(t, ok, e.Path+" missing for OLT")
121 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
122 }
123
124 onu := &voltha.Device{
125 Id: testDeviceId,
126 Root: false,
127 Vendor: "BBSM",
128 Model: "v0.0.1",
129 SerialNumber: "BBSM000a0001",
130 HardwareVersion: "v0.0.2",
131 FirmwareVersion: "v0.0.3",
132 AdminState: voltha.AdminState_ENABLED,
133 OperStatus: voltha.OperStatus_ACTIVE,
Elia Battistona1333642022-07-27 12:17:24 +0000134 ParentId: "abcdef1234",
135 ParentPortNo: 1,
Elia Battistone1cecb22022-03-21 10:05:25 +0100136 }
137 items = translateDevice(onu)
138
Elia Battiston4750d3c2022-07-14 13:24:56 +0000139 onuPath := getDevicePath(testDeviceId)
140 onuHwPath := getDeviceHardwarePath(testDeviceId)
141
142 expected = []YangItem{
143 {
144 Path: onuPath + "/type",
145 Value: DeviceTypeOnu,
146 },
147 {
148 Path: onuHwPath + "/mfg-name",
149 Value: "BBSM",
150 },
151 {
152 Path: onuHwPath + "/model-name",
153 Value: "v0.0.1",
154 },
155 {
156 Path: onuHwPath + "/hardware-rev",
157 Value: "v0.0.2",
158 },
159 {
160 Path: onuHwPath + "/firmware-rev",
161 Value: "v0.0.3",
162 },
163 {
164 Path: onuHwPath + "/serial-num",
165 Value: "BBSM000a0001",
166 },
167 {
168 Path: onuHwPath + "/state/admin-state",
169 Value: ietfAdminStateUnlocked,
170 },
171 {
172 Path: onuHwPath + "/state/oper-state",
173 Value: ietfOperStateEnabled,
174 },
Elia Battistona1333642022-07-27 12:17:24 +0000175 {
176 Path: onuHwPath + "/parent",
177 Value: "abcdef1234",
178 },
179 {
180 Path: onuHwPath + "/parent-rel-pos",
181 Value: "1",
182 },
Elia Battiston4750d3c2022-07-14 13:24:56 +0000183 }
184
185 assert.NotEmpty(t, items, "No ONU items")
186 for _, e := range expected {
187 val, ok := getItemWithPath(items, e.Path)
188 assert.True(t, ok, e.Path+" missing for ONU")
189 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
190 }
Elia Battistone1cecb22022-03-21 10:05:25 +0100191}
192
Elia Battiston4750d3c2022-07-14 13:24:56 +0000193func TestTranslateOnuPorts(t *testing.T) {
194 ports := &voltha.Ports{
195 Items: []*voltha.Port{
196 {
197 PortNo: 0,
198 Type: voltha.Port_ETHERNET_UNI,
199 OperStatus: voltha.OperStatus_ACTIVE,
200 },
201 },
Elia Battistone1cecb22022-03-21 10:05:25 +0100202 }
203
Elia Battiston4750d3c2022-07-14 13:24:56 +0000204 _, err := translateOnuPorts(testDeviceId, ports)
205 assert.Error(t, err, "No error for missing Ofp port")
206
207 ports = &voltha.Ports{
208 Items: []*voltha.Port{
209 {
210 PortNo: 0,
211 Type: voltha.Port_ETHERNET_UNI,
212 OfpPort: &openflow_13.OfpPort{
213 Name: "BBSM000a0001-1",
214 },
215 OperStatus: voltha.OperStatus_ACTIVE,
216 },
217 {
218 PortNo: 1,
219 Type: voltha.Port_ETHERNET_UNI,
220 OfpPort: &openflow_13.OfpPort{
221 Name: "BBSM000a0001-2",
222 },
223 OperStatus: voltha.OperStatus_UNKNOWN,
224 },
225 {
226 PortNo: 0,
227 Type: voltha.Port_PON_ONU,
228 OperStatus: voltha.OperStatus_UNKNOWN,
229 },
230 },
Elia Battistone1cecb22022-03-21 10:05:25 +0100231 }
232
Elia Battiston4750d3c2022-07-14 13:24:56 +0000233 portsItems, err := translateOnuPorts(testDeviceId, ports)
234 assert.Nil(t, err, "Translation error")
Elia Battistone1cecb22022-03-21 10:05:25 +0100235
Elia Battiston4750d3c2022-07-14 13:24:56 +0000236 /*2 items for 2 UNIs, PON is ignored*/
237 assert.Equal(t, 4, len(portsItems), "No ports items")
Elia Battistone1cecb22022-03-21 10:05:25 +0100238
Elia Battiston4750d3c2022-07-14 13:24:56 +0000239 interfacesPath := getDevicePath(testDeviceId) + "/data/ietf-interfaces:interfaces"
Elia Battistone1cecb22022-03-21 10:05:25 +0100240
Elia Battiston4750d3c2022-07-14 13:24:56 +0000241 expected := []YangItem{
242 {
243 Path: fmt.Sprintf("%s/interface[name='%s']/oper-status", interfacesPath, "BBSM000a0001-1"),
244 Value: ietfOperStateUp,
245 },
246 {
247 Path: fmt.Sprintf("%s/interface[name='%s']/type", interfacesPath, "BBSM000a0001-1"),
248 Value: "bbf-xpon-if-type:onu-v-vrefpoint",
249 },
250 {
251 Path: fmt.Sprintf("%s/interface[name='%s']/oper-status", interfacesPath, "BBSM000a0001-2"),
252 Value: ietfOperStateUnknown,
253 },
254 {
255 Path: fmt.Sprintf("%s/interface[name='%s']/type", interfacesPath, "BBSM000a0001-2"),
256 Value: "bbf-xpon-if-type:onu-v-vrefpoint",
257 },
258 }
259
260 for _, e := range expected {
261 val, ok := getItemWithPath(portsItems, e.Path)
262 assert.True(t, ok, e.Path+" missing for ports")
263 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
264 }
265}
266
267func TestTranslateOnuActive(t *testing.T) {
268 timestamp := time.Now()
269 eventHeader := &voltha.EventHeader{
270 Id: "Voltha.openolt.ONU_ACTIVATED.1657705515351182767",
271 RaisedTs: timestamppb.New(timestamp),
272 Category: voltha.EventCategory_EQUIPMENT,
273 Type: voltha.EventType_DEVICE_EVENT,
274 }
275
276 deviceEvent := &voltha.DeviceEvent{
277 ResourceId: testDeviceId,
278 DeviceEventName: "ONU_ACTIVATED_RAISE_EVENT",
279 Description: "ONU Event - ONU_ACTIVATED - Raised",
280 Context: map[string]string{},
281 }
282
283 _, _, err := TranslateOnuActivatedEvent(eventHeader, deviceEvent)
284 assert.Error(t, err, "Empty context produces no error")
285
286 deviceEvent.Context[eventContextKeyPonId] = "0"
287 deviceEvent.Context[eventContextKeyOnuSn] = "BBSM000a0001"
288 deviceEvent.Context[eventContextKeyOltSn] = "BBSIM_OLT_10"
289
290 notificationPath := "/bbf-xpon-onu-states:onu-state-change"
291 expected := []YangItem{
292 {
293 Path: notificationPath + "/detected-serial-number",
294 Value: "BBSM000a0001",
295 },
296 {
297 Path: notificationPath + "/onu-state-last-change",
298 Value: timestamp.Format(time.RFC3339),
299 },
300 {
301 Path: notificationPath + "/onu-state",
302 Value: "bbf-xpon-onu-types:onu-present",
303 },
304 {
305 Path: notificationPath + "/detected-registration-id",
306 Value: testDeviceId,
307 },
308 }
309
310 notificationItems, channelTerminationItems, err := TranslateOnuActivatedEvent(eventHeader, deviceEvent)
311 assert.Nil(t, err, "Translation error")
312
313 assert.NotEmpty(t, channelTerminationItems, "No channel termination items")
314
315 assert.NotEmpty(t, notificationItems, "No notification items")
316
317 _, ok := getItemWithPath(notificationItems, notificationPath+"/channel-termination-ref")
318 assert.True(t, ok, "No channel termination reference in notification")
319
320 for _, e := range expected {
321 val, ok := getItemWithPath(notificationItems, e.Path)
322 assert.True(t, ok, e.Path+" missing for notification")
323 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
Elia Battistone1cecb22022-03-21 10:05:25 +0100324 }
325}
Elia Battistona1333642022-07-27 12:17:24 +0000326
327func TestTranslateServices(t *testing.T) {
Elia Battistonaa7a0482022-08-17 12:24:02 +0000328 subscriber := clients.ProgrammedSubscriber{
329 Location: "of:00001/256",
330 TagInfo: clients.SadisUniTag{
331 UniTagMatch: 100,
332 PonCTag: 4096,
333 PonSTag: 102,
334 TechnologyProfileID: 64,
335 UpstreamBandwidthProfile: "BW1",
336 DownstreamBandwidthProfile: "BW2",
337 UpstreamOltBandwidthProfile: "OLTBW",
338 IsDhcpRequired: true,
339 IsIgmpRequired: false,
340 IsPPPoERequired: false,
341 ConfiguredMacAddress: "00:11:22:33:44:55",
342 EnableMacLearning: true,
343 UsPonCTagPriority: 1,
344 UsPonSTagPriority: 2,
345 DsPonCTagPriority: 3,
346 DsPonSTagPriority: -1,
347 ServiceName: "testService",
Elia Battistona1333642022-07-27 12:17:24 +0000348 },
349 }
350
Elia Battistonaa7a0482022-08-17 12:24:02 +0000351 alias := ServiceAlias{
352 Key: ServiceKey{
353 Port: "TESTPORT-1",
354 STag: "101",
355 CTag: "102",
356 TpId: "64",
Elia Battistona1333642022-07-27 12:17:24 +0000357 },
Elia Battistonaa7a0482022-08-17 12:24:02 +0000358 ServiceName: "TESTPORT-1-testService",
359 VlansName: "TESTPORT-1-testService-vlans",
Elia Battistona1333642022-07-27 12:17:24 +0000360 }
361
Elia Battistonaa7a0482022-08-17 12:24:02 +0000362 servicesItesm, err := translateService(subscriber.TagInfo, alias)
Elia Battistona1333642022-07-27 12:17:24 +0000363 assert.Nil(t, err, "Translation error")
364
365 assert.NotEmpty(t, servicesItesm, "No services items")
366
367 servicePortPath := ServiceProfilesPath + "/service-profile[name='TESTPORT-1-testService']/ports/port[name='TESTPORT-1']"
368
369 expected := []YangItem{
370 {
371 Path: servicePortPath + "/bbf-nt-service-profile-voltha:configured-mac-address",
372 Value: "00:11:22:33:44:55",
373 },
374 {
Elia Battistona1333642022-07-27 12:17:24 +0000375 Path: servicePortPath + "/bbf-nt-service-profile-voltha:mac-learning-enabled",
376 Value: "true",
377 },
378 {
379 Path: servicePortPath + "/bbf-nt-service-profile-voltha:dhcp-required",
380 Value: "true",
381 },
382 {
383 Path: servicePortPath + "/bbf-nt-service-profile-voltha:igmp-required",
384 Value: "false",
385 },
386 {
387 Path: servicePortPath + "/bbf-nt-service-profile-voltha:pppoe-required",
388 Value: "false",
389 },
390 }
391
Elia Battistonaa7a0482022-08-17 12:24:02 +0000392 _, ok := getItemWithPath(servicesItesm, servicePortPath+"/port-vlans/port-vlan[name='TESTPORT-1-testService-vlans']")
Elia Battistona1333642022-07-27 12:17:24 +0000393 assert.True(t, ok, "No vlans leafref in services")
394
395 _, ok = getItemWithPath(servicesItesm, servicePortPath+"/bbf-nt-service-profile-voltha:downstream-olt-bp-name")
396 assert.False(t, ok, "Downstream OLT bandwidth profile should not be present")
397
398 for _, e := range expected {
399 val, ok := getItemWithPath(servicesItesm, e.Path)
400 assert.True(t, ok, e.Path+" missing for services")
401 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
402 }
403}
404
405func TestTranslateVlans(t *testing.T) {
Elia Battistonaa7a0482022-08-17 12:24:02 +0000406 subscriber := clients.ProgrammedSubscriber{
407 Location: "of:00001/256",
408 TagInfo: clients.SadisUniTag{
409 UniTagMatch: 100,
410 PonCTag: 4096,
411 PonSTag: 102,
412 TechnologyProfileID: 64,
413 UpstreamBandwidthProfile: "BW1",
414 DownstreamBandwidthProfile: "BW2",
415 UpstreamOltBandwidthProfile: "OLTBW",
416 IsDhcpRequired: true,
417 IsIgmpRequired: false,
418 IsPPPoERequired: false,
419 ConfiguredMacAddress: "00:11:22:33:44:55",
420 EnableMacLearning: true,
421 UsPonCTagPriority: 1,
422 UsPonSTagPriority: 2,
423 DsPonCTagPriority: 3,
424 DsPonSTagPriority: -1,
425 ServiceName: "testService",
Elia Battistona1333642022-07-27 12:17:24 +0000426 },
427 }
428
Elia Battistonaa7a0482022-08-17 12:24:02 +0000429 alias := ServiceAlias{
430 Key: ServiceKey{
431 Port: "TESTPORT-1",
432 STag: "101",
433 CTag: "102",
434 TpId: "64",
Elia Battistona1333642022-07-27 12:17:24 +0000435 },
Elia Battistonaa7a0482022-08-17 12:24:02 +0000436 ServiceName: "TESTPORT-1-testService",
437 VlansName: "TESTPORT-1-testService-vlans",
Elia Battistona1333642022-07-27 12:17:24 +0000438 }
439
Elia Battistonaa7a0482022-08-17 12:24:02 +0000440 vlanItems, err := translateVlans(subscriber.TagInfo, alias)
Elia Battistona1333642022-07-27 12:17:24 +0000441 assert.Nil(t, err, "Translation error")
442
443 assert.NotEmpty(t, vlanItems, "No vlans items")
444
Elia Battistonaa7a0482022-08-17 12:24:02 +0000445 vlanPath := VlansPath + "/vlan-translation-profile[name='TESTPORT-1-testService-vlans']"
Elia Battistona1333642022-07-27 12:17:24 +0000446
447 expected := []YangItem{
448 {
449 Path: vlanPath + "/match-criteria/outer-tag/vlan-id",
450 Value: "100",
451 },
452 {
453 Path: vlanPath + "/ingress-rewrite/push-second-tag/vlan-id",
454 Value: "any",
455 },
456 {
457 Path: vlanPath + "/ingress-rewrite/push-outer-tag/vlan-id",
458 Value: "102",
459 },
460 {
461 Path: vlanPath + "/match-criteria/second-tag/vlan-id",
462 Value: "any",
463 },
464 {
465 Path: vlanPath + "/ingress-rewrite/push-second-tag/pbit",
466 Value: "1",
467 },
468 {
469 Path: vlanPath + "/ingress-rewrite/push-outer-tag/pbit",
470 Value: "2",
471 },
472 {
473 Path: vlanPath + "/ingress-rewrite/push-second-tag/bbf-voltha-vlan-translation:dpbit",
474 Value: "3",
475 },
476 }
477
478 _, ok := getItemWithPath(vlanItems, vlanPath+"/ingress-rewrite/push-outer-tag/bbf-voltha-vlan-translation:dpbit")
479 assert.False(t, ok, "Pbit value should not be present")
480
481 for _, e := range expected {
482 val, ok := getItemWithPath(vlanItems, e.Path)
483 assert.True(t, ok, e.Path+" missing for vlans")
484 assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
485 }
486}