]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Fix evpn bestpath calculation when path is not established
authorDonald Sharp <sharpd@nvidia.com>
Thu, 5 Dec 2024 18:12:00 +0000 (13:12 -0500)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Tue, 17 Dec 2024 16:34:59 +0000 (16:34 +0000)
If you have a bestpath list that looks something like this:

<local evpn mac route>
<learned from peer out swp60>
<learned from peer out swp57>

And a network event happens that causes the peer out swp60
to not be in an established state, yet we still have the
path_info for the destination for swp60, bestpath
will currently end up with this order:

<learned from peer out swp60>
<local evpn mac route>
<learned from peer out swp57>

This causes the local evpn mac route to be deleted in zebra( Wrong! ).

This is happening because swp60 is skipped in bestpath calculation and
not considered to be a path yet it stays at the front of the list.

Modify bestpath calculation such that when pulling the unsorted_list
together to pull path info's into that list when they are also
not in a established state.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
(cherry picked from commit 9f88cb56dc0fe7a4ce864f672c6ca420fcd420c2)

bgpd/bgp_route.c

index 7c18b17d97646b120291e7d6694ab1f5ed4318bd..12397e87e37cbac73f1ad9e37bec11e0fb592898 100644 (file)
@@ -2940,7 +2940,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
 
        old_select = NULL;
        pi = bgp_dest_get_bgp_path_info(dest);
-       while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) {
+       while (pi && (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED) ||
+                     (pi->peer != bgp->peer_self &&
+                      !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT) &&
+                      !peer_established(pi->peer->connection)))) {
                struct bgp_path_info *next = pi->next;
 
                if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
@@ -3034,6 +3037,30 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
                        continue;
                }
 
+               if (first->peer && first->peer != bgp->peer_self &&
+                   !CHECK_FLAG(first->peer->sflags, PEER_STATUS_NSF_WAIT) &&
+                   !peer_established(first->peer->connection)) {
+                       if (debug)
+                               zlog_debug("%s: %pBD(%s) pi %p from %s is not in established state",
+                                          __func__, dest, bgp->name_pretty, first,
+                                          first->peer->host);
+
+                       /*
+                        * Peer is not in established state we cannot sort this
+                        * item yet.  Let's wait, so hold this one to the side
+                        */
+                       if (unsorted_holddown) {
+                               first->next = unsorted_holddown;
+                               unsorted_holddown->prev = first;
+                               unsorted_holddown = first;
+                       } else
+                               unsorted_holddown = first;
+
+                       UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+
+                       continue;
+               }
+
                bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK);
 
                worse = NULL;