]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: When removing v6 address being used as a nexthop ensure peer is reset
authorDonald Sharp <sharpd@nvidia.com>
Wed, 29 Sep 2021 15:42:19 +0000 (11:42 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Mon, 4 Oct 2021 12:03:38 +0000 (08:03 -0400)
With v6 interface based peering, we send the global as well as the LL address
as nexthops to the peer.  When either of these were removed on the interface
we were not necessarily resetting the connection.  Leaving bgp in a state
where the peer had reachability for addresses that are no longer in use.

Modify the code that when we receive an interface address deletion
event.  Check to see that we are using the v6 address as nexthops
for that peer and if so, tell it to reset.

I initially struggled with a hard reset of the peer or a clear but
choose to follow other places in the code that we noticed address
changes that resulted in hard resets.

Ticket: #2799568
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
bgpd/bgp_zebra.c

index 2a67bb2f8c19d567cbfd99e80d7147806a7fddbc..09fe399c295dd5e3cbb60b84c9690f596bb20358 100644 (file)
@@ -338,8 +338,11 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
 
 static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
 {
+       struct listnode *node, *nnode;
        struct connected *ifc;
+       struct peer *peer;
        struct bgp *bgp;
+       struct prefix *addr;
 
        bgp = bgp_lookup_by_vrf_id(vrf_id);
 
@@ -356,6 +359,35 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
                bgp_connected_delete(bgp, ifc);
        }
 
+       addr = ifc->address;
+
+       if (bgp) {
+               /*
+                * When we are using the v6 global as part of the peering
+                * nexthops and we are removing it, then we need to
+                * clear the peer data saved for that nexthop and
+                * cause a re-announcement of the route.  Since
+                * we do not want the peering to bounce.
+                */
+               for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+                       afi_t afi;
+                       safi_t safi;
+
+                       if (addr->family == AF_INET)
+                               continue;
+
+                       if (!IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6)
+                           && memcmp(&peer->nexthop.v6_global,
+                                     &addr->u.prefix6, 16)
+                                      == 0) {
+                               memset(&peer->nexthop.v6_global, 0, 16);
+                               FOREACH_AFI_SAFI (afi, safi)
+                                       bgp_announce_route(peer, afi, safi,
+                                                          true);
+                       }
+               }
+       }
+
        connected_free(&ifc);
 
        return 0;