* [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