Merge pull request #6303 from dslicenc/stop-enhe-ras

bgpd: turn off RAs when numbered peers are deleted
This commit is contained in:
Russ White 2020-04-29 11:09:58 -04:00 committed by GitHub
commit 37d6afef2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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

@ -3822,6 +3822,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) {
@ -4242,6 +4246,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)