DPDK-dev Archive on 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox