]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Use source route's path attributes for type-5 routes
authorvivek <vivek@cumulusnetworks.com>
Mon, 4 Dec 2017 17:52:54 +0000 (09:52 -0800)
committermitesh <mitesh@cumulusnetworks.com>
Wed, 24 Jan 2018 00:24:39 +0000 (16:24 -0800)
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 <vivek@cumulusnetworks.com>
Ticket: CM-19051
Reviewed By: CCR-7009
Testing Done: Verify failed scenario

bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_route.c
bgpd/bgp_zebra.c

index 1a9b26764c3e147f8219933b826a8c39a6de7bbe..70500f39d400400c741145ba181d6c1d2bf3969d 100644 (file)
@@ -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;
+                       }
+               }
        }
 }
 
index cff9d65468f2a7ce22d58e3aeefff02d7c042c63..a8dcbc112b1cc18b4313bec527e4f4d0ecd95403 100644 (file)
@@ -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,
index 7ee84c3531876a39f3fea10ae637c39fe2f20c09..5ed1b424078cae872b58eadacd4edb228556d49a 100644 (file)
@@ -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);
        }
index 970b3eefbfe5cb8f624b3e980ebfcb603e327c40..8bd594995cbd52342d8651f290dff693efea229c 100644 (file)
@@ -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);