From: Don Slice Date: Tue, 21 Apr 2020 19:01:35 +0000 (+0000) Subject: bgpd: turn off RAs when numbered peers are deleted X-Git-Tag: base_7.4~23^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=b3a3290e23039e326337b8e254de06a83f7330de;p=mirror%2Ffrr.git 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 --- diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 1af9be46f1..cc208a8190 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -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); + } +} diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index e39d55567a..4e015e4aae 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -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 */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b7a7d2c382..2989e183ad 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 4f54bc81fb..cca3f4aaa3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5d28b138d6..cf6335d373 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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)