From 38ad215feb313775e066c807a9a2bdf672d3c067 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Tue, 8 Oct 2024 13:01:45 +0200 Subject: [PATCH 1/4] Revert "bgpd: Exclude case for remote prefix w/o link-local" This reverts commit 5f6a61f91fdbfa33df1b7112c961135156fbd894. Signed-off-by: Louis Scalbert --- bgpd/bgp_route.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 475b709a0766..18f1e5fd0436 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2467,16 +2467,13 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, if (NEXTHOP_IS_V6) { attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; if ((CHECK_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) && - IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) || - (!reflect && !transparent && - IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) && - peer->shared_network && - ((from == bgp->peer_self && peer->sort == BGP_PEER_EBGP) || - (from == bgp->peer_self && peer->sort != BGP_PEER_EBGP) || - (from != bgp->peer_self && - IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local) && - peer->sort == BGP_PEER_EBGP)))) { + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) + && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) + || (!reflect && !transparent + && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) + && peer->shared_network + && (from == bgp->peer_self + || peer->sort == BGP_PEER_EBGP))) { if (safi == SAFI_MPLS_VPN) attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL; From 34c1dd076e5f9ea2a7eb8820b204696dc692667d Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Wed, 9 Oct 2024 17:06:19 +0200 Subject: [PATCH 2/4] bgpd: do not insert link-local with local unchanged Do not add an IPv6 link-local nexthop if the originating peer does not provide one and the nexthop-local unchanged setting is enabled. Signed-off-by: Louis Scalbert --- bgpd/bgp_route.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 18f1e5fd0436..b0f91b58b9c9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2155,6 +2155,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, bool nh_reset = false; uint64_t cum_bw; mpls_label_t label; + bool global_and_ll = false; if (DISABLE_BGP_ANNOUNCE) return false; @@ -2465,22 +2466,26 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, * we do not announce LL address as `::`. */ if (NEXTHOP_IS_V6) { - attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - if ((CHECK_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) - && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) - || (!reflect && !transparent - && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) - && peer->shared_network - && (from == bgp->peer_self - || peer->sort == BGP_PEER_EBGP))) { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) { + /* nexthop local unchanged: only include the link-local nexthop if it + * was already present. + */ + if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) + global_and_ll = true; + } else if (!reflect && !transparent && + IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) && peer->shared_network && + (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP)) + global_and_ll = true; + + if (global_and_ll) { if (safi == SAFI_MPLS_VPN) attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL; else attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } + } else + attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* Clear off link-local nexthop in source, whenever it is not * needed to From 5bb99ccad2935adb006f7f727c2779b2c6e746e5 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Wed, 9 Oct 2024 17:08:44 +0200 Subject: [PATCH 3/4] bgpd: reset ipv6 invalid link-local nexthop If the "nexthop-local unchanged" setting is enabled, it preserves the IPv6 link-local nexthop from the originating peer. However, if the originating and destination peers are not on the same network segment, the originating peer's IPv6 link-local address will be unreachable from the destination peer. In such cases, reset the IPv6 link-local nexthop, even if "nexthop-local unchanged" is set on the destination peer. Signed-off-by: Louis Scalbert --- bgpd/bgp_route.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index b0f91b58b9c9..9cefec0706ee 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2492,8 +2492,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, * ensure more prefixes share the same attribute for * announcement. */ - if (!(CHECK_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))) + if (!(CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) || + !IPV6_ADDR_SAME(&peer->nexthop.v6_global, &from->nexthop.v6_global)) + /* Reset if "nexthop-local unchanged" is not set or originating and destination peer + * does not share the same subnet. + */ memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN); } From 6dc4d9506181e370680283a4f9ec34d84b06d5e2 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Tue, 8 Oct 2024 15:04:34 +0200 Subject: [PATCH 4/4] topotests: add bgp_nexthop_ipv6 Add bgp_nexthop_ipv6 to check the ipv6 link-local nexthop conformity in several situations. Signed-off-by: Louis Scalbert --- tests/topotests/bgp_nexthop_ipv6/exabgp.env | 53 ++++ tests/topotests/bgp_nexthop_ipv6/r1/bgpd.conf | 22 ++ .../r1/show_bgp_ipv6_step1.json | 162 +++++++++++ .../r1/show_bgp_ipv6_step2.json | 162 +++++++++++ .../topotests/bgp_nexthop_ipv6/r1/zebra.conf | 14 + tests/topotests/bgp_nexthop_ipv6/r2/bgpd.conf | 22 ++ .../r2/show_bgp_ipv6_step1.json | 162 +++++++++++ .../r2/show_bgp_ipv6_step2.json | 162 +++++++++++ .../topotests/bgp_nexthop_ipv6/r2/zebra.conf | 14 + .../topotests/bgp_nexthop_ipv6/r3/exabgp.cfg | 16 ++ .../r3/show_bgp_ipv6_step1.json | 0 .../r3/show_bgp_ipv6_step2.json | 0 tests/topotests/bgp_nexthop_ipv6/r4/bgpd.conf | 22 ++ .../r4/show_bgp_ipv6_step1.json | 210 ++++++++++++++ .../r4/show_bgp_ipv6_step2.json | 222 +++++++++++++++ .../topotests/bgp_nexthop_ipv6/r4/zebra.conf | 14 + tests/topotests/bgp_nexthop_ipv6/r5/bgpd.conf | 22 ++ .../r5/show_bgp_ipv6_step1.json | 222 +++++++++++++++ .../r5/show_bgp_ipv6_step2.json | 222 +++++++++++++++ .../topotests/bgp_nexthop_ipv6/r5/zebra.conf | 14 + tests/topotests/bgp_nexthop_ipv6/r6/bgpd.conf | 22 ++ .../r6/show_bgp_ipv6_step1.json | 162 +++++++++++ .../r6/show_bgp_ipv6_step2.json | 162 +++++++++++ .../topotests/bgp_nexthop_ipv6/r6/zebra.conf | 14 + tests/topotests/bgp_nexthop_ipv6/rr/bgpd.conf | 30 ++ .../rr/show_bgp_ipv6_step1.json | 220 +++++++++++++++ .../rr/show_bgp_ipv6_step2.json | 220 +++++++++++++++ .../rr/show_bgp_ipv6_summary.json | 6 + .../topotests/bgp_nexthop_ipv6/rr/zebra.conf | 18 ++ .../test_bgp_nexthop_ipv6_topo1.py | 263 ++++++++++++++++++ 30 files changed, 2854 insertions(+) create mode 100644 tests/topotests/bgp_nexthop_ipv6/exabgp.env create mode 100644 tests/topotests/bgp_nexthop_ipv6/r1/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r1/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r2/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r2/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r3/exabgp.cfg create mode 100644 tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r4/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r4/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r5/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r5/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r6/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/r6/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/rr/bgpd.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step1.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step2.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_summary.json create mode 100644 tests/topotests/bgp_nexthop_ipv6/rr/zebra.conf create mode 100644 tests/topotests/bgp_nexthop_ipv6/test_bgp_nexthop_ipv6_topo1.py diff --git a/tests/topotests/bgp_nexthop_ipv6/exabgp.env b/tests/topotests/bgp_nexthop_ipv6/exabgp.env new file mode 100644 index 000000000000..28e642360a39 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/exabgp.env @@ -0,0 +1,53 @@ +[exabgp.api] +encoder = text +highres = false +respawn = false +socket = '' + +[exabgp.bgp] +openwait = 60 + +[exabgp.cache] +attributes = true +nexthops = true + +[exabgp.daemon] +daemonize = true +pid = '/var/run/exabgp/exabgp.pid' +user = 'exabgp' +##daemonize = false + +[exabgp.log] +all = false +configuration = true +daemon = true +destination = '/var/log/exabgp.log' +enable = true +level = INFO +message = false +network = true +packets = false +parser = false +processes = true +reactor = true +rib = false +routes = false +short = false +timers = false + +[exabgp.pdb] +enable = false + +[exabgp.profile] +enable = false +file = '' + +[exabgp.reactor] +speed = 1.0 + +[exabgp.tcp] +acl = false +bind = '' +delay = 0 +once = false +port = 179 diff --git a/tests/topotests/bgp_nexthop_ipv6/r1/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/r1/bgpd.conf new file mode 100644 index 000000000000..7efa1b79fa5d --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r1/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65000 + no bgp ebgp-requires-policy + neighbor fd00:0:2::9 remote-as internal + neighbor fd00:0:2::9 timers 3 10 + address-family ipv4 unicast + redistribute connected route-map RMAP4 + ! + address-family ipv6 unicast + redistribute connected route-map RMAP6 + neighbor fd00:0:2::9 activate + +ip prefix-list RANGE4 seq 10 permit 172.16.0.0/16 le 24 +ip prefix-list RANGE4 seq 20 permit 10.0.0.0/8 ge 32 + +ipv6 prefix-list RANGE6 seq 10 permit fd00:100::0/64 +ipv6 prefix-list RANGE6 seq 20 permit 2001:db8::0/64 ge 128 + +route-map RMAP4 permit 10 + match ip address prefix-list RANGE4 +! +route-map RMAP6 permit 10 + match ipv6 address prefix-list RANGE6 diff --git a/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..9923edb348da --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step1.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.1.1.1", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..9923edb348da --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r1/show_bgp_ipv6_step2.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.1.1.1", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r1/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/r1/zebra.conf new file mode 100644 index 000000000000..d06a3e194ba3 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r1/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +ipv6 forwarding + +int eth-dummy + ip addr 172.16.1.1/24 + ip addr fd00:100::1/64 + +int eth-sw + ip addr 192.168.2.1/24 + ipv6 address fd00:0:2::1/64 + +int lo + ip addr 10.1.1.1/32 + ipv6 address 2001:db8::1/128 diff --git a/tests/topotests/bgp_nexthop_ipv6/r2/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/r2/bgpd.conf new file mode 100644 index 000000000000..4d4ae44e284b --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r2/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65000 + no bgp ebgp-requires-policy + neighbor fd00:0:2::9 remote-as internal + neighbor fd00:0:2::9 timers 3 10 + address-family ipv4 unicast + redistribute connected route-map RMAP4 + ! + address-family ipv6 unicast + redistribute connected route-map RMAP6 + neighbor fd00:0:2::9 activate + +ip prefix-list RANGE4 seq 10 permit 172.16.0.0/16 le 24 +ip prefix-list RANGE4 seq 20 permit 10.0.0.0/8 ge 32 + +ipv6 prefix-list RANGE6 seq 10 permit fd00:200::0/64 +ipv6 prefix-list RANGE6 seq 20 permit 2001:db8::0/64 ge 128 + +route-map RMAP4 permit 10 + match ip address prefix-list RANGE4 +! +route-map RMAP6 permit 10 + match ipv6 address prefix-list RANGE6 diff --git a/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..bb2efa16d9e8 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step1.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.2.2.2", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..bb2efa16d9e8 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r2/show_bgp_ipv6_step2.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.2.2.2", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r2", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r2/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/r2/zebra.conf new file mode 100644 index 000000000000..de8746df98f8 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r2/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +ipv6 forwarding + +int eth-dummy + ip addr 172.16.2.2/24 + ip addr fd00:200::1/64 + +int eth-sw + ip addr 192.168.2.2/24 + ipv6 address fd00:0:2::2/64 + +int lo + ip addr 10.2.2.2/32 + ipv6 address 2001:db8::2/128 \ No newline at end of file diff --git a/tests/topotests/bgp_nexthop_ipv6/r3/exabgp.cfg b/tests/topotests/bgp_nexthop_ipv6/r3/exabgp.cfg new file mode 100644 index 000000000000..373169bcbab4 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r3/exabgp.cfg @@ -0,0 +1,16 @@ +neighbor fd00:0:2::9 { + router-id 10.3.3.3; + local-address fd00:0:2::3; + local-as 65000; + peer-as 65000; + + family { + ipv6 unicast; + } + + static { + route fd00:300::0/64 next-hop fd00:0:2::3; + route 2001:db8::3/128 next-hop fd00:0:2::3; + } + hold-time 10; +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r3/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/topotests/bgp_nexthop_ipv6/r4/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/r4/bgpd.conf new file mode 100644 index 000000000000..b14c9bace4a6 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r4/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65001 + no bgp ebgp-requires-policy + neighbor fd00:0:2::9 remote-as external + neighbor fd00:0:2::9 timers 3 10 + address-family ipv4 unicast + redistribute connected route-map RMAP4 + ! + address-family ipv6 unicast + redistribute connected route-map RMAP6 + neighbor fd00:0:2::9 activate + +ip prefix-list RANGE4 seq 10 permit 172.16.0.0/16 le 24 +ip prefix-list RANGE4 seq 20 permit 10.0.0.0/8 ge 32 + +ipv6 prefix-list RANGE6 seq 10 permit fd00:400::0/64 +ipv6 prefix-list RANGE6 seq 20 permit 2001:db8::0/64 ge 128 + +route-map RMAP4 permit 10 + match ip address prefix-list RANGE4 +! +route-map RMAP6 permit 10 + match ipv6 address prefix-list RANGE6 diff --git a/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..dd8603f4e321 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step1.json @@ -0,0 +1,210 @@ +{ + "routerId": "10.4.4.4", + "localAS": 65001, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r4", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r4", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..35a31e63f921 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json @@ -0,0 +1,222 @@ +{ + "routerId": "10.4.4.4", + "localAS": 65001, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r4", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r4", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-sw", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r4/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/r4/zebra.conf new file mode 100644 index 000000000000..edc39684e1f5 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r4/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +ipv6 forwarding + +int eth-dummy + ip addr 172.16.4.4/24 + ip addr fd00:400::4/64 + +int eth-sw + ip addr 192.168.2.4/24 + ipv6 address fd00:0:2::4/64 + +int lo + ip addr 10.4.4.4/32 + ipv6 address 2001:db8::4/128 \ No newline at end of file diff --git a/tests/topotests/bgp_nexthop_ipv6/r5/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/r5/bgpd.conf new file mode 100644 index 000000000000..becea2bbe648 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r5/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor fd00:0:3::9 remote-as external + neighbor fd00:0:3::9 timers 3 10 + address-family ipv4 unicast + redistribute connected route-map RMAP4 + ! + address-family ipv6 unicast + redistribute connected route-map RMAP6 + neighbor fd00:0:3::9 activate + +ip prefix-list RANGE4 seq 10 permit 172.16.0.0/16 le 24 +ip prefix-list RANGE4 seq 20 permit 10.0.0.0/8 ge 32 + +ipv6 prefix-list RANGE6 seq 10 permit fd00:500::0/64 +ipv6 prefix-list RANGE6 seq 20 permit 2001:db8::0/64 ge 128 + +route-map RMAP4 permit 10 + match ip address prefix-list RANGE4 +! +route-map RMAP6 permit 10 + match ipv6 address prefix-list RANGE6 diff --git a/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..d0875474ae94 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step1.json @@ -0,0 +1,222 @@ +{ + "routerId": "10.5.5.5", + "localAS": 65002, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r5", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r5", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..d0875474ae94 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json @@ -0,0 +1,222 @@ +{ + "routerId": "10.5.5.5", + "localAS": 65002, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r5", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r5", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::9", + "hostname": "rr", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:rr:eth-r5", + "hostname": "rr", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r5/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/r5/zebra.conf new file mode 100644 index 000000000000..d278889ed908 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r5/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +ipv6 forwarding + +int eth-dummy + ip addr 172.16.5.5/24 + ip addr fd00:500::5/64 + +int eth-rr + ip addr 192.168.3.5/24 + ipv6 address fd00:0:3::5/64 + +int lo + ip addr 10.5.5.5/32 + ipv6 address 2001:db8::5/128 diff --git a/tests/topotests/bgp_nexthop_ipv6/r6/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/r6/bgpd.conf new file mode 100644 index 000000000000..801736ab988e --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r6/bgpd.conf @@ -0,0 +1,22 @@ +router bgp 65000 + no bgp ebgp-requires-policy + neighbor fd00:0:4::9 remote-as internal + neighbor fd00:0:4::9 timers 3 10 + address-family ipv4 unicast + redistribute connected route-map RMAP4 + ! + address-family ipv6 unicast + redistribute connected route-map RMAP6 + neighbor fd00:0:4::9 activate + +ip prefix-list RANGE4 seq 10 permit 172.16.0.0/16 le 24 +ip prefix-list RANGE4 seq 20 permit 10.0.0.0/8 ge 32 + +ipv6 prefix-list RANGE6 seq 10 permit fd00:600::0/64 +ipv6 prefix-list RANGE6 seq 20 permit 2001:db8::0/64 ge 128 + +route-map RMAP4 permit 10 + match ip address prefix-list RANGE4 +! +route-map RMAP6 permit 10 + match ipv6 address prefix-list RANGE6 diff --git a/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..cd48dd4697ce --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step1.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.6.6.6", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r6", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r6", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..cd48dd4697ce --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r6/show_bgp_ipv6_step2.json @@ -0,0 +1,162 @@ +{ + "routerId": "10.6.6.6", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r6", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "rr", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "::", + "hostname": "r6", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/r6/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/r6/zebra.conf new file mode 100644 index 000000000000..84bbb95a833a --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/r6/zebra.conf @@ -0,0 +1,14 @@ +ip forwarding +ipv6 forwarding + +int eth-dummy + ip addr 172.16.6.6/24 + ip addr fd00:600::6/64 + +int eth-rr + ip addr 192.168.4.6/24 + ipv6 address fd00:0:4::6/64 + +int lo + ip addr 10.6.6.6/32 + ipv6 address 2001:db8::6/128 diff --git a/tests/topotests/bgp_nexthop_ipv6/rr/bgpd.conf b/tests/topotests/bgp_nexthop_ipv6/rr/bgpd.conf new file mode 100644 index 000000000000..6dcded15258c --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/rr/bgpd.conf @@ -0,0 +1,30 @@ +router bgp 65000 + no bgp ebgp-requires-policy + neighbor fd00:0:2::1 remote-as internal + neighbor fd00:0:2::1 timers 3 10 + neighbor fd00:0:2::2 remote-as internal + neighbor fd00:0:2::2 timers 3 10 + neighbor fd00:0:2::3 remote-as internal + neighbor fd00:0:2::3 timers 3 10 + neighbor fd00:0:2::4 remote-as external + neighbor fd00:0:2::4 timers 3 10 + neighbor fd00:0:3::5 remote-as external + neighbor fd00:0:3::5 timers 3 10 + neighbor fd00:0:4::6 remote-as internal + neighbor fd00:0:4::6 timers 3 10 + address-family ipv4 unicast + neighbor fd00:0:2::1 route-reflector-client + neighbor fd00:0:2::2 route-reflector-client + neighbor fd00:0:2::3 route-reflector-client + neighbor fd00:0:4::6 route-reflector-client + address-family ipv6 unicast + neighbor fd00:0:2::1 route-reflector-client + neighbor fd00:0:2::1 activate + neighbor fd00:0:2::2 route-reflector-client + neighbor fd00:0:2::2 activate + neighbor fd00:0:2::3 route-reflector-client + neighbor fd00:0:2::3 activate + neighbor fd00:0:2::4 nexthop-local unchanged + neighbor fd00:0:2::4 activate + neighbor fd00:0:3::5 activate + neighbor fd00:0:4::6 activate diff --git a/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step1.json new file mode 100644 index 000000000000..c8b8e1e89356 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step1.json @@ -0,0 +1,220 @@ +{ + "routerId": "10.9.9.9", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "r1", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "r1", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "r2", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "r2", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "r4", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r4:eth-sw", + "hostname": "r4", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "r5", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r5:eth-rr", + "hostname": "r5", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "r6", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r6:eth-rr", + "hostname": "r6", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "r1", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "r1", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "r2", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "r2", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "r4", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r4:eth-sw", + "hostname": "r4", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "r5", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r5:eth-rr", + "hostname": "r5", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "r6", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r6:eth-rr", + "hostname": "r6", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step2.json new file mode 100644 index 000000000000..c8b8e1e89356 --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_step2.json @@ -0,0 +1,220 @@ +{ + "routerId": "10.9.9.9", + "localAS": 65000, + "routes": { + "2001:db8::1/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "r1", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "r1", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::2/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "r2", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "r2", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::3/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8::4/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "r4", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r4:eth-sw", + "hostname": "r4", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::5/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "r5", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r5:eth-rr", + "hostname": "r5", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "2001:db8::6/128": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "r6", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r6:eth-rr", + "hostname": "r6", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:100::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::1", + "hostname": "r1", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r1:eth-sw", + "hostname": "r1", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:200::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::2", + "hostname": "r2", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r2:eth-sw", + "hostname": "r2", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:300::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::3", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "fd00:400::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:2::4", + "hostname": "r4", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r4:eth-sw", + "hostname": "r4", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:500::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:3::5", + "hostname": "r5", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r5:eth-rr", + "hostname": "r5", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ], + "fd00:600::/64": [ + { + "nexthops": [ + { + "ip": "fd00:0:4::6", + "hostname": "r6", + "afi": "ipv6", + "scope": "global" + }, + { + "ip": "link-local:r6:eth-rr", + "hostname": "r6", + "afi": "ipv6", + "scope": "link-local", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_summary.json b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_summary.json new file mode 100644 index 000000000000..ceac91215dad --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/rr/show_bgp_ipv6_summary.json @@ -0,0 +1,6 @@ +{ + "ipv6Unicast": { + "failedPeers": 0, + "totalPeers": 6 + } +} diff --git a/tests/topotests/bgp_nexthop_ipv6/rr/zebra.conf b/tests/topotests/bgp_nexthop_ipv6/rr/zebra.conf new file mode 100644 index 000000000000..21d44f3a15fa --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/rr/zebra.conf @@ -0,0 +1,18 @@ +ip forwarding +ipv6 forwarding + +int eth-sw + ip addr 192.168.2.9/24 + ipv6 address fd00:0:2::9/64 + +int eth-r5 + ip addr 192.168.3.9/24 + ipv6 address fd00:0:3::9/64 + +int eth-r6 + ip addr 192.168.4.9/24 + ipv6 address fd00:0:4::9/64 + +int lo + ip addr 10.9.9.9/32 + ipv6 address 2001:db8::9/128 diff --git a/tests/topotests/bgp_nexthop_ipv6/test_bgp_nexthop_ipv6_topo1.py b/tests/topotests/bgp_nexthop_ipv6/test_bgp_nexthop_ipv6_topo1.py new file mode 100644 index 000000000000..24d71f5622ae --- /dev/null +++ b/tests/topotests/bgp_nexthop_ipv6/test_bgp_nexthop_ipv6_topo1.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_bgp_nexthop_ipv6_topo1.py +# +# Copyright (c) 2024 by +# Cumulus Networks, Inc. +# 6WIND S.A. +# + +""" +Ensure that BGP ipv6 nexthops are correct +""" + +import os +import sys +import pytest +from functools import partial +import json + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + """ + All peers are FRR BGP peers except r3 that is a exabgp peer. + rr is a route-reflector for AS 65000 iBGP peers. + Exabgp does not send any IPv6 Link-Local nexthop + + iBGP peers | eBGP peers + | + AS 65000 | + | + +---+ | + | r6| | + +---+ | + | | + fd00:0:3::0/64 | + | | AS 65002 + +---+ | +---+ + |rr |----fd00:0:4::0/64---| r5| + +---+ |_________+---+ + | | +---+ + fd00:0:2::0/64----------------| r4| + / | \ | +---+ + +---+ +---+ +---+ | AS 65001 + | r1| | r2| |r3 | | + +---+ +---+ +---+ + """ + + def connect_routers(tgen, left, right): + for rname in [left, right]: + if rname not in tgen.routers().keys(): + tgen.add_router(rname) + + switch = tgen.add_switch("s-{}-{}".format(left, right)) + switch.add_link(tgen.gears[left], nodeif="eth-{}".format(right)) + switch.add_link(tgen.gears[right], nodeif="eth-{}".format(left)) + + def connect_switchs(tgen, rname, switch): + if rname not in tgen.routers().keys(): + tgen.add_router(rname) + + switch.add_link(tgen.gears[rname], nodeif="eth-{}".format(switch.name)) + + def connect_dummy(tgen, rname, switch): + if rname not in tgen.routers().keys(): + tgen.add_router(rname) + + switch.add_link(tgen.gears[rname], nodeif="eth-dummy") + + # sw_du switch is for a dummy interface (for local network) + for i in range(1, 7): + if i == 3: + # r3 is an exabgp peer + continue + sw_du = tgen.add_switch("sw%s" % i) + connect_dummy(tgen, "r%s" % i, sw_du) + + # sw switch is for interconnecting peers on the same subnet + sw = tgen.add_switch("sw") + connect_switchs(tgen, "rr", sw) + connect_switchs(tgen, "r1", sw) + connect_switchs(tgen, "r2", sw) + connect_switchs(tgen, "r4", sw) + + # directly connected without switch routers + connect_routers(tgen, "rr", "r5") + connect_routers(tgen, "rr", "r6") + + ## Add iBGP ExaBGP neighbor + peer_ip = "fd00:0:2::3" ## peer + peer_route = "via fd00:0:2::9" ## router + r3 = tgen.add_exabgp_peer("r3", ip=peer_ip, defaultRoute=peer_route) + sw.add_link(r3) + + +##################################################### +## +## Tests starting +## +##################################################### + + +def setup_module(module): + "Setup topology" + tgen = Topogen(build_topo, module.__name__) + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + # Start r3 exabgp peer + r3 = tgen.gears["r3"] + r3.start(os.path.join(CWD, "r3"), os.path.join(CWD, "exabgp.env")) + + +def get_link_local(rname, ifname, cache): + ip = cache.get(rname, {}).get(ifname) + if ip: + return ip + + tgen = get_topogen() + out = tgen.gears[rname].vtysh_cmd("show interface %s json" % ifname, isjson=True) + for address in out[ifname]["ipAddresses"]: + if not address["address"].startswith("fe80::"): + continue + ip = address["address"].split("/")[0] + cache.setdefault(rname, {})[ifname] = ip + return ip + + +def replace_link_local(expected, cache): + for prefix, prefix_info in expected.get("routes", {}).items(): + for nexthop in prefix_info[0].get("nexthops", []): + ip = nexthop.get("ip", "") + if not ip.startswith("link-local:"): + continue + rname = ip.split(":")[1] + ifname = ip.split(":")[2] + ip = get_link_local(rname, ifname, cache) + nexthop["ip"] = ip + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def test_converge_protocols(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + rr = tgen.gears["rr"] + ref_file = "{}/{}/show_bgp_ipv6_summary.json".format(CWD, rr.name) + expected = json.loads(open(ref_file).read()) + + test_func = partial( + topotest.router_json_cmp, + rr, + "show bgp ipv6 summary json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}: BGP convergence".format(rr.name) + assert res is None, assertmsg + + +def test_bgp_ipv6_table_step1(): + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global link_local_cache + link_local_cache = {} + router_list = tgen.routers().values() + for router in router_list: + # router.cmd("vtysh -c 'sh bgp ipv6 json' >/tmp/show_bgp_ipv6_%s.json" % router.name) + ref_file = "{}/{}/show_bgp_ipv6_step1.json".format(CWD, router.name) + expected = json.loads(open(ref_file).read()) + replace_link_local(expected, link_local_cache) + + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp ipv6 unicast json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}: BGP IPv6 Nexthop failure".format(router.name) + assert res is None, assertmsg + + +def test_bgp_ipv6_table_step2(): + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + rr = tgen.gears["rr"] + rr.vtysh_cmd( + """ +configure terminal +router bgp 65000 + address-family ipv6 unicast + no neighbor fd00:0:2::4 nexthop-local unchanged +""" + ) + + router_list = tgen.routers().values() + for router in router_list: + # router.cmd("vtysh -c 'sh bgp ipv6 json' >/tmp/show_bgp_ipv6_%s.json" % router.name) + ref_file = "{}/{}/show_bgp_ipv6_step2.json".format(CWD, router.name) + expected = json.loads(open(ref_file).read()) + replace_link_local(expected, link_local_cache) + + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp ipv6 unicast json", + expected, + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=1) + assertmsg = "{}: BGP IPv6 Nexthop failure".format(router.name) + assert res is None, assertmsg + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args))