bgpd: When removing v6 address being used as a nexthop ensure peer is reset

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>
This commit is contained in:
Donald Sharp 2021-09-29 11:42:19 -04:00
parent e1a32ec1c5
commit f3d20a2aa5

View 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;