From: vivek Date: Mon, 4 Dec 2017 17:52:54 +0000 (-0800) Subject: bgpd: Use source route's path attributes for type-5 routes X-Git-Tag: frr-5.0-dev~244^2~12 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=2f69f6d36855cd7520b36d4bad1b63f146dd5cbe;p=mirror%2Ffrr.git bgpd: Use source route's path attributes for type-5 routes When an IPv4 or IPv6 unicast route is injected into EVPN as a type-5 route (upon user configuration), ensure that the source route (best path)'s path attributes are used to build the EVPN type-5 route. This will result in correct AS_PATH and ORIGIN attributes for the type-5 route so that it doesn't appear that all type-5 routes are locally sourced. This is necessary to ensure that external paths (IPv4 or IPv6 from EBGP peer) are preferred over internal EVPN paths, if both exist. Signed-off-by: Vivek Venkatraman Ticket: CM-19051 Reviewed By: CCR-7009 Testing Done: Verify failed scenario --- diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 1a9b26764c..70500f39d4 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1070,7 +1070,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, /* update evpn type-5 route entry */ static int update_evpn_type5_route(struct bgp *bgp_vrf, - struct prefix_evpn *evp) + struct prefix_evpn *evp, + struct attr* src_attr) { afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -1083,9 +1084,16 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, if (!bgp_def) return -1; - /* build path attribute for this route */ - memset(&attr, 0, sizeof(struct attr)); - bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + /* Build path attribute for this route - use the source attr, if + * present, else treat as locally originated. + */ + if (src_attr) + bgp_attr_dup(&attr, src_attr); + else { + memset(&attr, 0, sizeof(struct attr)); + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + } + /* Set nexthop to ourselves and fill in the Router MAC. */ attr.nexthop = bgp_vrf->originator_ip; attr.mp_nexthop_global_in = bgp_vrf->originator_ip; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; @@ -3222,8 +3230,14 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, } -/* advertise ip prefix as type-5 route*/ +/* + * Advertise IP prefix as type-5 route. The afi/safi and src_attr passed + * to this function correspond to those of the source IP prefix (best + * path in the case of the attr. In the case of a local prefix (when we + * are advertising local subnets), the src_attr will be NULL. + */ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, + struct attr *src_attr, afi_t afi, safi_t safi) { int ret = 0; @@ -3238,29 +3252,39 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, return; build_type5_prefix_from_ip_prefix(&evp, p); - ret = update_evpn_type5_route(bgp_vrf, &evp); - if (ret) { + ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr); + if (ret) zlog_err( - "%u failed to create type-5 route for prefix %s in vrf %s", + "%u: Failed to create type-5 route for prefix %s", bgp_vrf->vrf_id, - prefix2str(p, buf, sizeof(buf)), - vrf_id_to_name(bgp_vrf->vrf_id)); - } + prefix2str(p, buf, sizeof(buf))); } -/* advertise all type-5 routes for an address family */ +/* Inject all prefixes of a particular address-family (currently, IPv4 or + * IPv6 unicast) into EVPN as type-5 routes. This is invoked when the + * advertisement is enabled. + */ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi) { struct bgp_table *table = NULL; struct bgp_node *rn = NULL; + struct bgp_info *ri; table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - - if (!rn->info) - continue; - bgp_evpn_advertise_type5_route(bgp_vrf, &rn->p, afi, safi); + /* Need to identify the "selected" route entry to use its + * attribute. + * TODO: Support for AddPath for EVPN. + */ + for (ri = rn->info; ri; ri = ri->next) { + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + bgp_evpn_advertise_type5_route(bgp_vrf, &rn->p, + ri->attr, + afi, safi); + break; + } + } } } diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index cff9d65468..a8dcbc112b 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -57,6 +57,7 @@ static inline vni_t label2vni(mpls_label_t *label) extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, + struct attr *src_attr, afi_t afi, safi_t safi); extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p, diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7ee84c3531..5ed1b42407 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2226,7 +2226,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* advertise/withdraw type-5 routes */ if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { if (new_select) - bgp_evpn_advertise_type5_route(bgp, &rn->p, afi, safi); + bgp_evpn_advertise_type5_route(bgp, &rn->p, + new_select->attr, + afi, safi); else if (old_select) bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 970b3eefbf..8bd594995c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1872,10 +1872,12 @@ static void bgp_zebra_process_local_ip_prefix(int cmd, if (p.family == AF_INET) return bgp_evpn_advertise_type5_route(bgp_vrf, &p, + NULL, AFI_IP, SAFI_UNICAST); else return bgp_evpn_advertise_type5_route(bgp_vrf, &p, + NULL, AFI_IP6, SAFI_UNICAST);