Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FRR]Fixing BGP session not being stable after flapping #119

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
From 655c84f5ca5534323ae8accb8d313615440ab034 Mon Sep 17 00:00:00 2001
From: Mark Stapp <mjs@cisco.com>
Date: Thu, 26 Sep 2024 11:09:35 -0400
Subject: [PATCH 1/4] bgpd: Replace per-peer connection error with per-bgp

Replace the per-peer connection error with a per-bgp event and
a list. The io pthread enqueues peers per-bgp-instance, and the
error-handing code can process multiple peers if there have been
multiple failures.

Signed-off-by: Mark Stapp <mjs@cisco.com>

diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index b07e69ac3..4d5e1d9c5 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -100,7 +100,6 @@ void bgp_reads_off(struct peer_connection *connection)

event_cancel_async(fpt->master, &connection->t_read, NULL);
EVENT_OFF(connection->t_process_packet);
- EVENT_OFF(connection->t_process_packet_error);

UNSET_FLAG(connection->thread_flags, PEER_THREAD_READS_ON);
}
@@ -252,8 +251,7 @@ static void bgp_process_reads(struct event *thread)
/* Handle the error in the main pthread, include the
* specific state change from 'bgp_read'.
*/
- event_add_event(bm->master, bgp_packet_process_error, connection,
- code, &connection->t_process_packet_error);
+ bgp_enqueue_conn_err_peer(peer->bgp, connection->peer, code);
goto done;
}

diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 2e682c773..26c00cfe1 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -4003,35 +4003,60 @@ void bgp_send_delayed_eor(struct bgp *bgp)
}

/*
- * Task callback to handle socket error encountered in the io pthread. We avoid
- * having the io pthread try to enqueue fsm events or mess with the peer
- * struct.
+ * Task callback in the main pthread to handle socket error
+ * encountered in the io pthread. We avoid having the io pthread try
+ * to enqueue fsm events or mess with the peer struct.
*/
+
+/* Max number of peers to process without rescheduling */
+#define BGP_CONN_ERROR_DEQUEUE_MAX 10
+
void bgp_packet_process_error(struct event *thread)
{
struct peer_connection *connection;
struct peer *peer;
- int code;
+ struct bgp *bgp;
+ int counter = 0;
+ bool more_p = false;

- connection = EVENT_ARG(thread);
- peer = connection->peer;
- code = EVENT_VAL(thread);
+ bgp = EVENT_ARG(thread);

- if (bgp_debug_neighbor_events(peer))
- zlog_debug("%s [Event] BGP error %d on fd %d", peer->host, code,
- connection->fd);
-
- /* Closed connection or error on the socket */
- if (peer_established(connection)) {
- if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
- || CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART_HELPER))
- && CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
- peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
- } else
- peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+ /* Dequeue peers from the error list */
+ while ((peer = bgp_dequeue_conn_err_peer(bgp, &more_p)) != NULL) {
+ connection = peer->connection;
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [Event] BGP error %d on fd %d",
+ peer->host, peer->connection_errcode,
+ connection->fd);
+
+ /* Closed connection or error on the socket */
+ if (peer_established(connection)) {
+ if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
+ || CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER))
+ && CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+ peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
+ SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+ } else
+ peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+ }
+
+ /* No need for keepalives, if enabled */
+ bgp_keepalives_off(connection);
+
+ bgp_event_update(connection, peer->connection_errcode);
+
+ counter++;
+ if (counter >= BGP_CONN_ERROR_DEQUEUE_MAX)
+ break;
}

- bgp_event_update(connection, code);
+ /* Reschedule event if necessary */
+ if (more_p)
+ bgp_conn_err_reschedule(bgp);
+
+ if (bgp_debug_neighbor_events(NULL))
+ zlog_debug("%s: dequeued and processed %d peers", __func__,
+ counter);
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 591696de7..7159fe4df 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -86,6 +86,9 @@ DEFINE_QOBJ_TYPE(bgp);
DEFINE_QOBJ_TYPE(peer);
DEFINE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));

+/* Peers with connection error/failure, per bgp instance */
+DECLARE_LIST(bgp_peer_conn_errlist, struct peer, conn_err_link);
+
/* BGP process wide configuration. */
static struct bgp_master bgp_master;

@@ -2684,6 +2687,9 @@ int peer_delete(struct peer *peer)

assert(peer->connection->status != Deleted);

+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s: peer %pBP", __func__, peer);
+
bgp = peer->bgp;
accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);

@@ -2701,6 +2707,13 @@ int peer_delete(struct peer *peer)
PEER_THREAD_READS_ON));
assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON));

+ /* Ensure the peer is removed from the connection error list */
+ frr_with_mutex (&bgp->peer_errs_mtx) {
+ if (bgp_peer_conn_errlist_anywhere(peer))
+ bgp_peer_conn_errlist_del(&bgp->peer_conn_errlist,
+ peer);
+ }
+
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
peer_nsf_stop(peer);

@@ -3567,6 +3580,10 @@ static struct bgp *bgp_create(as_t *as, const char *name,
memset(&bgp->ebgprequirespolicywarning, 0,
sizeof(bgp->ebgprequirespolicywarning));

+ /* Init peer connection error info */
+ pthread_mutex_init(&bgp->peer_errs_mtx, NULL);
+ bgp_peer_conn_errlist_init(&bgp->peer_conn_errlist);
+
return bgp;
}

@@ -4000,6 +4017,18 @@ int bgp_delete(struct bgp *bgp)
if (i != ZEBRA_ROUTE_BGP)
bgp_redistribute_unset(bgp, afi, i, 0);

+ /* Clear list of peers with connection errors - each
+ * peer will need to check again, in case the io pthread is racing
+ * with us, but this batch cleanup should make the per-peer check
+ * cheaper.
+ */
+ frr_with_mutex (&bgp->peer_errs_mtx) {
+ do {
+ peer = bgp_peer_conn_errlist_pop(
+ &bgp->peer_conn_errlist);
+ } while (peer != NULL);
+ }
+
/* Free peers and peer-groups. */
for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
peer_group_delete(group);
@@ -4016,6 +4045,9 @@ int bgp_delete(struct bgp *bgp)

update_bgp_group_free(bgp);

+ /* Cancel peer connection errors event */
+ EVENT_OFF(bgp->t_conn_errors);
+
/* TODO - Other memory may need to be freed - e.g., NHT */

#ifdef ENABLE_BGP_VNC
@@ -4168,6 +4200,9 @@ void bgp_free(struct bgp *bgp)
bgp_srv6_cleanup(bgp);
bgp_confederation_id_unset(bgp);

+ bgp_peer_conn_errlist_init(&bgp->peer_conn_errlist);
+ pthread_mutex_destroy(&bgp->peer_errs_mtx);
+
for (int i = 0; i < bgp->confed_peers_cnt; i++)
XFREE(MTYPE_BGP_NAME, bgp->confed_peers[i].as_pretty);

@@ -8704,6 +8739,59 @@ void bgp_gr_apply_running_config(void)
}
}

+/*
+ * Enqueue a peer with a connection error to be handled in the main pthread
+ */
+int bgp_enqueue_conn_err_peer(struct bgp *bgp, struct peer *peer, int errcode)
+{
+ frr_with_mutex (&bgp->peer_errs_mtx) {
+ peer->connection_errcode = errcode;
+
+ /* Careful not to double-enqueue */
+ if (!bgp_peer_conn_errlist_anywhere(peer)) {
+ bgp_peer_conn_errlist_add_tail(&bgp->peer_conn_errlist,
+ peer);
+ }
+ }
+ /* Ensure an event is scheduled */
+ event_add_event(bm->master, bgp_packet_process_error, bgp, 0,
+ &bgp->t_conn_errors);
+ return 0;
+}
+
+/*
+ * Dequeue a peer that encountered a connection error; signal whether there
+ * are more queued peers.
+ */
+struct peer *bgp_dequeue_conn_err_peer(struct bgp *bgp, bool *more_p)
+{
+ struct peer *peer = NULL;
+ bool more = false;
+
+ frr_with_mutex (&bgp->peer_errs_mtx) {
+ peer = bgp_peer_conn_errlist_pop(&bgp->peer_conn_errlist);
+
+ if (bgp_peer_conn_errlist_const_first(
+ &bgp->peer_conn_errlist) != NULL)
+ more = true;
+ }
+
+ if (more_p)
+ *more_p = more;
+
+ return peer;
+}
+
+/*
+ * Reschedule the connection error event - probably after processing
+ * some of the peers on the list.
+ */
+void bgp_conn_err_reschedule(struct bgp *bgp)
+{
+ event_add_event(bm->master, bgp_packet_process_error, bgp, 0,
+ &bgp->t_conn_errors);
+}
+
printfrr_ext_autoreg_p("BP", printfrr_bp);
static ssize_t printfrr_bp(struct fbuf *buf, struct printfrr_eargs *ea,
const void *ptr)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0341ff68e..bc15c0662 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -353,6 +353,33 @@ struct as_confed {
struct bgp_mplsvpn_nh_label_bind_cache;
PREDECL_RBTREE_UNIQ(bgp_mplsvpn_nh_label_bind_cache);

+/* List of peers that have connection errors in the io pthread */
+PREDECL_LIST(bgp_peer_conn_errlist);
+
+/* List of info about peers that are being cleared from BGP RIBs in a batch */
+PREDECL_LIST(bgp_clearing_info);
+
+/* Hash of peers in clearing info object */
+PREDECL_HASH(bgp_clearing_hash);
+
+/* Info about a batch of peers that need to be cleared from the RIB.
+ * If many peers need to be cleared, we process them in batches, taking
+ * one walk through the RIB for each batch.
+ */
+struct bgp_clearing_info {
+ /* Hash of peers */
+ struct bgp_clearing_hash_head peers;
+
+ /* Event to schedule/reschedule processing */
+ struct thread *t_sched;
+
+ /* RIB dest for rescheduling */
+ struct bgp_dest *last_dest;
+
+ /* Linkage for list of batches per-bgp */
+ struct bgp_clearing_info_item link;
+};
+
/* BGP instance structure. */
struct bgp {
/* AS number of this BGP instance. */
@@ -827,6 +854,21 @@ struct bgp {
uint16_t tcp_keepalive_intvl;
uint16_t tcp_keepalive_probes;

+ /* List of peers that have connection errors in the IO pthread */
+ struct bgp_peer_conn_errlist_head peer_conn_errlist;
+
+ /* Mutex that guards the connection-errors list */
+ pthread_mutex_t peer_errs_mtx;
+
+ /* Event indicating that there have been connection errors; this
+ * is typically signalled in the IO pthread; it's handled in the
+ * main pthread.
+ */
+ struct event *t_conn_errors;
+
+ /* List of batches of peers being cleared from BGP RIBs */
+ struct bgp_clearing_info_head clearing_list;
+
struct timeval ebgprequirespolicywarning;
#define FIFTEENMINUTE2USEC (int64_t)15 * 60 * 1000000

@@ -1188,7 +1230,6 @@ struct peer_connection {

struct event *t_routeadv;
struct event *t_process_packet;
- struct event *t_process_packet_error;

struct event *t_stop_with_notify;

@@ -1856,6 +1897,15 @@ struct peer {
/* Add-Path Best selected paths number to advertise */
uint8_t addpath_best_selected[AFI_MAX][SAFI_MAX];

+ /* Linkage for list of peers with connection errors from IO pthread */
+ struct bgp_peer_conn_errlist_item conn_err_link;
+
+ /* Connection error code */
+ uint16_t connection_errcode;
+
+ /* Linkage for hash of clearing peers being cleared in a batch */
+ struct bgp_clearing_hash_item clear_hash_link;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(peer);
@@ -2490,6 +2540,10 @@ void bgp_gr_apply_running_config(void);
int bgp_global_gr_init(struct bgp *bgp);
int bgp_peer_gr_init(struct peer *peer);

+/* APIs for the per-bgp peer connection error list */
+int bgp_enqueue_conn_err_peer(struct bgp *bgp, struct peer *peer, int errcode);
+struct peer *bgp_dequeue_conn_err_peer(struct bgp *bgp, bool *more_p);
+void bgp_conn_err_reschedule(struct bgp *bgp);

#define BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(_bgp, _peer_list) \
do { \
--
2.43.2

26 changes: 26 additions & 0 deletions src/sonic-frr/patch/0085-bgpd-remove-apis-from-bgp_route.h.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
From 8ee8e2511328e8c27ad7c16bd0854cc4335df399 Mon Sep 17 00:00:00 2001
From: Mark Stapp <mjs@cisco.com>
Date: Tue, 1 Oct 2024 09:23:26 -0400
Subject: [PATCH 2/4] bgpd: remove apis from bgp_route.h

Remove a couple of apis that don't exist.

Signed-off-by: Mark Stapp <mjs@cisco.com>

diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 61492980a..39e282712 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -885,9 +885,6 @@ extern bool subgroup_announce_check(struct bgp_dest *dest,
const struct prefix *p, struct attr *attr,
struct attr *post_attr);

-extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer);
-extern void bgp_process_queues_drain_immediate(void);
-
/* for encap/vpn */
extern struct bgp_dest *bgp_safi_node_lookup(struct bgp_table *table,
safi_t safi,
--
2.43.2

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
From e9eee90c3f68dc83a92f519841732c951948875b Mon Sep 17 00:00:00 2001
From: Mark Stapp <mjs@cisco.com>
Date: Thu, 7 Nov 2024 10:55:19 -0500
Subject: [PATCH 4/4] zebra: move peer conn error list to connection struct

Move the peer connection error list to the peer_connection
struct; that seems to line up better with the way that struct
works.

Signed-off-by: Mark Stapp <mjs@cisco.com>

diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index 4d5e1d9c5..31aba90d2 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -251,7 +251,7 @@ static void bgp_process_reads(struct event *thread)
/* Handle the error in the main pthread, include the
* specific state change from 'bgp_read'.
*/
- bgp_enqueue_conn_err_peer(peer->bgp, connection->peer, code);
+ bgp_enqueue_conn_err(peer->bgp, connection, code);
goto done;
}

diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index e3f103724..7d5e2b5c6 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -87,7 +87,7 @@ DEFINE_QOBJ_TYPE(peer);
DEFINE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));

/* Peers with connection error/failure, per bgp instance */
-DECLARE_DLIST(bgp_peer_conn_errlist, struct peer, conn_err_link);
+DECLARE_DLIST(bgp_peer_conn_errlist, struct peer_connection, conn_err_link);

/* List of info about peers that are being cleared from BGP RIBs in a batch */
DECLARE_DLIST(bgp_clearing_info, struct bgp_clearing_info, link);
@@ -2722,9 +2722,9 @@ int peer_delete(struct peer *peer)

/* Ensure the peer is removed from the connection error list */
frr_with_mutex (&bgp->peer_errs_mtx) {
- if (bgp_peer_conn_errlist_anywhere(peer))
+ if (bgp_peer_conn_errlist_anywhere(peer->connection))
bgp_peer_conn_errlist_del(&bgp->peer_conn_errlist,
- peer);
+ peer->connection);
}

if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
@@ -3924,6 +3924,8 @@ int bgp_delete(struct bgp *bgp)
struct bgp_table *dest_table = NULL;
struct graceful_restart_info *gr_info;
uint32_t cnt_before, cnt_after;
+ struct bgp_clearing_info *cinfo;
+ struct peer_connection *connection;

assert(bgp);

@@ -4044,9 +4046,9 @@ int bgp_delete(struct bgp *bgp)
*/
frr_with_mutex (&bgp->peer_errs_mtx) {
do {
- peer = bgp_peer_conn_errlist_pop(
+ connection = bgp_peer_conn_errlist_pop(
&bgp->peer_conn_errlist);
- } while (peer != NULL);
+ } while (connection != NULL);
}

/* Free peers and peer-groups. */
@@ -8998,7 +9000,7 @@ static void bgp_process_conn_error(struct event *event)
bgp = EVENT_ARG(event);

frr_with_mutex (&bgp->peer_errs_mtx) {
- peer = bgp_peer_conn_errlist_pop(&bgp->peer_conn_errlist);
+ connection = bgp_peer_conn_errlist_pop(&bgp->peer_conn_errlist);

list_count =
bgp_peer_conn_errlist_count(&bgp->peer_conn_errlist);
@@ -9011,12 +9013,12 @@ static void bgp_process_conn_error(struct event *event)
bgp_clearing_batch_begin(bgp);

/* Dequeue peers from the error list */
- while (peer != NULL) {
- connection = peer->connection;
+ while (connection != NULL) {
+ peer = connection->peer;

if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [Event] BGP error %d on fd %d",
- peer->host, peer->connection_errcode,
+ peer->host, connection->connection_errcode,
connection->fd);

/* Closed connection or error on the socket */
@@ -9035,13 +9037,13 @@ static void bgp_process_conn_error(struct event *event)
bgp_keepalives_off(peer->connection);

/* Drive into state-machine changes */
- bgp_event_update(connection, peer->connection_errcode);
+ bgp_event_update(connection, connection->connection_errcode);

counter++;
if (counter >= BGP_CONN_ERROR_DEQUEUE_MAX)
break;

- peer = bgp_dequeue_conn_err_peer(bgp, &more_p);
+ connection = bgp_dequeue_conn_err(bgp, &more_p);
}

/* Reschedule event if necessary */
@@ -9058,18 +9060,19 @@ static void bgp_process_conn_error(struct event *event)
}

/*
- * Enqueue a peer with a connection error to be handled in the main pthread;
+ * Enqueue a connection with an error to be handled in the main pthread;
* this is called from the io pthread.
*/
-int bgp_enqueue_conn_err_peer(struct bgp *bgp, struct peer *peer, int errcode)
+int bgp_enqueue_conn_err(struct bgp *bgp, struct peer_connection *connection,
+ int errcode)
{
frr_with_mutex (&bgp->peer_errs_mtx) {
- peer->connection_errcode = errcode;
+ connection->connection_errcode = errcode;

/* Careful not to double-enqueue */
- if (!bgp_peer_conn_errlist_anywhere(peer)) {
+ if (!bgp_peer_conn_errlist_anywhere(connection)) {
bgp_peer_conn_errlist_add_tail(&bgp->peer_conn_errlist,
- peer);
+ connection);
}
}
/* Ensure an event is scheduled */
@@ -9079,16 +9082,16 @@ int bgp_enqueue_conn_err_peer(struct bgp *bgp, struct peer *peer, int errcode)
}

/*
- * Dequeue a peer that encountered a connection error; signal whether there
+ * Dequeue a connection that encountered a connection error; signal whether there
* are more queued peers.
*/
-struct peer *bgp_dequeue_conn_err_peer(struct bgp *bgp, bool *more_p)
+struct peer_connection *bgp_dequeue_conn_err(struct bgp *bgp, bool *more_p)
{
- struct peer *peer = NULL;
+ struct peer_connection *connection = NULL;
bool more = false;

frr_with_mutex (&bgp->peer_errs_mtx) {
- peer = bgp_peer_conn_errlist_pop(&bgp->peer_conn_errlist);
+ connection = bgp_peer_conn_errlist_pop(&bgp->peer_conn_errlist);

if (bgp_peer_conn_errlist_const_first(
&bgp->peer_conn_errlist) != NULL)
@@ -9098,7 +9101,7 @@ struct peer *bgp_dequeue_conn_err_peer(struct bgp *bgp, bool *more_p)
if (more_p)
*more_p = more;

- return peer;
+ return connection;
}

/*
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index ff3f1b9f1..b53ece40d 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1254,6 +1254,11 @@ struct peer_connection {
struct event *t_process_packet;

struct event *t_stop_with_notify;
+ /* Linkage for list connections with errors, from IO pthread */
+ struct bgp_peer_conn_errlist_item conn_err_link;
+
+ /* Connection error code */
+ uint16_t connection_errcode;

union sockunion su;
#define BGP_CONNECTION_SU_UNSPEC(connection) \
@@ -1921,12 +1926,6 @@ struct peer {
/* Add-Path Best selected paths number to advertise */
uint8_t addpath_best_selected[AFI_MAX][SAFI_MAX];

- /* Linkage for list of peers with connection errors from IO pthread */
- struct bgp_peer_conn_errlist_item conn_err_link;
-
- /* Connection error code */
- uint16_t connection_errcode;
-
/* Linkage for hash of clearing peers being cleared in a batch */
struct bgp_clearing_hash_item clear_hash_link;

@@ -2565,8 +2564,9 @@ int bgp_global_gr_init(struct bgp *bgp);
int bgp_peer_gr_init(struct peer *peer);

/* APIs for the per-bgp peer connection error list */
-int bgp_enqueue_conn_err_peer(struct bgp *bgp, struct peer *peer, int errcode);
-struct peer *bgp_dequeue_conn_err_peer(struct bgp *bgp, bool *more_p);
+int bgp_enqueue_conn_err(struct bgp *bgp, struct peer_connection *connection,
+ int errcode);
+struct peer_connection *bgp_dequeue_conn_err(struct bgp *bgp, bool *more_p);
void bgp_conn_err_reschedule(struct bgp *bgp);

#define BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(_bgp, _peer_list) \
--
2.43.2

4 changes: 4 additions & 0 deletions src/sonic-frr/patch/series
Original file line number Diff line number Diff line change
@@ -64,3 +64,7 @@
0081-bgpd-Optimize-evaluate-paths-for-a-peer-going-down.patch
0082-Revert-bgpd-upon-if-event-evaluate-bnc-with-matching.patch
0083-staticd-add-cli-to-support-steering-of-ipv4-traffic-over-srv6-sid-list.patch
0084-bgpd-Replace-per-peer-connection-error-with-per-bgp.patch
0085-bgpd-remove-apis-from-bgp_route.h.patch
0086-bgpd-batch-peer-connection-error-clearing.patch
0087-zebra-move-peer-conn-error-list-to-connection-struct.patch