From 0bf47adc64b05736285fe392365b8733b6f7c507 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 17 Jan 2025 17:28:00 +0100 Subject: [PATCH 1/2] bgpd: fix display json value of interface for BGP unnumbered The 'show bgp ipv[4,6] json' command does not display the interface value of the nexthop, when BGP sessions are unnumbered, whereas the non json output displays it correctly. The below example indicates 'r1-eth0' wheras in json, the value is not displayed. > r1# show bgp ipv4 > BGP table version is 3, local router ID is 10.254.254.1, vrf id 0 > Default local pref 100, local AS 101 > Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, > i internal, r RIB-failure, S Stale, R Removed > Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self > Origin codes: i - IGP, e - EGP, ? - incomplete > RPKI validation codes: V valid, I invalid, N Not found > > Network Next Hop Metric LocPrf Weight Path > *> 10.254.254.1/32 0.0.0.0 0 32768 ? > *> 10.254.254.2/32 r1-eth0 0 0 102 ? > > Displayed 2 routes and 2 total paths Fix this by adding an 'interface' keyword in the json attributes. > "nexthops":[{"ip":"2001:db8:1::2","hostname":"r2","afi":"ipv6", > "scope":"global"},{"interface":"r1-eth0","ip":"fe80::1868:d7ff:fe66:45ae", > "hostname":"r2","afi":"ipv6","scope":"link-local","used":true}]}] Signed-off-by: Philippe Guibert --- bgpd/bgp_route.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f27f0b97c0..a1b12e5a86 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9915,6 +9915,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p, == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) || (path->peer->conf_if)) { json_nexthop_ll = json_object_new_object(); + if (path->peer->conf_if) + json_object_string_add(json_nexthop_ll, "interface", + path->peer->conf_if); json_object_string_addf( json_nexthop_ll, "ip", "%pI6", &attr->mp_nexthop_local); From 50928a93c67ef505a5cab5baeb8820cc40d75dde Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 17 Jan 2025 17:26:50 +0100 Subject: [PATCH 2/2] topotests: bgp_ipv6_rtadv, add control over bgp updates Add a test to control the json values of the incoming BGP update received by an unnumbered BGP. Signed-off-by: Philippe Guibert --- .../bgp_ipv6_rtadv/r1/bgp_ipv4_routes.json | 35 +++++++++++++++++ .../bgp_ipv6_rtadv/r1/bgp_ipv6_routes.json | 35 +++++++++++++++++ .../bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py | 39 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv4_routes.json create mode 100644 tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv6_routes.json diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv4_routes.json b/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv4_routes.json new file mode 100644 index 0000000000..affe5cf8df --- /dev/null +++ b/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv4_routes.json @@ -0,0 +1,35 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "10.254.254.1", + "defaultLocPrf": 100, + "localAS": 101, + "routes": { + "10.254.254.2/32": [{ + "valid": true, + "bestpath": true, + "selectionReason":"First path received", + "pathFrom":"external", + "prefix":"10.254.254.2", + "prefixLen":32, + "network":"10.254.254.2/32", + "metric":0, + "weight":0, + "path":"102", + "origin":"incomplete", + "nexthops":[{ + "ip":"2001:db8:1::2", + "hostname":"r2", + "afi":"ipv6", + "scope":"global" + },{ + "interface":"r1-eth0", + "hostname":"r2", + "afi":"ipv6", + "scope":"link-local", + "used":true + }]}] + }, + "totalRoutes": 2, + "totalPaths": 2 +} diff --git a/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv6_routes.json b/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv6_routes.json new file mode 100644 index 0000000000..bccfb45771 --- /dev/null +++ b/tests/topotests/bgp_ipv6_rtadv/r1/bgp_ipv6_routes.json @@ -0,0 +1,35 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "10.254.254.1", + "defaultLocPrf": 100, + "localAS": 101, + "routes": { + "2001:db8:1::/64": [{ + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "prefix":"2001:db8:1::", + "prefixLen":64, + "network":"2001:db8:1::/64", + "metric":0, + "weight":0, + "path":"102", + "origin":"incomplete", + "nexthops":[{ + "ip":"2001:db8:1::2", + "hostname":"r2", + "afi":"ipv6", + "scope":"global" + },{ + "interface":"r1-eth0", + "hostname":"r2", + "afi":"ipv6", + "scope":"link-local", + "used":true + }]}] + }, + "totalRoutes": 1, + "totalPaths": 1 +} diff --git a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py index 045ac91fc7..5992c30116 100644 --- a/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py +++ b/tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py @@ -74,6 +74,45 @@ def teardown_module(_mod): def test_protocols_convergence(): + """ + Assert that BGP protocol has converged + by checking the incoming BGP updates have been received. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Check BGP IPv4 routing table. + logger.info("Checking BGP IPv4 routes for convergence") + router = tgen.gears["r1"] + + json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name) + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp ipv4 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + # Check BGP IPv6 routing table. + json_file = "{}/{}/bgp_ipv6_routes.json".format(CWD, router.name) + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp ipv6 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +def test_route_convergence(): """ Assert that all protocols have converged statuses as they depend on it.