bgpd: copy source vrf ASN to leaked route and block loops

When we leak routes and are using a different ASN in the
source vrf from the target vrf, it's possible we could
create loops because of an incomplete as-path (missing
the source vrf ASN). This fix adds the source vrf ASN and
stops the importing of a BGP prefix that has the target
ASN in the as-path in the source vrf.

Signed-off-by: Don Slice <dslice@nvidia.com>
This commit is contained in:
Don Slice 2021-06-09 16:50:20 -04:00 committed by Donatas Abraitis
parent 091abc6b28
commit d4426b62d2

View File

@ -34,6 +34,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_memory.h"
#include "bgpd/bgp_aspath.h"
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@ -2156,6 +2157,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct bgp *src_vrf;
struct interface *ifp = NULL;
char rd_buf[RD_ADDRSTRLEN];
struct aspath *new_aspath;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@ -2213,6 +2215,32 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
return;
}
bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
/* Check if leaked route has our asn. If so, don't import it. */
if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as)) {
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
if (bpi->extra && bpi->extra->vrfleak &&
(struct bgp_path_info *)bpi->extra->vrfleak->parent ==
path_vpn) {
break;
}
}
if (bpi) {
if (debug)
zlog_debug("%s: blocking import of %p, as-path match",
__func__, bpi);
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
bgp_process(to_bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
return;
}
if (debug)
zlog_debug("%s: updating RD %s, %pFX to %s", __func__, rd_buf,
p, to_bgp->name_pretty);
@ -2365,6 +2393,20 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
nexthop_self_flag = 0;
}
/*
* if the asn values are different, copy the asn of the source vrf
* into the entry before importing. This helps with as-path loop
* detection
*/
if (path_vpn->extra && path_vpn->extra->vrfleak &&
(to_bgp->as != path_vpn->extra->vrfleak->bgp_orig->as)) {
new_aspath = aspath_dup(static_attr.aspath);
new_aspath =
aspath_add_seq(new_aspath,
path_vpn->extra->vrfleak->bgp_orig->as);
static_attr.aspath = new_aspath;
}
new_attr = bgp_attr_intern(&static_attr);
bgp_attr_flush(&static_attr);