Add initial support for provisioning and removing services, getting service data
Change-Id: Ie49206d788a202e70a8d64f083c3f85b92ced8fb
diff --git a/internal/core/adapter.go b/internal/core/adapter.go
index 6a59650..5e19753 100644
--- a/internal/core/adapter.go
+++ b/internal/core/adapter.go
@@ -30,13 +30,13 @@
type VolthaYangAdapter struct {
volthaNbiClient *clients.VolthaNbiClient
- oltAppClient *clients.OltAppClient
+ onosClient *clients.OnosClient
}
-func NewVolthaYangAdapter(nbiClient *clients.VolthaNbiClient, oltClient *clients.OltAppClient) *VolthaYangAdapter {
+func NewVolthaYangAdapter(nbiClient *clients.VolthaNbiClient, onosClient *clients.OnosClient) *VolthaYangAdapter {
return &VolthaYangAdapter{
volthaNbiClient: nbiClient,
- oltAppClient: oltClient,
+ onosClient: onosClient,
}
}
@@ -58,7 +58,7 @@
if err != nil {
return nil, fmt.Errorf("get-onu-ports-failed: %v", err)
}
- logger.Debugw(ctx, "get-ports-success", log.Fields{"deviceId": device.Id, "ports": ports})
+ logger.Debugw(ctx, "get-onu-ports-success", log.Fields{"deviceId": device.Id, "ports": ports})
portsItems, err := translateOnuPorts(device.Id, ports)
if err != nil {
@@ -75,3 +75,114 @@
return items, nil
}
+
+func (t *VolthaYangAdapter) GetVlans(ctx context.Context) ([]YangItem, error) {
+ services, err := t.onosClient.GetProgrammedSubscribers()
+ if err != nil {
+ return nil, fmt.Errorf("get-programmed-subscribers-failed: %v", err)
+ }
+ logger.Debugw(ctx, "get-programmed-subscribers-success", log.Fields{"services": services})
+
+ //No need for other requests if there are no services
+ if len(services) == 0 {
+ return []YangItem{}, nil
+ }
+
+ ports, err := t.onosClient.GetPorts()
+ if err != nil {
+ return nil, fmt.Errorf("get-onos-ports-failed: %v", err)
+ }
+ logger.Debugw(ctx, "get-onos-ports-success", log.Fields{"ports": ports})
+
+ items, err := translateVlans(services, ports)
+ if err != nil {
+ return nil, fmt.Errorf("cannot-translate-vlans: %v", err)
+ }
+
+ return items, nil
+}
+
+func (t *VolthaYangAdapter) GetBandwidthProfiles(ctx context.Context) ([]YangItem, error) {
+ services, err := t.onosClient.GetProgrammedSubscribers()
+ if err != nil {
+ return nil, fmt.Errorf("get-programmed-subscribers-failed: %v", err)
+ }
+ logger.Debugw(ctx, "get-programmed-subscribers-success", log.Fields{"services": services})
+
+ //No need for other requests if there are no services
+ if len(services) == 0 {
+ return []YangItem{}, nil
+ }
+
+ bwProfilesMap := map[string]bool{}
+ bwProfiles := []clients.BandwidthProfile{}
+
+ for _, service := range services {
+ //Get information on downstream bw profile if new
+ if _, ok := bwProfilesMap[service.TagInfo.DownstreamBandwidthProfile]; !ok {
+ bw, err := t.onosClient.GetBandwidthProfile(service.TagInfo.DownstreamBandwidthProfile)
+ if err != nil {
+ return nil, fmt.Errorf("get-bw-profile-failed: %s %v", service.TagInfo.DownstreamBandwidthProfile, err)
+ }
+ logger.Debugw(ctx, "get-bw-profile-success", log.Fields{"bwProfile": bw})
+
+ bwProfiles = append(bwProfiles, *bw)
+ bwProfilesMap[service.TagInfo.DownstreamBandwidthProfile] = true
+ }
+
+ //Get information on upstream bw profile if new
+ if _, ok := bwProfilesMap[service.TagInfo.UpstreamBandwidthProfile]; !ok {
+ bw, err := t.onosClient.GetBandwidthProfile(service.TagInfo.UpstreamBandwidthProfile)
+ if err != nil {
+ return nil, fmt.Errorf("get-bw-profile-failed: %s %v", service.TagInfo.UpstreamBandwidthProfile, err)
+ }
+ logger.Debugw(ctx, "get-bw-profile-success", log.Fields{"bwProfile": bw})
+
+ bwProfiles = append(bwProfiles, *bw)
+ bwProfilesMap[service.TagInfo.UpstreamBandwidthProfile] = true
+ }
+ }
+
+ items, err := translateBandwidthProfiles(bwProfiles)
+ if err != nil {
+ return nil, fmt.Errorf("cannot-translate-bandwidth-profiles: %v", err)
+ }
+
+ return items, nil
+}
+
+func (t *VolthaYangAdapter) GetServices(ctx context.Context) ([]YangItem, error) {
+ services, err := t.onosClient.GetProgrammedSubscribers()
+ if err != nil {
+ return nil, fmt.Errorf("get-programmed-subscribers-failed: %v", err)
+ }
+ logger.Debugw(ctx, "get-programmed-subscribers-success", log.Fields{"services": services})
+
+ //No need for other requests if there are no services
+ if len(services) == 0 {
+ return []YangItem{}, nil
+ }
+
+ ports, err := t.onosClient.GetPorts()
+ if err != nil {
+ return nil, fmt.Errorf("get-onos-ports-failed: %v", err)
+ }
+ logger.Debugw(ctx, "get-onos-ports-success", log.Fields{"ports": ports})
+
+ items, err := translateServices(services, ports)
+ if err != nil {
+ return nil, fmt.Errorf("cannot-translate-services: %v", err)
+ }
+
+ return items, nil
+}
+
+func (t *VolthaYangAdapter) ProvisionService(portName string, sTag string, cTag string, technologyProfileId string) error {
+ _, err := t.onosClient.ProvisionService(portName, sTag, cTag, technologyProfileId)
+ return err
+}
+
+func (t *VolthaYangAdapter) RemoveService(portName string, sTag string, cTag string, technologyProfileId string) error {
+ _, err := t.onosClient.RemoveService(portName, sTag, cTag, technologyProfileId)
+ return err
+}
diff --git a/internal/core/translation.go b/internal/core/translation.go
index ef6582d..623e261 100644
--- a/internal/core/translation.go
+++ b/internal/core/translation.go
@@ -18,8 +18,10 @@
import (
"fmt"
+ "strconv"
"time"
+ "github.com/opencord/voltha-northbound-bbf-adapter/internal/clients"
"github.com/opencord/voltha-protos/v5/go/common"
"github.com/opencord/voltha-protos/v5/go/voltha"
)
@@ -28,6 +30,15 @@
DeviceAggregationModule = "bbf-device-aggregation"
DevicesPath = "/" + DeviceAggregationModule + ":devices"
+ ServiceProfileModule = "bbf-nt-service-profile"
+ ServiceProfilesPath = "/" + ServiceProfileModule + ":service-profiles"
+
+ VlansModule = "bbf-l2-access-attributes"
+ VlansPath = "/" + VlansModule + ":vlan-translation-profiles"
+
+ BandwidthProfileModule = "bbf-nt-line-profile"
+ BandwidthProfilesPath = "/" + BandwidthProfileModule + ":line-bandwidth-profiles"
+
//Device types
DeviceTypeOlt = "bbf-device-types:olt"
DeviceTypeOnu = "bbf-device-types:onu"
@@ -49,6 +60,10 @@
eventContextKeyPonId = "pon-id"
eventContextKeyOnuSn = "serial-number"
eventContextKeyOltSn = "olt-serial-number"
+
+ //Values to allow any VLAN ID
+ YangVlanIdAny = "any"
+ VolthaVlanIdAny = 4096
)
type YangItem struct {
@@ -66,6 +81,16 @@
return fmt.Sprintf("%s/device[name='%s']/data/ietf-hardware:hardware/component[name='%s']", DevicesPath, id, id)
}
+//GetServicePortPath returns the yang path to a service's port node
+func GetServicePortPath(serviceName string, portName string) string {
+ return fmt.Sprintf("%s/service-profile[name='%s']/ports/port[name='%s']", ServiceProfilesPath, serviceName, portName)
+}
+
+//GetVlansPath returns the yang path to a vlan translation profile's root node
+func GetVlansPath(serviceName string) string {
+ return fmt.Sprintf("%s/vlan-translation-profile[name='%s']", VlansPath, serviceName)
+}
+
//ietfHardwareAdminState returns the string that represents the ietf-hardware admin state
//enum value corresponding to the one of VOLTHA
func ietfHardwareAdminState(volthaAdminState voltha.AdminState_Types) string {
@@ -146,10 +171,20 @@
})
} else {
//ONU
- result = append(result, YangItem{
- Path: devicePath + "/type",
- Value: DeviceTypeOnu,
- })
+ result = append(result, []YangItem{
+ {
+ Path: devicePath + "/type",
+ Value: DeviceTypeOnu,
+ },
+ {
+ Path: hardwarePath + "/parent",
+ Value: device.ParentId,
+ },
+ {
+ Path: hardwarePath + "/parent-rel-pos",
+ Value: strconv.FormatUint(uint64(device.ParentPortNo), 10),
+ },
+ }...)
}
//Vendor name
@@ -284,3 +319,193 @@
return notification, channelTermination, nil
}
+
+//translateServices returns a slice of yang items that represent the currently programmed services
+func translateServices(subscribers []clients.ProgrammedSubscriber, ports []clients.OnosPort) ([]YangItem, error) {
+ //Create a map of port IDs to port names
+ //e.g. of:00000a0a0a0a0a0a/256 to BBSM000a0001-1
+ portNames := map[string]string{}
+
+ for _, port := range ports {
+ portId := fmt.Sprintf("%s/%s", port.Element, port.Port)
+ name, ok := port.Annotations["portName"]
+ if ok {
+ portNames[portId] = name
+ }
+ }
+
+ result := []YangItem{}
+
+ for _, subscriber := range subscribers {
+ portName, ok := portNames[subscriber.Location]
+ if !ok {
+ return nil, fmt.Errorf("no-port-name-for-location: %s", subscriber.Location)
+ }
+
+ serviceName := fmt.Sprintf("%s-%s", portName, subscriber.TagInfo.ServiceName)
+
+ portPath := GetServicePortPath(serviceName, portName)
+
+ if subscriber.TagInfo.ConfiguredMacAddress != "" {
+ result = append(result, YangItem{
+ Path: portPath + "/bbf-nt-service-profile-voltha:configured-mac-address",
+ Value: subscriber.TagInfo.ConfiguredMacAddress,
+ })
+ }
+
+ result = append(result, []YangItem{
+ {
+ Path: fmt.Sprintf("%s/port-vlans/port-vlan[name='%s']", portPath, serviceName),
+ Value: "",
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:technology-profile-id",
+ Value: strconv.Itoa(subscriber.TagInfo.TechnologyProfileID),
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:downstream-subscriber-bp-name",
+ Value: subscriber.TagInfo.DownstreamBandwidthProfile,
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:upstream-subscriber-bp-name",
+ Value: subscriber.TagInfo.UpstreamBandwidthProfile,
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:mac-learning-enabled",
+ Value: strconv.FormatBool(subscriber.TagInfo.EnableMacLearning),
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:dhcp-required",
+ Value: strconv.FormatBool(subscriber.TagInfo.IsDhcpRequired),
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:igmp-required",
+ Value: strconv.FormatBool(subscriber.TagInfo.IsIgmpRequired),
+ },
+ {
+ Path: portPath + "/bbf-nt-service-profile-voltha:pppoe-required",
+ Value: strconv.FormatBool(subscriber.TagInfo.IsPPPoERequired),
+ },
+ }...)
+
+ if subscriber.TagInfo.UpstreamOltBandwidthProfile != "" {
+ result = append(result, YangItem{
+ Path: portPath + "/bbf-nt-service-profile-voltha:upstream-olt-bp-name",
+ Value: subscriber.TagInfo.UpstreamOltBandwidthProfile,
+ })
+ }
+
+ if subscriber.TagInfo.DownstreamOltBandwidthProfile != "" {
+ result = append(result, YangItem{
+ Path: portPath + "/bbf-nt-service-profile-voltha:downstream-olt-bp-name",
+ Value: subscriber.TagInfo.UpstreamOltBandwidthProfile,
+ })
+ }
+ }
+
+ return result, nil
+}
+
+//translateVlans returns a slice of yang items that represent the vlans used by programmed services
+func translateVlans(subscribers []clients.ProgrammedSubscriber, ports []clients.OnosPort) ([]YangItem, error) {
+ //Create a map of port IDs to port names
+ //e.g. of:00000a0a0a0a0a0a/256 to BBSM000a0001-1
+ portNames := map[string]string{}
+
+ for _, port := range ports {
+ portId := fmt.Sprintf("%s/%s", port.Element, port.Port)
+ name, ok := port.Annotations["portName"]
+ if ok {
+ portNames[portId] = name
+ }
+ }
+
+ result := []YangItem{}
+
+ for _, subscriber := range subscribers {
+ portName, ok := portNames[subscriber.Location]
+ if !ok {
+ return nil, fmt.Errorf("no-port-name-for-location: %s", subscriber.Location)
+ }
+
+ serviceName := fmt.Sprintf("%s-%s", portName, subscriber.TagInfo.ServiceName)
+
+ vlansPath := GetVlansPath(serviceName)
+
+ uniTagMatch := YangVlanIdAny
+ sTag := YangVlanIdAny
+ cTag := YangVlanIdAny
+
+ if subscriber.TagInfo.UniTagMatch != VolthaVlanIdAny {
+ uniTagMatch = strconv.Itoa(subscriber.TagInfo.UniTagMatch)
+ }
+ if subscriber.TagInfo.PonSTag != VolthaVlanIdAny {
+ sTag = strconv.Itoa(subscriber.TagInfo.PonSTag)
+ }
+ if subscriber.TagInfo.PonCTag != VolthaVlanIdAny {
+ cTag = strconv.Itoa(subscriber.TagInfo.PonCTag)
+ }
+
+ if subscriber.TagInfo.UniTagMatch > 0 {
+ result = append(result, []YangItem{
+ {
+ Path: vlansPath + "/match-criteria/outer-tag/vlan-id",
+ Value: uniTagMatch,
+ },
+ {
+ Path: vlansPath + "/match-criteria/second-tag/vlan-id",
+ Value: "any",
+ },
+ }...)
+ }
+
+ if subscriber.TagInfo.UsPonSTagPriority >= 0 {
+ result = append(result, YangItem{
+ Path: vlansPath + "/ingress-rewrite/push-outer-tag/pbit",
+ Value: strconv.Itoa(subscriber.TagInfo.UsPonSTagPriority),
+ })
+ }
+ if subscriber.TagInfo.DsPonSTagPriority >= 0 {
+ result = append(result, YangItem{
+ Path: vlansPath + "/ingress-rewrite/push-outer-tag/bbf-voltha-vlan-translation:dpbit",
+ Value: strconv.Itoa(subscriber.TagInfo.DsPonSTagPriority),
+ })
+ }
+ if subscriber.TagInfo.UsPonCTagPriority >= 0 {
+ result = append(result, YangItem{
+ Path: vlansPath + "/ingress-rewrite/push-second-tag/pbit",
+ Value: strconv.Itoa(subscriber.TagInfo.UsPonCTagPriority),
+ })
+ }
+ if subscriber.TagInfo.DsPonCTagPriority >= 0 {
+ result = append(result, YangItem{
+ Path: vlansPath + "/ingress-rewrite/push-second-tag/bbf-voltha-vlan-translation:dpbit",
+ Value: strconv.Itoa(subscriber.TagInfo.DsPonCTagPriority),
+ })
+ }
+
+ result = append(result, []YangItem{
+ {
+ Path: vlansPath + "/ingress-rewrite/push-outer-tag/vlan-id",
+ Value: sTag,
+ },
+ {
+ Path: vlansPath + "/ingress-rewrite/push-second-tag/vlan-id",
+ Value: cTag,
+ },
+ }...)
+ }
+
+ return result, nil
+}
+
+//translateBandwidthProfiles returns a slice of yang items that represent the bandwidth profiles used by programmed services
+func translateBandwidthProfiles(bwProfiles []clients.BandwidthProfile) ([]YangItem, error) {
+ result := []YangItem{}
+
+ //TODO: The best way to translate this information is still under discussion, but the code
+ // to retrieve it is ready. Since this is not fundamental at the moment, an empty slice is
+ // returned, and the correct translation can be added here at a later time.
+
+ return result, nil
+}
diff --git a/internal/core/translation_test.go b/internal/core/translation_test.go
index 41dc1dc..837acd9 100644
--- a/internal/core/translation_test.go
+++ b/internal/core/translation_test.go
@@ -21,6 +21,7 @@
"testing"
"time"
+ "github.com/opencord/voltha-northbound-bbf-adapter/internal/clients"
"github.com/opencord/voltha-protos/v5/go/openflow_13"
"github.com/opencord/voltha-protos/v5/go/voltha"
"github.com/stretchr/testify/assert"
@@ -43,7 +44,22 @@
func TestDevicePath(t *testing.T) {
path := getDevicePath(testDeviceId)
- assert.Equal(t, fmt.Sprintf("/bbf-device-aggregation:devices/device[name='%s']", testDeviceId), path)
+ assert.Equal(t, "/bbf-device-aggregation:devices/device[name='123145abcdef']", path)
+}
+
+func TestDeviceHardwarePath(t *testing.T) {
+ path := getDeviceHardwarePath(testDeviceId)
+ assert.Equal(t, "/bbf-device-aggregation:devices/device[name='123145abcdef']/data/ietf-hardware:hardware/component[name='123145abcdef']", path)
+}
+
+func TestServicePortPath(t *testing.T) {
+ path := GetServicePortPath("testService", "testPort")
+ assert.Equal(t, "/bbf-nt-service-profile:service-profiles/service-profile[name='testService']/ports/port[name='testPort']", path)
+}
+
+func TestVlansPath(t *testing.T) {
+ path := GetVlansPath("testProfile")
+ assert.Equal(t, "/bbf-l2-access-attributes:vlan-translation-profiles/vlan-translation-profile[name='testProfile']", path)
}
func TestTranslateDevice(t *testing.T) {
@@ -115,6 +131,8 @@
FirmwareVersion: "v0.0.3",
AdminState: voltha.AdminState_ENABLED,
OperStatus: voltha.OperStatus_ACTIVE,
+ ParentId: "abcdef1234",
+ ParentPortNo: 1,
}
items = translateDevice(onu)
@@ -154,6 +172,14 @@
Path: onuHwPath + "/state/oper-state",
Value: ietfOperStateEnabled,
},
+ {
+ Path: onuHwPath + "/parent",
+ Value: "abcdef1234",
+ },
+ {
+ Path: onuHwPath + "/parent-rel-pos",
+ Value: "1",
+ },
}
assert.NotEmpty(t, items, "No ONU items")
@@ -297,3 +323,192 @@
assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
}
}
+
+func TestTranslateServices(t *testing.T) {
+ subscribers := []clients.ProgrammedSubscriber{
+ {
+ Location: "of:00001/256",
+ TagInfo: clients.SadisUniTag{
+ UniTagMatch: 100,
+ PonCTag: 4096,
+ PonSTag: 102,
+ TechnologyProfileID: 64,
+ UpstreamBandwidthProfile: "BW1",
+ DownstreamBandwidthProfile: "BW2",
+ UpstreamOltBandwidthProfile: "OLTBW",
+ IsDhcpRequired: true,
+ IsIgmpRequired: false,
+ IsPPPoERequired: false,
+ ConfiguredMacAddress: "00:11:22:33:44:55",
+ EnableMacLearning: true,
+ UsPonCTagPriority: 1,
+ UsPonSTagPriority: 2,
+ DsPonCTagPriority: 3,
+ DsPonSTagPriority: -1,
+ ServiceName: "testService",
+ },
+ },
+ }
+
+ ports := []clients.OnosPort{
+ {
+ Element: "of:00001",
+ Port: "256",
+ Annotations: map[string]string{
+ "portName": "TESTPORT-1",
+ },
+ },
+ {
+ Element: "of:00001",
+ Port: "257",
+ Annotations: map[string]string{
+ "portName": "TESTPORT-2",
+ },
+ },
+ }
+
+ servicesItesm, err := translateServices(subscribers, ports)
+ assert.Nil(t, err, "Translation error")
+
+ assert.NotEmpty(t, servicesItesm, "No services items")
+
+ servicePortPath := ServiceProfilesPath + "/service-profile[name='TESTPORT-1-testService']/ports/port[name='TESTPORT-1']"
+
+ expected := []YangItem{
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:configured-mac-address",
+ Value: "00:11:22:33:44:55",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:upstream-subscriber-bp-name",
+ Value: "BW1",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:downstream-subscriber-bp-name",
+ Value: "BW2",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:upstream-olt-bp-name",
+ Value: "OLTBW",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:mac-learning-enabled",
+ Value: "true",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:dhcp-required",
+ Value: "true",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:igmp-required",
+ Value: "false",
+ },
+ {
+ Path: servicePortPath + "/bbf-nt-service-profile-voltha:pppoe-required",
+ Value: "false",
+ },
+ }
+
+ _, ok := getItemWithPath(servicesItesm, servicePortPath+"/port-vlans/port-vlan[name='TESTPORT-1-testService']")
+ assert.True(t, ok, "No vlans leafref in services")
+
+ _, ok = getItemWithPath(servicesItesm, servicePortPath+"/bbf-nt-service-profile-voltha:downstream-olt-bp-name")
+ assert.False(t, ok, "Downstream OLT bandwidth profile should not be present")
+
+ for _, e := range expected {
+ val, ok := getItemWithPath(servicesItesm, e.Path)
+ assert.True(t, ok, e.Path+" missing for services")
+ assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
+ }
+}
+
+func TestTranslateVlans(t *testing.T) {
+ subscribers := []clients.ProgrammedSubscriber{
+ {
+ Location: "of:00001/256",
+ TagInfo: clients.SadisUniTag{
+ UniTagMatch: 100,
+ PonCTag: 4096,
+ PonSTag: 102,
+ TechnologyProfileID: 64,
+ UpstreamBandwidthProfile: "BW1",
+ DownstreamBandwidthProfile: "BW2",
+ UpstreamOltBandwidthProfile: "OLTBW",
+ IsDhcpRequired: true,
+ IsIgmpRequired: false,
+ IsPPPoERequired: false,
+ ConfiguredMacAddress: "00:11:22:33:44:55",
+ EnableMacLearning: true,
+ UsPonCTagPriority: 1,
+ UsPonSTagPriority: 2,
+ DsPonCTagPriority: 3,
+ DsPonSTagPriority: -1,
+ ServiceName: "testService",
+ },
+ },
+ }
+
+ ports := []clients.OnosPort{
+ {
+ Element: "of:00001",
+ Port: "256",
+ Annotations: map[string]string{
+ "portName": "TESTPORT-1",
+ },
+ },
+ {
+ Element: "of:00001",
+ Port: "257",
+ Annotations: map[string]string{
+ "portName": "TESTPORT-2",
+ },
+ },
+ }
+
+ vlanItems, err := translateVlans(subscribers, ports)
+ assert.Nil(t, err, "Translation error")
+
+ assert.NotEmpty(t, vlanItems, "No vlans items")
+
+ vlanPath := VlansPath + "/vlan-translation-profile[name='TESTPORT-1-testService']"
+
+ expected := []YangItem{
+ {
+ Path: vlanPath + "/match-criteria/outer-tag/vlan-id",
+ Value: "100",
+ },
+ {
+ Path: vlanPath + "/ingress-rewrite/push-second-tag/vlan-id",
+ Value: "any",
+ },
+ {
+ Path: vlanPath + "/ingress-rewrite/push-outer-tag/vlan-id",
+ Value: "102",
+ },
+ {
+ Path: vlanPath + "/match-criteria/second-tag/vlan-id",
+ Value: "any",
+ },
+ {
+ Path: vlanPath + "/ingress-rewrite/push-second-tag/pbit",
+ Value: "1",
+ },
+ {
+ Path: vlanPath + "/ingress-rewrite/push-outer-tag/pbit",
+ Value: "2",
+ },
+ {
+ Path: vlanPath + "/ingress-rewrite/push-second-tag/bbf-voltha-vlan-translation:dpbit",
+ Value: "3",
+ },
+ }
+
+ _, ok := getItemWithPath(vlanItems, vlanPath+"/ingress-rewrite/push-outer-tag/bbf-voltha-vlan-translation:dpbit")
+ assert.False(t, ok, "Pbit value should not be present")
+
+ for _, e := range expected {
+ val, ok := getItemWithPath(vlanItems, e.Path)
+ assert.True(t, ok, e.Path+" missing for vlans")
+ assert.Equal(t, e.Value, val, "Wrong value for "+e.Path)
+ }
+}