From d4426b62d221f4e15810dbe578de05df8991c991 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 9 Jun 2021 16:50:20 -0400 Subject: [PATCH] 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 --- bgpd/bgp_mplsvpn.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 9db73a1bd1..4e5a4150d1 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -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);