summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDon Slice <dslice@cumulusnetworks.com>2020-04-21 21:01:35 +0200
committerDon Slice <dslice@cumulusnetworks.com>2020-04-27 19:49:41 +0200
commitb3a3290e23039e326337b8e254de06a83f7330de (patch)
treea19e9af241258424dbbe0a6f967250af3f74540a /bgpd
parentMerge pull request #6298 from opensourcerouting/build-assorted-20200423 (diff)
downloadfrr-b3a3290e23039e326337b8e254de06a83f7330de.tar.xz
frr-b3a3290e23039e326337b8e254de06a83f7330de.zip
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>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_nht.c52
-rw-r--r--bgpd/bgp_nht.h3
-rw-r--r--bgpd/bgp_vty.c7
-rw-r--r--bgpd/bgp_zebra.c19
-rw-r--r--bgpd/bgpd.c35
5 files changed, 104 insertions, 12 deletions
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 1af9be46f..cc208a819 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 e39d55567..4e015e4aa 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 b7a7d2c38..2989e183a 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 4f54bc81f..cca3f4aaa 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 5d28b138d..cf6335d37 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)