From a783cc05f0870f686785edf0c4ca12fb6036716f Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Wed, 14 Sep 2022 11:13:41 +0800 Subject: [PATCH] bgpd: Handle route-refresh request received before EoR 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 to a neighbor before it sends the EoR for the 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 --- bgpd/bgp_packet.c | 31 +++++++++++++++++++++++++++++++ bgpd/bgpd.h | 1 + 2 files changed, 32 insertions(+) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 90695219a7..cc18808373 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -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; } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 28883c9e7c..f6162f33e4 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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;