diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:53:30 +0000 |
commit | 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 (patch) | |
tree | c05dc0f8e6aa3accc84e3e5cffc933ed94941383 /tests/topotests/bgp_remove_private_as | |
parent | Initial commit. (diff) | |
download | frr-upstream.tar.xz frr-upstream.zip |
Adding upstream version 8.4.4.upstream/8.4.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/topotests/bgp_remove_private_as')
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r1/bgpd.conf | 53 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r1/zebra.conf | 10 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r2/bgpd.conf | 22 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r2/zebra.conf | 14 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r3/bgpd.conf | 19 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r3/zebra.conf | 10 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r4/bgpd.conf | 19 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r4/zebra.conf | 10 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r5/bgpd.conf | 22 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/r5/zebra.conf | 14 | ||||
-rw-r--r-- | tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py | 430 |
11 files changed, 623 insertions, 0 deletions
diff --git a/tests/topotests/bgp_remove_private_as/r1/bgpd.conf b/tests/topotests/bgp_remove_private_as/r1/bgpd.conf new file mode 100644 index 0000000..9953689 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r1/bgpd.conf @@ -0,0 +1,53 @@ +router bgp 65001 + bgp router-id 192.0.2.1 + no bgp network import-check + neighbor 203.0.113.1 remote-as 65002 + neighbor 203.0.113.1 description r2 + neighbor 203.0.113.1 timers 3 10 + neighbor 203.0.113.3 remote-as 5555 + neighbor 203.0.113.3 description r5 + neighbor 203.0.113.3 timers 3 10 +! + address-family ipv4 unicast + network 100.64.0.0/32 + network 100.64.0.1/32 + network 100.64.0.2/32 + network 100.64.0.3/32 + network 100.64.0.4/32 + network 100.64.0.5/32 + neighbor 203.0.113.1 route-map set-as-paths out + neighbor 203.0.113.3 route-map set-as-paths out + exit-address-family +! +ip prefix-list match-0 seq 5 permit 100.64.0.0/32 +ip prefix-list match-1 seq 5 permit 100.64.0.1/32 +ip prefix-list match-2 seq 5 permit 100.64.0.2/32 +ip prefix-list match-3 seq 5 permit 100.64.0.3/32 +ip prefix-list match-4 seq 5 permit 100.64.0.4/32 +! +! all private +! at r3/r4, as-path should only have r2's asn +route-map set-as-paths permit 10 + match ip address prefix-list match-0 + set as-path prepend 4200000000 4200000001 4200000002 +! +! all private, include r3's asn +! at r3/r4, as-path should only have r2's asn +route-map set-as-paths permit 20 + match ip address prefix-list match-1 + set as-path prepend 65003 4200000000 4200000001 4200000002 65003 +! +! mix of private/public +route-map set-as-paths permit 30 + match ip address prefix-list match-2 + set as-path prepend 4200000000 1000 4200000001 2000 4200000002 +! +! mix of private/public, include r3's asn multiple times +route-map set-as-paths permit 40 + match ip address prefix-list match-3 + set as-path prepend 65003 4200000000 1000 4200000001 2000 4200000002 65003 +! +! all public +route-map set-as-paths permit 50 + match ip address prefix-list match-4 + set as-path prepend 1000 2000 2000 3000 diff --git a/tests/topotests/bgp_remove_private_as/r1/zebra.conf b/tests/topotests/bgp_remove_private_as/r1/zebra.conf new file mode 100644 index 0000000..35c82d7 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r1/zebra.conf @@ -0,0 +1,10 @@ +! to r2 +interface r1-eth0 + ip address 203.0.113.0/31 +! +! to r5 +interface r1-eth1 + ip address 203.0.113.2/31 +! +ip forwarding +! diff --git a/tests/topotests/bgp_remove_private_as/r2/bgpd.conf b/tests/topotests/bgp_remove_private_as/r2/bgpd.conf new file mode 100644 index 0000000..9655046 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r2/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65002 + bgp router-id 192.0.2.2 + neighbor 203.0.113.0 remote-as 65001 + neighbor 203.0.113.0 timers 3 10 + neighbor 203.0.113.0 description r1 + neighbor 203.0.113.4 remote-as 65003 + neighbor 203.0.113.4 solo + neighbor 203.0.113.4 timers 3 10 + neighbor 203.0.113.4 description r3 + neighbor 203.0.113.8 remote-as 4444 + neighbor 203.0.113.8 solo + neighbor 203.0.113.8 timers 3 10 + neighbor 203.0.113.8 description r4 +! + address-family ipv4 unicast + neighbor 203.0.113.0 route-map permit-all in + neighbor 203.0.113.4 route-map permit-all out + neighbor 203.0.113.8 route-map permit-all out + exit-address-family +! +route-map permit-all permit 10 +! diff --git a/tests/topotests/bgp_remove_private_as/r2/zebra.conf b/tests/topotests/bgp_remove_private_as/r2/zebra.conf new file mode 100644 index 0000000..0168614 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r2/zebra.conf @@ -0,0 +1,14 @@ +! to r1 +interface r2-eth0 + ip address 203.0.113.1/31 +! +! to r3 +interface r2-eth1 + ip address 203.0.113.5/31 +! +! to r4 +interface r2-eth2 + ip address 203.0.113.9/31 +! +ip forwarding +! diff --git a/tests/topotests/bgp_remove_private_as/r3/bgpd.conf b/tests/topotests/bgp_remove_private_as/r3/bgpd.conf new file mode 100644 index 0000000..0273d09 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r3/bgpd.conf @@ -0,0 +1,19 @@ +router bgp 65003 + bgp router-id 192.0.2.3 + neighbor 203.0.113.5 remote-as 65002 + neighbor 203.0.113.5 timers 3 10 + neighbor 203.0.113.5 description r2 + neighbor 203.0.113.7 remote-as 5555 + neighbor 203.0.113.7 timers 3 10 + neighbor 203.0.113.7 description r5 +! + address-family ipv4 unicast + neighbor 203.0.113.5 route-map permit-all in + neighbor 203.0.113.5 allowas-in 10 + neighbor 203.0.113.5 soft-reconfiguration inbound + neighbor 203.0.113.7 route-map permit-all in + neighbor 203.0.113.7 allowas-in 10 + neighbor 203.0.113.7 soft-reconfiguration inbound + exit-address-family +! +route-map permit-all permit 10 diff --git a/tests/topotests/bgp_remove_private_as/r3/zebra.conf b/tests/topotests/bgp_remove_private_as/r3/zebra.conf new file mode 100644 index 0000000..e6a0ce3 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r3/zebra.conf @@ -0,0 +1,10 @@ +! to r2 +interface r3-eth0 + ip address 203.0.113.4/31 +! +! to r5 +interface r3-eth1 + ip address 203.0.113.6/31 +! +ip forwarding +! diff --git a/tests/topotests/bgp_remove_private_as/r4/bgpd.conf b/tests/topotests/bgp_remove_private_as/r4/bgpd.conf new file mode 100644 index 0000000..f480105 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r4/bgpd.conf @@ -0,0 +1,19 @@ +router bgp 4444 + bgp router-id 192.0.2.4 + neighbor 203.0.113.9 remote-as 65002 + neighbor 203.0.113.9 timers 3 10 + neighbor 203.0.113.9 description r2 + neighbor 203.0.113.11 remote-as 5555 + neighbor 203.0.113.11 timers 3 10 + neighbor 203.0.113.11 description r5 +! + address-family ipv4 unicast + neighbor 203.0.113.9 route-map permit-all in + neighbor 203.0.113.9 allowas-in 10 + neighbor 203.0.113.9 soft-reconfiguration inbound + neighbor 203.0.113.11 route-map permit-all in + neighbor 203.0.113.11 allowas-in 10 + neighbor 203.0.113.11 soft-reconfiguration inbound + exit-address-family +! +route-map permit-all permit 10 diff --git a/tests/topotests/bgp_remove_private_as/r4/zebra.conf b/tests/topotests/bgp_remove_private_as/r4/zebra.conf new file mode 100644 index 0000000..4de3300 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r4/zebra.conf @@ -0,0 +1,10 @@ +! to r2 +interface r4-eth0 + ip address 203.0.113.8/31 +! +! to r5 +interface r4-eth1 + ip address 203.0.113.10/31 +! +ip forwarding +! diff --git a/tests/topotests/bgp_remove_private_as/r5/bgpd.conf b/tests/topotests/bgp_remove_private_as/r5/bgpd.conf new file mode 100644 index 0000000..67b4d43 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r5/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 5555 + bgp router-id 192.0.2.5 + neighbor 203.0.113.2 remote-as 65001 + neighbor 203.0.113.2 timers 3 10 + neighbor 203.0.113.2 description r1 + neighbor 203.0.113.6 remote-as 65003 + neighbor 203.0.113.6 solo + neighbor 203.0.113.6 timers 3 10 + neighbor 203.0.113.6 description r3 + neighbor 203.0.113.10 remote-as 4444 + neighbor 203.0.113.10 solo + neighbor 203.0.113.10 timers 3 10 + neighbor 203.0.113.10 description r4 +! + address-family ipv4 unicast + neighbor 203.0.113.2 route-map permit-all in + neighbor 203.0.113.6 route-map permit-all out + neighbor 203.0.113.10 route-map permit-all out + exit-address-family +! +route-map permit-all permit 10 +! diff --git a/tests/topotests/bgp_remove_private_as/r5/zebra.conf b/tests/topotests/bgp_remove_private_as/r5/zebra.conf new file mode 100644 index 0000000..f02daf4 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/r5/zebra.conf @@ -0,0 +1,14 @@ +! to r1 +interface r5-eth0 + ip address 203.0.113.3/31 +! +! to r3 +interface r5-eth1 + ip address 203.0.113.7/31 +! +! to r4 +interface r5-eth2 + ip address 203.0.113.11/31 +! +ip forwarding +! diff --git a/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py b/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py new file mode 100644 index 0000000..1108919 --- /dev/null +++ b/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py @@ -0,0 +1,430 @@ +#!/usr/bin/env python + +# +# test_bgp_remove_private_as.py +# +# Copyright (C) 2022 NVIDIA Corporation +# Trey Aspelund +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NVIDIA BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_bgp_remove_private_as.py tests the following conditions: +1. "remove-private-AS" strips all private ASNs from the AS-path unless: + a. the ASN belongs to the peer + b. the ASN is both local + private + c. the AS-path is not completely comprised of public ASNs +2. "remove-private-AS all" strips all private ASNs from the AS-path unless: + a. the ASN belongs to the peer + b. the ASN is both local + private +3. "remove-private-AS replace-AS" swaps private ASNs with local ASN unless: + a. the ASN belongs to the peer + b. the AS-path is not completely comprised of public ASNs +4. "remove-private-AS all replace-AS" swaps private ASNs with local ASN unless: + a. the ASN belongs to the peer + +All conditions are tested while the local ASN is private. +All conditions are tested while the local ASN is public. +All conditions are tested against an eBGP peer in a private ASN. +All conditions are tested against an eBGP peer in a public ASN. +""" + +import os +import sys +import json +import time +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from functools import partial + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + """ + We are effectively creating two hub/spoke topologies with r2 and r5 acting + as hubs. "remove-private-AS" will be configured on r2/r5 towards r3/r4, and + r1 will act as the originator of the test prefixes. AS-Path validation will + be done on r3/r4. + + Topology: + +-----+ +-----+ +-----+ + | r1 |----->|r2/r5|---->| r3 | + +-----+ +-----+ +-----+ + | + v + +-----+ + | r4 | + +-----+ + ASNs: + - r1: 65001 + - r2: 65002 + - r3: 65003 + - r4: 4444 + - r5: 5555 + """ + for routern in range(1, 6): + tgen.add_router(f"r{routern}") + + ####################### + # Connections to r2 + ####################### + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r4"]) + + ####################### + # Connections to r5 + ####################### + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r5"]) + + switch = tgen.add_switch("s5") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r5"]) + + switch = tgen.add_switch("s6") + switch.add_link(tgen.gears["r4"]) + switch.add_link(tgen.gears["r5"]) + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, f"{rname}/zebra.conf") + ) + router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, f"{rname}/bgpd.conf")) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_remove_private_as(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Test routes + prefixes = [ + "100.64.0.0/32", + "100.64.0.1/32", + "100.64.0.2/32", + "100.64.0.3/32", + "100.64.0.4/32", + ] + + # r2/r5 are setup with remove-private-AS configs. + tx_routers = ["r2", "r5"] + + # We will validate the paths received by r3/r4. + rx_routers = ["r3", "r4"] + + # Config options for remove-private-AS + remove_types = [ + "remove-private-AS", + "remove-private-AS all", + "remove-private-AS replace-AS", + "remove-private-AS all replace-AS", + ] + + # Expected as-paths for each test route from the perspective of each + # rx_router, accounting for each variation of remove-private-AS. + # + # Structure: + # expected_paths = { + # rx_router: { + # remove_type: { + # tx_router: { + # prefix: "path" + # } + # } + # } + # } + expected_paths = { + "r3": { + "remove-private-AS": { + "r2": { + "100.64.0.0/32": "65002", + "100.64.0.1/32": "65002 65003 65003", + "100.64.0.2/32": "65002 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "65002 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "65002 65001 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555", + "100.64.0.1/32": "5555 65003 65003", + "100.64.0.2/32": "5555 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "5555 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "5555 65001 1000 2000 2000 3000", + }, + }, + "remove-private-AS all": { + "r2": { + "100.64.0.0/32": "65002", + "100.64.0.1/32": "65002 65003 65003", + "100.64.0.2/32": "65002 1000 2000", + "100.64.0.3/32": "65002 65003 1000 2000 65003", + "100.64.0.4/32": "65002 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555", + "100.64.0.1/32": "5555 65003 65003", + "100.64.0.2/32": "5555 1000 2000", + "100.64.0.3/32": "5555 65003 1000 2000 65003", + "100.64.0.4/32": "5555 1000 2000 2000 3000", + }, + }, + "remove-private-AS replace-AS": { + "r2": { + "100.64.0.0/32": "65002 65002 65002 65002 65002", + "100.64.0.1/32": "65002 65002 65003 65002 65002 65002 65003", + "100.64.0.2/32": "65002 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "65002 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "65002 65001 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555 5555 5555 5555 5555", + "100.64.0.1/32": "5555 5555 65003 5555 5555 5555 65003", + "100.64.0.2/32": "5555 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "5555 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "5555 65001 1000 2000 2000 3000", + }, + }, + "remove-private-AS all replace-AS": { + "r2": { + "100.64.0.0/32": "65002 65002 65002 65002 65002", + "100.64.0.1/32": "65002 65002 65003 65002 65002 65002 65003", + "100.64.0.2/32": "65002 65002 65002 1000 65002 2000 65002", + "100.64.0.3/32": "65002 65002 65003 65002 1000 65002 2000 65002 65003", + "100.64.0.4/32": "65002 65002 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555 5555 5555 5555 5555", + "100.64.0.1/32": "5555 5555 65003 5555 5555 5555 65003", + "100.64.0.2/32": "5555 5555 5555 1000 5555 2000 5555", + "100.64.0.3/32": "5555 5555 65003 5555 1000 5555 2000 5555 65003", + "100.64.0.4/32": "5555 5555 1000 2000 2000 3000", + }, + }, + }, + "r4": { + "remove-private-AS": { + "r2": { + "100.64.0.0/32": "65002", + "100.64.0.1/32": "65002", + "100.64.0.2/32": "65002 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "65002 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "65002 65001 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555", + "100.64.0.1/32": "5555", + "100.64.0.2/32": "5555 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "5555 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "5555 65001 1000 2000 2000 3000", + }, + }, + "remove-private-AS all": { + "r2": { + "100.64.0.0/32": "65002", + "100.64.0.1/32": "65002", + "100.64.0.2/32": "65002 1000 2000", + "100.64.0.3/32": "65002 1000 2000", + "100.64.0.4/32": "65002 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555", + "100.64.0.1/32": "5555", + "100.64.0.2/32": "5555 1000 2000", + "100.64.0.3/32": "5555 1000 2000", + "100.64.0.4/32": "5555 1000 2000 2000 3000", + }, + }, + "remove-private-AS replace-AS": { + "r2": { + "100.64.0.0/32": "65002 65002 65002 65002 65002", + "100.64.0.1/32": "65002 65002 65002 65002 65002 65002 65002", + "100.64.0.2/32": "65002 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "65002 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "65002 65001 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555 5555 5555 5555 5555", + "100.64.0.1/32": "5555 5555 5555 5555 5555 5555 5555", + "100.64.0.2/32": "5555 65001 4200000000 1000 4200000001 2000 4200000002", + "100.64.0.3/32": "5555 65001 65003 4200000000 1000 4200000001 2000 4200000002 65003", + "100.64.0.4/32": "5555 65001 1000 2000 2000 3000", + }, + }, + "remove-private-AS all replace-AS": { + "r2": { + "100.64.0.0/32": "65002 65002 65002 65002 65002", + "100.64.0.1/32": "65002 65002 65002 65002 65002 65002 65002", + "100.64.0.2/32": "65002 65002 65002 1000 65002 2000 65002", + "100.64.0.3/32": "65002 65002 65002 65002 1000 65002 2000 65002 65002", + "100.64.0.4/32": "65002 65002 1000 2000 2000 3000", + }, + "r5": { + "100.64.0.0/32": "5555 5555 5555 5555 5555", + "100.64.0.1/32": "5555 5555 5555 5555 5555 5555 5555", + "100.64.0.2/32": "5555 5555 5555 1000 5555 2000 5555", + "100.64.0.3/32": "5555 5555 5555 5555 1000 5555 2000 5555 5555", + "100.64.0.4/32": "5555 5555 1000 2000 2000 3000", + }, + }, + }, + } + + # Simple lookup of remote peer ip by routers in session (local --> remote). + # + # Structure: + # peer_to_ip = { + # local_rtr: { + # peer_rtr: peer_ip + # } + # } + peer_to_ip = { + "r1": {"r2": "203.0.113.1", "r5": "203.0.113.3"}, + "r2": {"r1": "203.0.113.0", "r3": "203.0.113.4", "r4": "203.0.113.8"}, + "r3": {"r2": "203.0.113.5", "r5": "203.0.113.7"}, + "r4": {"r2": "203.0.113.9", "r5": "203.0.113.11"}, + "r5": {"r1": "203.0.113.2", "r3": "203.0.113.6", "r4": "203.0.113.10"}, + } + + def __bgp_up(): + """Return True if all configured peers are Established.""" + for router in tx_routers: + output = json.loads( + tgen.gears[router].vtysh_cmd("show ip bgp summary json") + ) + numPeers = output["ipv4Unicast"]["totalPeers"] + numConverged = 0 + for peer_data in output["ipv4Unicast"]["peers"].values(): + if peer_data["state"] == "Established": + numConverged += 1 + if numConverged == numPeers: + return True + return False + + def __bgp_converged(): + """Return True if all prefixes have been received from tx_routers.""" + for router in rx_routers: + output = json.loads( + tgen.gears[router].vtysh_cmd("show ip bgp summary json") + ) + numPeers = output["ipv4Unicast"]["totalPeers"] + numConverged = 0 + for peer in tx_routers: + peer_ip = peer_to_ip[router][peer] + numPrefixes = output["ipv4Unicast"]["peers"][peer_ip]["pfxRcd"] + if numPrefixes == len(prefixes): + numConverged += 1 + if numConverged == numPeers: + return True + return False + + def _routers_up(tx_rtrs, rx_rtrs): + """Ensure all BGP sessions are up and all routes are installed.""" + # all sessions go through tx_routers, so ensure all their peers are up + test_func = partial(__bgp_up) + _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) + assert result == True, "Not all peers in Established state!" + + # ensure correct number of routes are installed + test_func = partial(__bgp_converged) + _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) + assert result == True, "Not all routes installed in time!" + + def _change_remove_type(new_type, op): + """Update config with next remove-private-AS config variant.""" + no = "no" if op == "del" else "" + for tr in tx_routers: + for rr in rx_routers: + p_ip = peer_to_ip[tr][rr] + tgen.gears[tr].vtysh_multicmd( + f""" + configure terminal + router bgp + address-family ipv4 unicast + {no} neighbor {p_ip} {new_type} + """ + ) + + def _validate_paths(remove_type): + """Compare actual AS-Path against expected AS-Path.""" + for rtr in rx_routers: + for peer in tx_routers: + p_ip = peer_to_ip[rtr][peer] + adj_rib_in = json.loads( + tgen.gears[rtr].vtysh_cmd( + f"show ip bgp neighbor {p_ip} received-routes json" + ) + ) + for pfx in prefixes: + good_path = expected_paths[rtr][remove_type][peer][pfx] + real_path = adj_rib_in["receivedRoutes"][pfx]["path"] + return real_path == good_path + + ####################### + # Begin Test + ####################### + + # make sure all peers come up and exchange routes + _routers_up(tx_routers, rx_routers) + + # test each variation of remove-private-AS + for rmv_type in remove_types: + _change_remove_type(rmv_type, "add") + + test_func = partial(_validate_paths, rmv_type) + _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5) + assert result == True, "Not all routes have correct AS-Path values!" + + # each variation sets a separate peer flag in bgpd. we need to clear + # the old flag after each iteration so we only test the flags we expect. + _change_remove_type(rmv_type, "del") + + return True + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |