bgpd: turn off RAs when numbered peers are deleted

Problem reported that in many circumstances, RAs created in the
process of bringing up numbered IPv6 peers with extended-nexthop
capability enabled (for ipv4 over ipv6) were not stopped on the
interface when those peers were deleted.  Found several circumstances
where this occurred and fix them in this patch.

Ticket: CM-26875
Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
Don Slice 2020-04-21 19:01:35 +00:00
parent abe94d6562
commit b3a3290e23
5 changed files with 104 additions and 12 deletions

View file

@ -873,7 +873,7 @@ void bgp_nht_register_nexthops(struct bgp *bgp)
}
}
void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
{
struct bgp *bgp;
struct bgp_node *rn;
@ -891,9 +891,8 @@ void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
return;
if (!sockunion2hostprefix(&peer->su, &p)) {
if (BGP_DEBUG(nht, NHT))
zlog_debug("%s: Unable to convert prefix to sockunion",
__func__);
zlog_warn("%s: Unable to convert sockunion to prefix for %s",
__func__, peer->host);
return;
}
@ -922,3 +921,48 @@ void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
BGP_UNNUM_DEFAULT_RA_INTERVAL);
}
}
void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
{
struct bgp *bgp;
struct bgp_node *rn;
struct bgp_nexthop_cache *bnc;
struct nexthop *nhop;
struct interface *ifp;
struct prefix p;
if (peer->ifp)
return;
bgp = peer->bgp;
if (!bgp->nexthop_cache_table[AFI_IP6])
return;
if (!sockunion2hostprefix(&peer->su, &p)) {
zlog_warn("%s: Unable to convert sockunion to prefix for %s",
__func__, peer->host);
return;
}
if (p.family != AF_INET6)
return;
rn = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
if (!rn)
return;
bnc = bgp_node_get_bgp_nexthop_info(rn);
if (!bnc)
return;
if (peer != bnc->nht_info)
return;
for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
zclient_send_interface_radv_req(zclient, nhop->vrf_id, ifp, 0,
0);
}
}

View file

@ -87,6 +87,7 @@ extern void bgp_nht_register_nexthops(struct bgp *bgp);
* this code can walk the registered nexthops and
* register the important ones with zebra for RA.
*/
extern void bgp_nht_register_enhe_capability_interfaces(struct peer *peer);
extern void bgp_nht_reg_enhe_cap_intfs(struct peer *peer);
extern void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer);
#endif /* _BGP_NHT_H */

View file

@ -3818,6 +3818,10 @@ DEFUN (no_neighbor,
}
other = peer->doppelganger;
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
bgp_zebra_terminate_radv(peer->bgp, peer);
peer_notify_unconfig(peer);
peer_delete(peer);
if (other && other->status != Deleted) {
@ -4238,6 +4242,9 @@ DEFUN (no_neighbor_set_peer_group,
return CMD_WARNING_CONFIG_FAILED;
}
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
bgp_zebra_terminate_radv(peer->bgp, peer);
peer_notify_unconfig(peer);
ret = peer_delete(peer);

View file

@ -1939,8 +1939,14 @@ void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer)
zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id,
peer->host);
zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 1,
ra_interval);
/*
* If unnumbered peer (peer->ifp) call thru zapi to start RAs.
* If we don't have an ifp pointer, call function to find the
* ifps for a numbered enhe peer to turn RAs on.
*/
peer->ifp ? zclient_send_interface_radv_req(zclient, bgp->vrf_id,
peer->ifp, 1, ra_interval)
: bgp_nht_reg_enhe_cap_intfs(peer);
}
void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer)
@ -1953,7 +1959,14 @@ void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer)
zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id,
peer->host);
zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0);
/*
* If unnumbered peer (peer->ifp) call thru zapi to stop RAs.
* If we don't have an ifp pointer, call function to find the
* ifps for a numbered enhe peer to turn RAs off.
*/
peer->ifp ? zclient_send_interface_radv_req(zclient, bgp->vrf_id,
peer->ifp, 0, 0)
: bgp_nht_dereg_enhe_cap_intfs(peer);
}
int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni)

View file

@ -2490,6 +2490,11 @@ static void peer_group2peer_config_copy(struct peer_group *group,
: BGP_DEFAULT_EBGP_ROUTEADV;
}
/* capability extended-nexthop apply */
if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE))
if (CHECK_FLAG(conf->flags, PEER_FLAG_CAPABILITY_ENHE))
SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
/* password apply */
if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
PEER_STR_ATTR_INHERIT(peer, group, password,
@ -2577,6 +2582,10 @@ int peer_group_delete(struct peer_group *group)
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
other = peer->doppelganger;
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
bgp_zebra_terminate_radv(bgp, peer);
peer_delete(peer);
if (other && other->status != Deleted) {
other->group = NULL;
@ -2621,6 +2630,9 @@ int peer_group_remote_as_delete(struct peer_group *group)
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
other = peer->doppelganger;
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
bgp_zebra_terminate_radv(peer->bgp, peer);
peer_delete(peer);
if (other && other->status != Deleted) {
@ -4065,8 +4077,22 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
/* Update flag override state accordingly. */
COND_FLAG(peer->flags_override, flag, set != invert);
if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
bgp_nht_register_enhe_capability_interfaces(peer);
/*
* For the extended next-hop encoding flag we need to turn RAs
* on if flag is being set, but only turn RAs off if the flag
* is being unset on this peer and if this peer is a member of a
* peer-group, the peer-group also doesn't have the flag set.
*/
if (flag == PEER_FLAG_CAPABILITY_ENHE) {
if (set) {
bgp_zebra_initiate_radv(peer->bgp, peer);
} else if (peer_group_active(peer)) {
if (!CHECK_FLAG(peer->group->conf->flags, flag))
bgp_zebra_terminate_radv(peer->bgp,
peer);
} else
bgp_zebra_terminate_radv(peer->bgp, peer);
}
/* Execute flag action on peer. */
if (action.type == peer_change_reset)
@ -4099,8 +4125,9 @@ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
/* Update flag on peer-group member. */
COND_FLAG(member->flags, flag, set != member_invert);
if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
bgp_nht_register_enhe_capability_interfaces(member);
if (flag == PEER_FLAG_CAPABILITY_ENHE)
set ? bgp_zebra_initiate_radv(member->bgp, member)
: bgp_zebra_terminate_radv(member->bgp, member);
/* Execute flag action on peer-group member. */
if (action.type == peer_change_reset)