File 0024-bgpd-Validate-only-affected-RPKI-prefixes-instead-of.patch of Package frr.40395
From 3ff9ed09acc45d1b95dd1ceb96e19d52022a5063 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcel=20R=C3=B6thke?= <marcel.roethke@haw-hamburg.de>
Date: Tue, 24 Mar 2020 14:36:04 +0100
Subject: [PATCH 1/3] bgpd: preinitialize rtrlib tr structures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
References: bsc#1235237,https://github.com/FRRouting/frr/pull/6577/commits/a633498e0bc7d15edb8fd24b595ff8d32aa50a12
Upstream: yes
The tr_*_config structs were previously not pre initialized because
every field is initialized explicitly. But future rtrlib version will
introduce additional fields. Preinitialising the entire struct will
ensure forward compatibility.
Signed-off-by: Marcel Röthke <marcel.roethke@haw-hamburg.de>
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 1ba07e95e6..be1df08ad2 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -811,7 +811,7 @@ static int add_tcp_cache(const char *host, const char *port,
{
struct rtr_socket *rtr_socket;
struct tr_tcp_config *tcp_config =
- XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
+ XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
struct tr_socket *tr_socket =
XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
struct cache *cache =
@@ -845,7 +845,7 @@ static int add_ssh_cache(const char *host, const unsigned int port,
const uint8_t preference)
{
struct tr_ssh_config *ssh_config =
- XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
+ XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
struct cache *cache =
XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
struct tr_socket *tr_socket =
--
2.43.0
From 2fc4ea56a58f950e0b6cb41da2f64bcc190df37c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcel=20R=C3=B6thke?= <marcel.roethke@haw-hamburg.de>
Date: Thu, 11 Jun 2020 16:11:09 +0200
Subject: [PATCH 2/3] bgpd: fix rpki revalidation for invalid announcements
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
References: bsc#1235237,https://github.com/FRRouting/frr/pull/6577/commits/bac31cb8856bbcc505717c962d0646199247cc4c
Upstream: yes
Announcements that are marked as invalid were previously not revalidated.
This was fixed by replacing the range lookup with a subtree lookup.
Signed-off-by: Marcel Röthke <marcel.roethke@haw-hamburg.de>
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index be1df08ad2..3228b38990 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -402,25 +402,23 @@ static int bgpd_sync_callback(struct thread *thread)
if (!peer->bgp->rib[afi][safi])
continue;
- struct list *matches = list_new();
-
- matches->del =
- (void (*)(void *))bgp_unlock_node;
-
- bgp_table_range_lookup(
- peer->bgp->rib[afi][safi], prefix,
- rec.max_len, matches);
-
-
- struct bgp_node *bgp_node;
- struct listnode *bgp_listnode;
-
- for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
- bgp_node))
- revalidate_bgp_node(bgp_node, afi,
- safi);
-
- list_delete(&matches);
+ struct bgp_node *match;
+ struct bgp_node *node;
+
+ match = bgp_table_subtree_lookup(
+ peer->bgp->rib[afi][safi], prefix);
+ node = match;
+
+ while (node) {
+ if (bgp_node_has_bgp_path_info_data(
+ node)) {
+ revalidate_bgp_node(node, afi,
+ safi);
+ }
+
+ node = bgp_route_next_until(node,
+ match);
+ }
}
}
}
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index dcf9852a67..8acd42ffc0 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -164,90 +164,42 @@ void bgp_delete_listnode(struct bgp_node *node)
}
}
-static struct bgp_node *
-bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit,
- const uint8_t maxlen)
+struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
+ const struct prefix *p)
{
- const struct prefix *p = bgp_node_get_prefix(node);
+ struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
+ struct bgp_node *matched = NULL;
- if (node->l_left) {
- const struct prefix *left_p =
- bgp_node_get_prefix(bgp_node_from_rnode(node->l_left));
+ if (node == NULL)
+ return NULL;
- if (p->prefixlen < maxlen && left_p->prefixlen <= maxlen)
- return bgp_node_from_rnode(node->l_left);
- }
- if (node->l_right) {
- const struct prefix *right_p =
- bgp_node_get_prefix(bgp_node_from_rnode(node->l_right));
+ while (node) {
+ const struct prefix *node_p = bgp_node_get_prefix(node);
- if (p->prefixlen < maxlen && right_p->prefixlen <= maxlen)
- return bgp_node_from_rnode(node->l_right);
- }
+ if (node_p->prefixlen >= p->prefixlen) {
+ if (!prefix_match(p, node_p))
+ return NULL;
- while (node->parent && node != limit) {
- if (bgp_node_from_rnode(node->parent->l_left) == node
- && node->parent->l_right) {
- return bgp_node_from_rnode(node->parent->l_right);
+ matched = node;
+ break;
}
- node = bgp_node_from_rnode(node->parent);
- }
- return NULL;
-}
-void bgp_table_range_lookup(const struct bgp_table *table,
- const struct prefix *p,
- uint8_t maxlen, struct list *matches)
-{
- struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
- struct bgp_node *matched = NULL;
+ if (!prefix_match(node_p, p))
+ return NULL;
- if (node == NULL)
- return;
-
- const struct prefix *node_p = bgp_node_get_prefix(node);
-
- while (node && node_p->prefixlen <= p->prefixlen
- && prefix_match(node_p, p)) {
- if (bgp_node_has_bgp_path_info_data(node)
- && node_p->prefixlen == p->prefixlen) {
+ if (node_p->prefixlen == p->prefixlen) {
matched = node;
break;
}
+
node = bgp_node_from_rnode(node->link[prefix_bit(
&p->u.prefix, node_p->prefixlen)]);
- node_p = bgp_node_get_prefix(node);
}
- if (!node)
- return;
-
- node_p = bgp_node_get_prefix(node);
- if (matched == NULL && node_p->prefixlen <= maxlen
- && prefix_match(p, node_p) && node->parent == NULL)
- matched = node;
- else if ((matched == NULL && node_p->prefixlen > maxlen)
- || !node->parent)
- return;
- else if (matched == NULL && node->parent)
- matched = node = bgp_node_from_rnode(node->parent);
-
if (!matched)
- return;
-
- if (bgp_node_has_bgp_path_info_data(matched)) {
- bgp_lock_node(matched);
- listnode_add(matches, matched);
- }
+ return NULL;
- while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) {
- node_p = bgp_node_get_prefix(node);
- if (prefix_match(p, node_p)) {
- if (bgp_node_has_bgp_path_info_data(node)) {
- bgp_lock_node(node);
- listnode_add(matches, node);
- }
- }
- }
+ bgp_lock_node(matched);
+ return matched;
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index da2ca3181a..c35833e66b 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -347,9 +347,15 @@ static inline uint64_t bgp_table_version(struct bgp_table *table)
return table->version;
}
-void bgp_table_range_lookup(const struct bgp_table *table,
- const struct prefix *p,
- uint8_t maxlen, struct list *matches);
+/* Find the subtree of the prefix p
+ *
+ * This will return the first node that belongs the the subtree of p. Including
+ * p itself, if it is in the tree.
+ *
+ * If the subtree is not present in the table, NULL is returned.
+ */
+struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
+ const struct prefix *p);
static inline struct bgp_aggregate *
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 79a8bb4408..7d81d42afb 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -73,70 +73,64 @@ static void add_node(struct bgp_table *table, const char *prefix_str)
rn->info = node;
}
-static void print_range_result(struct list *list)
+static bool prefix_in_array(const struct prefix *p, struct prefix *prefix_array,
+ size_t prefix_array_size)
{
-
- struct listnode *listnode;
- struct bgp_node *bnode;
-
- for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
- char buf[PREFIX2STR_BUFFER];
-
- prefix2str(bgp_node_get_prefix(bnode), buf, PREFIX2STR_BUFFER);
- printf("%s\n", buf);
+ for (size_t i = 0; i < prefix_array_size; ++i) {
+ if (prefix_same(p, &prefix_array[i]))
+ return true;
}
+ return false;
}
-static void check_lookup_result(struct list *list, va_list arglist)
+static void check_lookup_result(struct bgp_node *match, va_list arglist)
{
char *prefix_str;
- unsigned int prefix_count = 0;
+ struct prefix *prefixes = NULL;
+ size_t prefix_count = 0;
- printf("Searching results\n");
while ((prefix_str = va_arg(arglist, char *))) {
- struct listnode *listnode;
- struct bgp_node *bnode;
- struct prefix p;
- bool found = false;
+ ++prefix_count;
+ prefixes = realloc(prefixes, sizeof(*prefixes) * prefix_count);
- prefix_count++;
- printf("Searching for %s\n", prefix_str);
-
- if (str2prefix(prefix_str, &p) <= 0)
+ if (str2prefix(prefix_str, &prefixes[prefix_count - 1]) <= 0)
assert(0);
+ }
- for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
- if (prefix_same(bgp_node_get_prefix(bnode), &p))
- found = true;
- }
+ /* check if the result is empty and if it is allowd to be empty */
+ assert((prefix_count == 0 && !match) || prefix_count > 0);
+ if (!match)
+ return;
- assert(found);
- }
+ struct bgp_node *node = match;
+
+ while ((node = bgp_route_next_until(node, match))) {
+ const struct prefix *node_p = bgp_node_get_prefix(node);
- printf("Checking for unexpected result items\n");
- printf("Expecting %d found %d\n", prefix_count, listcount(list));
- assert(prefix_count == listcount(list));
+ if (bgp_node_has_bgp_path_info_data(node)
+ && !prefix_in_array(node_p, prefixes, prefix_count)) {
+ char buf[PREFIX2STR_BUFFER];
+
+ prefix2str(node_p, buf, PREFIX2STR_BUFFER);
+ printf("prefix %s was not expected!\n", buf);
+ assert(0);
+ }
+ }
}
-static void do_test(struct bgp_table *table, const char *prefix,
- uint32_t maxlen, ...)
+static void do_test(struct bgp_table *table, const char *prefix, ...)
{
va_list arglist;
- struct list *list = list_new();
struct prefix p;
- list->del = (void (*)(void *))bgp_unlock_node;
- va_start(arglist, maxlen);
- printf("\nDoing lookup for %s-%d\n", prefix, maxlen);
+ va_start(arglist, prefix);
+ printf("\nDoing lookup for %s\n", prefix);
if (str2prefix(prefix, &p) <= 0)
assert(0);
- bgp_table_range_lookup(table, &p, maxlen, list);
- print_range_result(list);
-
- check_lookup_result(list, arglist);
+ struct bgp_node *node = bgp_table_subtree_lookup(table, &p);
- list_delete(&list);
+ check_lookup_result(node, arglist);
va_end(arglist);
@@ -163,27 +157,22 @@ static void test_range_lookup(void)
for (int i = 0; i < num_prefixes; i++)
add_node(table, prefixes[i]);
- do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL);
- do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
- "1.16.160.0/19", NULL);
-
- do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+ do_test(table, "1.16.0.0/17", "1.16.64.0/19", "1.16.32.0/20",
+ "1.16.32.0/20", "1.16.32.0/21", NULL);
+ do_test(table, "1.16.128.0/17", "1.16.128.0/18", "1.16.192.0/18",
"1.16.160.0/19", NULL);
- do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18",
- "1.16.192.0/18", NULL);
-
- do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18",
+ do_test(table, "1.16.0.0/16", "1.16.0.0/16", "1.16.128.0/18",
"1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
"1.16.32.0/20", "1.16.32.0/21", NULL);
- do_test(table, "1.17.0.0/16", 20, NULL);
+ do_test(table, "1.17.0.0/16", NULL);
- do_test(table, "128.0.0.0/8", 16, NULL);
+ do_test(table, "128.0.0.0/8", NULL);
- do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL);
+ do_test(table, "16.0.0.0/8", "16.0.0.0/16", NULL);
- do_test(table, "0.0.0.0/2", 21, "1.16.0.0/16", "1.16.128.0/18",
+ do_test(table, "0.0.0.0/2", "1.16.0.0/16", "1.16.128.0/18",
"1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
"1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL);
}
diff --git a/tests/bgpd/test_bgp_table.py b/tests/bgpd/test_bgp_table.py
index 4deaf08c22..53bd37233a 100644
--- a/tests/bgpd/test_bgp_table.py
+++ b/tests/bgpd/test_bgp_table.py
@@ -3,5 +3,5 @@ import frrtest
class TestTable(frrtest.TestMultiOut):
program = './test_bgp_table'
-for i in range(9):
+for i in range(7):
TestTable.onesimple('Checks successfull')
--
2.43.0
From 6bdf1f6de994e6fd2c62345c651149635f3a0d81 Mon Sep 17 00:00:00 2001
From: Marius Tomaschewski <mt@suse.com>
Date: Fri, 29 Aug 2025 12:57:51 +0200
Subject: [PATCH 3/3] bgpd: Validate only affected RPKI prefixes instead of a
full RIB
References: bsc#1235237,CVE-2024-55553,https://github.com/opensourcerouting/frr/commit/2fa79333fbf70a0f401f418f53c2d9a3779485b9,https://github.com/FRRouting/frr/commit/b0800bfdf04b4fcf48504737ebfe4ba7f05268d3
Upstream: yes
This is backport of https://github.com/FRRouting/frr/commit/b0800bfdf04b4fcf48504737ebfe4ba7f05268d3 for 7.4
based on https://github.com/opensourcerouting/frr/commit/2fa79333fbf70a0f401f418f53c2d9a3779485b9 for 7.5
(no bgp_node rename https://github.com/FRRouting/frr/commit/9bcb3eef541180a17341d1d4510586efc35711db in 7.4).
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Signed-off-by: Marius Tomaschewski <mt@suse.com>
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 3228b38990..85bcaa7f7f 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -62,6 +62,7 @@
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server")
DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group")
+DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_REVALIDATE, "BGP RPKI Revalidation");
#define RPKI_VALID 1
#define RPKI_NOTFOUND 2
@@ -127,9 +128,7 @@ static enum route_map_cmd_result_t route_match(void *rule,
route_map_object_t type,
void *object);
static void *route_match_compile(const char *arg);
-static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
- safi_t safi);
-static void revalidate_all_routes(void);
+static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, safi_t safi);
static struct rtr_mgr_config *rtr_config;
static struct list *cache_list;
@@ -341,10 +340,9 @@ inline int is_running(void)
return rtr_is_running;
}
-static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
+static void pfx_record_to_prefix(struct pfx_record *record,
+ struct prefix *prefix)
{
- struct prefix *prefix = prefix_new();
-
prefix->prefixlen = record->min_len;
if (record->prefix.ver == LRTR_IPV4) {
@@ -355,75 +353,104 @@ static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr,
prefix->u.prefix6.s6_addr32);
}
-
- return prefix;
}
-static int bgpd_sync_callback(struct thread *thread)
-{
+struct rpki_revalidate_prefix {
struct bgp *bgp;
- struct listnode *node;
- struct prefix *prefix;
- struct pfx_record rec;
+ struct prefix prefix;
+ afi_t afi;
+ safi_t safi;
+};
- thread_add_read(bm->master, bgpd_sync_callback, NULL,
- rpki_sync_socket_bgpd, NULL);
+static int rpki_revalidate_prefix(struct thread *thread)
+{
+ struct rpki_revalidate_prefix *rrp = THREAD_ARG(thread);
+ struct bgp_node *match, *node;
- if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
- while (read(rpki_sync_socket_bgpd, &rec,
- sizeof(struct pfx_record))
- != -1)
- ;
+ match = bgp_table_subtree_lookup(rrp->bgp->rib[rrp->afi][rrp->safi],
+ &rrp->prefix);
- atomic_store_explicit(&rtr_update_overflow, 0,
- memory_order_seq_cst);
- revalidate_all_routes();
- return 0;
- }
+ node = match;
- int retval =
- read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
- if (retval != sizeof(struct pfx_record)) {
- RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
- return retval;
+ while (node) {
+ if (bgp_node_has_bgp_path_info_data(node)) {
+ revalidate_bgp_node(node, rrp->afi, rrp->safi);
+ }
+
+ node = bgp_route_next_until(node, match);
}
- prefix = pfx_record_to_prefix(&rec);
- afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+ XFREE(MTYPE_BGP_RPKI_REVALIDATE, rrp);
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
- struct peer *peer;
- struct listnode *peer_listnode;
+ return 0;
+}
- for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
- safi_t safi;
+static void revalidate_single_prefix(struct prefix prefix,
+ afi_t afi)
+{
+ struct bgp *bgp;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ safi_t safi;
+
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ struct bgp_table *table = bgp->rib[afi][safi];
+ struct rpki_revalidate_prefix *rrp;
+
+ if (!table)
+ continue;
+
+ rrp = XCALLOC(MTYPE_BGP_RPKI_REVALIDATE, sizeof(*rrp));
+ rrp->bgp = bgp;
+ rrp->prefix = prefix;
+ rrp->afi = afi;
+ rrp->safi = safi;
+ thread_add_event(bm->master, rpki_revalidate_prefix,
+ rrp, 0, &bgp->t_revalidate[afi][safi]);
+ }
+ }
+}
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- if (!peer->bgp->rib[afi][safi])
- continue;
+static int bgpd_sync_callback(struct thread *thread)
+{
+ struct prefix prefix;
+ struct pfx_record rec;
+ afi_t afi;
+ int retval;
- struct bgp_node *match;
- struct bgp_node *node;
+ if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
+ ssize_t size = 0;
- match = bgp_table_subtree_lookup(
- peer->bgp->rib[afi][safi], prefix);
- node = match;
+ retval = read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ while (retval != -1) {
+ if (retval != sizeof(struct pfx_record))
+ break;
- while (node) {
- if (bgp_node_has_bgp_path_info_data(
- node)) {
- revalidate_bgp_node(node, afi,
- safi);
- }
+ size += retval;
+ pfx_record_to_prefix(&rec, &prefix);
+ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+ revalidate_single_prefix(prefix, afi);
- node = bgp_route_next_until(node,
- match);
- }
- }
+ retval = read(rpki_sync_socket_bgpd, &rec,
+ sizeof(struct pfx_record));
}
+
+ atomic_store_explicit(&rtr_update_overflow, 0, memory_order_seq_cst);
+ return 0;
+ }
+
+ retval = read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+ if (retval != sizeof(struct pfx_record)) {
+ RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
+ return 0;
}
+ pfx_record_to_prefix(&rec, &prefix);
+
+ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+
+ revalidate_single_prefix(prefix, afi);
- prefix_free(&prefix);
return 0;
}
@@ -453,33 +480,6 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
}
}
-static void revalidate_all_routes(void)
-{
- struct bgp *bgp;
- struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
- struct peer *peer;
- struct listnode *peer_listnode;
-
- for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
-
- for (size_t i = 0; i < 2; i++) {
- safi_t safi;
- afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
-
- for (safi = SAFI_UNICAST; safi < SAFI_MAX;
- safi++) {
- if (!peer->bgp->rib[afi][safi])
- continue;
-
- bgp_soft_reconfig_in(peer, afi, safi);
- }
- }
- }
- }
-}
-
static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
const struct pfx_record rec,
const bool added __attribute__((unused)))
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index cf6335d373..a53b04854f 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -3311,6 +3311,9 @@ int bgp_delete(struct bgp *bgp)
hook_call(bgp_inst_delete, bgp);
+ FOREACH_AFI_SAFI (afi, safi)
+ THREAD_OFF(bgp->t_revalidate[afi][safi]);
+
THREAD_OFF(bgp->t_startup);
THREAD_OFF(bgp->t_maxmed_onstartup);
THREAD_OFF(bgp->t_update_delay);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 4a5772a53b..167fd94734 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -392,6 +392,7 @@ struct bgp {
/* BGP update delay on startup */
struct thread *t_update_delay;
struct thread *t_establish_wait;
+ struct thread *t_revalidate[AFI_MAX][SAFI_MAX];
uint8_t update_delay_over;
uint8_t main_zebra_update_hold;
uint8_t main_peers_update_hold;
--
2.43.0