From: Maria Matejka Date: Thu, 8 May 2025 21:03:57 +0000 (+0200) Subject: BGP: Fix repeated route refresh request X-Git-Tag: v3.0.3~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=066ebdd5d9f446cf4c2f15411854b16e5a4eb8fd;p=thirdparty%2Fbird.git BGP: Fix repeated route refresh request The previous approach was crashing on rapid successions of route refreshs without even completing the previous ones. Now the newly requested refreshs just queue and don't start multiple refreshs over and over again. --- diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 706e9b0bd..33459add0 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -152,6 +152,7 @@ static void bgp_listen_sock_err(sock *sk UNUSED, int err); static void bgp_initiate_disable(struct bgp_proto *p, int err_val); static void bgp_graceful_restart_feed(struct bgp_channel *c); +static void bgp_restart_route_refresh(void *_bc); static inline int @@ -762,6 +763,11 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) c->feed_state = BFS_NONE; c->load_state = BFS_NONE; + c->enhanced_rr_restart = (event) { + .hook = bgp_restart_route_refresh, + .data = c, + }; + /* Channels where peer may do GR */ uint gr_ready = active && local->gr_aware && rem->gr_able; uint llgr_ready = active && local->llgr_aware && rem->llgr_able; @@ -1689,16 +1695,10 @@ bgp_reload_in(struct proto *P, uintptr_t _ UNUSED, int __ UNUSED) cli_msg(-8006, "%s: not reloading, not up", P->name); } -struct bgp_enhanced_refresh_request { - struct rt_feeding_request rfr; - struct bgp_channel *c; -}; - static void bgp_done_route_refresh(struct rt_feeding_request *rfr) { - SKIP_BACK_DECLARE(struct bgp_enhanced_refresh_request, berr, rfr, rfr); - struct bgp_channel *c = berr->c; + SKIP_BACK_DECLARE(struct bgp_channel, c, enhanced_rr_request, rfr); SKIP_BACK_DECLARE(struct bgp_proto, p, p, c->c.proto); /* Schedule EoRR packet */ @@ -1706,8 +1706,6 @@ bgp_done_route_refresh(struct rt_feeding_request *rfr) c->feed_state = BFS_REFRESHED; bgp_schedule_packet(p->conn, c, PKT_UPDATE); - - mb_free(berr); } const char * @@ -1721,19 +1719,42 @@ bgp_begin_route_refresh(struct bgp_proto *p, struct bgp_channel *c) return "from table by simple refeed"; } - struct bgp_enhanced_refresh_request *berr = mb_alloc(p->p.pool, sizeof *berr); - *berr = (struct bgp_enhanced_refresh_request) { - .c = c, - .rfr.done = bgp_done_route_refresh, - }; + switch (c->feed_state) + { + case BFS_NONE: + break; + + case BFS_REFRESHING: + case BFS_REFRESHED: + return c->enhanced_rr_again ? "already queued" : "again"; + default: + return "requested before End-Of-RIB sent"; + } + + c->enhanced_rr_request.done = bgp_done_route_refresh; c->feed_state = BFS_REFRESHING; bgp_schedule_packet(p->conn, c, PKT_BEGIN_REFRESH); - rt_export_refeed(&c->c.out_req, &berr->rfr); + rt_export_refeed(&c->c.out_req, &c->enhanced_rr_request); return "from table by enhanced route refresh"; } +static void +bgp_restart_route_refresh(void *_bc) +{ + struct bgp_channel *c = _bc; + SKIP_BACK_DECLARE(struct bgp_proto, p, p, c->c.proto); + + if ((c->feed_state != BFS_NONE) || (!c->enhanced_rr_again)) + return; + + c->enhanced_rr_again = 0; + + const char *info = bgp_begin_route_refresh(p, c); + BGP_TRACE(D_EVENTS, "Restarting route refresh on %s %s", c->c.name, info); +} + void bgp_reload_out(struct proto *P, uintptr_t _ UNUSED, int __ UNUSED) { diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index c3a49f5c6..73f2b8882 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -436,6 +436,10 @@ struct bgp_channel { struct rt_export_feeder stale_feed; /* Feeder request for stale route modification */ event stale_event; /* Feeder event for stale route modification */ + struct rt_feeding_request enhanced_rr_request; /* Refeed request for enhanced route refresh */ + event enhanced_rr_restart; /* Event to restart enhanced route request */ + u8 enhanced_rr_again; /* Another refeed requested while refeeding */ + u8 add_path_rx; /* Session expects receive of ADD-PATH extended NLRI */ u8 add_path_tx; /* Session expects transmit of ADD-PATH extended NLRI */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 9ee6d0adb..d41921a5b 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -3170,6 +3170,9 @@ bgp_fire_tx(struct bgp_conn *conn) if (c->feed_state == BFS_LOADED) { + if (c->enhanced_rr_again) + ev_send_loop(p->p.loop, &c->enhanced_rr_restart); + c->feed_state = BFS_NONE; end = bgp_create_end_mark(c, pkt); return bgp_send(conn, PKT_UPDATE, end - buf); @@ -3177,6 +3180,9 @@ bgp_fire_tx(struct bgp_conn *conn) else if (c->feed_state == BFS_REFRESHED) { + if (c->enhanced_rr_again) + ev_send_loop(p->p.loop, &c->enhanced_rr_restart); + c->feed_state = BFS_NONE; end = bgp_create_end_refresh(c, pkt); return bgp_send(conn, PKT_ROUTE_REFRESH, end - buf);