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

openSUSE Build Service is sponsored by