mirror of
https://github.com/FRRouting/frr.git
synced 2025-05-01 05:57:15 +02:00
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:
commit
80a80e1af0
|
@ -2095,6 +2095,25 @@ struct bgp_process_queue {
|
||||||
unsigned int queued;
|
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,
|
static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
afi_t afi, safi_t safi)
|
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_AGGREGATE
|
||||||
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
|
|| 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 bgp_node *rn = cnq->rn;
|
||||||
struct peer *peer = wq->spec.data;
|
struct peer *peer = wq->spec.data;
|
||||||
struct bgp_info *ri;
|
struct bgp_info *ri;
|
||||||
|
struct bgp *bgp;
|
||||||
afi_t afi = bgp_node_table(rn)->afi;
|
afi_t afi = bgp_node_table(rn)->afi;
|
||||||
safi_t safi = bgp_node_table(rn)->safi;
|
safi_t safi = bgp_node_table(rn)->safi;
|
||||||
|
|
||||||
assert(rn && peer);
|
assert(rn && peer);
|
||||||
|
bgp = peer->bgp;
|
||||||
|
|
||||||
/* It is possible that we have multiple paths for a prefix from a peer
|
/* It is possible that we have multiple paths for a prefix from a peer
|
||||||
* if that peer is using AddPath.
|
* 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
|
/* If this is an EVPN route, process for
|
||||||
* un-import. */
|
* un-import. */
|
||||||
if (safi == SAFI_EVPN)
|
if (safi == SAFI_EVPN)
|
||||||
bgp_evpn_unimport_route(peer->bgp, afi, safi,
|
bgp_evpn_unimport_route(bgp, afi, safi,
|
||||||
&rn->p, ri);
|
&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);
|
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_node *rn;
|
||||||
struct bgp_info *ri;
|
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)) {
|
|| ri->sub_type == BGP_ROUTE_IMPORTED)) {
|
||||||
|
|
||||||
if (bgp_fibupd_safi(safi))
|
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);
|
bgp_info_reap(rn, ri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3984,7 +4017,8 @@ void bgp_cleanup_routes(struct bgp *bgp)
|
||||||
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
|
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
|
||||||
if (afi == AFI_L2VPN)
|
if (afi == AFI_L2VPN)
|
||||||
continue;
|
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)
|
* 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;
|
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn)) {
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info) {
|
if (rn->info) {
|
||||||
bgp_cleanup_table(
|
bgp_cleanup_table(bgp,
|
||||||
(struct bgp_table *)(rn->info),
|
(struct bgp_table *)(rn->info),
|
||||||
safi);
|
safi);
|
||||||
bgp_table_finish((struct bgp_table **)&(
|
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;
|
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn)) {
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info) {
|
if (rn->info) {
|
||||||
bgp_cleanup_table(
|
bgp_cleanup_table(bgp,
|
||||||
(struct bgp_table *)(rn->info),
|
(struct bgp_table *)(rn->info),
|
||||||
safi);
|
safi);
|
||||||
bgp_table_finish((struct bgp_table **)&(
|
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;
|
for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
|
||||||
rn = bgp_route_next(rn)) {
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info) {
|
if (rn->info) {
|
||||||
bgp_cleanup_table((struct bgp_table *)(rn->info),
|
bgp_cleanup_table(bgp,
|
||||||
|
(struct bgp_table *)(rn->info),
|
||||||
SAFI_EVPN);
|
SAFI_EVPN);
|
||||||
bgp_table_finish((struct bgp_table **)&(rn->info));
|
bgp_table_finish((struct bgp_table **)&(rn->info));
|
||||||
rn->info = NULL;
|
rn->info = NULL;
|
||||||
|
|
|
@ -1303,7 +1303,8 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||||
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 zapi_route api;
|
||||||
struct peer *peer;
|
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
|
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
||||||
* know of this instance.
|
* know of this instance.
|
||||||
*/
|
*/
|
||||||
if (!bgp_install_info_to_zebra(peer->bgp))
|
if (!bgp_install_info_to_zebra(bgp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(&api, 0, sizeof(api));
|
memset(&api, 0, sizeof(api));
|
||||||
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
|
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.type = ZEBRA_ROUTE_BGP;
|
||||||
api.safi = safi;
|
api.safi = safi;
|
||||||
api.prefix = *p;
|
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)
|
if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
|
||||||
|| CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
|
|| 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);
|
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
|
||||||
|
|
||||||
if (bgp_debug_zebra(p)) {
|
if (bgp_debug_zebra(p)) {
|
||||||
char buf[PREFIX_STRLEN];
|
char buf[PREFIX_STRLEN];
|
||||||
|
|
||||||
prefix2str(&api.prefix, buf, sizeof(buf));
|
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);
|
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||||
|
|
|
@ -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 *,
|
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
||||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
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_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_initiate_radv(struct bgp *bgp, struct peer *peer);
|
||||||
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
|
extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
|
||||||
|
|
Loading…
Reference in a new issue