Merge pull request #1938 from donaldsharp/vpn_peer_withdrawal

bgpd: Fix peer withdrawal and route leaking for vpn's and vrf's
This commit is contained in:
paulzlabn 2018-03-21 18:27:22 -07:00 committed by GitHub
commit 80a80e1af0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 14 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);