diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/README.md b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/README.md index 2456301ebd0..caf12697c34 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/README.md +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/README.md @@ -4,8 +4,6 @@ Validate BGP in multipath UCMP support with link bandwidth community -NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/issues/3520 - ## Testbed type [TESTBED_DUT_ATE_4LINKS](https://github.com/openconfig/featureprofiles/blob/main/topologies/atedut_4.testbed) @@ -23,7 +21,7 @@ NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/ * Enable an Accept-route all import-policy/export-policy for eBGP session under the neighbor AFI/SAFI - IPv6 unicast and IPv4 unicast. * Create an single IPv4 internal target network attached to ATE port 2 and 3 -* [TODO] Create an single IPv6 internal target network attached to ATE port 2 and 3 +* Create an single IPv6 internal target network attached to ATE port 2 and 3 ### Tests @@ -33,13 +31,13 @@ NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/ * Test Configuration * Configure ATE port 1, 2 and 3 on different AS, with boths AFI/SAFI * Advertise IPv4 and IPv6 internal target, both, form both ATE port-1 and ATE port-2 in eBGP. - * [TODO] For ATE port 2 attach `link-bandwidth:23456:10K` extended-community - * [TODO] For ATE port 3 attach `link-bandwidth:23456:5K` extended-community + * For ATE port 2 attach `link-bandwidth:23456:10K` extended-community + * For ATE port 3 attach `link-bandwidth:23456:5K` extended-community * Enable multipath, set maximum-paths limit to 2, enable allow multiple AS, and send community type to [STANDARD, EXTENDED, LARGE] * /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/afi-safis/afi-safi/use-multiple-paths/config/enabled - * [TODO] /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/allow-multiple-as - * [TODO] /network-instances/network-instance/protocols/protocol/bgp/globalp/afi-safis/afi-safi/use-multiple-paths/ebgp/config/maximum-paths + * /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/allow-multiple-as + * /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/maximum-paths * /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/config/send-community-type * /network-instances/network-instance/protocols/protocol/bgp/global/use-multiple-paths/ebgp/link-bandwidth-ext-community/config/enabled * Advertise equal cost paths from port2 and port3 of ATE @@ -48,20 +46,20 @@ NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/ * Use UDP traffic with src and dst port randomly selected from 1-65535 range for each packet. Or equivalent pattern guaranteeng high entropy of traffic. * Behaviour Validation * Check entries in AFT for advertised prefix, it should have 2 entries.\ - [TODO] The `weight` leafs of next-hops shall be in 2:1 ratio. + The `weight` leafs of next-hops shall be in 2:1 ratio. * Find next-hop-group IDs for both internal target networks: * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv4 internal target network]/state/**next-hop-group** * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv6 internal target network]/state/**next-hop-group** * using next-hop-group as key find number and weight of next-hops of both internal target network * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/index * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/**weight** - * [TODO] Check entire traffic should be unequally forwarded between DUT + * Check entire traffic should be unequally forwarded between DUT port2 and port3 only * 66% via port2 * 33% via port3 * with +/-5% tolerance -* [TODO] RT-1.52.2: Verify use of equal community type +* RT-1.52.2: Verify use of equal community type * Test Configuration Use test configuration as in RT-1.52.1 above with following modifications: @@ -70,20 +68,20 @@ NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/ * For ATE port 3 attach `link-bandwidth:23456:10K` extended-community * Behaviour Validation * Check entries in AFT for advertised prefix, it should have 2 entries.\ - [TODO] The `weight` leafs of next-hops shall be in 1:1 ratio. + The `weight` leafs of next-hops shall be in 1:1 ratio. * Find next-hop-group IDs for both internal target networks: * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv4 internal target network]/state/**next-hop-group** * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv6 internal target network]/state/**next-hop-group** * using next-hop-group as key find number and weight of next-hops of both internal target network * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/index * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/**weight** - * [TODO] Check entire traffic should be unequally forwarded between DUT + * Check entire traffic should be unequally forwarded between DUT port2 and port3 only * 50% via port2 * 50% via port3 * with +/-5% tolerance -* [TODO] RT-1.52.3: Verify BGP multipath when some path missing link-bandwidth extended-community +* RT-1.52.3: Verify BGP multipath when some path missing link-bandwidth extended-community * Test Configuration Use test configuration as in RT-1.52.1 above with following modifications: @@ -93,33 +91,19 @@ NOTE: [TODO] items are tracked at https://github.com/openconfig/featureprofiles/ * For ATE port 3 **DO NOT** attach any link-bandwidth extended-community * Behaviour Validation * Check entries in AFT for advertised prefix, it should have 2 entries.\ - [TODO] The `weight` leafs of next-hops shall be in 1:1 ratio. + The `weight` leafs of next-hops shall be in 1:1 ratio. * Find next-hop-group IDs for both internal target networks: * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv4 internal target network]/state/**next-hop-group** * /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry[prefix=IPv6 internal target network]/state/**next-hop-group** * using next-hop-group as key find number and weight of next-hops of both internal target network * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/index * /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=next-hop-group ID]/next-hops/next-hop/state/**weight** - * [TODO] Check entire traffic should be unequally forwarded between DUT + * Check entire traffic should be unequally forwarded between DUT port2 and port3 only * 50% via port2 * 50% via port3 * with +/-5% tolerance - -## Config Parameter Coverage - -* /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/afi-safis/afi-safi/use-multiple-paths/config/enabled -* /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/allow-multiple-as -* /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/maximum-paths -* /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/config/send-community-type -* /network-instances/network-instance/protocols/protocol/bgp/global/use-multiple-paths/ebgp/link-bandwidth-ext-community/config/enabled - -## Telemetry Parameter Coverage - -* /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry/state/next-hop-group -* /network-instances/network-instance/afts/next-hop-groups/next-hop-group[id=]/next-hops/next-hop[index=]/state/weight - ## OpenConfig Path and RPC Coverage ```yaml @@ -127,6 +111,18 @@ rpcs: gnmi: gNMI.Get: gNMI.Subscribe: +paths: + ## Config Parameter Coverage + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/afi-safis/afi-safi/use-multiple-paths/config/enabled: + /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/allow-multiple-as: + /network-instances/network-instance/protocols/protocol/bgp/global/afi-safis/afi-safi/use-multiple-paths/ebgp/config/maximum-paths: + /network-instances/network-instance/protocols/protocol/bgp/peer-groups/peer-group/config/send-community-type: + /network-instances/network-instance/protocols/protocol/bgp/global/use-multiple-paths/ebgp/link-bandwidth-ext-community/config/enabled: + + ## Telemetry Parameter Coverage + /network-instances/network-instance/afts/ipv4-unicast/ipv4-entry/state/next-hop-group: + /network-instances/network-instance/afts/next-hop-groups/next-hop-group/next-hops/next-hop/state/weight: + ``` ## Required DUT platform diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go index 3ab2c1cc4fd..5f452a05e61 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/bgp_multipath_wecmp_test.go @@ -42,10 +42,10 @@ const ( trafficPps = 1000 totalPackets = 120000 lossTolerancePct = 0 - lbToleranceFms = 5 + lbToleranceFms = 10 ) -var linkBw = []int{10, 5} +var linkBw = []int{10} func TestMain(m *testing.M) { fptest.RunTests(m) @@ -71,13 +71,32 @@ func configureOTG(t *testing.T, bs *cfgplugins.BGPSession) { routeAddress.SetPrefix(prefixP4Len) routeAddress.SetCount(prefixesCount) bgp4PeerRoute.AddPath().SetPathId(pathID) - bgpExtCom := bgp4PeerRoute.ExtendedCommunities().Add() - bgpExtCom.NonTransitive2OctetAsType().LinkBandwidthSubtype().SetBandwidth(float32(linkBw[i-2] * 1000)) } configureFlow(bs) } +func attachLBWithInternalNetwork(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) { + devices := top.Devices().Items() + byName := func(i, j int) bool { return devices[i].Name() < devices[j].Name() } + sort.Slice(devices, byName) + + for _, i := range []int{2, 3} { + bgp4Peer := devices[i].Bgp().Ipv4Interfaces().Items()[0].Peers().Items()[0] + bgp4PeerRoute := bgp4Peer.V4Routes().Items()[0] + bgp4PeerRoute.ExtendedCommunities().Clear() + if i-2 < len(linkBw) { + bgpExtCom := bgp4PeerRoute.ExtendedCommunities().Add() + bgpExtCom.NonTransitive2OctetAsType().LinkBandwidthSubtype().SetBandwidth(float32(linkBw[i-2] * 1000)) + bgpExtCom.NonTransitive2OctetAsType().LinkBandwidthSubtype().SetGlobal2ByteAs(23456) + } + } + + ate.OTG().PushConfig(t, top) + ate.OTG().StartProtocols(t) + otgutils.WaitForARP(t, ate.OTG(), top, "IPv4") +} + func configureFlow(bs *cfgplugins.BGPSession) { bs.ATETop.Flows().Clear() @@ -118,8 +137,15 @@ func checkPacketLoss(t *testing.T, ate *ondatra.ATEDevice) { func verifyECMPLoadBalance(t *testing.T, ate *ondatra.ATEDevice, pc int, expectedLinks int) { framesTx := gnmi.Get(t, ate.OTG(), gnmi.OTG().Port(ate.Port(t, "port1").ID()).Counters().OutFrames().State()) - expectedPerLinkFmsP3 := int(float32(linkBw[0]) / (float32(linkBw[0] + linkBw[1])) * float32(framesTx)) - expectedPerLinkFmsP4 := int(float32(linkBw[1]) / (float32(linkBw[0] + linkBw[1])) * float32(framesTx)) + var lb1, lb2 float32 + if len(linkBw) == 1 { + lb1, lb2 = float32(linkBw[0]), float32(linkBw[0]) + } else { + lb1, lb2 = float32(linkBw[0]), float32(linkBw[1]) + } + + expectedPerLinkFmsP3 := int(lb1 / (lb1 + lb2) * float32(framesTx)) + expectedPerLinkFmsP4 := int(lb2 / (lb1 + lb2) * float32(framesTx)) t.Logf("Total packets %d flow through the %d links and expected per link packets: %d, %d", framesTx, expectedLinks, expectedPerLinkFmsP3, expectedPerLinkFmsP4) p3Min := expectedPerLinkFmsP3 - (expectedPerLinkFmsP3 * lbToleranceFms / 100) @@ -146,13 +172,21 @@ func verifyECMPLoadBalance(t *testing.T, ate *ondatra.ATEDevice, pc int, expecte func TestBGPSetup(t *testing.T) { bs := cfgplugins.NewBGPSession(t, cfgplugins.PortCount4, nil) bs.WithEBGP(t, []oc.E_BgpTypes_AFI_SAFI_TYPE{oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST}, []string{"port3", "port4"}, true, false) + dni := deviations.DefaultNetworkInstance(bs.DUT) bgp := bs.DUTConf.GetOrCreateNetworkInstance(dni).GetOrCreateProtocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_BGP, "BGP").GetOrCreateBgp() + bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().Enabled = ygot.Bool(true) + + if !deviations.SkipBgpSendCommunityType(bs.DUT) { + bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).SetSendCommunityType([]oc.E_Bgp_CommunityType{oc.Bgp_CommunityType_STANDARD, oc.Bgp_CommunityType_EXTENDED, oc.Bgp_CommunityType_LARGE}) + } + if deviations.MultipathUnsupportedNeighborOrAfisafi(bs.DUT) { t.Logf("MultipathUnsupportedNeighborOrAfisafi is supported") bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateUseMultiplePaths().Enabled = ygot.Bool(true) bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateUseMultiplePaths().GetOrCreateEbgp().AllowMultipleAs = ygot.Bool(true) } + if deviations.SkipAfiSafiPathForBgpMultipleAs(bs.DUT) { var communitySetCLIConfig string t.Log("AfiSafi Path For BgpMultipleAs is not supported") @@ -170,13 +204,19 @@ func TestBGPSetup(t *testing.T) { helpers.GnmiCLIConfig(t, bs.DUT, communitySetCLIConfig) } } else { - t.Logf("AfiSafi Path For BgpMultipleAs is supported") - gEBGP := bgp.GetOrCreateGlobal().GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().GetOrCreateEbgp() - if !deviations.SkipSettingAllowMultipleAS(bs.DUT) { - gEBGP.AllowMultipleAs = ygot.Bool(true) + if deviations.SkipSettingAllowMultipleAS(bs.DUT) { + bgp.GetOrCreateGlobal().GetOrCreateUseMultiplePaths().GetOrCreateEbgp().MaximumPaths = ygot.Uint32(maxPaths) + bgp.GetOrCreateGlobal().GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().GetOrCreateEbgp().GetOrCreateLinkBandwidthExtCommunity().Enabled = ygot.Bool(true) + switch bs.DUT.Vendor() { + case ondatra.ARISTA: + helpers.GnmiCLIConfig(t, bs.DUT, "router bgp 65501\n ucmp mode 1\n") + default: + t.Fatalf("Unsupported vendor %s for deviation 'SkipSettingAllowMultipleAS'", bs.DUT.Vendor()) + } + } else { + bgp.GetOrCreateGlobal().GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().GetOrCreateEbgp().AllowMultipleAs = ygot.Bool(true) } } - bgp.GetOrCreatePeerGroup(cfgplugins.BGPPeerGroup1).GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).GetOrCreateUseMultiplePaths().Enabled = ygot.Bool(true) configureOTG(t, bs) bs.PushAndStart(t) @@ -187,22 +227,55 @@ func TestBGPSetup(t *testing.T) { t.Logf("Verify OTG BGP sessions up") cfgplugins.VerifyOTGBGPEstablished(t, bs.ATE) + testCases := []struct { + name string + desc string + linkBw []int + }{ + { + name: "RT-1.52.1", + desc: "Verify BGP multipath when some path missing link-bandwidth extended-community", + linkBw: []int{10}, + }, + { + name: "RT-1.52.2", + desc: "Verify use of equal community type", + linkBw: []int{10, 10}, + }, + { + name: "RT-1.52.1", + desc: "Verify use of unequal community type", + linkBw: []int{10, 5}, + }, + } + aftsPath := gnmi.OC().NetworkInstance(dni).Afts() prefix := prefixesStart + "/" + strconv.Itoa(prefixP4Len) - ipv4Entry := gnmi.Get[*oc.NetworkInstance_Afts_Ipv4Entry](t, bs.DUT, aftsPath.Ipv4Entry(prefix).State()) - hopGroup := gnmi.Get[*oc.NetworkInstance_Afts_NextHopGroup](t, bs.DUT, aftsPath.NextHopGroup(ipv4Entry.GetNextHopGroup()).State()) - if got, want := len(hopGroup.NextHop), 2; got != want { - t.Errorf("prefix: %s, found %d hops, want %d", ipv4Entry.GetPrefix(), got, want) - } else { - t.Logf("prefix: %s, found %d hops, want %d", ipv4Entry.GetPrefix(), got, want) - } - sleepTime := time.Duration(totalPackets/trafficPps) + 5 - bs.ATE.OTG().StartTraffic(t) - time.Sleep(sleepTime * time.Second) - bs.ATE.OTG().StopTraffic(t) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + linkBw = tc.linkBw + attachLBWithInternalNetwork(t, bs.ATE, bs.ATETop) + time.Sleep(30 * time.Second) - otgutils.LogFlowMetrics(t, bs.ATE.OTG(), bs.ATETop) - checkPacketLoss(t, bs.ATE) - verifyECMPLoadBalance(t, bs.ATE, int(cfgplugins.PortCount4), 2) + ipv4Entry := gnmi.Get[*oc.NetworkInstance_Afts_Ipv4Entry](t, bs.DUT, aftsPath.Ipv4Entry(prefix).State()) + hopGroup := gnmi.Get[*oc.NetworkInstance_Afts_NextHopGroup](t, bs.DUT, aftsPath.NextHopGroup(ipv4Entry.GetNextHopGroup()).State()) + if got, want := len(hopGroup.NextHop), 2; got != want { + t.Errorf("prefix: %s, found %d hops, want %d", ipv4Entry.GetPrefix(), got, want) + } else { + for i, nh := range hopGroup.NextHop { + t.Logf("Prefix %s, NextHop(%d) weight: %d", ipv4Entry.GetPrefix(), i, nh.GetWeight()) + } + } + + sleepTime := time.Duration(totalPackets/trafficPps) + 5 + bs.ATE.OTG().StartTraffic(t) + time.Sleep(sleepTime * time.Second) + bs.ATE.OTG().StopTraffic(t) + + otgutils.LogFlowMetrics(t, bs.ATE.OTG(), bs.ATETop) + checkPacketLoss(t, bs.ATE) + verifyECMPLoadBalance(t, bs.ATE, int(cfgplugins.PortCount4), 2) + }) + } } diff --git a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto index cba5b2008ac..820d96d3595 100644 --- a/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto +++ b/feature/bgp/multipath/otg_tests/bgp_multipath_wecmp_lbw_community_test/metadata.textproto @@ -13,6 +13,7 @@ platform_exceptions: { ipv4_missing_enabled: true skip_setting_allow_multiple_as: true skip_afi_safi_path_for_bgp_multiple_as: true + skip_bgp_send_community_type: true } } platform_exceptions: { @@ -43,7 +44,7 @@ platform_exceptions: { interface_enabled: true default_network_instance: "default" missing_value_for_defaults: true - skip_setting_allow_multiple_as: false + skip_setting_allow_multiple_as: true } } tags: TAGS_DATACENTER_EDGE