All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH dpdk 0/2] rib: allow iteration to include the top-level route
@ 2026-05-18  9:59 Robin Jarry
  2026-05-18  9:59 ` [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode Robin Jarry
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Robin Jarry @ 2026-05-18  9:59 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin

rte_rib_get_nxt() and rte_rib6_get_nxt() use an untyped int parameter
and anonymous enums for the traversal mode. The first patch gives these
enums proper type names (rte_rib_nxt_mode, rte_rib6_nxt_mode) and
renames the parameter from "flag" to "mode".

The existing traversal modes (ALL and COVER) always skip the exact match
top-level route. The second patch adds a RTE_RIB_GET_NXT_ALL_TOP mode
(and its IPv6 counterpart) so that callers who need the full subtree
including the root can get it without a separate rte_rib_lookup_exact()
call.

Robin Jarry (2):
  rib: rename nxt flag parameter to mode
  rib: add mode to include top-level route in traversal

 app/test/test_rib.c  | 16 ++++++++++++++++
 app/test/test_rib6.c | 16 ++++++++++++++++
 lib/rib/rte_rib.c    | 16 ++++++++++++----
 lib/rib/rte_rib.h    | 16 ++++++++++------
 lib/rib/rte_rib6.c   | 16 ++++++++++++----
 lib/rib/rte_rib6.h   | 18 +++++++++++-------
 6 files changed, 77 insertions(+), 21 deletions(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode
  2026-05-18  9:59 [PATCH dpdk 0/2] rib: allow iteration to include the top-level route Robin Jarry
@ 2026-05-18  9:59 ` Robin Jarry
  2026-09-30 17:12   ` Medvedkin, Vladimir
  2026-05-18  9:59 ` [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal Robin Jarry
  2026-10-02 10:15 ` [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route Robin Jarry
  2 siblings, 1 reply; 10+ messages in thread
From: Robin Jarry @ 2026-05-18  9:59 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin

The flag parameter in rte_rib_get_nxt() and rte_rib6_get_nxt() is a
plain int used as a typed enumeration. Give the anonymous enums proper
names (rte_rib_nxt_mode, rte_rib6_nxt_mode) and rename the parameter
from "flag" to "mode" to reflect its purpose.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 lib/rib/rte_rib.c  |  4 ++--
 lib/rib/rte_rib.h  | 12 ++++++------
 lib/rib/rte_rib6.c |  4 ++--
 lib/rib/rte_rib6.h | 14 +++++++-------
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
index 046db131ca00..89061829a23c 100644
--- a/lib/rib/rte_rib.c
+++ b/lib/rib/rte_rib.c
@@ -175,7 +175,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
 RTE_EXPORT_SYMBOL(rte_rib_get_nxt)
 struct rte_rib_node *
 rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
-	uint8_t depth, struct rte_rib_node *last, int flag)
+	uint8_t depth, struct rte_rib_node *last, enum rte_rib_nxt_mode mode)
 {
 	struct rte_rib_node *tmp, *prev = NULL;
 
@@ -205,7 +205,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
 				(is_covered(tmp->ip, ip, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
-			if (flag == RTE_RIB_GET_NXT_COVER)
+			if (mode == RTE_RIB_GET_NXT_COVER)
 				return prev;
 		}
 		tmp = (tmp->left) ? tmp->left : tmp->right;
diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
index c325b3e3618c..0fabfb2a41a6 100644
--- a/lib/rib/rte_rib.h
+++ b/lib/rib/rte_rib.h
@@ -26,11 +26,11 @@ extern "C" {
 /**
  * rte_rib_get_nxt() flags
  */
-enum {
-	/** flag to get all subroutes in a RIB tree */
+enum rte_rib_nxt_mode {
+	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB_GET_NXT_ALL,
-	/** flag to get first matched subroutes in a RIB tree */
-	RTE_RIB_GET_NXT_COVER
+	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
+	RTE_RIB_GET_NXT_COVER,
 };
 
 struct rte_rib;
@@ -120,7 +120,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  *   pointer to the last returned prefix to get next prefix
  *   or
  *   NULL to get first more specific prefix
- * @param flag
+ * @param mode
  *  -RTE_RIB_GET_NXT_ALL
  *   get all prefixes from subtrie
  *  -RTE_RIB_GET_NXT_COVER
@@ -131,7 +131,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  */
 struct rte_rib_node *
 rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip, uint8_t depth,
-	struct rte_rib_node *last, int flag);
+	struct rte_rib_node *last, enum rte_rib_nxt_mode mode);
 
 /**
  * Remove prefix from the RIB
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index ec8ff68e8700..c23881f6247e 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -195,7 +195,7 @@ RTE_EXPORT_SYMBOL(rte_rib6_get_nxt)
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
 	const struct rte_ipv6_addr *ip,
-	uint8_t depth, struct rte_rib6_node *last, int flag)
+	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_nxt_mode mode)
 {
 	struct rte_rib6_node *tmp, *prev = NULL;
 	struct rte_ipv6_addr tmp_ip;
@@ -229,7 +229,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
-			if (flag == RTE_RIB6_GET_NXT_COVER)
+			if (mode == RTE_RIB6_GET_NXT_COVER)
 				return prev;
 		}
 		tmp = (tmp->left != NULL) ? tmp->left : tmp->right;
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index d66d9e7c07c6..ed2761492bc8 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -25,13 +25,13 @@ extern "C" {
 #define RTE_RIB6_IPV6_ADDR_SIZE (RTE_DEPRECATED(RTE_RIB6_IPV6_ADDR_SIZE) RTE_IPV6_ADDR_SIZE)
 
 /**
- * rte_rib6_get_nxt() flags
+ * rte_rib6_get_nxt() mode
  */
-enum {
-	/** flag to get all subroutes in a RIB tree */
+enum rte_rib6_nxt_mode {
+	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB6_GET_NXT_ALL,
-	/** flag to get first matched subroutes in a RIB tree */
-	RTE_RIB6_GET_NXT_COVER
+	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
+	RTE_RIB6_GET_NXT_COVER,
 };
 
 struct rte_rib6;
@@ -179,7 +179,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  *   pointer to the last returned prefix to get next prefix
  *   or
  *   NULL to get first more specific prefix
- * @param flag
+ * @param mode
  *  -RTE_RIB6_GET_NXT_ALL
  *   get all prefixes from subtrie
  *  -RTE_RIB6_GET_NXT_COVER
@@ -191,7 +191,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
 	const struct rte_ipv6_addr *ip,
-	uint8_t depth, struct rte_rib6_node *last, int flag);
+	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_nxt_mode mode);
 
 /**
  * Remove prefix from the RIB
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal
  2026-05-18  9:59 [PATCH dpdk 0/2] rib: allow iteration to include the top-level route Robin Jarry
  2026-05-18  9:59 ` [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode Robin Jarry
@ 2026-05-18  9:59 ` Robin Jarry
  2026-09-30 17:12   ` Medvedkin, Vladimir
  2026-10-02 10:15 ` [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route Robin Jarry
  2 siblings, 1 reply; 10+ messages in thread
From: Robin Jarry @ 2026-05-18  9:59 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin

rte_rib_get_nxt() and rte_rib6_get_nxt() skip the exact match
top-level route when iterating subroutes. This is the expected behavior
in most cases but some users need the full subtree including the root.

Add a RTE_RIB_GET_NXT_ALL_TOP (and RTE_RIB6_GET_NXT_ALL_TOP) mode
that uses >= instead of > when comparing depths so that the top-level
route is returned as well.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_rib.c  | 16 ++++++++++++++++
 app/test/test_rib6.c | 16 ++++++++++++++++
 lib/rib/rte_rib.c    | 12 ++++++++++--
 lib/rib/rte_rib.h    |  4 ++++
 lib/rib/rte_rib6.c   | 12 ++++++++++--
 lib/rib/rte_rib6.h   |  4 ++++
 6 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/app/test/test_rib.c b/app/test/test_rib.c
index a4a683140df3..f56490e67ec0 100644
--- a/app/test/test_rib.c
+++ b/app/test/test_rib.c
@@ -300,6 +300,7 @@ test_tree_traversal(void)
 	uint32_t ip1 = RTE_IPV4(10, 10, 10, 0);
 	uint32_t ip2 = RTE_IPV4(10, 10, 130, 80);
 	uint8_t depth = 30;
+	unsigned int num;
 
 	config.max_nodes = MAX_RULES;
 	config.ext_sz = 0;
@@ -313,11 +314,26 @@ test_tree_traversal(void)
 	node = rte_rib_insert(rib, ip2, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 
+	node = rte_rib_insert(rib, 0, 0);
+	RTE_TEST_ASSERT(node != NULL, "Failed to insert default rule\n");
+
 	node = NULL;
 	node = rte_rib_get_nxt(rib, RTE_IPV4(10, 10, 130, 0), 24, node,
 			RTE_RIB_GET_NXT_ALL);
 	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
+
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL_TOP)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib_get_nxt\n");
+
 	rte_rib_free(rib);
 
 	return TEST_SUCCESS;
diff --git a/app/test/test_rib6.c b/app/test/test_rib6.c
index 0295a9640cfa..542c955eee8c 100644
--- a/app/test/test_rib6.c
+++ b/app/test/test_rib6.c
@@ -300,7 +300,9 @@ test_tree_traversal(void)
 	struct rte_ipv6_addr ip = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0);
 	struct rte_ipv6_addr ip1 = RTE_IPV6(0x0a00, 0x0200, 0, 0, 0, 0, 0, 0);
 	struct rte_ipv6_addr ip2 = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0x0050);
+	struct rte_ipv6_addr unspec = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0);
 	uint8_t depth = 126;
+	unsigned int num;
 
 	config.max_nodes = MAX_RULES;
 	config.ext_sz = 0;
@@ -312,11 +314,25 @@ test_tree_traversal(void)
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 	node = rte_rib6_insert(rib, &ip2, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+	node = rte_rib6_insert(rib, &unspec, 0);
+	RTE_TEST_ASSERT(node != NULL, "Failed to insert default route\n");
 
 	node = NULL;
 	node = rte_rib6_get_nxt(rib, &ip, 32, node, RTE_RIB6_GET_NXT_ALL);
 	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
+
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL_TOP)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib6_get_nxt\n");
+
 	rte_rib6_free(rib);
 
 	return TEST_SUCCESS;
diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
index 89061829a23c..a3c287e215ec 100644
--- a/lib/rib/rte_rib.c
+++ b/lib/rib/rte_rib.c
@@ -167,6 +167,14 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
 	return __rib_lookup_exact(rib, ip, depth);
 }
 
+static bool
+depth_match(struct rte_rib_node *node, uint8_t depth, int flag)
+{
+	if (flag == RTE_RIB_GET_NXT_ALL_TOP)
+		return node->depth >= depth;
+	return node->depth > depth;
+}
+
 /*
  *  Traverses on subtree and retrieves more specific routes
  *  for a given in args ip/depth prefix
@@ -195,7 +203,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
 					(is_covered(tmp->ip, ip, depth) &&
-					(tmp->depth > depth)))
+					(depth_match(tmp, depth, mode))))
 				return tmp;
 		}
 		tmp = (tmp->parent) ? tmp->parent->right : NULL;
@@ -203,7 +211,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
 	while (tmp) {
 		if (is_valid_node(tmp) &&
 				(is_covered(tmp->ip, ip, depth) &&
-				(tmp->depth > depth))) {
+				(depth_match(tmp, depth, mode)))) {
 			prev = tmp;
 			if (mode == RTE_RIB_GET_NXT_COVER)
 				return prev;
diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
index 0fabfb2a41a6..5e72fa9273e2 100644
--- a/lib/rib/rte_rib.h
+++ b/lib/rib/rte_rib.h
@@ -31,6 +31,8 @@ enum rte_rib_nxt_mode {
 	RTE_RIB_GET_NXT_ALL,
 	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB_GET_NXT_COVER,
+	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
+	RTE_RIB_GET_NXT_ALL_TOP,
 };
 
 struct rte_rib;
@@ -125,6 +127,8 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  *   get all prefixes from subtrie
  *  -RTE_RIB_GET_NXT_COVER
  *   get only first more specific prefix even if it have more specifics
+ *  -RTE_RIB_GET_NXT_ALL_TOP
+ *   get the top-level exact matching prefix, if any
  * @return
  *  pointer to the next more specific prefix
  *  NULL if there is no prefixes left
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index c23881f6247e..5114fb522e3e 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -186,6 +186,14 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 	return NULL;
 }
 
+static bool
+depth_match(struct rte_rib6_node *node, uint8_t depth, enum rte_rib6_nxt_mode mode)
+{
+	if (mode == RTE_RIB6_GET_NXT_ALL_TOP)
+		return node->depth >= depth;
+	return node->depth > depth;
+}
+
 /*
  *  Traverses on subtree and retrieves more specific routes
  *  for a given in args ip/depth prefix
@@ -219,7 +227,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
 					(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
-					(tmp->depth > depth)))
+					(depth_match(tmp, depth, mode))))
 				return tmp;
 		}
 		tmp = (tmp->parent != NULL) ? tmp->parent->right : NULL;
@@ -227,7 +235,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 	while (tmp) {
 		if (is_valid_node(tmp) &&
 				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
-				(tmp->depth > depth))) {
+				(depth_match(tmp, depth, mode)))) {
 			prev = tmp;
 			if (mode == RTE_RIB6_GET_NXT_COVER)
 				return prev;
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index ed2761492bc8..1d8b56b89b13 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -32,6 +32,8 @@ enum rte_rib6_nxt_mode {
 	RTE_RIB6_GET_NXT_ALL,
 	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB6_GET_NXT_COVER,
+	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
+	RTE_RIB6_GET_NXT_ALL_TOP,
 };
 
 struct rte_rib6;
@@ -184,6 +186,8 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  *   get all prefixes from subtrie
  *  -RTE_RIB6_GET_NXT_COVER
  *   get only first more specific prefix even if it have more specifics
+ *  -RTE_RIB6_GET_NXT_ALL_TOP
+ *   get the top-level exact matching prefix, if any
  * @return
  *  pointer to the next more specific prefix
  *  NULL if there is no prefixes left
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode
  2026-05-18  9:59 ` [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode Robin Jarry
@ 2026-09-30 17:12   ` Medvedkin, Vladimir
  2026-10-02  9:52     ` Robin Jarry
  0 siblings, 1 reply; 10+ messages in thread
From: Medvedkin, Vladimir @ 2026-09-30 17:12 UTC (permalink / raw)
  To: Robin Jarry, dev

Hi Robin,

As a general comment, do we really need these changes? ABI policy 
recommends not to do so

https://doc.dpdk.org/guides-26.07/contributing/abi_policy.html#abi-changes

" Change the API only for significant reasons, such as performance 
enhancements. Avoid API breakages due to changes such as reorganizing 
public structure fields for aesthetic or readability purposes."


On 5/18/2026 10:59 AM, Robin Jarry wrote:
> The flag parameter in rte_rib_get_nxt() and rte_rib6_get_nxt() is a
> plain int used as a typed enumeration. Give the anonymous enums proper
> names (rte_rib_nxt_mode, rte_rib6_nxt_mode) and rename the parameter
> from "flag" to "mode" to reflect its purpose.
>
> Signed-off-by: Robin Jarry <rjarry@redhat.com>
> ---
>   lib/rib/rte_rib.c  |  4 ++--
>   lib/rib/rte_rib.h  | 12 ++++++------
>   lib/rib/rte_rib6.c |  4 ++--
>   lib/rib/rte_rib6.h | 14 +++++++-------
>   4 files changed, 17 insertions(+), 17 deletions(-)
>
> diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
> index 046db131ca00..89061829a23c 100644
> --- a/lib/rib/rte_rib.c
> +++ b/lib/rib/rte_rib.c
> @@ -175,7 +175,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
>   RTE_EXPORT_SYMBOL(rte_rib_get_nxt)
>   struct rte_rib_node *
>   rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
> -	uint8_t depth, struct rte_rib_node *last, int flag)
> +	uint8_t depth, struct rte_rib_node *last, enum rte_rib_nxt_mode mode)
>   {
>   	struct rte_rib_node *tmp, *prev = NULL;
>   
> @@ -205,7 +205,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
>   				(is_covered(tmp->ip, ip, depth) &&
>   				(tmp->depth > depth))) {
>   			prev = tmp;
> -			if (flag == RTE_RIB_GET_NXT_COVER)
> +			if (mode == RTE_RIB_GET_NXT_COVER)
>   				return prev;
>   		}
>   		tmp = (tmp->left) ? tmp->left : tmp->right;
> diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
> index c325b3e3618c..0fabfb2a41a6 100644
> --- a/lib/rib/rte_rib.h
> +++ b/lib/rib/rte_rib.h
> @@ -26,11 +26,11 @@ extern "C" {
>   /**
>    * rte_rib_get_nxt() flags
mode instead of flags
>    */
> -enum {
> -	/** flag to get all subroutes in a RIB tree */
> +enum rte_rib_nxt_mode {
rte_rib_get_nxt_mode?
> +	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
>   	RTE_RIB_GET_NXT_ALL,
> -	/** flag to get first matched subroutes in a RIB tree */
> -	RTE_RIB_GET_NXT_COVER
> +	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
> +	RTE_RIB_GET_NXT_COVER,
>   };
>   
>   struct rte_rib;
> @@ -120,7 +120,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
>    *   pointer to the last returned prefix to get next prefix
>    *   or
>    *   NULL to get first more specific prefix
> - * @param flag
> + * @param mode
>    *  -RTE_RIB_GET_NXT_ALL
>    *   get all prefixes from subtrie
>    *  -RTE_RIB_GET_NXT_COVER
> @@ -131,7 +131,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
>    */
>   struct rte_rib_node *
>   rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip, uint8_t depth,
> -	struct rte_rib_node *last, int flag);
> +	struct rte_rib_node *last, enum rte_rib_nxt_mode mode);
>   
>   /**
>    * Remove prefix from the RIB
> diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
> index ec8ff68e8700..c23881f6247e 100644
> --- a/lib/rib/rte_rib6.c
> +++ b/lib/rib/rte_rib6.c
> @@ -195,7 +195,7 @@ RTE_EXPORT_SYMBOL(rte_rib6_get_nxt)
>   struct rte_rib6_node *
>   rte_rib6_get_nxt(struct rte_rib6 *rib,
>   	const struct rte_ipv6_addr *ip,
> -	uint8_t depth, struct rte_rib6_node *last, int flag)
> +	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_nxt_mode mode)
>   {
>   	struct rte_rib6_node *tmp, *prev = NULL;
>   	struct rte_ipv6_addr tmp_ip;
> @@ -229,7 +229,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
>   				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
>   				(tmp->depth > depth))) {
>   			prev = tmp;
> -			if (flag == RTE_RIB6_GET_NXT_COVER)
> +			if (mode == RTE_RIB6_GET_NXT_COVER)
>   				return prev;
>   		}
>   		tmp = (tmp->left != NULL) ? tmp->left : tmp->right;
> diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
> index d66d9e7c07c6..ed2761492bc8 100644
> --- a/lib/rib/rte_rib6.h
> +++ b/lib/rib/rte_rib6.h
> @@ -25,13 +25,13 @@ extern "C" {
>   #define RTE_RIB6_IPV6_ADDR_SIZE (RTE_DEPRECATED(RTE_RIB6_IPV6_ADDR_SIZE) RTE_IPV6_ADDR_SIZE)
>   
>   /**
> - * rte_rib6_get_nxt() flags
> + * rte_rib6_get_nxt() mode
>    */
> -enum {
> -	/** flag to get all subroutes in a RIB tree */
> +enum rte_rib6_nxt_mode {
rte_rib6_get_nxt_mode?
> +	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
>   	RTE_RIB6_GET_NXT_ALL,
> -	/** flag to get first matched subroutes in a RIB tree */
> -	RTE_RIB6_GET_NXT_COVER
> +	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
> +	RTE_RIB6_GET_NXT_COVER,
>   };
>   
>   struct rte_rib6;
> @@ -179,7 +179,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
>    *   pointer to the last returned prefix to get next prefix
>    *   or
>    *   NULL to get first more specific prefix
> - * @param flag
> + * @param mode
>    *  -RTE_RIB6_GET_NXT_ALL
>    *   get all prefixes from subtrie
>    *  -RTE_RIB6_GET_NXT_COVER
> @@ -191,7 +191,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
>   struct rte_rib6_node *
>   rte_rib6_get_nxt(struct rte_rib6 *rib,
>   	const struct rte_ipv6_addr *ip,
> -	uint8_t depth, struct rte_rib6_node *last, int flag);
> +	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_nxt_mode mode);
>   
>   /**
>    * Remove prefix from the RIB

-- 
Regards,
Vladimir


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal
  2026-05-18  9:59 ` [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal Robin Jarry
@ 2026-09-30 17:12   ` Medvedkin, Vladimir
  2026-10-02  9:50     ` Robin Jarry
  0 siblings, 1 reply; 10+ messages in thread
From: Medvedkin, Vladimir @ 2026-09-30 17:12 UTC (permalink / raw)
  To: Robin Jarry, dev

Hi Robin,

I'd suggest to reflect changes in release notes. Please find other 
comments inline.

On 5/18/2026 10:59 AM, Robin Jarry wrote:
> rte_rib_get_nxt() and rte_rib6_get_nxt() skip the exact match
> top-level route when iterating subroutes. This is the expected behavior
> in most cases but some users need the full subtree including the root.
>
> Add a RTE_RIB_GET_NXT_ALL_TOP (and RTE_RIB6_GET_NXT_ALL_TOP) mode
> that uses >= instead of > when comparing depths so that the top-level
> route is returned as well.
>
> Signed-off-by: Robin Jarry <rjarry@redhat.com>
> ---
>   app/test/test_rib.c  | 16 ++++++++++++++++
>   app/test/test_rib6.c | 16 ++++++++++++++++
>   lib/rib/rte_rib.c    | 12 ++++++++++--
>   lib/rib/rte_rib.h    |  4 ++++
>   lib/rib/rte_rib6.c   | 12 ++++++++++--
>   lib/rib/rte_rib6.h   |  4 ++++
>   6 files changed, 60 insertions(+), 4 deletions(-)
>
> diff --git a/app/test/test_rib.c b/app/test/test_rib.c
> index a4a683140df3..f56490e67ec0 100644
> --- a/app/test/test_rib.c
> +++ b/app/test/test_rib.c
> @@ -300,6 +300,7 @@ test_tree_traversal(void)
>   	uint32_t ip1 = RTE_IPV4(10, 10, 10, 0);
>   	uint32_t ip2 = RTE_IPV4(10, 10, 130, 80);
>   	uint8_t depth = 30;
> +	unsigned int num;
>   
>   	config.max_nodes = MAX_RULES;
>   	config.ext_sz = 0;
> @@ -313,11 +314,26 @@ test_tree_traversal(void)
>   	node = rte_rib_insert(rib, ip2, depth);
>   	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
>   
> +	node = rte_rib_insert(rib, 0, 0);
> +	RTE_TEST_ASSERT(node != NULL, "Failed to insert default rule\n");
> +
>   	node = NULL;
>   	node = rte_rib_get_nxt(rib, RTE_IPV4(10, 10, 130, 0), 24, node,
>   			RTE_RIB_GET_NXT_ALL);
>   	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
>   
> +	num = 0;
> +	node = NULL;
> +	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL)) != NULL)
> +		num++;
> +	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
> +
> +	num = 0;
> +	node = NULL;
> +	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL_TOP)) != NULL)
> +		num++;
> +	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib_get_nxt\n");
> +
>   	rte_rib_free(rib);
>   
>   	return TEST_SUCCESS;
> diff --git a/app/test/test_rib6.c b/app/test/test_rib6.c
> index 0295a9640cfa..542c955eee8c 100644
> --- a/app/test/test_rib6.c
> +++ b/app/test/test_rib6.c
> @@ -300,7 +300,9 @@ test_tree_traversal(void)
>   	struct rte_ipv6_addr ip = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0);
>   	struct rte_ipv6_addr ip1 = RTE_IPV6(0x0a00, 0x0200, 0, 0, 0, 0, 0, 0);
>   	struct rte_ipv6_addr ip2 = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0x0050);
> +	struct rte_ipv6_addr unspec = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0);
>   	uint8_t depth = 126;
> +	unsigned int num;
>   
>   	config.max_nodes = MAX_RULES;
>   	config.ext_sz = 0;
> @@ -312,11 +314,25 @@ test_tree_traversal(void)
>   	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
>   	node = rte_rib6_insert(rib, &ip2, depth);
>   	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
> +	node = rte_rib6_insert(rib, &unspec, 0);
> +	RTE_TEST_ASSERT(node != NULL, "Failed to insert default route\n");
>   
>   	node = NULL;
>   	node = rte_rib6_get_nxt(rib, &ip, 32, node, RTE_RIB6_GET_NXT_ALL);
>   	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
>   
> +	num = 0;
> +	node = NULL;
> +	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL)) != NULL)
second arg should be &unspec
> +		num++;
> +	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
> +
> +	num = 0;
> +	node = NULL;
> +	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL_TOP)) != NULL)
same here
> +		num++;
> +	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib6_get_nxt\n");
> +
>   	rte_rib6_free(rib);
>   
>   	return TEST_SUCCESS;
> diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
> index 89061829a23c..a3c287e215ec 100644
> --- a/lib/rib/rte_rib.c
> +++ b/lib/rib/rte_rib.c
> @@ -167,6 +167,14 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
>   	return __rib_lookup_exact(rib, ip, depth);
>   }
>   
> +static bool
> +depth_match(struct rte_rib_node *node, uint8_t depth, int flag)

3d arg enum rte_rib_nxt_mode mode?

> +{
> +	if (flag == RTE_RIB_GET_NXT_ALL_TOP)
> +		return node->depth >= depth;
> +	return node->depth > depth;
> +}
> +
>   /*
>    *  Traverses on subtree and retrieves more specific routes
>    *  for a given in args ip/depth prefix
> @@ -195,7 +203,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
>   			tmp = tmp->parent;
>   			if (is_valid_node(tmp) &&
>   					(is_covered(tmp->ip, ip, depth) &&
> -					(tmp->depth > depth)))
> +					(depth_match(tmp, depth, mode))))
extra parenthesis, same for v6
>   				return tmp;
>   		}
>   		tmp = (tmp->parent) ? tmp->parent->right : NULL;
> @@ -203,7 +211,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
>   	while (tmp) {
>   		if (is_valid_node(tmp) &&
>   				(is_covered(tmp->ip, ip, depth) &&
> -				(tmp->depth > depth))) {
> +				(depth_match(tmp, depth, mode)))) {
>   			prev = tmp;
>   			if (mode == RTE_RIB_GET_NXT_COVER)
>   				return prev;
> diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
> index 0fabfb2a41a6..5e72fa9273e2 100644
> --- a/lib/rib/rte_rib.h
> +++ b/lib/rib/rte_rib.h
> @@ -31,6 +31,8 @@ enum rte_rib_nxt_mode {
>   	RTE_RIB_GET_NXT_ALL,
>   	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
>   	RTE_RIB_GET_NXT_COVER,
> +	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
> +	RTE_RIB_GET_NXT_ALL_TOP,
>   };
>   
>   struct rte_rib;
> @@ -125,6 +127,8 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
>    *   get all prefixes from subtrie
>    *  -RTE_RIB_GET_NXT_COVER
>    *   get only first more specific prefix even if it have more specifics
> + *  -RTE_RIB_GET_NXT_ALL_TOP
> + *   get the top-level exact matching prefix, if any

RTE_RIB_GET_NXT_ALL_TOP is effectively RTE_RIB_GET_NXT_ALL + exact 
match. Better definition would be something like:

get all prefixes from the subtrie, including the ip/depth prefix itself 
if present. Top prefix is returned last.

>    * @return
>    *  pointer to the next more specific prefix
>    *  NULL if there is no prefixes left
> diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
> index c23881f6247e..5114fb522e3e 100644
> --- a/lib/rib/rte_rib6.c
> +++ b/lib/rib/rte_rib6.c
> @@ -186,6 +186,14 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
>   	return NULL;
>   }
>   
> +static bool
> +depth_match(struct rte_rib6_node *node, uint8_t depth, enum rte_rib6_nxt_mode mode)
> +{
> +	if (mode == RTE_RIB6_GET_NXT_ALL_TOP)
> +		return node->depth >= depth;
> +	return node->depth > depth;
> +}
> +
>   /*
>    *  Traverses on subtree and retrieves more specific routes
>    *  for a given in args ip/depth prefix
> @@ -219,7 +227,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
>   			tmp = tmp->parent;
>   			if (is_valid_node(tmp) &&
>   					(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
> -					(tmp->depth > depth)))
> +					(depth_match(tmp, depth, mode))))
>   				return tmp;
>   		}
>   		tmp = (tmp->parent != NULL) ? tmp->parent->right : NULL;
> @@ -227,7 +235,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
>   	while (tmp) {
>   		if (is_valid_node(tmp) &&
>   				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
> -				(tmp->depth > depth))) {
> +				(depth_match(tmp, depth, mode)))) {
>   			prev = tmp;
>   			if (mode == RTE_RIB6_GET_NXT_COVER)
>   				return prev;
> diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
> index ed2761492bc8..1d8b56b89b13 100644
> --- a/lib/rib/rte_rib6.h
> +++ b/lib/rib/rte_rib6.h
> @@ -32,6 +32,8 @@ enum rte_rib6_nxt_mode {
>   	RTE_RIB6_GET_NXT_ALL,
>   	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
>   	RTE_RIB6_GET_NXT_COVER,
> +	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
> +	RTE_RIB6_GET_NXT_ALL_TOP,
>   };
>   
>   struct rte_rib6;
> @@ -184,6 +186,8 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
>    *   get all prefixes from subtrie
>    *  -RTE_RIB6_GET_NXT_COVER
>    *   get only first more specific prefix even if it have more specifics
> + *  -RTE_RIB6_GET_NXT_ALL_TOP
> + *   get the top-level exact matching prefix, if any
>    * @return
>    *  pointer to the next more specific prefix
>    *  NULL if there is no prefixes left

-- 
Regards,
Vladimir


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal
  2026-09-30 17:12   ` Medvedkin, Vladimir
@ 2026-10-02  9:50     ` Robin Jarry
  0 siblings, 0 replies; 10+ messages in thread
From: Robin Jarry @ 2026-10-02  9:50 UTC (permalink / raw)
  To: Medvedkin, Vladimir, dev

Hey Vladimir,

Medvedkin, Vladimir, Sep 30, 2026 at 19:12:
> I'd suggest to reflect changes in release notes. Please find other 
> comments inline.

Will do.

>> +	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL)) != NULL)
> second arg should be &unspec
>> +		num++;
>> +	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
>> +
>> +	num = 0;
>> +	node = NULL;
>> +	while ((node = rte_rib6_get_nxt(rib, 0, 0, node, RTE_RIB6_GET_NXT_ALL_TOP)) != NULL)
> same here

Indeed, good catch. Although for some reason, the test passes :s

>> +static bool
>> +depth_match(struct rte_rib_node *node, uint8_t depth, int flag)
>
> 3d arg enum rte_rib_nxt_mode mode?

Yes, better.

>> @@ -195,7 +203,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
>>   			tmp = tmp->parent;
>>   			if (is_valid_node(tmp) &&
>>   					(is_covered(tmp->ip, ip, depth) &&
>> -					(tmp->depth > depth)))
>> +					(depth_match(tmp, depth, mode))))
> extra parenthesis, same for v6

I wanted to stick to the style of the line above which also has an
extraneous parenthesis. I'll remove it.

>> @@ -125,6 +127,8 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
>>    *   get all prefixes from subtrie
>>    *  -RTE_RIB_GET_NXT_COVER
>>    *   get only first more specific prefix even if it have more specifics
>> + *  -RTE_RIB_GET_NXT_ALL_TOP
>> + *   get the top-level exact matching prefix, if any
>
> RTE_RIB_GET_NXT_ALL_TOP is effectively RTE_RIB_GET_NXT_ALL + exact 
> match. Better definition would be something like:
>
> get all prefixes from the subtrie, including the ip/depth prefix itself 
> if present. Top prefix is returned last.

Ack.

-- 
Robin

# Prices subject to change without notice.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode
  2026-09-30 17:12   ` Medvedkin, Vladimir
@ 2026-10-02  9:52     ` Robin Jarry
  0 siblings, 0 replies; 10+ messages in thread
From: Robin Jarry @ 2026-10-02  9:52 UTC (permalink / raw)
  To: Medvedkin, Vladimir, dev

Medvedkin, Vladimir, Sep 30, 2026 at 19:12:
> Hi Robin,
>
> As a general comment, do we really need these changes? ABI policy 
> recommends not to do so
>
> https://doc.dpdk.org/guides-26.07/contributing/abi_policy.html#abi-changes
>
> " Change the API only for significant reasons, such as performance 
> enhancements. Avoid API breakages due to changes such as reorganizing 
> public structure fields for aesthetic or readability purposes."

It isn't imperative, but since it does not break neither the API nor the
ABI: the enums are int and their names didn't change, I thought it would
be a nice clarification.

>> @@ -26,11 +26,11 @@ extern "C" {
>>   /**
>>    * rte_rib_get_nxt() flags
> mode instead of flags
>>    */
>> -enum {
>> -	/** flag to get all subroutes in a RIB tree */
>> +enum rte_rib_nxt_mode {
> rte_rib_get_nxt_mode?

Ack

>> @@ -25,13 +25,13 @@ extern "C" {
>>   #define RTE_RIB6_IPV6_ADDR_SIZE (RTE_DEPRECATED(RTE_RIB6_IPV6_ADDR_SIZE) RTE_IPV6_ADDR_SIZE)
>>   
>>   /**
>> - * rte_rib6_get_nxt() flags
>> + * rte_rib6_get_nxt() mode
>>    */
>> -enum {
>> -	/** flag to get all subroutes in a RIB tree */
>> +enum rte_rib6_nxt_mode {
> rte_rib6_get_nxt_mode?

Ack.

-- 
Robin

# Membership dues are not refundable.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route
  2026-05-18  9:59 [PATCH dpdk 0/2] rib: allow iteration to include the top-level route Robin Jarry
  2026-05-18  9:59 ` [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode Robin Jarry
  2026-05-18  9:59 ` [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal Robin Jarry
@ 2026-10-02 10:15 ` Robin Jarry
  2026-10-02 10:15   ` [PATCH dpdk v2 1/2] rib: rename nxt flag parameter to mode Robin Jarry
  2026-10-02 10:15   ` [PATCH dpdk v2 2/2] rib: add mode to include top-level route in traversal Robin Jarry
  2 siblings, 2 replies; 10+ messages in thread
From: Robin Jarry @ 2026-10-02 10:15 UTC (permalink / raw)
  To: dev

rte_rib_get_nxt() and rte_rib6_get_nxt() use an untyped int parameter
and anonymous enums for the traversal mode. The first patch gives these
enums proper type names (rte_rib_nxt_mode, rte_rib6_nxt_mode) and
renames the parameter from "flag" to "mode".

The existing traversal modes (ALL and COVER) always skip the exact match
top-level route. The second patch adds a RTE_RIB_GET_NXT_ALL_TOP mode
(and its IPv6 counterpart) so that callers who need the full subtree
including the root can get it without a separate rte_rib_lookup_exact()
call.

v2:

* fixed rib6 unit test (0 -> &unspec)
* added release notes entry
* changed enum names (rte_rib*_nxt_mode -> rte_rib*_get_nxt_mode)
* minor style nits

Robin Jarry (2):
  rib: rename nxt flag parameter to mode
  rib: add mode to include top-level route in traversal

 app/test/test_rib.c                    | 16 ++++++++++++++++
 app/test/test_rib6.c                   | 16 ++++++++++++++++
 doc/guides/rel_notes/release_26_11.rst |  6 ++++++
 lib/rib/rte_rib.c                      | 20 ++++++++++++++------
 lib/rib/rte_rib.h                      | 19 ++++++++++++-------
 lib/rib/rte_rib6.c                     | 20 ++++++++++++++------
 lib/rib/rte_rib6.h                     | 20 +++++++++++++-------
 7 files changed, 91 insertions(+), 26 deletions(-)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH dpdk v2 1/2] rib: rename nxt flag parameter to mode
  2026-10-02 10:15 ` [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route Robin Jarry
@ 2026-10-02 10:15   ` Robin Jarry
  2026-10-02 10:15   ` [PATCH dpdk v2 2/2] rib: add mode to include top-level route in traversal Robin Jarry
  1 sibling, 0 replies; 10+ messages in thread
From: Robin Jarry @ 2026-10-02 10:15 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin

The flag parameter in rte_rib_get_nxt() and rte_rib6_get_nxt() is a
plain int used as a typed enumeration. Give the anonymous enums proper
names (rte_rib_nxt_mode, rte_rib6_nxt_mode) and rename the parameter
from "flag" to "mode" to reflect its purpose.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 lib/rib/rte_rib.c  |  4 ++--
 lib/rib/rte_rib.h  | 14 +++++++-------
 lib/rib/rte_rib6.c |  4 ++--
 lib/rib/rte_rib6.h | 14 +++++++-------
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
index 046db131ca00..c1dcb054d4e5 100644
--- a/lib/rib/rte_rib.c
+++ b/lib/rib/rte_rib.c
@@ -175,7 +175,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
 RTE_EXPORT_SYMBOL(rte_rib_get_nxt)
 struct rte_rib_node *
 rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
-	uint8_t depth, struct rte_rib_node *last, int flag)
+	uint8_t depth, struct rte_rib_node *last, enum rte_rib_get_nxt_mode mode)
 {
 	struct rte_rib_node *tmp, *prev = NULL;
 
@@ -205,7 +205,7 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
 				(is_covered(tmp->ip, ip, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
-			if (flag == RTE_RIB_GET_NXT_COVER)
+			if (mode == RTE_RIB_GET_NXT_COVER)
 				return prev;
 		}
 		tmp = (tmp->left) ? tmp->left : tmp->right;
diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
index c325b3e3618c..bba9ad98823f 100644
--- a/lib/rib/rte_rib.h
+++ b/lib/rib/rte_rib.h
@@ -24,13 +24,13 @@ extern "C" {
 #endif
 
 /**
- * rte_rib_get_nxt() flags
+ * rte_rib_get_nxt() mode
  */
-enum {
-	/** flag to get all subroutes in a RIB tree */
+enum rte_rib_get_nxt_mode {
+	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB_GET_NXT_ALL,
-	/** flag to get first matched subroutes in a RIB tree */
-	RTE_RIB_GET_NXT_COVER
+	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
+	RTE_RIB_GET_NXT_COVER,
 };
 
 struct rte_rib;
@@ -120,7 +120,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  *   pointer to the last returned prefix to get next prefix
  *   or
  *   NULL to get first more specific prefix
- * @param flag
+ * @param mode
  *  -RTE_RIB_GET_NXT_ALL
  *   get all prefixes from subtrie
  *  -RTE_RIB_GET_NXT_COVER
@@ -131,7 +131,7 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  */
 struct rte_rib_node *
 rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip, uint8_t depth,
-	struct rte_rib_node *last, int flag);
+	struct rte_rib_node *last, enum rte_rib_get_nxt_mode mode);
 
 /**
  * Remove prefix from the RIB
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index 918ddbdfd30c..41561c4291e3 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -196,7 +196,7 @@ RTE_EXPORT_SYMBOL(rte_rib6_get_nxt)
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
 	const struct rte_ipv6_addr *ip,
-	uint8_t depth, struct rte_rib6_node *last, int flag)
+	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_get_nxt_mode mode)
 {
 	struct rte_rib6_node *tmp, *prev = NULL;
 	struct rte_ipv6_addr tmp_ip;
@@ -230,7 +230,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
-			if (flag == RTE_RIB6_GET_NXT_COVER)
+			if (mode == RTE_RIB6_GET_NXT_COVER)
 				return prev;
 		}
 		tmp = (tmp->left != NULL) ? tmp->left : tmp->right;
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index e3fb464ae68e..1a013e8fb4aa 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -22,13 +22,13 @@ extern "C" {
 #endif
 
 /**
- * rte_rib6_get_nxt() flags
+ * rte_rib6_get_nxt() mode
  */
-enum {
-	/** flag to get all subroutes in a RIB tree */
+enum rte_rib6_get_nxt_mode {
+	/** get all subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB6_GET_NXT_ALL,
-	/** flag to get first matched subroutes in a RIB tree */
-	RTE_RIB6_GET_NXT_COVER
+	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
+	RTE_RIB6_GET_NXT_COVER,
 };
 
 struct rte_rib6;
@@ -105,7 +105,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  *   pointer to the last returned prefix to get next prefix
  *   or
  *   NULL to get first more specific prefix
- * @param flag
+ * @param mode
  *  -RTE_RIB6_GET_NXT_ALL
  *   get all prefixes from subtrie
  *  -RTE_RIB6_GET_NXT_COVER
@@ -117,7 +117,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
 	const struct rte_ipv6_addr *ip,
-	uint8_t depth, struct rte_rib6_node *last, int flag);
+	uint8_t depth, struct rte_rib6_node *last, enum rte_rib6_get_nxt_mode mode);
 
 /**
  * Remove prefix from the RIB
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH dpdk v2 2/2] rib: add mode to include top-level route in traversal
  2026-10-02 10:15 ` [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route Robin Jarry
  2026-10-02 10:15   ` [PATCH dpdk v2 1/2] rib: rename nxt flag parameter to mode Robin Jarry
@ 2026-10-02 10:15   ` Robin Jarry
  1 sibling, 0 replies; 10+ messages in thread
From: Robin Jarry @ 2026-10-02 10:15 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin

rte_rib_get_nxt() and rte_rib6_get_nxt() skip the exact match
top-level route when iterating subroutes. This is the expected behavior
in most cases but some users need the full subtree including the root.

Add a RTE_RIB_GET_NXT_ALL_TOP (and RTE_RIB6_GET_NXT_ALL_TOP) mode
that uses >= instead of > when comparing depths so that the top-level
route is returned as well.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_rib.c                    | 16 ++++++++++++++++
 app/test/test_rib6.c                   | 16 ++++++++++++++++
 doc/guides/rel_notes/release_26_11.rst |  6 ++++++
 lib/rib/rte_rib.c                      | 16 ++++++++++++----
 lib/rib/rte_rib.h                      |  5 +++++
 lib/rib/rte_rib6.c                     | 16 ++++++++++++----
 lib/rib/rte_rib6.h                     |  6 ++++++
 7 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/app/test/test_rib.c b/app/test/test_rib.c
index a4a683140df3..f56490e67ec0 100644
--- a/app/test/test_rib.c
+++ b/app/test/test_rib.c
@@ -300,6 +300,7 @@ test_tree_traversal(void)
 	uint32_t ip1 = RTE_IPV4(10, 10, 10, 0);
 	uint32_t ip2 = RTE_IPV4(10, 10, 130, 80);
 	uint8_t depth = 30;
+	unsigned int num;
 
 	config.max_nodes = MAX_RULES;
 	config.ext_sz = 0;
@@ -313,11 +314,26 @@ test_tree_traversal(void)
 	node = rte_rib_insert(rib, ip2, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 
+	node = rte_rib_insert(rib, 0, 0);
+	RTE_TEST_ASSERT(node != NULL, "Failed to insert default rule\n");
+
 	node = NULL;
 	node = rte_rib_get_nxt(rib, RTE_IPV4(10, 10, 130, 0), 24, node,
 			RTE_RIB_GET_NXT_ALL);
 	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
+
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib_get_nxt(rib, 0, 0, node, RTE_RIB_GET_NXT_ALL_TOP)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib_get_nxt\n");
+
 	rte_rib_free(rib);
 
 	return TEST_SUCCESS;
diff --git a/app/test/test_rib6.c b/app/test/test_rib6.c
index 0295a9640cfa..e97d2f49df1d 100644
--- a/app/test/test_rib6.c
+++ b/app/test/test_rib6.c
@@ -300,7 +300,9 @@ test_tree_traversal(void)
 	struct rte_ipv6_addr ip = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0);
 	struct rte_ipv6_addr ip1 = RTE_IPV6(0x0a00, 0x0200, 0, 0, 0, 0, 0, 0);
 	struct rte_ipv6_addr ip2 = RTE_IPV6(0x0a00, 0x0282, 0, 0, 0, 0, 0, 0x0050);
+	struct rte_ipv6_addr unspec = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0);
 	uint8_t depth = 126;
+	unsigned int num;
 
 	config.max_nodes = MAX_RULES;
 	config.ext_sz = 0;
@@ -312,11 +314,25 @@ test_tree_traversal(void)
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 	node = rte_rib6_insert(rib, &ip2, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+	node = rte_rib6_insert(rib, &unspec, 0);
+	RTE_TEST_ASSERT(node != NULL, "Failed to insert default route\n");
 
 	node = NULL;
 	node = rte_rib6_get_nxt(rib, &ip, 32, node, RTE_RIB6_GET_NXT_ALL);
 	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib6_get_nxt(rib, &unspec, 0, node, RTE_RIB6_GET_NXT_ALL)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 2, "Invalid number of routes\n");
+
+	num = 0;
+	node = NULL;
+	while ((node = rte_rib6_get_nxt(rib, &unspec, 0, node, RTE_RIB6_GET_NXT_ALL_TOP)) != NULL)
+		num++;
+	RTE_TEST_ASSERT(num == 3, "Default route not returned by rte_rib6_get_nxt\n");
+
 	rte_rib6_free(rib);
 
 	return TEST_SUCCESS;
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 030bd84cea04..5976db81157c 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -138,6 +138,12 @@ New Features
   Added ``rte_bbdev_queue_stats_get()`` function to retrieve statistics
   for a specific queue, complementing the existing device-level statistics API.
 
+* **Added a new mode for RIB and RIB6 traversal.**
+
+  ``rte_rib{,6}_get_nxt()`` now accept a new mode of traversal: ``RTE_RIB{,6}_GET_NXT_ALL_TOP``
+  which behaves like ``RTE_RIB{,6}_GET_NXT_ALL`` but also returns the top-level exact-match
+  route, if any.
+
 
 Removed Items
 -------------
diff --git a/lib/rib/rte_rib.c b/lib/rib/rte_rib.c
index c1dcb054d4e5..e15196f01954 100644
--- a/lib/rib/rte_rib.c
+++ b/lib/rib/rte_rib.c
@@ -167,6 +167,14 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth)
 	return __rib_lookup_exact(rib, ip, depth);
 }
 
+static bool
+depth_match(struct rte_rib_node *node, uint8_t depth, enum rte_rib_get_nxt_mode mode)
+{
+	if (mode == RTE_RIB_GET_NXT_ALL_TOP)
+		return node->depth >= depth;
+	return node->depth > depth;
+}
+
 /*
  *  Traverses on subtree and retrieves more specific routes
  *  for a given in args ip/depth prefix
@@ -194,16 +202,16 @@ rte_rib_get_nxt(struct rte_rib *rib, uint32_t ip,
 				(tmp->parent->right == NULL))) {
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
-					(is_covered(tmp->ip, ip, depth) &&
-					(tmp->depth > depth)))
+					is_covered(tmp->ip, ip, depth) &&
+					depth_match(tmp, depth, mode))
 				return tmp;
 		}
 		tmp = (tmp->parent) ? tmp->parent->right : NULL;
 	}
 	while (tmp) {
 		if (is_valid_node(tmp) &&
-				(is_covered(tmp->ip, ip, depth) &&
-				(tmp->depth > depth))) {
+				is_covered(tmp->ip, ip, depth) &&
+				depth_match(tmp, depth, mode)) {
 			prev = tmp;
 			if (mode == RTE_RIB_GET_NXT_COVER)
 				return prev;
diff --git a/lib/rib/rte_rib.h b/lib/rib/rte_rib.h
index bba9ad98823f..e23624ae39a0 100644
--- a/lib/rib/rte_rib.h
+++ b/lib/rib/rte_rib.h
@@ -31,6 +31,8 @@ enum rte_rib_get_nxt_mode {
 	RTE_RIB_GET_NXT_ALL,
 	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB_GET_NXT_COVER,
+	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
+	RTE_RIB_GET_NXT_ALL_TOP,
 };
 
 struct rte_rib;
@@ -125,6 +127,9 @@ rte_rib_lookup_exact(struct rte_rib *rib, uint32_t ip, uint8_t depth);
  *   get all prefixes from subtrie
  *  -RTE_RIB_GET_NXT_COVER
  *   get only first more specific prefix even if it have more specifics
+ *  -RTE_RIB_GET_NXT_ALL_TOP
+ *   get all prefixes from subtrie including the ip/depth prefix itself
+ *   if present. Top prefix is returned last.
  * @return
  *  pointer to the next more specific prefix
  *  NULL if there is no prefixes left
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index 41561c4291e3..8384bc58cd63 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -187,6 +187,14 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 	return NULL;
 }
 
+static bool
+depth_match(struct rte_rib6_node *node, uint8_t depth, enum rte_rib6_get_nxt_mode mode)
+{
+	if (mode == RTE_RIB6_GET_NXT_ALL_TOP)
+		return node->depth >= depth;
+	return node->depth > depth;
+}
+
 /*
  *  Traverses on subtree and retrieves more specific routes
  *  for a given in args ip/depth prefix
@@ -219,16 +227,16 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 				(tmp->parent->right == NULL))) {
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
-					(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
-					(tmp->depth > depth)))
+					rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
+					depth_match(tmp, depth, mode))
 				return tmp;
 		}
 		tmp = (tmp->parent != NULL) ? tmp->parent->right : NULL;
 	}
 	while (tmp) {
 		if (is_valid_node(tmp) &&
-				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
-				(tmp->depth > depth))) {
+				rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
+				depth_match(tmp, depth, mode)) {
 			prev = tmp;
 			if (mode == RTE_RIB6_GET_NXT_COVER)
 				return prev;
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index 1a013e8fb4aa..a0a3ae98dc47 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -29,6 +29,8 @@ enum rte_rib6_get_nxt_mode {
 	RTE_RIB6_GET_NXT_ALL,
 	/** get first matched subroutes in a RIB tree, excluding any exact match top-level route */
 	RTE_RIB6_GET_NXT_COVER,
+	/** get all subroutes in a RIB tree, including the exact match top-level route, if any */
+	RTE_RIB6_GET_NXT_ALL_TOP,
 };
 
 struct rte_rib6;
@@ -110,6 +112,10 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  *   get all prefixes from subtrie
  *  -RTE_RIB6_GET_NXT_COVER
  *   get only first more specific prefix even if it have more specifics
+ *  -RTE_RIB6_GET_NXT_ALL_TOP
+ *   get all prefixes from the subtrie, including the ip/depth prefix itself
+ *   if present. Top prefix is returned last.
+ *
  * @return
  *  pointer to the next more specific prefix
  *  NULL if there is no prefixes left
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-10-02 10:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18  9:59 [PATCH dpdk 0/2] rib: allow iteration to include the top-level route Robin Jarry
2026-05-18  9:59 ` [PATCH dpdk 1/2] rib: rename nxt flag parameter to mode Robin Jarry
2026-09-30 17:12   ` Medvedkin, Vladimir
2026-10-02  9:52     ` Robin Jarry
2026-05-18  9:59 ` [PATCH dpdk 2/2] rib: add mode to include top-level route in traversal Robin Jarry
2026-09-30 17:12   ` Medvedkin, Vladimir
2026-10-02  9:50     ` Robin Jarry
2026-10-02 10:15 ` [PATCH dpdk v2 0/2] rib: allow iteration to include the top-level route Robin Jarry
2026-10-02 10:15   ` [PATCH dpdk v2 1/2] rib: rename nxt flag parameter to mode Robin Jarry
2026-10-02 10:15   ` [PATCH dpdk v2 2/2] rib: add mode to include top-level route in traversal Robin Jarry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.