From c3b74d1bb98efe98a35fb32f5e54e3a408041ab8 Mon Sep 17 00:00:00 2001 From: sunilprgit Date: Thu, 28 Mar 2024 19:52:06 +0530 Subject: [PATCH] Add automation for testcase RT-7.5 (#2859) --- .../otg_tests/link_bandwidth_test/README.md | 0 .../link_bandwidth_test.go | 829 ++++++++++++++++++ .../link_bandwidth_test/metadata.textproto | 25 + internal/deviations/deviations.go | 5 + proto/metadata.proto | 3 +- proto/metadata_go_proto/metadata.pb.go | 97 +- testregistry.textproto | 2 +- 7 files changed, 918 insertions(+), 43 deletions(-) rename feature/{bgp/policybase => experimental/bgp}/otg_tests/link_bandwidth_test/README.md (100%) create mode 100644 feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go create mode 100644 feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto diff --git a/feature/bgp/policybase/otg_tests/link_bandwidth_test/README.md b/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md similarity index 100% rename from feature/bgp/policybase/otg_tests/link_bandwidth_test/README.md rename to feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md diff --git a/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go b/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go new file mode 100644 index 00000000000..a45aaefada9 --- /dev/null +++ b/feature/experimental/bgp/otg_tests/link_bandwidth_test/link_bandwidth_test.go @@ -0,0 +1,829 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package link_bandwidth_test + +import ( + "testing" + "time" + + "github.com/open-traffic-generator/snappi/gosnappi" + "github.com/openconfig/featureprofiles/internal/attrs" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/otgutils" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + otgtelemetry "github.com/openconfig/ondatra/gnmi/otg" + "github.com/openconfig/ygnmi/ygnmi" + "github.com/openconfig/ygot/ygot" +) + +const ( + ipv4PrefixLen = 30 + ipv6PrefixLen = 126 + v41Route = "203.0.113.0" + v41TrafficStart = "203.0.113.1" + v42Route = "203.0.114.0" + v42TrafficStart = "203.0.114.1" + v43Route = "203.0.115.0" + v43TrafficStart = "203.0.115.1" + v4RoutePrefix = uint32(24) + v61Route = "2001:db8:128:128::0" + v61TrafficStart = "2001:db8:128:128::1" + v62Route = "2001:db8:128:129::0" + v62TrafficStart = "2001:db8:128:129::1" + v63Route = "2001:db8:128:130::0" + v63TrafficStart = "2001:db8:128:130::1" + v6RoutePrefix = uint32(64) + dutAS = uint32(65656) + ateAS = uint32(65657) + bgpName = "BGP" + maskLenExact = "exact" + localPref = 200 + v4Flow = "flow-v4" + v6Flow = "flow-v6" +) + +var ( + dutPort1 = attrs.Attributes{ + Desc: "dutPort1", + IPv4: "192.0.2.1", + IPv4Len: ipv4PrefixLen, + IPv6: "2001:db8::192:0:2:1", + IPv6Len: ipv6PrefixLen, + } + + atePort1 = attrs.Attributes{ + Name: "atePort1", + MAC: "02:00:01:01:01:01", + IPv4: "192.0.2.2", + IPv4Len: ipv4PrefixLen, + IPv6: "2001:db8::192:0:2:2", + IPv6Len: ipv6PrefixLen, + } + + dutPort2 = attrs.Attributes{ + Desc: "dutPort2", + IPv4: "192.0.2.5", + IPv4Len: ipv4PrefixLen, + IPv6: "2001:db8::192:0:2:5", + IPv6Len: ipv6PrefixLen, + } + + atePort2 = attrs.Attributes{ + Name: "atePort2", + MAC: "02:00:01:01:01:02", + IPv4: "192.0.2.6", + IPv4Len: ipv4PrefixLen, + IPv6: "2001:db8::192:0:2:6", + IPv6Len: ipv6PrefixLen, + } + + advertisedIPv41 = ipAddr{address: v41Route, prefix: v4RoutePrefix} + advertisedIPv42 = ipAddr{address: v42Route, prefix: v4RoutePrefix} + advertisedIPv43 = ipAddr{address: v43Route, prefix: v4RoutePrefix} + advertisedIPv61 = ipAddr{address: v61Route, prefix: v6RoutePrefix} + advertisedIPv62 = ipAddr{address: v62Route, prefix: v6RoutePrefix} + advertisedIPv63 = ipAddr{address: v63Route, prefix: v6RoutePrefix} + extCommunitySet = map[string]string{ + "linkbw_0": "link-bandwidth:100:0", + "linkbw_1M": "link-bandwidth:100:1M", + "inkbw_2G": "link-bandwidth:100:2G", + "regex_match_comm100": "^100:.*$", + "linkbw_any": "^link-bandwidth:.*:.$", + "linkbw_any_0": "^link-bandwidth:.*:0$", + } +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +type ipAddr struct { + address string + prefix uint32 +} + +type testData struct { + dut *ondatra.DUTDevice + ate *ondatra.ATEDevice + top gosnappi.Config + otgP1 gosnappi.Device + otgP2 gosnappi.Device +} + +type extCommunity struct { + prefixSet1Comm string + prefixSet2Comm string + prefixSet3Comm string +} + +type flowConfig struct { + src attrs.Attributes + dstNw string + dstIP string +} + +func TestBGPLinkBandwidth(t *testing.T) { + dut := ondatra.DUT(t, "dut") + configureDUT(t, dut) + ate := ondatra.ATE(t, "ate") + top := gosnappi.NewConfig() + devs := configureOTG(t, ate, top) + td := testData{ + dut: dut, + ate: ate, + top: top, + otgP1: devs[0], + otgP2: devs[1], + } + type testCase struct { + name string + policyName string + applyPolicy func(t *testing.T, dut *ondatra.DUTDevice, policyName string) + validate func(t *testing.T, dut *ondatra.DUTDevice, policyName string) + routeCommunity extCommunity + localPerf bool + validateRouteCommunityV4 func(t *testing.T, td testData, ec extCommunity, localPerf bool) + validateRouteCommunityV6 func(t *testing.T, td testData, ec extCommunity, localPerf bool) + } + baseSetupConfigAndVerification(t, td) + configureExtCommunityRoutingPolicy(t, dut) + testCases := []testCase{ + { + name: "Policy set link bandwidth 0", + policyName: "set_linkbw_0", + applyPolicy: applyPolicyDut, + validate: validatPolicyDut, + routeCommunity: extCommunity{prefixSet1Comm: "link-bandwidth:100:0", prefixSet2Comm: "link-bandwidth:100:0", prefixSet3Comm: "link-bandwidth:100:0"}, + localPerf: false, + validateRouteCommunityV4: validateRouteCommunityV4, + validateRouteCommunityV6: validateRouteCommunityV6, + }, + { + name: "Policy set not_match_100_set_linkbw_1M", + policyName: "not_match_100_set_linkbw_1M", + applyPolicy: applyPolicyDut, + validate: validatPolicyDut, + routeCommunity: extCommunity{prefixSet1Comm: "none", prefixSet2Comm: "100:100", prefixSet3Comm: "link-bandwidth:100:0"}, + localPerf: false, + validateRouteCommunityV4: validateRouteCommunityV4, + validateRouteCommunityV6: validateRouteCommunityV6, + }, + { + name: "Policy set match_100_set_linkbw_2G", + policyName: "match_100_set_linkbw_2G", + applyPolicy: applyPolicyDut, + validate: validatPolicyDut, + routeCommunity: extCommunity{prefixSet1Comm: "none", prefixSet2Comm: "link-bandwidth:100:2000000000", prefixSet3Comm: "link-bandwidth:100:0"}, + localPerf: false, + validateRouteCommunityV4: validateRouteCommunityV4, + validateRouteCommunityV6: validateRouteCommunityV6, + }, + { + name: "Policy set del_linkbw", + policyName: "del_linkbw", + applyPolicy: applyPolicyDut, + validate: validatPolicyDut, + routeCommunity: extCommunity{prefixSet1Comm: "none", prefixSet2Comm: "100:100", prefixSet3Comm: "none"}, + localPerf: false, + validateRouteCommunityV4: validateRouteCommunityV4, + validateRouteCommunityV6: validateRouteCommunityV6, + }, + { + name: "Policy set rm_any_zero_bw_set_LocPref_5", + policyName: "match_linkbw_0_remove_and_set_localpref_5", + applyPolicy: applyPolicyDut, + validate: validatPolicyDut, + routeCommunity: extCommunity{prefixSet1Comm: "none", prefixSet2Comm: "100:100", prefixSet3Comm: "none"}, + localPerf: true, + validateRouteCommunityV4: validateRouteCommunityV4, + validateRouteCommunityV6: validateRouteCommunityV6, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Logf("Description: %s", tc.name) + tc.applyPolicy(t, dut, tc.policyName) + tc.validate(t, dut, tc.policyName) + tc.validateRouteCommunityV4(t, td, tc.routeCommunity, tc.localPerf) + tc.validateRouteCommunityV6(t, td, tc.routeCommunity, tc.localPerf) + }) + } +} + +func applyPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName string) { + // Apply ipv4 policy to bgp neighbour. + root := &oc.Root{} + dni := deviations.DefaultNetworkInstance(dut) + path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName). + Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() + + policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName). + GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv4).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateApplyPolicy() + policy.SetImportPolicy([]string{policyName}) + gnmi.Replace(t, dut, path.Config(), policy) + + // Apply ipv6 policy to bgp neighbour. + path = gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() + policy = root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv6).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).GetOrCreateApplyPolicy() + policy.SetImportPolicy([]string{policyName}) + gnmi.Replace(t, dut, path.Config(), policy) +} + +func validatPolicyDut(t *testing.T, dut *ondatra.DUTDevice, policyName string) { + dni := deviations.DefaultNetworkInstance(dut) + path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() + policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) + importPolicies := policy.GetImportPolicy() + if len(importPolicies) != 1 { + t.Fatalf("ImportPolicy Ipv4 got= %v, want %v", importPolicies, []string{policyName}) + } +} + +func validateRouteCommunityV4(t *testing.T, td testData, ec extCommunity, localPerf bool) { + prefixes := map[string]string{ + v41Route: ec.prefixSet1Comm, + v42Route: ec.prefixSet2Comm, + v43Route: ec.prefixSet3Comm, + } + for prefix, community := range prefixes { + validateRouteCommunityV4Prefix(t, td, community, prefix, localPerf) + } +} + +func validateRouteCommunityV4Prefix(t *testing.T, td testData, community, v4Prefix string, localPerf bool) { + _, ok := gnmi.WatchAll(t, + td.ate.OTG(), + gnmi.OTG().BgpPeer(td.otgP2.Name()+".BGP4.peer").UnicastIpv4PrefixAny().State(), + time.Minute, + func(v *ygnmi.Value[*otgtelemetry.BgpPeer_UnicastIpv4Prefix]) bool { + _, present := v.Val() + return present + }).Await(t) + if ok { + bgpPrefixes := gnmi.GetAll(t, td.ate.OTG(), gnmi.OTG().BgpPeer(td.otgP2.Name()+".BGP4.peer").UnicastIpv4PrefixAny().State()) + t.Logf("bgp prefix:%v", bgpPrefixes) + for _, bgpPrefix := range bgpPrefixes { + if bgpPrefix.GetAddress() == v4Prefix { + t.Logf("Prefix recevied on OTG is correct, got Address %s, want prefix %v", bgpPrefix.GetAddress(), v4Prefix) + switch community { + case "none": + if len(bgpPrefix.Community) != 0 { + t.Fatalf("community is not empty it should be none") + } + case "100:100": + for _, gotCommunity := range bgpPrefix.Community { + t.Logf("community AS:%d val: %d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + if gotCommunity.GetCustomAsNumber() != 100 && gotCommunity.GetCustomAsValue() != 100 { + t.Fatalf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + } + } + default: + // TODO Verification as OTG not supported for Extended community/ + t.Logf("TODO: https://github.com/open-traffic-generator/snappi/issues/220 Verification as OTG not supported for Extended community") + if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { + verifyExtCommunityIndexV4(t, td, v4Prefix) + } + } + } + } + } +} + +func validateRouteCommunityV6(t *testing.T, td testData, ec extCommunity, localPerf bool) { + prefixes := map[string]string{ + v61Route: ec.prefixSet1Comm, + v62Route: ec.prefixSet2Comm, + v63Route: ec.prefixSet3Comm, + } + for prefix, community := range prefixes { + validateRouteCommunityV6Prefix(t, td, community, prefix, localPerf) + } +} + +func validateRouteCommunityV6Prefix(t *testing.T, td testData, community, v6Prefix string, localPerf bool) { + + // This function to verify received route communities on ATE ports. + _, ok := gnmi.WatchAll(t, + td.ate.OTG(), + gnmi.OTG().BgpPeer(td.otgP2.Name()+".BGP6.peer").UnicastIpv6PrefixAny().State(), + time.Minute, + func(v *ygnmi.Value[*otgtelemetry.BgpPeer_UnicastIpv6Prefix]) bool { + _, present := v.Val() + return present + }).Await(t) + if ok { + bgpPrefixes := gnmi.GetAll(t, td.ate.OTG(), gnmi.OTG().BgpPeer(td.otgP2.Name()+".BGP6.peer").UnicastIpv6PrefixAny().State()) + for _, bgpPrefix := range bgpPrefixes { + if bgpPrefix.GetAddress() == v6Prefix { + t.Logf("Prefix recevied on OTG is correct, got prefix:%v , want prefix %v", bgpPrefix, v6Prefix) + switch community { + case "none": + if len(bgpPrefix.Community) != 0 { + t.Fatalf("community is not empty it should be none") + } + case "100:100": + for _, gotCommunity := range bgpPrefix.Community { + t.Logf("community AS:%d val: %d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + if gotCommunity.GetCustomAsNumber() != 100 && gotCommunity.GetCustomAsValue() != 100 { + t.Fatalf("community is not 100:100 got AS number:%d AS value:%d", gotCommunity.GetCustomAsNumber(), gotCommunity.GetCustomAsValue()) + } + } + default: + + // TODO Verification as OTG not supported for Extended community. + t.Logf("TODO: https://github.com/open-traffic-generator/snappi/issues/220 Verification as OTG not supported for Extended community") + if deviations.BgpExtendedCommunityIndexUnsupported(td.dut) { + verifyExtCommunityIndexV6(t, td, v6Prefix) + } + } + } + } + } +} + +func configureImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice) { + root := &oc.Root{} + rp := root.GetOrCreateRoutingPolicy() + pdef1 := rp.GetOrCreatePolicyDefinition("allow-all") + stmt1, err := pdef1.AppendNewStatement("allow-all") + if err != nil { + t.Fatalf("AppendNewStatement failed: %v", err) + } + stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Replace(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + + // Apply ipv4 policy to bgp neighbour. + dni := deviations.DefaultNetworkInstance(dut) + path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv4). + AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() + + policy := root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName). + GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv4).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateApplyPolicy() + policy.SetImportPolicy([]string{"allow-all"}) + gnmi.Replace(t, dut, path.Config(), policy) + + // Apply ipv6 policy to bgp neighbour. + path = gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp(). + Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() + + policy = root.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName). + GetOrCreateBgp().GetOrCreateNeighbor(atePort1.IPv6).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).GetOrCreateApplyPolicy() + policy.SetImportPolicy([]string{"allow-all"}) + gnmi.Replace(t, dut, path.Config(), policy) +} + +func validateImportRoutingPolicyAllowAll(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice) { + dni := deviations.DefaultNetworkInstance(dut) + path := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp(). + Neighbor(atePort1.IPv4).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).ApplyPolicy() + + policy := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, path.State()) + importPolicies := policy.GetImportPolicy() + if len(importPolicies) != 1 { + t.Fatalf("ImportPolicy Ipv4 = %v, want %v", importPolicies, []string{"allow-all"}) + } + bgpRIBPath := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() + locRib := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv4Unicast_LocRib](t, dut, bgpRIBPath. + AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast().LocRib().State()) + + found := 0 + expected := map[string]bool{ + advertisedIPv41.address: true, + advertisedIPv42.address: true, + advertisedIPv43.address: true, + } + for route, prefix := range locRib.Route { + if expected[prefix.GetPrefix()] { + found++ + t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", route.Prefix, route.Origin, route.PathId, prefix.GetPrefix()) + } + } + if found != len(expected) { + t.Errorf("Not all V4 routes found. expected:%d got:%d", len(expected), found) + } + + // Verify ipv6 policy. + pathV6 := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Neighbor(atePort1.IPv6).AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).ApplyPolicy() + policyV6 := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Neighbor_AfiSafi_ApplyPolicy](t, dut, pathV6.State()) + importPolicies = policyV6.GetImportPolicy() + if len(importPolicies) != 1 { + t.Errorf("ImportPolicy Ipv6 got= %v, want= %v", importPolicies, []string{"allow-all"}) + } + bgpRIBPathV6 := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() + locRibv6 := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv6Unicast_LocRib](t, dut, bgpRIBPathV6.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Ipv6Unicast().LocRib().State()) + found = 0 + expectedV6 := map[string]bool{ + advertisedIPv61.address: true, + advertisedIPv62.address: true, + advertisedIPv63.address: true, + } + for route, prefix := range locRibv6.Route { + if expectedV6[prefix.GetPrefix()] { + found++ + t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", route.Prefix, route.Origin, route.PathId, prefix.GetPrefix()) + } + } + if found != len(expectedV6) { + t.Errorf("Not all v6 Routes found expected:%d got:%d", len(expectedV6), found) + } +} + +func configureExtCommunityRoutingPolicy(t *testing.T, dut *ondatra.DUTDevice) { + root := &oc.Root{} + for name, community := range extCommunitySet { + rp := root.GetOrCreateRoutingPolicy() + pdef := rp.GetOrCreateDefinedSets().GetOrCreateBgpDefinedSets() + stmt, err := pdef.NewExtCommunitySet(name) + if err != nil { + t.Fatalf("NewExtCommunitySet failed: %v", err) + } + stmt.SetExtCommunityMember([]string{community}) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rp) + } + + // Configure routing policy link bandwidth zero. + rpSetLinkBwZero := root.GetOrCreateRoutingPolicy() + pdef1 := rpSetLinkBwZero.GetOrCreatePolicyDefinition("set_linkbw_0") + pdef1Stmt1, err := pdef1.AppendNewStatement("zero_linkbw") + if err != nil { + t.Fatalf("AppendNewStatement zero_linkbw failed: %v", err) + } + ref := pdef1Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() + ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_0") + ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) + ref.SetMethod(oc.SetCommunity_Method_REFERENCE) + pdef1Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) + pdef1Stmt2, err := pdef1.AppendNewStatement("accept_all_routes") + if err != nil { + t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) + } + pdef1Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpSetLinkBwZero) + + // Configure routing Policy not_match_100_set_linkbw_1M. + rpNotMatch := root.GetOrCreateRoutingPolicy() + pdef2 := rpNotMatch.GetOrCreatePolicyDefinition("not_match_100_set_linkbw_1M") + pdef2Stmt1, err := pdef2.AppendNewStatement("1-megabit-match") + if err != nil { + t.Fatalf("AppendNewStatement 1-megabit-match failed: %v", err) + } + ref = pdef2Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() + ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_1M") + ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) + ref1 := pdef2Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() + ref1.SetExtCommunitySet("regex_match_comm100") + ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_INVERT) + pdef2Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) + pdef2Stmt2, err := pdef2.AppendNewStatement("accept_all_routes") + if err != nil { + t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) + } + pdef2Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpNotMatch) + + // Configure routing policy match_100_set_linkbw_2G. + rpMatch := root.GetOrCreateRoutingPolicy() + pdef3 := rpMatch.GetOrCreatePolicyDefinition("match_100_set_linkbw_2G") + pdef3Stmt1, err := pdef3.AppendNewStatement("2-gigabit-match") + if err != nil { + t.Fatalf("AppendNewStatement match_100_set_linkbw_2G failed: %v", err) + } + ref = pdef3Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() + ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_2G") + ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_ADD) + ref1 = pdef3Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() + ref1.SetExtCommunitySet("regex_match_comm100") + ref1.SetMatchSetOptions(oc.RoutingPolicy_MatchSetOptionsType_ANY) + pdef3Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) + pdef3Stmt2, err := pdef3.AppendNewStatement("accept_all_routes") + if err != nil { + t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) + } + pdef3Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpMatch) + + // Configure routing policy del_linkbw. + rpDelLinkbw := root.GetOrCreateRoutingPolicy() + pdef4 := rpDelLinkbw.GetOrCreatePolicyDefinition("del_linkbw") + pdef4Stmt1, err := pdef4.AppendNewStatement("del_linkbw") + if err != nil { + t.Fatalf("AppendNewStatement del_linkbw failed: %v", err) + } + ref = pdef4Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() + ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_any") + ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_REMOVE) + ref.SetMethod(oc.SetCommunity_Method_REFERENCE) + pdef4Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) + pdef4Stmt2, err := pdef4.AppendNewStatement("accept_all_routes") + if err != nil { + t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) + } + pdef4Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpDelLinkbw) + + // Configure routing policy match_linkbw_0_remove_and_set_localpref_5. + rpMatchLB0Perf5 := root.GetOrCreateRoutingPolicy() + pdef5 := rpMatchLB0Perf5.GetOrCreatePolicyDefinition("match_linkbw_0_remove_and_set_localpref_5") + pdef5Stmt1, err := pdef5.AppendNewStatement("match_and_remove_linkbw_any_0") + if err != nil { + t.Fatalf("AppendNewStatement match_and_remove_linkbw_any_0 failed: %v", err) + } + ref = pdef5Stmt1.GetOrCreateActions().GetOrCreateBgpActions().GetOrCreateSetExtCommunity() + ref.GetOrCreateReference().SetExtCommunitySetRef("linkbw_any_0") + ref.SetOptions(oc.BgpPolicy_BgpSetCommunityOptionType_REMOVE) + ref.SetMethod(oc.SetCommunity_Method_REFERENCE) + ref1 = pdef5Stmt1.GetOrCreateConditions().GetOrCreateBgpConditions().GetMatchExtCommunitySet() + ref1.SetExtCommunitySet("linkbw_any_0") + pdef5Stmt1.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_NEXT_STATEMENT) + pdef5Stmt1.GetOrCreateActions().GetOrCreateBgpActions().SetLocalPref = ygot.Uint32(5) + pdef5Stmt2, err := pdef5.AppendNewStatement("accept_all_routes") + if err != nil { + t.Fatalf("AppendNewStatement accept_all_routes failed: %v", err) + } + pdef5Stmt2.GetOrCreateActions().SetPolicyResult(oc.RoutingPolicy_PolicyResultType_ACCEPT_ROUTE) + gnmi.Update(t, dut, gnmi.OC().RoutingPolicy().Config(), rpMatchLB0Perf5) +} + +func createFlow(t *testing.T, td testData, fc flowConfig) { + td.top.Flows().Clear() + v4Flow := td.top.Flows().Add().SetName(v4Flow) + v4Flow.Metrics().SetEnable(true) + v4Flow.TxRx().Device(). + SetTxNames([]string{fc.src.Name + ".IPv4"}). + SetRxNames([]string{fc.dstNw}) + v4Flow.Size().SetFixed(512) + v4Flow.Rate().SetPps(100) + v4Flow.Duration().Continuous() + e1 := v4Flow.Packet().Add().Ethernet() + e1.Src().SetValue(fc.src.MAC) + v4 := v4Flow.Packet().Add().Ipv4() + v4.Src().SetValue(fc.src.IPv4) + v4.Dst().Increment().SetStart(fc.dstIP).SetCount(1) + + td.ate.OTG().PushConfig(t, td.top) + td.ate.OTG().StartProtocols(t) + otgutils.WaitForARP(t, td.ate.OTG(), td.top, "IPv4") +} + +func createFlowV6(t *testing.T, td testData, fc flowConfig) { + td.top.Flows().Clear() + v6Flow := td.top.Flows().Add().SetName(v6Flow) + v6Flow.Metrics().SetEnable(true) + v6Flow.TxRx().Device(). + SetTxNames([]string{fc.src.Name + ".IPv6"}). + SetRxNames([]string{fc.dstNw}) + v6Flow.Size().SetFixed(512) + v6Flow.Rate().SetPps(100) + v6Flow.Duration().Continuous() + e1 := v6Flow.Packet().Add().Ethernet() + e1.Src().SetValue(fc.src.MAC) + v6 := v6Flow.Packet().Add().Ipv6() + v6.Src().SetValue(fc.src.IPv6) + v6.Dst().Increment().SetStart(fc.dstIP).SetCount(1) + td.ate.OTG().PushConfig(t, td.top) + td.ate.OTG().StartProtocols(t) + otgutils.WaitForARP(t, td.ate.OTG(), td.top, "IPv6") +} + +func checkTraffic(t *testing.T, td testData, flowName string) { + td.ate.OTG().StartTraffic(t) + time.Sleep(time.Second * 30) + td.ate.OTG().StopTraffic(t) + otgutils.LogFlowMetrics(t, td.ate.OTG(), td.top) + otgutils.LogPortMetrics(t, td.ate.OTG(), td.top) + recvMetric := gnmi.Get(t, td.ate.OTG(), gnmi.OTG().Flow(flowName).State()) + txPackets := recvMetric.GetCounters().GetOutPkts() + rxPackets := recvMetric.GetCounters().GetInPkts() + lostPackets := txPackets - rxPackets + lossPct := lostPackets * 100 / txPackets + + if lossPct > 1 { + t.Errorf("FAIL in checkTraffic - Got %v%% packet loss for %s ; expected < 1%%", lossPct, flowName) + } +} + +func (td *testData) advertiseRoutesWithEBGP(t *testing.T) { + t.Helper() + + root := &oc.Root{} + ni := root.GetOrCreateNetworkInstance(deviations.DefaultNetworkInstance(td.dut)) + bgpP := ni.GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName) + bgpP.SetEnabled(true) + bgp := bgpP.GetOrCreateBgp() + + g := bgp.GetOrCreateGlobal() + g.SetAs(dutAS) + g.SetRouterId(dutPort1.IPv4) + g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + g.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + + nV41 := bgp.GetOrCreateNeighbor(atePort1.IPv4) + nV41.SetPeerAs(ateAS) + nV41.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + nV42 := bgp.GetOrCreateNeighbor(atePort2.IPv4) + nV42.SetPeerAs(dutAS) + nV42.SetSendCommunity(oc.Bgp_CommunityType_BOTH) + nV42.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + nV61 := bgp.GetOrCreateNeighbor(atePort1.IPv6) + nV61.SetPeerAs(ateAS) + nV61.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + nV62 := bgp.GetOrCreateNeighbor(atePort2.IPv6) + nV62.SetPeerAs(dutAS) + nV62.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) + gnmi.Update(t, td.dut, gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Config(), ni) + + // Configure eBGP on OTG port1. + ipv41 := td.otgP1.Ethernets().Items()[0].Ipv4Addresses().Items()[0] + dev1BGP := td.otgP1.Bgp().SetRouterId(atePort1.IPv4) + bgp4Peer1 := dev1BGP.Ipv4Interfaces().Add().SetIpv4Name(ipv41.Name()).Peers().Add().SetName(td.otgP1.Name() + ".BGP4.peer") + bgp4Peer1.SetPeerAddress(dutPort1.IPv4).SetAsNumber(ateAS).SetAsType(gosnappi.BgpV4PeerAsType.EBGP) + ipv61 := td.otgP1.Ethernets().Items()[0].Ipv6Addresses().Items()[0] + bgp6Peer1 := dev1BGP.Ipv6Interfaces().Add().SetIpv6Name(ipv61.Name()).Peers().Add().SetName(td.otgP1.Name() + ".BGP6.peer") + bgp6Peer1.SetPeerAddress(dutPort1.IPv6).SetAsNumber(ateAS).SetAsType(gosnappi.BgpV6PeerAsType.EBGP) + + // Configure emulated network on ATE port1. + netv41 := bgp4Peer1.V4Routes().Add().SetName("v4-bgpNet-dev1") + netv41.Addresses().Add().SetAddress(advertisedIPv41.address).SetPrefix(advertisedIPv41.prefix) + netv61 := bgp6Peer1.V6Routes().Add().SetName("v6-bgpNet-dev1") + netv61.Addresses().Add().SetAddress(advertisedIPv61.address).SetPrefix(advertisedIPv61.prefix) + + // Configure routes with BGP community. + netv42 := bgp4Peer1.V4Routes().Add().SetName("v4-bgpNet-dev2") + netv42.Addresses().Add().SetAddress(advertisedIPv42.address).SetPrefix(advertisedIPv42.prefix) + commv4 := netv42.Communities().Add() + commv4.SetType(gosnappi.BgpCommunityType.MANUAL_AS_NUMBER) + commv4.SetAsNumber(100) + commv4.SetAsCustom(100) + netv62 := bgp6Peer1.V6Routes().Add().SetName("v6-bgpNet-dev2") + netv62.Addresses().Add().SetAddress(advertisedIPv62.address).SetPrefix(advertisedIPv62.prefix) + commv6 := netv62.Communities().Add() + commv6.SetType(gosnappi.BgpCommunityType.MANUAL_AS_NUMBER) + commv6.SetAsNumber(100) + commv6.SetAsCustom(100) + + // Configure routes with Link bandwidth community. + netv43 := bgp4Peer1.V4Routes().Add().SetName("v4-bgpNet-dev3") + netv43.Addresses().Add().SetAddress(advertisedIPv43.address).SetPrefix(advertisedIPv43.prefix) + extcommv4 := netv43.ExtendedCommunities().Add().NonTransitive2OctetAsType().LinkBandwidthSubtype() + extcommv4.SetGlobal2ByteAs(100) + extcommv4.SetBandwidth(0) + netv63 := bgp6Peer1.V6Routes().Add().SetName("v6-bgpNet-dev3") + netv63.Addresses().Add().SetAddress(advertisedIPv63.address).SetPrefix(advertisedIPv63.prefix) + extcommv6 := netv63.ExtendedCommunities().Add().NonTransitive2OctetAsType().LinkBandwidthSubtype() + extcommv6.SetGlobal2ByteAs(100) + extcommv6.SetBandwidth(0) + + // Configure iBGP on OTG port2. + ipv42 := td.otgP2.Ethernets().Items()[0].Ipv4Addresses().Items()[0] + dev2BGP := td.otgP2.Bgp().SetRouterId(atePort2.IPv4) + bgp4Peer2 := dev2BGP.Ipv4Interfaces().Add().SetIpv4Name(ipv42.Name()).Peers().Add().SetName(td.otgP2.Name() + ".BGP4.peer") + bgp4Peer2.SetPeerAddress(dutPort2.IPv4).SetAsNumber(dutAS).SetAsType(gosnappi.BgpV4PeerAsType.IBGP) + bgp4Peer2.Capability().SetIpv4UnicastAddPath(true).SetIpv6UnicastAddPath(true) + bgp4Peer2.LearnedInformationFilter().SetUnicastIpv4Prefix(true).SetUnicastIpv6Prefix(true) + ipv62 := td.otgP2.Ethernets().Items()[0].Ipv6Addresses().Items()[0] + bgp6Peer2 := dev2BGP.Ipv6Interfaces().Add().SetIpv6Name(ipv62.Name()).Peers().Add().SetName(td.otgP2.Name() + ".BGP6.peer") + bgp6Peer2.SetPeerAddress(dutPort2.IPv6).SetAsNumber(dutAS).SetAsType(gosnappi.BgpV6PeerAsType.IBGP) + bgp6Peer2.Capability().SetIpv4UnicastAddPath(true).SetIpv6UnicastAddPath(true).SetExtendedNextHopEncoding(true) + bgp6Peer2.LearnedInformationFilter().SetUnicastIpv4Prefix(true).SetUnicastIpv6Prefix(true) +} + +func (td *testData) verifyDUTBGPEstablished(t *testing.T) { + sp := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(td.dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().NeighborAny().SessionState().State() + watch := gnmi.WatchAll(t, td.dut, sp, 2*time.Minute, func(val *ygnmi.Value[oc.E_Bgp_Neighbor_SessionState]) bool { + state, ok := val.Val() + if !ok || state != oc.Bgp_Neighbor_SessionState_ESTABLISHED { + return false + } + return true + }) + if val, ok := watch.Await(t); !ok { + t.Fatalf("BGP sessions not established in verifyDUTBGPEstablished : got %v", val) + } +} + +// verifyOTGBGPEstablished verifies on OTG BGP peer establishment. +func (td *testData) verifyOTGBGPEstablished(t *testing.T) { + sp := gnmi.OTG().BgpPeerAny().SessionState().State() + watch := gnmi.WatchAll(t, td.ate.OTG(), sp, 2*time.Minute, func(val *ygnmi.Value[otgtelemetry.E_BgpPeer_SessionState]) bool { + state, ok := val.Val() + if !ok || state != otgtelemetry.BgpPeer_SessionState_ESTABLISHED { + return false + } + return true + }) + state, ok := watch.Await(t) + if !ok { + t.Fatalf("BGP sessions not established : verifyOTGBGPEstablished (%v)", state) + } +} + +func configureDUT(t *testing.T, dut *ondatra.DUTDevice) { + t.Helper() + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + b := &gnmi.SetBatch{} + gnmi.BatchReplace(b, gnmi.OC().Interface(p1.Name()).Config(), dutPort1.NewOCInterface(p1.Name(), dut)) + gnmi.BatchReplace(b, gnmi.OC().Interface(p2.Name()).Config(), dutPort2.NewOCInterface(p2.Name(), dut)) + b.Set(t, dut) + if deviations.ExplicitPortSpeed(dut) { + fptest.SetPortSpeed(t, p1) + fptest.SetPortSpeed(t, p2) + } + + fptest.ConfigureDefaultNetworkInstance(t, dut) + + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, p1.Name(), deviations.DefaultNetworkInstance(dut), 0) + fptest.AssignToNetworkInstance(t, dut, p2.Name(), deviations.DefaultNetworkInstance(dut), 0) + } +} + +func configureOTG(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) []gosnappi.Device { + t.Helper() + p1 := ate.Port(t, "port1") + p2 := ate.Port(t, "port2") + + d1 := atePort1.AddToOTG(top, p1, &dutPort1) + d2 := atePort2.AddToOTG(top, p2, &dutPort2) + return []gosnappi.Device{d1, d2} +} + +// TODO to move base setup config in helper. +func baseSetupConfigAndVerification(t *testing.T, td testData) { + td.advertiseRoutesWithEBGP(t) + td.ate.OTG().PushConfig(t, td.top) + td.ate.OTG().StartProtocols(t) + otgutils.WaitForARP(t, td.ate.OTG(), td.top, "IPv4") + otgutils.WaitForARP(t, td.ate.OTG(), td.top, "IPv6") + td.verifyDUTBGPEstablished(t) + td.verifyOTGBGPEstablished(t) + configureImportRoutingPolicyAllowAll(t, td.dut) + validateImportRoutingPolicyAllowAll(t, td.dut, td.ate) + createFlow(t, td, flowConfig{src: atePort2, dstNw: "v4-bgpNet-dev1", dstIP: v41TrafficStart}) + checkTraffic(t, td, v4Flow) + createFlowV6(t, td, flowConfig{src: atePort2, dstNw: "v6-bgpNet-dev1", dstIP: v61TrafficStart}) + checkTraffic(t, td, v6Flow) + createFlow(t, td, flowConfig{src: atePort2, dstNw: "v4-bgpNet-dev2", dstIP: v42TrafficStart}) + checkTraffic(t, td, v4Flow) + createFlowV6(t, td, flowConfig{src: atePort2, dstNw: "v6-bgpNet-dev2", dstIP: v62TrafficStart}) + checkTraffic(t, td, v6Flow) + createFlow(t, td, flowConfig{src: atePort2, dstNw: "v4-bgpNet-dev3", dstIP: v43TrafficStart}) + checkTraffic(t, td, v4Flow) + createFlowV6(t, td, flowConfig{src: atePort2, dstNw: "v6-bgpNet-dev3", dstIP: v63TrafficStart}) + checkTraffic(t, td, v6Flow) +} + +func verifyExtCommunityIndexV4(t *testing.T, td testData, v4Address string) { + dni := deviations.DefaultNetworkInstance(td.dut) + bgpRIBPath := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() + locRib := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv4Unicast_LocRib](t, td.dut, bgpRIBPath.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Ipv4Unicast().LocRib().State()) + t.Logf("RIB: %v", locRib) + for route, prefix := range locRib.Route { + if prefix.GetPrefix() != v4Address { + continue + } + t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", route.Prefix, route.Origin, route.PathId, prefix.GetPrefix()) + if prefix.ExtCommunityIndex == nil { + t.Fatalf("No V4 community index found") + } + extCommunity := bgpRIBPath.ExtCommunity(prefix.GetExtCommunityIndex()).ExtCommunity().State() + if extCommunity == nil { + t.Fatalf("No V4 community found at given index: %v", prefix.GetExtCommunityIndex()) + } + } +} + +func verifyExtCommunityIndexV6(t *testing.T, td testData, v6Address string) { + dni := deviations.DefaultNetworkInstance(td.dut) + bgpRIBPathV6 := gnmi.OC().NetworkInstance(dni).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, bgpName).Bgp().Rib() + locRibv6 := gnmi.Get[*oc.NetworkInstance_Protocol_Bgp_Rib_AfiSafi_Ipv6Unicast_LocRib](t, td.dut, bgpRIBPathV6.AfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Ipv6Unicast().LocRib().State()) + t.Logf("RIB: %v", locRibv6) + for route, prefix := range locRibv6.Route { + if prefix.GetPrefix() != v6Address { + continue + } + t.Logf("Found Route(prefix %s, origin: %v, pathid: %d) => %s", route.Prefix, route.Origin, route.PathId, prefix.GetPrefix()) + if prefix.ExtCommunityIndex == nil { + t.Fatalf("No V6 community index found") + } + extCommunity := bgpRIBPathV6.ExtCommunity(prefix.GetExtCommunityIndex()).ExtCommunity().State() + if extCommunity == nil { + t.Fatalf("No V6 community found at given index: %v", prefix.GetExtCommunityIndex()) + } + } +} diff --git a/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto b/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto new file mode 100644 index 00000000000..5e5b04d3695 --- /dev/null +++ b/feature/experimental/bgp/otg_tests/link_bandwidth_test/metadata.textproto @@ -0,0 +1,25 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "a8344612-0db0-42a1-96cf-38846a7f1603" +plan_id: "RT-7.5" +description: "BGP Policy - Match and Set Link Bandwidth Community" +testbed: TESTBED_DUT_ATE_2LINKS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + route_policy_under_afi_unsupported: true + omit_l2_mtu: true + missing_value_for_defaults: true + interface_enabled: true + default_network_instance: "default" + skip_set_rp_match_set_options: true + skip_setting_disable_metric_propagation: true + bgp_conditions_match_community_set_unsupported: true + bgp_extended_community_index_unsupported: true + } +} +tags: TAGS_AGGREGATION +tags: TAGS_DATACENTER_EDGE diff --git a/internal/deviations/deviations.go b/internal/deviations/deviations.go index 6c2bedde4fd..c51d87f31d4 100644 --- a/internal/deviations/deviations.go +++ b/internal/deviations/deviations.go @@ -896,3 +896,8 @@ func PLQGeneratorCapabilitiesMaxMTU(dut *ondatra.DUTDevice) uint32 { func PLQGeneratorCapabilitiesMaxPPS(dut *ondatra.DUTDevice) uint64 { return lookupDUTDeviations(dut).GetPlqGeneratorCapabilitiesMaxPps() } + +// BgpExtendedCommunityIndexUnsupported return true if BGP extended community index is not supported. +func BgpExtendedCommunityIndexUnsupported(dut *ondatra.DUTDevice) bool { + return lookupDUTDeviations(dut).GetBgpExtendedCommunityIndexUnsupported() +} diff --git a/proto/metadata.proto b/proto/metadata.proto index 51bf2118ac1..9ec70094cdf 100644 --- a/proto/metadata.proto +++ b/proto/metadata.proto @@ -471,7 +471,8 @@ message Metadata { uint32 plq_generator_capabilities_max_mtu = 165; // Device that does not support PLQ Generator max_pps to be atleast >= 100000000. uint64 plq_generator_capabilities_max_pps = 166; - + // Support for bgp extended community index + bool bgp_extended_community_index_unsupported = 167; // Reserved field numbers and identifiers. reserved 84, 9, 28, 20, 90, 97, 55, 89, 19; } diff --git a/proto/metadata_go_proto/metadata.pb.go b/proto/metadata_go_proto/metadata.pb.go index 81689727efc..41d04aaa027 100644 --- a/proto/metadata_go_proto/metadata.pb.go +++ b/proto/metadata_go_proto/metadata.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.23.4 +// protoc-gen-go v1.28.1 +// protoc v3.21.12 // source: metadata.proto package metadata_go_proto @@ -742,6 +742,8 @@ type Metadata_Deviations struct { PlqGeneratorCapabilitiesMaxMtu uint32 `protobuf:"varint,165,opt,name=plq_generator_capabilities_max_mtu,json=plqGeneratorCapabilitiesMaxMtu,proto3" json:"plq_generator_capabilities_max_mtu,omitempty"` // Device that does not support PLQ Generator max_pps to be atleast >= 100000000. PlqGeneratorCapabilitiesMaxPps uint64 `protobuf:"varint,166,opt,name=plq_generator_capabilities_max_pps,json=plqGeneratorCapabilitiesMaxPps,proto3" json:"plq_generator_capabilities_max_pps,omitempty"` + // Support for bgp extended community index + BgpExtendedCommunityIndexUnsupported bool `protobuf:"varint,167,opt,name=bgp_extended_community_index_unsupported,json=bgpExtendedCommunityIndexUnsupported,proto3" json:"bgp_extended_community_index_unsupported,omitempty"` } func (x *Metadata_Deviations) Reset() { @@ -1826,6 +1828,13 @@ func (x *Metadata_Deviations) GetPlqGeneratorCapabilitiesMaxPps() uint64 { return 0 } +func (x *Metadata_Deviations) GetBgpExtendedCommunityIndexUnsupported() bool { + if x != nil { + return x.BgpExtendedCommunityIndexUnsupported + } + return false +} + type Metadata_PlatformExceptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1889,7 +1898,7 @@ var file_metadata_proto_rawDesc = []byte{ 0x74, 0x69, 0x6e, 0x67, 0x1a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x6f, 0x6e, 0x64, 0x61, 0x74, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x62, 0x65, - 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdd, 0x5d, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x5e, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6c, 0x61, 0x6e, 0x49, @@ -1920,7 +1929,7 @@ var file_metadata_proto_rawDesc = []byte{ 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x67, 0x65, 0x78, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x0e, 0x68, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, - 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xde, 0x55, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, + 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x1a, 0xb7, 0x56, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x70, 0x76, 0x34, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, @@ -2603,43 +2612,49 @@ var file_metadata_proto_rawDesc = []byte{ 0x69, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x70, 0x73, 0x18, 0xa6, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, 0x70, 0x6c, 0x71, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x4d, 0x61, 0x78, 0x50, - 0x70, 0x73, 0x4a, 0x04, 0x08, 0x54, 0x10, 0x55, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, - 0x08, 0x1c, 0x10, 0x1d, 0x4a, 0x04, 0x08, 0x14, 0x10, 0x15, 0x4a, 0x04, 0x08, 0x5a, 0x10, 0x5b, - 0x4a, 0x04, 0x08, 0x61, 0x10, 0x62, 0x4a, 0x04, 0x08, 0x37, 0x10, 0x38, 0x4a, 0x04, 0x08, 0x59, - 0x10, 0x5a, 0x4a, 0x04, 0x08, 0x13, 0x10, 0x14, 0x1a, 0xa0, 0x01, 0x0a, 0x12, 0x50, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x41, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, - 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x12, 0x47, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x0a, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x07, - 0x54, 0x65, 0x73, 0x74, 0x62, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x42, - 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x10, - 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, - 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, - 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, - 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x34, 0x4c, 0x49, - 0x4e, 0x4b, 0x53, 0x10, 0x04, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, - 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x39, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x5f, - 0x4c, 0x41, 0x47, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, - 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, - 0x4e, 0x4b, 0x53, 0x10, 0x06, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, - 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x38, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, - 0x07, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, - 0x5f, 0x34, 0x30, 0x30, 0x5a, 0x52, 0x10, 0x08, 0x22, 0x6d, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, - 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x41, - 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, - 0x54, 0x41, 0x47, 0x53, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, - 0x45, 0x44, 0x47, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x45, - 0x44, 0x47, 0x45, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x54, 0x52, - 0x41, 0x4e, 0x53, 0x49, 0x54, 0x10, 0x04, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x73, 0x12, 0x57, 0x0a, 0x28, 0x62, 0x67, 0x70, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x5f, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0xa7, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x62, 0x67, 0x70, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x54, 0x10, + 0x55, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x1c, 0x10, 0x1d, 0x4a, 0x04, 0x08, + 0x14, 0x10, 0x15, 0x4a, 0x04, 0x08, 0x5a, 0x10, 0x5b, 0x4a, 0x04, 0x08, 0x61, 0x10, 0x62, 0x4a, + 0x04, 0x08, 0x37, 0x10, 0x38, 0x4a, 0x04, 0x08, 0x59, 0x10, 0x5a, 0x4a, 0x04, 0x08, 0x13, 0x10, + 0x14, 0x1a, 0xa0, 0x01, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x78, + 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x47, 0x0a, 0x0a, 0x64, + 0x65, 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x62, 0x65, 0x64, + 0x12, 0x17, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x45, 0x53, + 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, + 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, 0x4c, + 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, + 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, 0x53, + 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, + 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x34, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x04, 0x12, 0x1e, + 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, + 0x45, 0x5f, 0x39, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x5f, 0x4c, 0x41, 0x47, 0x10, 0x05, 0x12, 0x1e, + 0x0a, 0x1a, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x44, 0x55, + 0x54, 0x5f, 0x41, 0x54, 0x45, 0x5f, 0x32, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x06, 0x12, 0x1a, + 0x0a, 0x16, 0x54, 0x45, 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x41, 0x54, + 0x45, 0x5f, 0x38, 0x4c, 0x49, 0x4e, 0x4b, 0x53, 0x10, 0x07, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x45, + 0x53, 0x54, 0x42, 0x45, 0x44, 0x5f, 0x44, 0x55, 0x54, 0x5f, 0x34, 0x30, 0x30, 0x5a, 0x52, 0x10, + 0x08, 0x22, 0x6d, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, + 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x14, 0x0a, 0x10, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x44, 0x41, + 0x54, 0x41, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x10, 0x02, 0x12, + 0x0d, 0x0a, 0x09, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x45, 0x44, 0x47, 0x45, 0x10, 0x03, 0x12, 0x10, + 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x49, 0x54, 0x10, 0x04, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/testregistry.textproto b/testregistry.textproto index 846fa782588..fff14aa11e3 100644 --- a/testregistry.textproto +++ b/testregistry.textproto @@ -769,7 +769,7 @@ test: { test: { id: "RT-7.5" description: "BGP Policy - Set Link Bandwidth Community" - readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/bgp/policybase/otg_tests/link_bandwidth_test/README.md" + readme: "https://github.com/openconfig/featureprofiles/blob/main/feature/experimental/bgp/otg_tests/link_bandwidth_test/README.md" } test: { id: "RT-7.6"