]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: evpn path selection changes for MAC-IP SYNC route handling
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Sat, 28 Mar 2020 16:51:14 +0000 (09:51 -0700)
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Wed, 5 Aug 2020 13:46:12 +0000 (06:46 -0700)
When a SYNC route i.e. a route with a local ES as destination is
rxed on a switch (say L11) from an ES peer (say L12) a local
MAC/neigh entry is created on L11 with the local access port
as dest port.

Creation of the local entry triggers a local path advertisement from
L11. This could be a "locally-active" path or a "locally-inactive"
path. Inactive paths are advertised with the proxy bit.

To ensure that the local entry is not deleted by a SYNC route it is
given absolute precedence over peer-paths.

If there are two non-local paths with the same dest ES and same MM
seq number the non-proxy path is preferred. This is done to ensure
that we don't lose track of the peer-activity.

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_table.h

index d931b128e30a2961da9b425f79702adc7fc897d8..37a98c10ce98e8985dd99a0ddd18465c1eba52df 100644 (file)
@@ -545,6 +545,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
        uint32_t new_mm_seq;
        uint32_t exist_mm_seq;
        int nh_cmp;
+       esi_t *exist_esi;
+       esi_t *new_esi;
+       bool same_esi;
+       bool old_proxy;
+       bool new_proxy;
 
        *paths_eq = 0;
 
@@ -621,6 +626,47 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
                        }
                }
 
+               new_esi = bgp_evpn_attr_get_esi(newattr);
+               exist_esi = bgp_evpn_attr_get_esi(existattr);
+               if (bgp_evpn_is_esi_valid(new_esi) &&
+                               !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
+                       same_esi = true;
+               } else {
+                       same_esi = false;
+               }
+
+               /* If both paths have the same non-zero ES and
+                * one path is local it wins.
+                * PS: Note the local path wins even if the remote
+                * has the higher MM seq. The local path's
+                * MM seq will be fixed up to match the highest
+                * rem seq, subsequently.
+                */
+               if (same_esi) {
+                       char esi_buf[ESI_STR_LEN];
+
+                       if (bgp_evpn_is_path_local(bgp, new)) {
+                               *reason = bgp_path_selection_evpn_local_path;
+                               if (debug)
+                                       zlog_debug(
+                                               "%s: %s wins over %s as ES %s is same and local",
+                                               pfx_buf, new_buf, exist_buf,
+                                               esi_to_str(new_esi, esi_buf,
+                                               sizeof(esi_buf)));
+                               return 1;
+                       }
+                       if (bgp_evpn_is_path_local(bgp, exist)) {
+                               *reason = bgp_path_selection_evpn_local_path;
+                               if (debug)
+                                       zlog_debug(
+                                               "%s: %s loses to %s as ES %s is same and local",
+                                               pfx_buf, new_buf, exist_buf,
+                                               esi_to_str(new_esi, esi_buf,
+                                               sizeof(esi_buf)));
+                               return 0;
+                       }
+               }
+
                new_mm_seq = mac_mobility_seqnum(newattr);
                exist_mm_seq = mac_mobility_seqnum(existattr);
 
@@ -644,6 +690,30 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
                        return 0;
                }
 
+               /* if the sequence numbers and ESI are the same and one path
+                * is non-proxy it wins (over proxy)
+                */
+               new_proxy = bgp_evpn_attr_is_proxy(newattr);
+               old_proxy = bgp_evpn_attr_is_proxy(existattr);
+               if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
+                               old_proxy != new_proxy) {
+                       if (!new_proxy) {
+                               *reason = bgp_path_selection_evpn_non_proxy;
+                               if (debug)
+                                       zlog_debug(
+                                               "%s: %s wins over %s, same seq/es and non-proxy",
+                                               pfx_buf, new_buf, exist_buf);
+                               return 1;
+                       }
+
+                       *reason = bgp_path_selection_evpn_non_proxy;
+                       if (debug)
+                               zlog_debug(
+                                       "%s: %s loses to %s, same seq/es and non-proxy",
+                                       pfx_buf, new_buf, exist_buf);
+                       return 0;
+               }
+
                /*
                 * if sequence numbers are the same path with the lowest IP
                 * wins
@@ -1176,6 +1246,17 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
        return 1;
 }
 
+
+int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
+                            struct bgp_path_info *exist, int *paths_eq)
+{
+       enum bgp_path_selection_reason reason;
+       char pfx_buf[PREFIX2STR_BUFFER];
+
+       return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
+                               AFI_L2VPN, SAFI_EVPN, &reason);
+}
+
 /* Compare two bgp route entity.  Return -1 if new is preferred, 1 if exist
  * is preferred, or 0 if they are the same (usually will only occur if
  * multipath is enabled
@@ -7938,7 +8019,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                vty_out(vty, "%s", bgp_origin_str[attr->origin]);
 
        if (json_paths) {
-               if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) {
+               if (bgp_evpn_is_esi_valid(&attr->esi)) {
                        json_object_string_add(json_path, "esi",
                                        esi_to_str(&attr->esi,
                                        esi_buf, sizeof(esi_buf)));
@@ -7989,7 +8070,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                vty_out(vty, "\n");
 
                if (safi == SAFI_EVPN) {
-                       if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) {
+                       if (bgp_evpn_is_esi_valid(&attr->esi)) {
                                vty_out(vty, "%*s", 20, " ");
                                vty_out(vty, "ESI:%s\n",
                                                esi_to_str(&attr->esi,
@@ -8615,6 +8696,10 @@ static const char *bgp_path_selection_reason2str(
                return "EVPN sequence number";
        case bgp_path_selection_evpn_lower_ip:
                return "EVPN lower IP";
+       case bgp_path_selection_evpn_local_path:
+               return "EVPN local ES path";
+       case bgp_path_selection_evpn_non_proxy:
+               return "EVPN non proxy";
        case bgp_path_selection_weight:
                return "Weight";
        case bgp_path_selection_local_pref:
index 691d5cdec2ec199a625a124b3e7050b3684b7b4a..3f734d26724bebcfaa0d27763ba10c5237090797 100644 (file)
@@ -682,4 +682,6 @@ extern int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi);
 extern bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
                                       uint8_t type, uint8_t stype,
                                       struct attr *attr, struct bgp_dest *dest);
+extern int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
+                            struct bgp_path_info *exist, int *paths_eq);
 #endif /* _QUAGGA_BGP_ROUTE_H */
index a9ec36d29bb75363b4899488620cb8299a9c5166..cf0086b52e91f5bf71ae5f5deba7fc0132d3834a 100644 (file)
@@ -51,6 +51,8 @@ enum bgp_path_selection_reason {
        bgp_path_selection_first,
        bgp_path_selection_evpn_sticky_mac,
        bgp_path_selection_evpn_seq,
+       bgp_path_selection_evpn_local_path,
+       bgp_path_selection_evpn_non_proxy,
        bgp_path_selection_evpn_lower_ip,
        bgp_path_selection_weight,
        bgp_path_selection_local_pref,