From cd1d13354e5355af013c2d9cf7727fb02ad85063 Mon Sep 17 00:00:00 2001 From: Rajesh Varatharaj Date: Tue, 30 Apr 2024 15:24:38 -0700 Subject: [PATCH] bgpd: Fix BGP to update correct v6 next-hop globally Issue: In a dual-stack IPv4/IPv6 BGP session, after the interface is deactivated (ifdown) and then reloaded (ifreload), the global next-hop within BGP is incorrectly updated. Currently, only unnumbered neighbors are handled. We also need to handle an IPv4 neighbor when IPv6 AFI-SAFI is enabled. Fix: When the primary global v6 unicast address is received from Zebra, BGP updates the peer's global next-hop with the correct address and send update to its negibors. Testing: UT, and TestEbgpMultihop tests UT logs: with fix: root@cumulus:mgmt:/tmp# ifdown swp1s0; ifreload -a root@:mgmt:/tmp# vtysh -c "show ip bgp vrf all neighbors" | grep Nexthop Nexthop: 20.1.2.101 Nexthop global: 2001:10:1:2::101 Nexthop local: fe80::7efe:90ff:fefa:e158 without fix after ifreload: Nexthop: 20.1.2.101 Nexthop global: :: Nexthop local: fe80::7efe:90ff:fefa:e158 Ticket: #3870831 Signed-off-by: Rajesh Varatharaj and Pooja Doijode pdoijode@nvidia.com --- bgpd/bgp_zebra.c | 14 +++++++------- zebra/rt_netlink.c | 9 ++++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 15ed98933e8d..885e2cd7a2cb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -343,18 +343,18 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS) continue; /* - * If the Peer's interface name matches the - * interface name for which BGP received the - * update and if the received interface address - * is a globalV6 and if the peer is currently + * Is a globalV6 and if the peer is currently * using a v4-mapped-v6 addr or a link local * address, then copy the Rxed global v6 addr * into peer's v6_global and send updates out * with new nexthop addr. + * Making sure peer nexthop ifname in sync with + * local ifname. peer->su.sin6.sin6_scope_id can + * be used only for unnumbered. */ - if ((peer->conf_if && - (strcmp(peer->conf_if, ifc->ifp->name) == - 0)) && + if ((peer->nexthop.ifp && + (strcmp(peer->nexthop.ifp->name, + ifc->ifp->name) == 0)) && !IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) && ((IS_MAPPED_IPV6( &peer->nexthop.v6_global)) || diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4a15b7400496..12ba2589993e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -4309,13 +4309,16 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) zif->link_ifindex); if (!link_if) return 0; - } else if (IS_ZEBRA_IF_BRIDGE(ifp)) + } else if (IS_ZEBRA_IF_BRIDGE(ifp)) { link_if = ifp; - else { + } else { link_if = NULL; + char ip_buf[ETHER_ADDR_STRLEN]; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - " Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring"); + " Neighbor Entry IF %s(%u) and IP %s is not on a VLAN or BRIDGE, ignoring", + ifp->name, ndm->ndm_ifindex, + ipaddr2str(&ip, ip_buf, sizeof(ip_buf))); } memset(&mac, 0, sizeof(mac));