]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Handle route-refresh request received before EoR
authorXiao Liang <shaw.leon@gmail.com>
Wed, 14 Sep 2022 03:13:41 +0000 (11:13 +0800)
committerXiao Liang <shaw.leon@gmail.com>
Fri, 16 Sep 2022 10:26:21 +0000 (18:26 +0800)
See the BGP message sequence:

    R1                  R2
    |      updates      |
    |------------------>|
    |                   |
    |  refresh request  |
    x<------------------|
    |                   |
    |   updates cont.   |
    |------------------>|
    |                   |
    |    end-of-rib     |
    |------------------>|
    |                   |

When R1 and R2 establish BGP session, R1 begins to send initial updates.
If R2 sends a route-refresh request before EoR, it's silently ignored
by R1, and routes received earlier have no chance to be processed again.

RFC7313 says, "for a BGP speaker that supports the BGP Graceful Restart,
it MUST NOT send a BoRR for an <AFI, SAFI> to a neighbor before it sends
the EoR for the <AFI, SAFI> to the neighbor." But it doesn't forbid
route-refresh request to be sent before receiving EoR.

To handle this scenario, postpone response to refresh request until EoR
is sent.

Signed-off-by: Xiao Liang <shaw.leon@gmail.com>
bgpd/bgp_packet.c
bgpd/bgpd.h

index 90695219a7ea37c518c325b914182400e64a1c54..cc188083733650345756b836166879bf5044506e 100644 (file)
@@ -360,6 +360,31 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
        return BGP_NLRI_PARSE_ERROR;
 }
 
+
+/*
+ * Check if route-refresh request from peer is pending (received before EoR),
+ * and process it now.
+ */
+static void bgp_process_pending_refresh(struct peer *peer, afi_t afi,
+                                       safi_t safi)
+{
+       if (CHECK_FLAG(peer->af_sflags[afi][safi],
+                      PEER_STATUS_REFRESH_PENDING)) {
+               UNSET_FLAG(peer->af_sflags[afi][safi],
+                          PEER_STATUS_REFRESH_PENDING);
+               bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
+                                      BGP_ROUTE_REFRESH_BORR);
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug(
+                               "%pBP sending route-refresh (BoRR) for %s/%s (for pending REQUEST)",
+                               peer, afi2str(afi), safi2str(safi));
+
+               SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_BORR_SEND);
+               UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EORR_SEND);
+               bgp_announce_route(peer, afi, safi, true);
+       }
+}
+
 /*
  * Checks a variety of conditions to determine whether the peer needs to be
  * rescheduled for packet generation again, and does so if necessary.
@@ -558,6 +583,9 @@ void bgp_generate_updgrp_packets(struct thread *thread)
                                                        BGP_UPDATE_EOR_PKT(
                                                                peer, afi, safi,
                                                                s);
+                                                       bgp_process_pending_refresh(
+                                                               peer, afi,
+                                                               safi);
                                                }
                                        }
                                }
@@ -2564,6 +2592,9 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
                                                "%pBP rcvd route-refresh (REQUEST) for %s/%s before EoR",
                                                peer, afi2str(afi),
                                                safi2str(safi));
+                               /* Can't send BoRR now, postpone after EoR */
+                               SET_FLAG(peer->af_sflags[afi][safi],
+                                        PEER_STATUS_REFRESH_PENDING);
                                return BGP_PACKET_NOOP;
                        }
 
index 28883c9e7c71b0083a317c7678138fb2d4cd9999..f6162f33e460e7e58a24a3bc1db4e7ba6f477329 100644 (file)
@@ -1456,6 +1456,7 @@ struct peer {
 #define PEER_STATUS_EORR_RECEIVED (1U << 10) /* EoRR received from peer */
 /* LLGR aware peer */
 #define PEER_STATUS_LLGR_WAIT (1U << 11)
+#define PEER_STATUS_REFRESH_PENDING (1U << 12) /* refresh request from peer */
 
        /* Configured timer values. */
        _Atomic uint32_t holdtime;