summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaulzlabn <paulz@labn.net>2018-03-21 18:27:22 -0700
committerGitHub <noreply@github.com>2018-03-21 18:27:22 -0700
commit80a80e1af0781052846d2bc66c4d29f15f618689 (patch)
treedad9cf6ce8599093d7a489ccb47210ba101aecca
parentc6323200a7ea111fadfc9035841f8165f319c3ca (diff)
parent568e10ca581e0519eb613f0fcd08dff794e27cd3 (diff)
Merge pull request #1938 from donaldsharp/vpn_peer_withdrawal
bgpd: Fix peer withdrawal and route leaking for vpn's and vrf's
-rw-r--r--bgpd/bgp_route.c51
-rw-r--r--bgpd/bgp_zebra.c11
-rw-r--r--bgpd/bgp_zebra.h3
3 files changed, 51 insertions, 14 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 35732d1bf5..41dff0a7e2 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2095,6 +2095,25 @@ struct bgp_process_queue {
unsigned int queued;
};
+/*
+ * old_select = The old best path
+ * new_select = the new best path
+ *
+ * if (!old_select && new_select)
+ * We are sending new information on.
+ *
+ * if (old_select && new_select) {
+ * if (new_select != old_select)
+ * We have a new best path send a change
+ * else
+ * We've received a update with new attributes that needs
+ * to be passed on.
+ * }
+ *
+ * if (old_select && !new_select)
+ * We have no eligible route that we can announce or the rn
+ * is being removed.
+ */
static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
afi_t afi, safi_t safi)
{
@@ -2294,7 +2313,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, safi);
+ bgp_zebra_withdraw(p, old_select, bgp, safi);
}
}
@@ -3664,10 +3683,12 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
struct bgp_node *rn = cnq->rn;
struct peer *peer = wq->spec.data;
struct bgp_info *ri;
+ struct bgp *bgp;
afi_t afi = bgp_node_table(rn)->afi;
safi_t safi = bgp_node_table(rn)->safi;
assert(rn && peer);
+ bgp = peer->bgp;
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
@@ -3686,8 +3707,18 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
/* If this is an EVPN route, process for
* un-import. */
if (safi == SAFI_EVPN)
- bgp_evpn_unimport_route(peer->bgp, afi, safi,
+ bgp_evpn_unimport_route(bgp, afi, safi,
&rn->p, ri);
+ /* Handle withdraw for VRF route-leaking and L3VPN */
+ if (SAFI_UNICAST == safi
+ && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT))
+ vpn_leak_from_vrf_withdraw(bgp_get_default(),
+ bgp, ri);
+ if (SAFI_MPLS_VPN == safi &&
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ vpn_leak_to_vrf_withdraw(bgp, ri);
+
bgp_rib_remove(rn, ri, peer, afi, safi);
}
}
@@ -3953,7 +3984,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
}
}
-static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
+static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
+ safi_t safi)
{
struct bgp_node *rn;
struct bgp_info *ri;
@@ -3969,7 +4001,8 @@ static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
|| ri->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(&rn->p, ri, safi);
+ bgp_zebra_withdraw(&rn->p, ri,
+ bgp, safi);
bgp_info_reap(rn, ri);
}
}
@@ -3984,7 +4017,8 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
if (afi == AFI_L2VPN)
continue;
- bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
+ bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
+ SAFI_UNICAST);
/*
* VPN and ENCAP and EVPN tables are two-level (RD is top level)
*/
@@ -3994,7 +4028,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next(rn)) {
if (rn->info) {
- bgp_cleanup_table(
+ bgp_cleanup_table(bgp,
(struct bgp_table *)(rn->info),
safi);
bgp_table_finish((struct bgp_table **)&(
@@ -4007,7 +4041,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next(rn)) {
if (rn->info) {
- bgp_cleanup_table(
+ bgp_cleanup_table(bgp,
(struct bgp_table *)(rn->info),
safi);
bgp_table_finish((struct bgp_table **)&(
@@ -4021,7 +4055,8 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
rn = bgp_route_next(rn)) {
if (rn->info) {
- bgp_cleanup_table((struct bgp_table *)(rn->info),
+ bgp_cleanup_table(bgp,
+ (struct bgp_table *)(rn->info),
SAFI_EVPN);
bgp_table_finish((struct bgp_table **)&(rn->info));
rn->info = NULL;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 486ea3937a..bc6ee73da8 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1303,7 +1303,8 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
safi);
}
-void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
+void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
+ struct bgp *bgp, safi_t safi)
{
struct zapi_route api;
struct peer *peer;
@@ -1329,12 +1330,12 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
*/
- if (!bgp_install_info_to_zebra(peer->bgp))
+ if (!bgp_install_info_to_zebra(bgp))
return;
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
- api.vrf_id = peer->bgp->vrf_id;
+ api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
@@ -1353,14 +1354,14 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
- || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+ || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
if (bgp_debug_zebra(p)) {
char buf[PREFIX_STRLEN];
prefix2str(&api.prefix, buf, sizeof(buf));
- zlog_debug("Tx route delete VRF %u %s", peer->bgp->vrf_id, buf);
+ zlog_debug("Tx route delete VRF %u %s", bgp->vrf_id, buf);
}
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index da5160bc16..c30f63039b 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -33,7 +33,8 @@ extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t);
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
-extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t);
+extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *,
+ struct bgp *, safi_t);
extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer);
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);