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