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 <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>
This commit is contained in:
Xiao Liang 2022-09-14 11:13:41 +08:00
parent a05ae6c440
commit a783cc05f0
2 changed files with 32 additions and 0 deletions

View 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;
}

View 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;