Skip to content

Commit

Permalink
Added subtests to extend UCMP support with Link Bandwidth Community (#…
Browse files Browse the repository at this point in the history
…3530)

* Added subtests to extend UCMP support with Link Bandwidth Community

* PR comment fixes
  • Loading branch information
self-maurya authored Oct 23, 2024
1 parent dcbc957 commit 3621ce6
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -93,40 +91,38 @@ 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=<id>]/next-hops/next-hop[index=<index>]/state/weight

## OpenConfig Path and RPC Coverage

```yaml
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()

Expand Down Expand Up @@ -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)
Expand All @@ -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")
Expand All @@ -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)
Expand All @@ -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)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 3621ce6

Please sign in to comment.