* [PATCH v1 00/12] add lookup fib nodes in graph library @ 2025-04-15 12:10 Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 01/12] fib: move macro to header file Ankur Dwivedi ` (12 more replies) 0 siblings, 13 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi This patch series adds two inbuilt nodes ip4_lookup_fib and ip6_lookup_fib in graph library. These nodes uses the existing Forwarding Information Base (FIB) library to create FIB, to do route addition and route lookup. Two new commands (for ipv4 and ipv6) for providing the lookup mode is added in the dpdk-graph application. fib or lpm can be given as lookup mode. If these new lookup mode commands are not given, the dpdk-graph uses lpm (Longest Prefix Match) or lpm6 by default. If fib is given as lookup mode then the ip4_lookup_fib or ip6_lookup_fib nodes are used by the application. Ankur Dwivedi (12): fib: move macro to header file node: add IP4 lookup FIB node node: add IP4 FIB route add node: add process callback for IP4 FIB node: add next node in packet classification app/graph: add IP4 lookup mode command fib: move macro to header file node: add IP6 lookup FIB node node: add IP6 FIB route add node: add process callback for IP6 FIB node: add next node in packet classification app/graph: add IP6 lookup mode command app/graph/commands.list | 2 + app/graph/ip4_route.c | 34 +++- app/graph/ip6_route.c | 33 +++- app/graph/l3fwd.c | 24 +++ app/graph/module_api.h | 13 ++ doc/guides/tools/graph.rst | 24 ++- lib/fib/rte_fib.c | 3 - lib/fib/rte_fib.h | 3 + lib/fib/rte_fib6.c | 11 +- lib/fib/rte_fib6.h | 3 + lib/node/ip4_lookup_fib.c | 327 ++++++++++++++++++++++++++++++++++++ lib/node/ip6_lookup_fib.c | 316 ++++++++++++++++++++++++++++++++++ lib/node/meson.build | 4 +- lib/node/pkt_cls.c | 2 + lib/node/pkt_cls_priv.h | 2 + lib/node/rte_node_ip4_api.h | 19 +++ lib/node/rte_node_ip6_api.h | 19 +++ 17 files changed, 812 insertions(+), 27 deletions(-) create mode 100644 lib/node/ip4_lookup_fib.c create mode 100644 lib/node/ip6_lookup_fib.c -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 01/12] fib: move macro to header file 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 02/12] node: add IP4 lookup FIB node Ankur Dwivedi ` (11 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Moves RTE_FIB_NAMESIZE to header file, in order to use it outside the fib library. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/fib/rte_fib.c | 3 --- lib/fib/rte_fib.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fib/rte_fib.c b/lib/fib/rte_fib.c index 2c05d46500..184210f380 100644 --- a/lib/fib/rte_fib.c +++ b/lib/fib/rte_fib.c @@ -28,9 +28,6 @@ static struct rte_tailq_elem rte_fib_tailq = { }; EAL_REGISTER_TAILQ(rte_fib_tailq) -/* Maximum length of a FIB name. */ -#define RTE_FIB_NAMESIZE 64 - #if defined(RTE_LIBRTE_FIB_DEBUG) #define FIB_RETURN_IF_TRUE(cond, retval) do { \ if (cond) \ diff --git a/lib/fib/rte_fib.h b/lib/fib/rte_fib.h index 53f04b8049..874bf1688b 100644 --- a/lib/fib/rte_fib.h +++ b/lib/fib/rte_fib.h @@ -27,6 +27,9 @@ extern "C" { struct rte_fib; struct rte_rib; +/* Maximum length of a FIB name. */ +#define RTE_FIB_NAMESIZE 64 + /** Maximum depth value possible for IPv4 FIB. */ #define RTE_FIB_MAXDEPTH 32 -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 02/12] node: add IP4 lookup FIB node 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 01/12] fib: move macro to header file Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-16 7:32 ` Nitin Saxena 2025-04-16 9:34 ` Medvedkin, Vladimir 2025-04-15 12:10 ` [PATCH v1 03/12] node: add IP4 FIB route add Ankur Dwivedi ` (10 subsequent siblings) 12 siblings, 2 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a lookup FIB node for IP4. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 127 ++++++++++++++++++++++++++++++++++++++ lib/node/meson.build | 3 +- 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_lookup_fib.c diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c new file mode 100644 index 0000000000..9c71610718 --- /dev/null +++ b/lib/node/ip4_lookup_fib.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2025 Marvell. + */ + +#include <rte_errno.h> +#include <rte_ether.h> +#include <rte_fib.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> + +#include "rte_node_ip4_api.h" + +#include "node_private.h" + +/* IP4 Lookup global data struct */ +struct ip4_lookup_fib_node_main { + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; +}; + +struct ip4_lookup_fib_node_ctx { + /* Socket's FIB */ + struct rte_fib *fib; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; + +#define FIB_MAX_ROUTES (1 << 16) +#define FIB_NUM_TBL8 (1 << 15) +#define FIB_DEFAULT_NH 999 + +#define IP4_LOOKUP_NODE_FIB(ctx) \ + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) + +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) + +static int +setup_fib(unsigned int socket) +{ + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; + struct rte_fib_conf conf; + char s[RTE_FIB_NAMESIZE]; + + /* One fib per socket */ + if (nm->fib[socket]) + return 0; + + conf.type = RTE_FIB_DIR24_8; + conf.default_nh = FIB_DEFAULT_NH; + conf.max_routes = FIB_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; + conf.flags = 0; + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); + nm->fib[socket] = rte_fib_create(s, socket, &conf); + if (nm->fib[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + static uint8_t init_once; + unsigned int socket; + uint16_t lcore_id; + int rc; + + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + /* Setup FIB for all sockets */ + RTE_LCORE_FOREACH(lcore_id) + { + socket = rte_lcore_to_socket_id(lcore_id); + rc = setup_fib(socket); + if (rc) { + node_err("ip4_lookup_fib", + "Failed to setup fib for sock %u, rc=%d", + socket, rc); + return rc; + } + } + init_once = 1; + } + + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph->socket]; + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); + + return 0; +} + +static struct rte_node_xstats ip4_lookup_fib_xstats = { + .nb_xstats = 1, + .xstat_desc = { + [0] = "ip4_lookup_fib_error", + }, +}; + +static struct rte_node_register ip4_lookup_fib_node = { + .name = "ip4_lookup_fib", + + .init = ip4_lookup_fib_node_init, + .xstats = &ip4_lookup_fib_xstats, + + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip4_lookup_fib_node); diff --git a/lib/node/meson.build b/lib/node/meson.build index 0bed97a96c..d2011c8f56 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -13,6 +13,7 @@ sources = files( 'ethdev_tx.c', 'ip4_local.c', 'ip4_lookup.c', + 'ip4_lookup_fib.c', 'ip4_reassembly.c', 'ip4_rewrite.c', 'ip6_lookup.c', @@ -34,4 +35,4 @@ headers = files( # Strict-aliasing rules are violated by uint8_t[] to context size casts. cflags += '-fno-strict-aliasing' -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag', 'fib'] -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v1 02/12] node: add IP4 lookup FIB node 2025-04-15 12:10 ` [PATCH v1 02/12] node: add IP4 lookup FIB node Ankur Dwivedi @ 2025-04-16 7:32 ` Nitin Saxena 2025-04-16 10:26 ` [EXTERNAL] " Ankur Dwivedi 2025-04-16 9:34 ` Medvedkin, Vladimir 1 sibling, 1 reply; 36+ messages in thread From: Nitin Saxena @ 2025-04-16 7:32 UTC (permalink / raw) To: Ankur Dwivedi Cc: dev, jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla Hi Ankur, Please see my comments inline below Thanks, Nitin On Tue, Apr 15, 2025 at 5:41 PM Ankur Dwivedi <adwivedi@marvell.com> wrote: > > Adds a lookup FIB node for IP4. > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > --- > lib/node/ip4_lookup_fib.c | 127 ++++++++++++++++++++++++++++++++++++++ > lib/node/meson.build | 3 +- > 2 files changed, 129 insertions(+), 1 deletion(-) > create mode 100644 lib/node/ip4_lookup_fib.c > > diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > new file mode 100644 > index 0000000000..9c71610718 > --- /dev/null > +++ b/lib/node/ip4_lookup_fib.c > @@ -0,0 +1,127 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2025 Marvell. > + */ > + > +#include <rte_errno.h> > +#include <rte_ether.h> > +#include <rte_fib.h> > +#include <rte_graph.h> > +#include <rte_graph_worker.h> > +#include <rte_ip.h> > + > +#include "rte_node_ip4_api.h" > + > +#include "node_private.h" > + > +/* IP4 Lookup global data struct */ > +struct ip4_lookup_fib_node_main { > + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; > +}; > + > +struct ip4_lookup_fib_node_ctx { > + /* Socket's FIB */ > + struct rte_fib *fib; > + /* Dynamic offset to mbuf priv1 */ > + int mbuf_priv1_off; > +}; > + > +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; > + > +#define FIB_MAX_ROUTES (1 << 16) > +#define FIB_NUM_TBL8 (1 << 15) > +#define FIB_DEFAULT_NH 999 These macros may not be required if we expose public setup_api() with arguments. See below > + > +#define IP4_LOOKUP_NODE_FIB(ctx) \ > + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) > + > +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > + > +static int > +setup_fib(unsigned int socket) Should we add public API to allow applications to control MAX_ROUTES? In a typical stack multiple fibs can be set up for each VRF (~~ port_id). A public API: int rte_ip4_lookup_fib_setup(int fib_index, int port_id, uint32_t max_routes) where For now we can assume fib_index == 0, is global fib table (can be extended to VRF later). Socket_id can be determined from port_Id > +{ > + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; > + struct rte_fib_conf conf; > + char s[RTE_FIB_NAMESIZE]; > + > + /* One fib per socket */ > + if (nm->fib[socket]) > + return 0; > + > + conf.type = RTE_FIB_DIR24_8; > + conf.default_nh = FIB_DEFAULT_NH; FIB_DEFAULT_NH can be defined in such a way, fast path can decode next_edge from return of rte_fib_lookup_bulk() Like union { struct u64; struct { uint32_t next_hop_id; uint16_t next_edge; uint16_t. reserved; }; } rte_ip4_lookup_fib_nexthop_t; FIB_DEFAULT_NH should be set as rte_ip4_lookup_fib_nexthop_t default_next_hop = {.next_edge = IP4_FIB_LOOKUP_NEXT_DROP} This way in fast path a return from fib_bulk() can be directly used to send packet to pkt_drop node > + conf.max_routes = FIB_MAX_ROUTES; > + conf.rib_ext_sz = 0; > + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; > + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; > + conf.flags = 0; > + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); > + nm->fib[socket] = rte_fib_create(s, socket, &conf); > + if (nm->fib[socket] == NULL) > + return -rte_errno; > + > + return 0; > +} > + > +static int > +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) > +{ > + static uint8_t init_once; > + unsigned int socket; > + uint16_t lcore_id; > + int rc; > + > + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); > + > + if (!init_once) { > + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( > + &node_mbuf_priv1_dynfield_desc); > + if (node_mbuf_priv1_dynfield_offset < 0) > + return -rte_errno; You may need to rebase this patch on top of https://patches.dpdk.org/project/dpdk/patch/20250409135554.2180390-2-nsaxena@marvell.com/ for using global mbuf field > + > + /* Setup FIB for all sockets */ > + RTE_LCORE_FOREACH(lcore_id) Instead can be use rte_socket_count() which allow to loop for socket instead of port? Ideally we may need to add fib for virtual interfaces or VRF (later) > + { > + socket = rte_lcore_to_socket_id(lcore_id); > + rc = setup_fib(socket); > + if (rc) { > + node_err("ip4_lookup_fib", > + "Failed to setup fib for sock %u, rc=%d", > + socket, rc); > + return rc; > + } > + } > + init_once = 1; > + } > + > + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ > + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph->socket]; > + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; > + > + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); > + > + return 0; > +} > + > +static struct rte_node_xstats ip4_lookup_fib_xstats = { > + .nb_xstats = 1, > + .xstat_desc = { > + [0] = "ip4_lookup_fib_error", > + }, > +}; > + > +static struct rte_node_register ip4_lookup_fib_node = { > + .name = "ip4_lookup_fib", > + > + .init = ip4_lookup_fib_node_init, > + .xstats = &ip4_lookup_fib_xstats, > + > + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, > + .next_nodes = { > + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", > + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", > + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", > + }, > +}; > + > +RTE_NODE_REGISTER(ip4_lookup_fib_node); > diff --git a/lib/node/meson.build b/lib/node/meson.build > index 0bed97a96c..d2011c8f56 100644 > --- a/lib/node/meson.build > +++ b/lib/node/meson.build > @@ -13,6 +13,7 @@ sources = files( > 'ethdev_tx.c', > 'ip4_local.c', > 'ip4_lookup.c', > + 'ip4_lookup_fib.c', > 'ip4_reassembly.c', > 'ip4_rewrite.c', > 'ip6_lookup.c', > @@ -34,4 +35,4 @@ headers = files( > > # Strict-aliasing rules are violated by uint8_t[] to context size casts. > cflags += '-fno-strict-aliasing' > -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] > +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag', 'fib'] > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v1 02/12] node: add IP4 lookup FIB node 2025-04-16 7:32 ` Nitin Saxena @ 2025-04-16 10:26 ` Ankur Dwivedi 0 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-16 10:26 UTC (permalink / raw) To: Nitin Saxena Cc: dev, Jerin Jacob, vladimir.medvedkin, Nithin Kumar Dabilpuram, Pavan Nikhilesh Bhagavatula, Sunil Kumar Kori, Rakesh Kudurumalla Hi Nitin, >> lib/node/ip4_lookup_fib.c | 127 >++++++++++++++++++++++++++++++++++++++ >> lib/node/meson.build | 3 +- >> 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 >> lib/node/ip4_lookup_fib.c >> >> diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c new >> file mode 100644 index 0000000000..9c71610718 >> --- /dev/null >> +++ b/lib/node/ip4_lookup_fib.c >> @@ -0,0 +1,127 @@ >> +/* SPDX-License-Identifier: BSD-3-Clause >> + * Copyright(C) 2025 Marvell. >> + */ >> + >> +#include <rte_errno.h> >> +#include <rte_ether.h> >> +#include <rte_fib.h> >> +#include <rte_graph.h> >> +#include <rte_graph_worker.h> >> +#include <rte_ip.h> >> + >> +#include "rte_node_ip4_api.h" >> + >> +#include "node_private.h" >> + >> +/* IP4 Lookup global data struct */ >> +struct ip4_lookup_fib_node_main { >> + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; }; >> + >> +struct ip4_lookup_fib_node_ctx { >> + /* Socket's FIB */ >> + struct rte_fib *fib; >> + /* Dynamic offset to mbuf priv1 */ >> + int mbuf_priv1_off; >> +}; >> + >> +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; >> + >> +#define FIB_MAX_ROUTES (1 << 16) >> +#define FIB_NUM_TBL8 (1 << 15) >> +#define FIB_DEFAULT_NH 999 > >These macros may not be required if we expose public setup_api() with >arguments. See below > >> + >> +#define IP4_LOOKUP_NODE_FIB(ctx) \ >> + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) >> + >> +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ >> + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) >> + >> +static int >> +setup_fib(unsigned int socket) > >Should we add public API to allow applications to control MAX_ROUTES? >In a typical stack multiple fibs can be set up for each VRF (~~ port_id). > >A public API: > >int rte_ip4_lookup_fib_setup(int fib_index, int port_id, uint32_t >max_routes) where If a public API is used, then apart from max_routes other config values can also come from application. > >For now we can assume fib_index == 0, is global fib table (can be extended to >VRF later). Socket_id can be determined from port_Id > >> +{ >> + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; >> + struct rte_fib_conf conf; >> + char s[RTE_FIB_NAMESIZE]; >> + >> + /* One fib per socket */ >> + if (nm->fib[socket]) >> + return 0; >> + >> + conf.type = RTE_FIB_DIR24_8; >> + conf.default_nh = FIB_DEFAULT_NH; > >FIB_DEFAULT_NH can be defined in such a way, fast path can decode next_edge >from return of rte_fib_lookup_bulk() Like union { > struct u64; > struct { > uint32_t next_hop_id; > uint16_t next_edge; > uint16_t. reserved; > }; >} rte_ip4_lookup_fib_nexthop_t; > >FIB_DEFAULT_NH should be set as > >rte_ip4_lookup_fib_nexthop_t default_next_hop = {.next_edge = >IP4_FIB_LOOKUP_NEXT_DROP} > >This way in fast path a return from fib_bulk() can be directly used to send >packet to pkt_drop node > >> + conf.max_routes = FIB_MAX_ROUTES; >> + conf.rib_ext_sz = 0; >> + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; >> + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; >> + conf.flags = 0; >> + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); >> + nm->fib[socket] = rte_fib_create(s, socket, &conf); >> + if (nm->fib[socket] == NULL) >> + return -rte_errno; >> + >> + return 0; >> +} >> + >> +static int >> +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct >> +rte_node *node) { >> + static uint8_t init_once; >> + unsigned int socket; >> + uint16_t lcore_id; >> + int rc; >> + >> + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > >> + RTE_NODE_CTX_SZ); >> + >> + if (!init_once) { >> + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( >> + &node_mbuf_priv1_dynfield_desc); >> + if (node_mbuf_priv1_dynfield_offset < 0) >> + return -rte_errno; > >You may need to rebase this patch on top of >https://urldefense.proofpoint.com/v2/url?u=https- >3A__patches.dpdk.org_project_dpdk_patch_20250409135554.2180390- >2D2-2Dnsaxena- >40marvell.com_&d=DwIFaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=ILjiNF3GF25y6 >QdHZUxMl6JrStU0MIuCtO5dMzn3Ybk&m=1hUHMoAkw- >1lUlg8qgybA7IfcnVOlVLxtms8KdhzsGpHV4vAjS2o5n7g-rJ- >0xLu&s=OAkNegP6hCJA0d3swI7FZ34IzVXE8DN5QHkNj15_S38&e= >for using global mbuf field Ok. > >> + >> + /* Setup FIB for all sockets */ >> + RTE_LCORE_FOREACH(lcore_id) > >Instead can be use rte_socket_count() which allow to loop for socket instead of >port? Ideally we may need to add fib for virtual interfaces or VRF (later) Ok. > >> + { >> + socket = rte_lcore_to_socket_id(lcore_id); >> + rc = setup_fib(socket); >> + if (rc) { >> + node_err("ip4_lookup_fib", >> + "Failed to setup fib for sock %u, rc=%d", >> + socket, rc); >> + return rc; >> + } >> + } >> + init_once = 1; >> + } >> + >> + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ >> + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph- >>socket]; >> + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = >> + node_mbuf_priv1_dynfield_offset; >> + >> + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); >> + >> + return 0; >> +} >> + >> +static struct rte_node_xstats ip4_lookup_fib_xstats = { >> + .nb_xstats = 1, >> + .xstat_desc = { >> + [0] = "ip4_lookup_fib_error", >> + }, >> +}; >> + >> +static struct rte_node_register ip4_lookup_fib_node = { >> + .name = "ip4_lookup_fib", >> + >> + .init = ip4_lookup_fib_node_init, >> + .xstats = &ip4_lookup_fib_xstats, >> + >> + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, >> + .next_nodes = { >> + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", >> + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", >> + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", >> + }, >> +}; >> + >> +RTE_NODE_REGISTER(ip4_lookup_fib_node); >> diff --git a/lib/node/meson.build b/lib/node/meson.build index >> 0bed97a96c..d2011c8f56 100644 >> --- a/lib/node/meson.build >> +++ b/lib/node/meson.build >> @@ -13,6 +13,7 @@ sources = files( >> 'ethdev_tx.c', >> 'ip4_local.c', >> 'ip4_lookup.c', >> + 'ip4_lookup_fib.c', >> 'ip4_reassembly.c', >> 'ip4_rewrite.c', >> 'ip6_lookup.c', >> @@ -34,4 +35,4 @@ headers = files( >> >> # Strict-aliasing rules are violated by uint8_t[] to context size casts. >> cflags += '-fno-strict-aliasing' >> -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', >> 'ip_frag'] >> +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', >> +'ip_frag', 'fib'] >> -- >> 2.25.1 >> ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v1 02/12] node: add IP4 lookup FIB node 2025-04-15 12:10 ` [PATCH v1 02/12] node: add IP4 lookup FIB node Ankur Dwivedi 2025-04-16 7:32 ` Nitin Saxena @ 2025-04-16 9:34 ` Medvedkin, Vladimir 2025-04-16 10:07 ` [EXTERNAL] " Ankur Dwivedi 1 sibling, 1 reply; 36+ messages in thread From: Medvedkin, Vladimir @ 2025-04-16 9:34 UTC (permalink / raw) To: Ankur Dwivedi, dev; +Cc: jerinj, ndabilpuram, pbhagavatula, skori, rkudurumalla Hi Ankur, On 15/04/2025 13:10, Ankur Dwivedi wrote: > Adds a lookup FIB node for IP4. > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > --- > lib/node/ip4_lookup_fib.c | 127 ++++++++++++++++++++++++++++++++++++++ > lib/node/meson.build | 3 +- > 2 files changed, 129 insertions(+), 1 deletion(-) > create mode 100644 lib/node/ip4_lookup_fib.c > > diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > new file mode 100644 > index 0000000000..9c71610718 > --- /dev/null > +++ b/lib/node/ip4_lookup_fib.c > @@ -0,0 +1,127 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2025 Marvell. > + */ > + > +#include <rte_errno.h> > +#include <rte_ether.h> > +#include <rte_fib.h> > +#include <rte_graph.h> > +#include <rte_graph_worker.h> > +#include <rte_ip.h> > + > +#include "rte_node_ip4_api.h" > + > +#include "node_private.h" > + > +/* IP4 Lookup global data struct */ > +struct ip4_lookup_fib_node_main { > + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; > +}; > + > +struct ip4_lookup_fib_node_ctx { > + /* Socket's FIB */ > + struct rte_fib *fib; > + /* Dynamic offset to mbuf priv1 */ > + int mbuf_priv1_off; > +}; > + > +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; > + > +#define FIB_MAX_ROUTES (1 << 16) why only 64k routes? Modern BGP full view has about 1M prefixes > +#define FIB_NUM_TBL8 (1 << 15) > +#define FIB_DEFAULT_NH 999 why this particular value? It is ok to use magic values in examples, but not for libs. Consider something like 0 or UINT{8,16,32,64}MAX or some meaningful value within graph infra > + > +#define IP4_LOOKUP_NODE_FIB(ctx) \ > + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) > + > +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > + > +static int > +setup_fib(unsigned int socket) > +{ > + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; > + struct rte_fib_conf conf; > + char s[RTE_FIB_NAMESIZE]; > + > + /* One fib per socket */ > + if (nm->fib[socket]) > + return 0; > + > + conf.type = RTE_FIB_DIR24_8; > + conf.default_nh = FIB_DEFAULT_NH; > + conf.max_routes = FIB_MAX_ROUTES; > + conf.rib_ext_sz = 0; > + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; > + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; > + conf.flags = 0; > + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); > + nm->fib[socket] = rte_fib_create(s, socket, &conf); > + if (nm->fib[socket] == NULL) > + return -rte_errno; > + > + return 0; > +} > + > +static int > +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) > +{ > + static uint8_t init_once; > + unsigned int socket; > + uint16_t lcore_id; > + int rc; > + > + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); > + > + if (!init_once) { > + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( > + &node_mbuf_priv1_dynfield_desc); > + if (node_mbuf_priv1_dynfield_offset < 0) > + return -rte_errno; > + > + /* Setup FIB for all sockets */ > + RTE_LCORE_FOREACH(lcore_id) > + { > + socket = rte_lcore_to_socket_id(lcore_id); > + rc = setup_fib(socket); > + if (rc) { > + node_err("ip4_lookup_fib", > + "Failed to setup fib for sock %u, rc=%d", > + socket, rc); > + return rc; > + } > + } > + init_once = 1; > + } > + > + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ > + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph->socket]; > + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; > + > + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); > + > + return 0; > +} > + > +static struct rte_node_xstats ip4_lookup_fib_xstats = { > + .nb_xstats = 1, > + .xstat_desc = { > + [0] = "ip4_lookup_fib_error", > + }, > +}; > + > +static struct rte_node_register ip4_lookup_fib_node = { > + .name = "ip4_lookup_fib", > + > + .init = ip4_lookup_fib_node_init, > + .xstats = &ip4_lookup_fib_xstats, > + > + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, > + .next_nodes = { > + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", > + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", > + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", > + }, > +}; > + > +RTE_NODE_REGISTER(ip4_lookup_fib_node); > diff --git a/lib/node/meson.build b/lib/node/meson.build > index 0bed97a96c..d2011c8f56 100644 > --- a/lib/node/meson.build > +++ b/lib/node/meson.build > @@ -13,6 +13,7 @@ sources = files( > 'ethdev_tx.c', > 'ip4_local.c', > 'ip4_lookup.c', > + 'ip4_lookup_fib.c', > 'ip4_reassembly.c', > 'ip4_rewrite.c', > 'ip6_lookup.c', > @@ -34,4 +35,4 @@ headers = files( > > # Strict-aliasing rules are violated by uint8_t[] to context size casts. > cflags += '-fno-strict-aliasing' > -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] > +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag', 'fib'] -- Regards, Vladimir ^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v1 02/12] node: add IP4 lookup FIB node 2025-04-16 9:34 ` Medvedkin, Vladimir @ 2025-04-16 10:07 ` Ankur Dwivedi 0 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-16 10:07 UTC (permalink / raw) To: Medvedkin, Vladimir, dev Cc: Jerin Jacob, Nithin Kumar Dabilpuram, Pavan Nikhilesh Bhagavatula, Sunil Kumar Kori, Rakesh Kudurumalla Hi Vladimir, >On 15/04/2025 13:10, Ankur Dwivedi wrote: >> Adds a lookup FIB node for IP4. >> >> Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> >> --- >> lib/node/ip4_lookup_fib.c | 127 >++++++++++++++++++++++++++++++++++++++ >> lib/node/meson.build | 3 +- >> 2 files changed, 129 insertions(+), 1 deletion(-) >> create mode 100644 lib/node/ip4_lookup_fib.c >> >> diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c new >> file mode 100644 index 0000000000..9c71610718 >> --- /dev/null >> +++ b/lib/node/ip4_lookup_fib.c >> @@ -0,0 +1,127 @@ >> +/* SPDX-License-Identifier: BSD-3-Clause >> + * Copyright(C) 2025 Marvell. >> + */ >> + >> +#include <rte_errno.h> >> +#include <rte_ether.h> >> +#include <rte_fib.h> >> +#include <rte_graph.h> >> +#include <rte_graph_worker.h> >> +#include <rte_ip.h> >> + >> +#include "rte_node_ip4_api.h" >> + >> +#include "node_private.h" >> + >> +/* IP4 Lookup global data struct */ >> +struct ip4_lookup_fib_node_main { >> + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; }; >> + >> +struct ip4_lookup_fib_node_ctx { >> + /* Socket's FIB */ >> + struct rte_fib *fib; >> + /* Dynamic offset to mbuf priv1 */ >> + int mbuf_priv1_off; >> +}; >> + >> +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; >> + >> +#define FIB_MAX_ROUTES (1 << 16) >why only 64k routes? Modern BGP full view has about 1M prefixes >> +#define FIB_NUM_TBL8 (1 << 15) >> +#define FIB_DEFAULT_NH 999 >why this particular value? It is ok to use magic values in examples, but not for >libs. Consider something like 0 or UINT{8,16,32,64}MAX or some meaningful >value within graph infra UINT{8,16,32,64}MAX should be fine. Also, I am thinking about taking the values in fib conf as input from application. >> + >> +#define IP4_LOOKUP_NODE_FIB(ctx) \ >> + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) >> + >> +#define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ >> + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) >> + >> +static int >> +setup_fib(unsigned int socket) >> +{ >> + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; >> + struct rte_fib_conf conf; >> + char s[RTE_FIB_NAMESIZE]; >> + >> + /* One fib per socket */ >> + if (nm->fib[socket]) >> + return 0; >> + >> + conf.type = RTE_FIB_DIR24_8; >> + conf.default_nh = FIB_DEFAULT_NH; >> + conf.max_routes = FIB_MAX_ROUTES; >> + conf.rib_ext_sz = 0; >> + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; >> + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; >> + conf.flags = 0; >> + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); >> + nm->fib[socket] = rte_fib_create(s, socket, &conf); >> + if (nm->fib[socket] == NULL) >> + return -rte_errno; >> + >> + return 0; >> +} >> + >> +static int >> +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct >> +rte_node *node) { >> + static uint8_t init_once; >> + unsigned int socket; >> + uint16_t lcore_id; >> + int rc; >> + >> + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > >> +RTE_NODE_CTX_SZ); >> + >> + if (!init_once) { >> + node_mbuf_priv1_dynfield_offset = >rte_mbuf_dynfield_register( >> + &node_mbuf_priv1_dynfield_desc); >> + if (node_mbuf_priv1_dynfield_offset < 0) >> + return -rte_errno; >> + >> + /* Setup FIB for all sockets */ >> + RTE_LCORE_FOREACH(lcore_id) >> + { >> + socket = rte_lcore_to_socket_id(lcore_id); >> + rc = setup_fib(socket); >> + if (rc) { >> + node_err("ip4_lookup_fib", >> + "Failed to setup fib for sock %u, >rc=%d", >> + socket, rc); >> + return rc; >> + } >> + } >> + init_once = 1; >> + } >> + >> + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ >> + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph- >>socket]; >> + IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx) = >> +node_mbuf_priv1_dynfield_offset; >> + >> + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); >> + >> + return 0; >> +} >> + >> +static struct rte_node_xstats ip4_lookup_fib_xstats = { >> + .nb_xstats = 1, >> + .xstat_desc = { >> + [0] = "ip4_lookup_fib_error", >> + }, >> +}; >> + >> +static struct rte_node_register ip4_lookup_fib_node = { >> + .name = "ip4_lookup_fib", >> + >> + .init = ip4_lookup_fib_node_init, >> + .xstats = &ip4_lookup_fib_xstats, >> + >> + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, >> + .next_nodes = { >> + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", >> + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", >> + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", >> + }, >> +}; >> + >> +RTE_NODE_REGISTER(ip4_lookup_fib_node); >> diff --git a/lib/node/meson.build b/lib/node/meson.build index >> 0bed97a96c..d2011c8f56 100644 >> --- a/lib/node/meson.build >> +++ b/lib/node/meson.build >> @@ -13,6 +13,7 @@ sources = files( >> 'ethdev_tx.c', >> 'ip4_local.c', >> 'ip4_lookup.c', >> + 'ip4_lookup_fib.c', >> 'ip4_reassembly.c', >> 'ip4_rewrite.c', >> 'ip6_lookup.c', >> @@ -34,4 +35,4 @@ headers = files( >> >> # Strict-aliasing rules are violated by uint8_t[] to context size casts. >> cflags += '-fno-strict-aliasing' >> -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', >> 'ip_frag'] >> +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', >> +'ip_frag', 'fib'] > >-- >Regards, >Vladimir ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 03/12] node: add IP4 FIB route add 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 01/12] fib: move macro to header file Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 02/12] node: add IP4 lookup FIB node Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 04/12] node: add process callback for IP4 FIB Ankur Dwivedi ` (9 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a public function to add IP4 route to FIB. The applications should call this function to add IP4 routes to FIB. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 36 ++++++++++++++++++++++++++++++++++++ lib/node/rte_node_ip4_api.h | 19 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c index 9c71610718..e87864e672 100644 --- a/lib/node/ip4_lookup_fib.c +++ b/lib/node/ip4_lookup_fib.c @@ -2,6 +2,9 @@ * Copyright(C) 2025 Marvell. */ +#include <arpa/inet.h> + +#include <eal_export.h> #include <rte_errno.h> #include <rte_ether.h> #include <rte_fib.h> @@ -37,6 +40,39 @@ static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) +int +rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip4_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + struct in_addr in; + uint8_t socket; + uint32_t val; + int ret; + + in.s_addr = htonl(ip); + inet_ntop(AF_INET, &in, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip4_lookup_fib", "FIB: Adding route %s / %d nh (0x%x)", abuf, depth, val); + + for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { + if (!ip4_lookup_fib_nm.fib[socket]) + continue; + + ret = rte_fib_add(ip4_lookup_fib_nm.fib[socket], ip, depth, val); + if (ret < 0) { + node_err("ip4_lookup_fib", + "Unable to add entry %s / %d nh (%x) to FIB on sock %d, rc=%d", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + static int setup_fib(unsigned int socket) { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 950751a525..93047a0634 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -117,6 +117,25 @@ int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, __rte_experimental int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); +/** + * Add ipv4 route to FIB. + * + * @param ip + * IP address of route to be added. + * @param depth + * Depth of the rule to be added. + * @param next_hop + * Next hop id of the rule result to be added. + * @param next_node + * Next node to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip4_lookup_next next_node); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (2 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 03/12] node: add IP4 FIB route add Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-16 7:54 ` Nitin Saxena 2025-04-16 12:54 ` Medvedkin, Vladimir 2025-04-15 12:10 ` [PATCH v1 05/12] node: add next node in packet classification Ankur Dwivedi ` (8 subsequent siblings) 12 siblings, 2 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds the process callback function for ip4_lookup_fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 164 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c index e87864e672..c535b191f8 100644 --- a/lib/node/ip4_lookup_fib.c +++ b/lib/node/ip4_lookup_fib.c @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +static uint16_t +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); + struct rte_ipv4_hdr *ipv4_hdr; + uint64_t next_hop[nb_objs]; + uint16_t lookup_err = 0; + void **to_next, **from; + uint16_t last_spec = 0; + rte_edge_t next_index; + uint16_t n_left_from; + uint32_t ip[nb_objs]; + uint16_t held = 0; + uint32_t drop_nh; + uint16_t next; + int i, rc; + + /* Speculative next */ + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; + /* Drop node */ + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16; + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE) + rte_prefetch0(&objs[i]); + +#if RTE_GRAPH_BURST_SIZE > 64 + for (i = 0; i < 4 && i < n_left_from; i++) { + rte_prefetch0(pkts[i]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, + sizeof(struct rte_ether_hdr))); + } +#endif + + i = 0; + while (n_left_from >= 4) { +#if RTE_GRAPH_BURST_SIZE > 64 + if (likely(n_left_from > 7)) { + rte_prefetch0(pkts[4]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[5]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[6]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[7]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, + sizeof(struct rte_ether_hdr))); + } +#endif + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + pkts += 4; + n_left_from -= 4; + /* Extract DIP of mbuf0 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf1 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf2 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf3 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + } + while (n_left_from > 0) { + mbuf0 = pkts[0]; + pkts += 1; + n_left_from -= 1; + + /* Extract DIP of mbuf0 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + } + + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); + if (unlikely(rc != 0)) + return 0; + + for (i = 0; i < nb_objs; i++) { + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { + next_hop[i] = drop_nh; + lookup_err += 1; + } + + mbuf0 = (struct rte_mbuf *)objs[i]; + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; + next = (uint16_t)(next_hop[i] >> 16); + + if (unlikely(next_index ^ next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + } + + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + + return nb_objs; +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) int rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, @@ -147,6 +310,7 @@ static struct rte_node_xstats ip4_lookup_fib_xstats = { }; static struct rte_node_register ip4_lookup_fib_node = { + .process = ip4_lookup_fib_node_process, .name = "ip4_lookup_fib", .init = ip4_lookup_fib_node_init, -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-15 12:10 ` [PATCH v1 04/12] node: add process callback for IP4 FIB Ankur Dwivedi @ 2025-04-16 7:54 ` Nitin Saxena 2025-04-16 12:54 ` Medvedkin, Vladimir 1 sibling, 0 replies; 36+ messages in thread From: Nitin Saxena @ 2025-04-16 7:54 UTC (permalink / raw) To: Ankur Dwivedi Cc: dev, jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla Hi Ankur, Same comments apply to IPv6 nodes as well. See for ip4 lookup comments Thanks, Nitin On Tue, Apr 15, 2025 at 6:20 PM Ankur Dwivedi <adwivedi@marvell.com> wrote: > > Adds the process callback function for ip4_lookup_fib node. > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > --- > lib/node/ip4_lookup_fib.c | 164 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 164 insertions(+) > > diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > index e87864e672..c535b191f8 100644 > --- a/lib/node/ip4_lookup_fib.c > +++ b/lib/node/ip4_lookup_fib.c > @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; > #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > > +static uint16_t > +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, > + uint16_t nb_objs) > +{ > + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; > + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); > + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); > + struct rte_ipv4_hdr *ipv4_hdr; > + uint64_t next_hop[nb_objs]; > + uint16_t lookup_err = 0; > + void **to_next, **from; > + uint16_t last_spec = 0; > + rte_edge_t next_index; > + uint16_t n_left_from; > + uint32_t ip[nb_objs]; > + uint16_t held = 0; > + uint32_t drop_nh; > + uint16_t next; > + int i, rc; > + > + /* Speculative next */ > + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; Is it possible if we add next_edge in node->ctx? Save next_index in node->init() function and at the end of process() function for better speculative performance Also in general, this function is assuming packets are being forwarded to rewrite node but there be can other paths as well like - LOCAL - PUNT etc. So let next_hop returned from rte_fib_lookup_bulk() determine the next_edge (even pkt_drop node). Control plane feeds next_edge in 8B next_hop which I defined in other patch and also below (rte_ip4_lookup_fib_next_hop_t) > + /* Drop node */ > + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16; Let drop be determined from next_hop returned from rte_ip4_lookup_fib_next_hop_t Control plane feeds default next_hop as part of setup_fib() as follows struct { struct { uint32_t next_hop_od; uint16_t next_edge; uint16_t reserved; }; uint64_t u4; } rte_ip4_lookpu_fib_next_hop_t; default_nh = {,next = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP}; which is programmed in setup_fib > + > + pkts = (struct rte_mbuf **)objs; > + from = objs; > + n_left_from = nb_objs; > + > + /* Get stream for the speculated next node */ > + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); > + > + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE) > + rte_prefetch0(&objs[i]); > + > +#if RTE_GRAPH_BURST_SIZE > 64 > + for (i = 0; i < 4 && i < n_left_from; i++) { > + rte_prefetch0(pkts[i]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, > + sizeof(struct rte_ether_hdr))); > + } > +#endif > + > + i = 0; > + while (n_left_from >= 4) { > +#if RTE_GRAPH_BURST_SIZE > 64 > + if (likely(n_left_from > 7)) { > + rte_prefetch0(pkts[4]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[5]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[6]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[7]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, > + sizeof(struct rte_ether_hdr))); > + } > +#endif > + > + mbuf0 = pkts[0]; > + mbuf1 = pkts[1]; > + mbuf2 = pkts[2]; > + mbuf3 = pkts[3]; > + pkts += 4; > + n_left_from -= 4; > + /* Extract DIP of mbuf0 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf1 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf2 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf3 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + } > + while (n_left_from > 0) { > + mbuf0 = pkts[0]; > + pkts += 1; > + n_left_from -= 1; > + > + /* Extract DIP of mbuf0 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + } > + > + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); > + if (unlikely(rc != 0)) > + return 0; > + > + for (i = 0; i < nb_objs; i++) { > + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { This check can be removed since we have programmed drop node in default_nh. > + next_hop[i] = drop_nh; > + lookup_err += 1; > + } > + > + mbuf0 = (struct rte_mbuf *)objs[i]; > + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; > + next = (uint16_t)(next_hop[i] >> 16); Please get next and next_hop from next_hop itself node_mbuf_priv1(mbuf0, dyn)->nh = ((rte_ip4_lookup_fib_next_hop_t *)next_hop[i])->next_edge next = ((rte_ip4_lookup_fib_next_hop_t *)next_hop[i])->next_hop_id; > + > + if (unlikely(next_index ^ next)) { > + /* Copy things successfully speculated till now */ > + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > + from += last_spec; > + to_next += last_spec; > + held += last_spec; > + last_spec = 0; > + > + rte_node_enqueue_x1(graph, node, next, from[0]); > + from += 1; > + } else { > + last_spec += 1; > + } > + } > + > + /* !!! Home run !!! */ > + if (likely(last_spec == nb_objs)) { > + rte_node_next_stream_move(graph, node, next_index); > + return nb_objs; > + } > + > + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); > + held += last_spec; > + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); Save current next_index in node->ctx to make speculation work in next iteration. > + rte_node_next_stream_put(graph, node, next_index, held); > + > + return nb_objs; > +} > + > RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) > int > rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, > @@ -147,6 +310,7 @@ static struct rte_node_xstats ip4_lookup_fib_xstats = { > }; > > static struct rte_node_register ip4_lookup_fib_node = { > + .process = ip4_lookup_fib_node_process, > .name = "ip4_lookup_fib", > > .init = ip4_lookup_fib_node_init, > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-15 12:10 ` [PATCH v1 04/12] node: add process callback for IP4 FIB Ankur Dwivedi 2025-04-16 7:54 ` Nitin Saxena @ 2025-04-16 12:54 ` Medvedkin, Vladimir 2025-04-18 7:38 ` [EXTERNAL] " Ankur Dwivedi 1 sibling, 1 reply; 36+ messages in thread From: Medvedkin, Vladimir @ 2025-04-16 12:54 UTC (permalink / raw) To: Ankur Dwivedi, dev; +Cc: jerinj, ndabilpuram, pbhagavatula, skori, rkudurumalla Hi Ankur, On 15/04/2025 13:10, Ankur Dwivedi wrote: > Adds the process callback function for ip4_lookup_fib node. > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > --- > lib/node/ip4_lookup_fib.c | 164 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 164 insertions(+) > > diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > index e87864e672..c535b191f8 100644 > --- a/lib/node/ip4_lookup_fib.c > +++ b/lib/node/ip4_lookup_fib.c > @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; > #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > > +static uint16_t > +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, > + uint16_t nb_objs) > +{ > + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; > + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); > + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); > + struct rte_ipv4_hdr *ipv4_hdr; > + uint64_t next_hop[nb_objs]; > + uint16_t lookup_err = 0; > + void **to_next, **from; > + uint16_t last_spec = 0; > + rte_edge_t next_index; > + uint16_t n_left_from; > + uint32_t ip[nb_objs]; > + uint16_t held = 0; > + uint32_t drop_nh; > + uint16_t next; > + int i, rc; > + > + /* Speculative next */ > + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; > + /* Drop node */ > + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << 16; > + > + pkts = (struct rte_mbuf **)objs; > + from = objs; > + n_left_from = nb_objs; > + > + /* Get stream for the speculated next node */ > + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); > + > + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE) > + rte_prefetch0(&objs[i]); Does this prefetching loop make any sense? Unless objs are not passed across threads this array likely to be in the cache already. And if objs are passed across threads, then why do you start prefetching from the next cache line instead of the first, and why don't you stop at nb_objs? > + > +#if RTE_GRAPH_BURST_SIZE > 64 > + for (i = 0; i < 4 && i < n_left_from; i++) { > + rte_prefetch0(pkts[i]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, > + sizeof(struct rte_ether_hdr))); This construction does not make sense to me. Same as similar constructions below The second prefetch has memory dependency of the data, that will be prefetched by the first one. Does removing this prefetch affects performance? > + } > +#endif > + > + i = 0; > + while (n_left_from >= 4) { > +#if RTE_GRAPH_BURST_SIZE > 64 > + if (likely(n_left_from > 7)) { > + rte_prefetch0(pkts[4]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[5]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[6]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, > + sizeof(struct rte_ether_hdr))); > + rte_prefetch0(pkts[7]); > + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, > + sizeof(struct rte_ether_hdr))); > + } > +#endif > + > + mbuf0 = pkts[0]; > + mbuf1 = pkts[1]; > + mbuf2 = pkts[2]; > + mbuf3 = pkts[3]; > + pkts += 4; > + n_left_from -= 4; > + /* Extract DIP of mbuf0 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf1 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf2 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + > + /* Extract DIP of mbuf3 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + } > + while (n_left_from > 0) { > + mbuf0 = pkts[0]; > + pkts += 1; > + n_left_from -= 1; > + > + /* Extract DIP of mbuf0 */ > + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, > + sizeof(struct rte_ether_hdr)); > + /* Extract cksum, ttl as ipv4 hdr is in cache */ > + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; > + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > + > + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > + } > + > + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); > + if (unlikely(rc != 0)) > + return 0; > + > + for (i = 0; i < nb_objs; i++) { > + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { > + next_hop[i] = drop_nh; maybe it is worth just do define FIB_DEFAULT_NH as a drop_nh vaue to omit these next_hop reassignments? > + lookup_err += 1; > + } > + > + mbuf0 = (struct rte_mbuf *)objs[i]; > + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; > + next = (uint16_t)(next_hop[i] >> 16); > + > + if (unlikely(next_index ^ next)) { > + /* Copy things successfully speculated till now */ > + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > + from += last_spec; > + to_next += last_spec; > + held += last_spec; > + last_spec = 0; > + > + rte_node_enqueue_x1(graph, node, next, from[0]); > + from += 1; > + } else { > + last_spec += 1; > + } > + } > + > + /* !!! Home run !!! */ > + if (likely(last_spec == nb_objs)) { > + rte_node_next_stream_move(graph, node, next_index); > + return nb_objs; > + } > + > + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); > + held += last_spec; > + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > + rte_node_next_stream_put(graph, node, next_index, held); > + > + return nb_objs; > +} > + > RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) > int > rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, > @@ -147,6 +310,7 @@ static struct rte_node_xstats ip4_lookup_fib_xstats = { > }; > > static struct rte_node_register ip4_lookup_fib_node = { > + .process = ip4_lookup_fib_node_process, > .name = "ip4_lookup_fib", > > .init = ip4_lookup_fib_node_init, -- Regards, Vladimir ^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-16 12:54 ` Medvedkin, Vladimir @ 2025-04-18 7:38 ` Ankur Dwivedi 2025-04-19 18:14 ` Vladimir Medvedkin 0 siblings, 1 reply; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-18 7:38 UTC (permalink / raw) To: Medvedkin, Vladimir, dev Cc: Jerin Jacob, Nithin Kumar Dabilpuram, Pavan Nikhilesh Bhagavatula, Sunil Kumar Kori, Rakesh Kudurumalla Hi Vladimir, >> diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c >> index e87864e672..c535b191f8 100644 >> --- a/lib/node/ip4_lookup_fib.c >> +++ b/lib/node/ip4_lookup_fib.c >> @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main >ip4_lookup_fib_nm; >> #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ >> (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) >> >> +static uint16_t >> +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node >*node, void **objs, >> + uint16_t nb_objs) >> +{ >> + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; >> + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); >> + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); >> + struct rte_ipv4_hdr *ipv4_hdr; >> + uint64_t next_hop[nb_objs]; >> + uint16_t lookup_err = 0; >> + void **to_next, **from; >> + uint16_t last_spec = 0; >> + rte_edge_t next_index; >> + uint16_t n_left_from; >> + uint32_t ip[nb_objs]; >> + uint16_t held = 0; >> + uint32_t drop_nh; >> + uint16_t next; >> + int i, rc; >> + >> + /* Speculative next */ >> + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; >> + /* Drop node */ >> + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << >16; >> + >> + pkts = (struct rte_mbuf **)objs; >> + from = objs; >> + n_left_from = nb_objs; >> + >> + /* Get stream for the speculated next node */ >> + to_next = rte_node_next_stream_get(graph, node, next_index, >> +nb_objs); >> + >> + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += >OBJS_PER_CLINE) >> + rte_prefetch0(&objs[i]); > >Does this prefetching loop make any sense? Unless objs are not passed across >threads this array likely to be in the cache already. > >And if objs are passed across threads, then why do you start prefetching from >the next cache line instead of the first, and why don't you stop at nb_objs? For example if cache size is 64 bytes. Then there will be 8 pointers to mbuf per cache line (if address size is 8 bytes). If nb_objs is 256, then the remaining pointers needs to be prefetched to cache. This loop helps to prefetch nb_objs pointers to cache. The loop can be changed to stop at nb_objs. for (i = OBJS_PER_CLINE; i < nb_objs; i += OBJS_PER_CLINE) { } > >> + >> +#if RTE_GRAPH_BURST_SIZE > 64 >> + for (i = 0; i < 4 && i < n_left_from; i++) { >> + rte_prefetch0(pkts[i]); >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, >> + sizeof(struct rte_ether_hdr))); > >This construction does not make sense to me. Same as similar constructions >below > >The second prefetch has memory dependency of the data, that will be >prefetched by the first one. Does removing this prefetch affects performance? The first prefetches the data at mbuf address. The second prefetch is for the address containing ipv4 header. Both can be in separate cache lines, as ipv4 starts at mbuf->buf_addr + mbuf->data_off + sizeof(ethernet header). data_off is generally 64 bytes or 128 bytes depending on cache line size. > >> + } >> +#endif >> + >> + i = 0; >> + while (n_left_from >= 4) { >> +#if RTE_GRAPH_BURST_SIZE > 64 >> + if (likely(n_left_from > 7)) { >> + rte_prefetch0(pkts[4]); >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void >*, >> + sizeof(struct rte_ether_hdr))); >> + rte_prefetch0(pkts[5]); >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void >*, >> + sizeof(struct rte_ether_hdr))); >> + rte_prefetch0(pkts[6]); >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void >*, >> + sizeof(struct rte_ether_hdr))); >> + rte_prefetch0(pkts[7]); >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void >*, >> + sizeof(struct rte_ether_hdr))); >> + } >> +#endif >> + >> + mbuf0 = pkts[0]; >> + mbuf1 = pkts[1]; >> + mbuf2 = pkts[2]; >> + mbuf3 = pkts[3]; >> + pkts += 4; >> + n_left_from -= 4; >> + /* Extract DIP of mbuf0 */ >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct >rte_ipv4_hdr *, >> + sizeof(struct rte_ether_hdr)); >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- >>hdr_checksum; >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; >> + >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); >> + >> + /* Extract DIP of mbuf1 */ >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct >rte_ipv4_hdr *, >> + sizeof(struct rte_ether_hdr)); >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ >> + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr- >>hdr_checksum; >> + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; >> + >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); >> + >> + /* Extract DIP of mbuf2 */ >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct >rte_ipv4_hdr *, >> + sizeof(struct rte_ether_hdr)); >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ >> + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr- >>hdr_checksum; >> + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; >> + >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); >> + >> + /* Extract DIP of mbuf3 */ >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct >rte_ipv4_hdr *, >> + sizeof(struct rte_ether_hdr)); >> + >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ >> + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr- >>hdr_checksum; >> + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; >> + >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); >> + } >> + while (n_left_from > 0) { >> + mbuf0 = pkts[0]; >> + pkts += 1; >> + n_left_from -= 1; >> + >> + /* Extract DIP of mbuf0 */ >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct >rte_ipv4_hdr *, >> + sizeof(struct rte_ether_hdr)); >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- >>hdr_checksum; >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; >> + >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); >> + } >> + >> + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); >> + if (unlikely(rc != 0)) >> + return 0; >> + >> + for (i = 0; i < nb_objs; i++) { >> + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { >> + next_hop[i] = drop_nh; >maybe it is worth just do define FIB_DEFAULT_NH as a drop_nh vaue to omit >these next_hop reassignments? Ack. >> + lookup_err += 1; >> + } >> + >> + mbuf0 = (struct rte_mbuf *)objs[i]; >> + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; >> + next = (uint16_t)(next_hop[i] >> 16); >> + >> + if (unlikely(next_index ^ next)) { >> + /* Copy things successfully speculated till now */ >> + rte_memcpy(to_next, from, last_spec * >sizeof(from[0])); >> + from += last_spec; >> + to_next += last_spec; >> + held += last_spec; >> + last_spec = 0; >> + >> + rte_node_enqueue_x1(graph, node, next, from[0]); >> + from += 1; >> + } else { >> + last_spec += 1; >> + } >> + } >> + >> + /* !!! Home run !!! */ >> + if (likely(last_spec == nb_objs)) { >> + rte_node_next_stream_move(graph, node, next_index); >> + return nb_objs; >> + } >> + >> + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); >> + held += last_spec; >> + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); >> + rte_node_next_stream_put(graph, node, next_index, held); >> + >> + return nb_objs; >> +} >> + >> RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) >> int >> rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t >> next_hop, @@ -147,6 +310,7 @@ static struct rte_node_xstats >ip4_lookup_fib_xstats = { >> }; >> >> static struct rte_node_register ip4_lookup_fib_node = { >> + .process = ip4_lookup_fib_node_process, >> .name = "ip4_lookup_fib", >> >> .init = ip4_lookup_fib_node_init, > >-- >Regards, >Vladimir ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [EXTERNAL] Re: [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-18 7:38 ` [EXTERNAL] " Ankur Dwivedi @ 2025-04-19 18:14 ` Vladimir Medvedkin 2025-04-23 9:46 ` Ankur Dwivedi 0 siblings, 1 reply; 36+ messages in thread From: Vladimir Medvedkin @ 2025-04-19 18:14 UTC (permalink / raw) To: Ankur Dwivedi Cc: Medvedkin, Vladimir, dev, Jerin Jacob, Nithin Kumar Dabilpuram, Pavan Nikhilesh Bhagavatula, Sunil Kumar Kori, Rakesh Kudurumalla [-- Attachment #1: Type: text/plain, Size: 11564 bytes --] Hi Ankur, пт, 18 апр. 2025 г. в 15:45, Ankur Dwivedi <adwivedi@marvell.com>: > > Hi Vladimir, > >> diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > >> index e87864e672..c535b191f8 100644 > >> --- a/lib/node/ip4_lookup_fib.c > >> +++ b/lib/node/ip4_lookup_fib.c > >> @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main > >ip4_lookup_fib_nm; > >> #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > >> (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > >> > >> +static uint16_t > >> +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node > >*node, void **objs, > >> + uint16_t nb_objs) > >> +{ > >> + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; > >> + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); > >> + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); > >> + struct rte_ipv4_hdr *ipv4_hdr; > >> + uint64_t next_hop[nb_objs]; > >> + uint16_t lookup_err = 0; > >> + void **to_next, **from; > >> + uint16_t last_spec = 0; > >> + rte_edge_t next_index; > >> + uint16_t n_left_from; > >> + uint32_t ip[nb_objs]; > >> + uint16_t held = 0; > >> + uint32_t drop_nh; > >> + uint16_t next; > >> + int i, rc; > >> + > >> + /* Speculative next */ > >> + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; > >> + /* Drop node */ > >> + drop_nh = ((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << > >16; > >> + > >> + pkts = (struct rte_mbuf **)objs; > >> + from = objs; > >> + n_left_from = nb_objs; > >> + > >> + /* Get stream for the speculated next node */ > >> + to_next = rte_node_next_stream_get(graph, node, next_index, > >> +nb_objs); > >> + > >> + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += > >OBJS_PER_CLINE) > >> + rte_prefetch0(&objs[i]); > > > >Does this prefetching loop make any sense? Unless objs are not passed > across > >threads this array likely to be in the cache already. > > > >And if objs are passed across threads, then why do you start prefetching > from > >the next cache line instead of the first, and why don't you stop at > nb_objs? > For example if cache size is 64 bytes. Then there will be 8 pointers to > mbuf per cache line (if address size is 8 bytes). If nb_objs is 256, then > the remaining pointers needs to be prefetched to cache. This loop helps to > prefetch nb_objs pointers to cache. > My comment was about necessity. I'll rephrase and enumerate my questions to be more clear: 1. Are mbuf pointers contained in the objs array not in cache? My assumptions here are: - If you run graph in RTC mode, objs array is very likely already be in your L1 cache (since some previous node/nodes just put packets there) - In dispatch mode it doesn't make much sense to run this lookup node in an another thread separately from the remaining nodes processing IPv4 2. if you still thing this prefetching loop is required here, then: > The loop can be changed to stop at nb_objs. > for (i = OBJS_PER_CLINE; i < nb_objs; i += OBJS_PER_CLINE) { } > > why you start from the OBJS_PER_CLINE (second cache line of the objs array) 3. "i < nb_objs". Should be "i < RTE_ALIGN_CEIL(nb_objs, OBJS_PER_CLINE) / OBJS_PER_CLINE" > > >> + > >> +#if RTE_GRAPH_BURST_SIZE > 64 > >> + for (i = 0; i < 4 && i < n_left_from; i++) { > >> + rte_prefetch0(pkts[i]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, > >> + sizeof(struct rte_ether_hdr))); > > > >This construction does not make sense to me. Same as similar constructions > >below > > > >The second prefetch has memory dependency of the data, that will be > >prefetched by the first one. Does removing this prefetch affects > performance? > The first prefetches the data at mbuf address. The second prefetch is for > the address containing ipv4 header. Both can be in separate cache lines, as > ipv4 starts at mbuf->buf_addr + mbuf->data_off + sizeof(ethernet header). > data_off is generally 64 bytes or 128 bytes depending on cache line size. > > > Indeed, both of them are in separate cache lines. But my point here is about data dependency for the second prefetch. In order to issue the prefetch instruction for the cache line containing the ipv4 header you must know the address. You calculate this address by: rte_pktmbuf_mtod_offset(pkts[i], void *, sizeof(struct rte_ether_hdr)) rte_pktmbuf_mtod_offset is accessing mbuf->buf_addr and mbuf->data_off , as you mentioned. But, these fields are not in your L1 cache at the moment, because you just asked to prefetch them with the previous instruction. So my suggestion here would be to look at how it is done in ipv4_lookup_sse.c:ip4_lookup_node_process_vec() Simplifying, in a run loop it prefetches mbuf + 2, then prefetches CL with the v4 header of the mbuf + 1 (assuming in a previous invocation mbuf CL was already fetched into L1), and finally does processing of the mbuf + 0 (again, assuming the previous iteration ipv4 CL was fetched). > >> + } > >> +#endif > >> + > >> + i = 0; > >> + while (n_left_from >= 4) { > >> +#if RTE_GRAPH_BURST_SIZE > 64 > >> + if (likely(n_left_from > 7)) { > >> + rte_prefetch0(pkts[4]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[5]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[6]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[7]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + } > >> +#endif > >> + > >> + mbuf0 = pkts[0]; > >> + mbuf1 = pkts[1]; > >> + mbuf2 = pkts[2]; > >> + mbuf3 = pkts[3]; > >> + pkts += 4; > >> + n_left_from -= 4; > >> + /* Extract DIP of mbuf0 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf1 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf2 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf3 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + } > >> + while (n_left_from > 0) { > >> + mbuf0 = pkts[0]; > >> + pkts += 1; > >> + n_left_from -= 1; > >> + > >> + /* Extract DIP of mbuf0 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + } > >> + > >> + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); > >> + if (unlikely(rc != 0)) > >> + return 0; > >> + > >> + for (i = 0; i < nb_objs; i++) { > >> + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { > >> + next_hop[i] = drop_nh; > >maybe it is worth just do define FIB_DEFAULT_NH as a drop_nh vaue to omit > >these next_hop reassignments? > Ack. > >> + lookup_err += 1; > >> + } > >> + > >> + mbuf0 = (struct rte_mbuf *)objs[i]; > >> + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; > >> + next = (uint16_t)(next_hop[i] >> 16); > >> + > >> + if (unlikely(next_index ^ next)) { > >> + /* Copy things successfully speculated till now */ > >> + rte_memcpy(to_next, from, last_spec * > >sizeof(from[0])); > >> + from += last_spec; > >> + to_next += last_spec; > >> + held += last_spec; > >> + last_spec = 0; > >> + > >> + rte_node_enqueue_x1(graph, node, next, from[0]); > >> + from += 1; > >> + } else { > >> + last_spec += 1; > >> + } > >> + } > >> + > >> + /* !!! Home run !!! */ > >> + if (likely(last_spec == nb_objs)) { > >> + rte_node_next_stream_move(graph, node, next_index); > >> + return nb_objs; > >> + } > >> + > >> + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); > >> + held += last_spec; > >> + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > >> + rte_node_next_stream_put(graph, node, next_index, held); > >> + > >> + return nb_objs; > >> +} > >> + > >> RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) > >> int > >> rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t > >> next_hop, @@ -147,6 +310,7 @@ static struct rte_node_xstats > >ip4_lookup_fib_xstats = { > >> }; > >> > >> static struct rte_node_register ip4_lookup_fib_node = { > >> + .process = ip4_lookup_fib_node_process, > >> .name = "ip4_lookup_fib", > >> > >> .init = ip4_lookup_fib_node_init, > > > >-- > >Regards, > >Vladimir > > -- Regards, Vladimir [-- Attachment #2: Type: text/html, Size: 18085 bytes --] ^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v1 04/12] node: add process callback for IP4 FIB 2025-04-19 18:14 ` Vladimir Medvedkin @ 2025-04-23 9:46 ` Ankur Dwivedi 0 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-23 9:46 UTC (permalink / raw) To: Vladimir Medvedkin Cc: Medvedkin, Vladimir, dev, Jerin Jacob, Nithin Kumar Dabilpuram, Pavan Nikhilesh Bhagavatula, Sunil Kumar Kori, Rakesh Kudurumalla Hi Vladimir, >Hi Ankur, > >пт, 18 апр. 2025 г. в 15:45, Ankur Dwivedi <adwivedi@marvell.com ><mailto:adwivedi@marvell.com> >: > > > > Hi Vladimir, > >> diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c > >> index e87864e672..c535b191f8 100644 > >> --- a/lib/node/ip4_lookup_fib.c > >> +++ b/lib/node/ip4_lookup_fib.c > >> @@ -40,6 +40,169 @@ static struct ip4_lookup_fib_node_main > >ip4_lookup_fib_nm; > >> #define IP4_LOOKUP_NODE_PRIV1_OFF(ctx) \ > >> (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) > >> > >> +static uint16_t > >> +ip4_lookup_fib_node_process(struct rte_graph *graph, struct >rte_node > >*node, void **objs, > >> + uint16_t nb_objs) > >> +{ > >> + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; > >> + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); > >> + const int dyn = IP4_LOOKUP_NODE_PRIV1_OFF(node->ctx); > >> + struct rte_ipv4_hdr *ipv4_hdr; > >> + uint64_t next_hop[nb_objs]; > >> + uint16_t lookup_err = 0; > >> + void **to_next, **from; > >> + uint16_t last_spec = 0; > >> + rte_edge_t next_index; > >> + uint16_t n_left_from; > >> + uint32_t ip[nb_objs]; > >> + uint16_t held = 0; > >> + uint32_t drop_nh; > >> + uint16_t next; > >> + int i, rc; > >> + > >> + /* Speculative next */ > >> + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; > >> + /* Drop node */ > >> + drop_nh = >((uint32_t)RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP) << > >16; > >> + > >> + pkts = (struct rte_mbuf **)objs; > >> + from = objs; > >> + n_left_from = nb_objs; > >> + > >> + /* Get stream for the speculated next node */ > >> + to_next = rte_node_next_stream_get(graph, node, next_index, > >> +nb_objs); > >> + > >> + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += > >OBJS_PER_CLINE) > >> + rte_prefetch0(&objs[i]); > > > >Does this prefetching loop make any sense? Unless objs are not >passed across > >threads this array likely to be in the cache already. > > > >And if objs are passed across threads, then why do you start >prefetching from > >the next cache line instead of the first, and why don't you stop at >nb_objs? > For example if cache size is 64 bytes. Then there will be 8 pointers to >mbuf per cache line (if address size is 8 bytes). If nb_objs is 256, then the >remaining pointers needs to be prefetched to cache. This loop helps to >prefetch nb_objs pointers to cache. > > > >My comment was about necessity. I'll rephrase and enumerate my questions >to be more clear: >1. Are mbuf pointers contained in the objs array not in cache? My assumptions >here are: > - If you run graph in RTC mode, objs array is very likely already be in your L1 >cache (since some previous node/nodes just put packets there) Yes, the objs are more likely to be in L1 cache in RTC. But if they are not the above loop prefetches them. > - In dispatch mode it doesn't make much sense to run this lookup node in an >another thread separately from the remaining nodes processing IPv4 If its run in another thread/lcore, the above prefetching will help. > >2. if you still thing this prefetching loop is required here, then: > > > The loop can be changed to stop at nb_objs. > for (i = OBJS_PER_CLINE; i < nb_objs; i += OBJS_PER_CLINE) { } > > > > why you start from the OBJS_PER_CLINE (second cache line of the objs array) Because the first line is prefetched in __rte_node_process() which is called in rte_graph_walk(). >3. "i < nb_objs". Should be "i < RTE_ALIGN_CEIL(nb_objs, OBJS_PER_CLINE) / >OBJS_PER_CLINE" In this loop i will be incremented by 1. But the for loop which I mentioned above, also does the same thing but i is incremented by OBJS_PER_CLINE. > > > > > >> + > >> +#if RTE_GRAPH_BURST_SIZE > 64 > >> + for (i = 0; i < 4 && i < n_left_from; i++) { > >> + rte_prefetch0(pkts[i]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, > >> + sizeof(struct rte_ether_hdr))); > > > >This construction does not make sense to me. Same as similar >constructions > >below > > > >The second prefetch has memory dependency of the data, that will >be > >prefetched by the first one. Does removing this prefetch affects >performance? > The first prefetches the data at mbuf address. The second prefetch is >for the address containing ipv4 header. Both can be in separate cache lines, as >ipv4 starts at mbuf->buf_addr + mbuf->data_off + sizeof(ethernet header). >data_off is generally 64 bytes or 128 bytes depending on cache line size. > > > > > >Indeed, both of them are in separate cache lines. But my point here is about >data dependency for the second prefetch. In order to issue the prefetch >instruction for the cache line containing the ipv4 header you must know the >address. You calculate this address by: >rte_pktmbuf_mtod_offset(pkts[i], void *, sizeof(struct rte_ether_hdr)) >rte_pktmbuf_mtod_offset is accessing mbuf->buf_addr and mbuf->data_off , >as you mentioned. But, these fields are not in your L1 cache at the moment, >because you just asked to prefetch them with the previous instruction. Ack. >So my suggestion here would be to look at how it is done in >ipv4_lookup_sse.c:ip4_lookup_node_process_vec() >Simplifying, in a run loop it prefetches mbuf + 2, then prefetches CL with the v4 >header of the mbuf + 1 (assuming in a previous invocation mbuf CL was >already fetched into L1), and finally does processing of the mbuf + 0 (again, >assuming the previous iteration ipv4 CL was fetched). I have seen the implementation. The code looks fine to me. I will try to add similar code in fib lookup. > > > >> + } > >> +#endif > >> + > >> + i = 0; > >> + while (n_left_from >= 4) { > >> +#if RTE_GRAPH_BURST_SIZE > 64 > >> + if (likely(n_left_from > 7)) { > >> + rte_prefetch0(pkts[4]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[5]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[6]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + rte_prefetch0(pkts[7]); > >> + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void > >*, > >> + sizeof(struct rte_ether_hdr))); > >> + } > >> +#endif > >> + > >> + mbuf0 = pkts[0]; > >> + mbuf1 = pkts[1]; > >> + mbuf2 = pkts[2]; > >> + mbuf3 = pkts[3]; > >> + pkts += 4; > >> + n_left_from -= 4; > >> + /* Extract DIP of mbuf0 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr- >>time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf1 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr- >>time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf2 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr- >>time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + > >> + /* Extract DIP of mbuf3 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr- >>time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + } > >> + while (n_left_from > 0) { > >> + mbuf0 = pkts[0]; > >> + pkts += 1; > >> + n_left_from -= 1; > >> + > >> + /* Extract DIP of mbuf0 */ > >> + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct > >rte_ipv4_hdr *, > >> + sizeof(struct rte_ether_hdr)); > >> + /* Extract cksum, ttl as ipv4 hdr is in cache */ > >> + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr- > >>hdr_checksum; > >> + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr- >>time_to_live; > >> + > >> + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); > >> + } > >> + > >> + rc = rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); > >> + if (unlikely(rc != 0)) > >> + return 0; > >> + > >> + for (i = 0; i < nb_objs; i++) { > >> + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) { > >> + next_hop[i] = drop_nh; > >maybe it is worth just do define FIB_DEFAULT_NH as a drop_nh vaue >to omit > >these next_hop reassignments? > Ack. > >> + lookup_err += 1; > >> + } > >> + > >> + mbuf0 = (struct rte_mbuf *)objs[i]; > >> + node_mbuf_priv1(mbuf0, dyn)->nh = >(uint16_t)next_hop[i]; > >> + next = (uint16_t)(next_hop[i] >> 16); > >> + > >> + if (unlikely(next_index ^ next)) { > >> + /* Copy things successfully speculated till now */ > >> + rte_memcpy(to_next, from, last_spec * > >sizeof(from[0])); > >> + from += last_spec; > >> + to_next += last_spec; > >> + held += last_spec; > >> + last_spec = 0; > >> + > >> + rte_node_enqueue_x1(graph, node, next, from[0]); > >> + from += 1; > >> + } else { > >> + last_spec += 1; > >> + } > >> + } > >> + > >> + /* !!! Home run !!! */ > >> + if (likely(last_spec == nb_objs)) { > >> + rte_node_next_stream_move(graph, node, next_index); > >> + return nb_objs; > >> + } > >> + > >> + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, >lookup_err); > >> + held += last_spec; > >> + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); > >> + rte_node_next_stream_put(graph, node, next_index, held); > >> + > >> + return nb_objs; > >> +} > >> + > >> >RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) > >> int > >> rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t > >> next_hop, @@ -147,6 +310,7 @@ static struct rte_node_xstats > >ip4_lookup_fib_xstats = { > >> }; > >> > >> static struct rte_node_register ip4_lookup_fib_node = { > >> + .process = ip4_lookup_fib_node_process, > >> .name = "ip4_lookup_fib", > >> > >> .init = ip4_lookup_fib_node_init, > > > >-- > >Regards, > >Vladimir > > > > > >-- > >Regards, > >Vladimir Regards, Ankur ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 05/12] node: add next node in packet classification 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (3 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 04/12] node: add process callback for IP4 FIB Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 06/12] app/graph: add IP4 lookup mode command Ankur Dwivedi ` (7 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi The ip4_lookup_fib is added as next node in packet classification. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/pkt_cls.c | 1 + lib/node/pkt_cls_priv.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index 9d21b7f307..3bd0ec0bbc 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -232,6 +232,7 @@ struct rte_node_register pkt_cls_node = { [PKT_CLS_NEXT_PKT_DROP] = "pkt_drop", [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", [PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", + [PKT_CLS_NEXT_IP4_LOOKUP_FIB] = "ip4_lookup_fib", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/pkt_cls_priv.h b/lib/node/pkt_cls_priv.h index 16135807a1..5d24ec0fbd 100644 --- a/lib/node/pkt_cls_priv.h +++ b/lib/node/pkt_cls_priv.h @@ -14,6 +14,7 @@ enum pkt_cls_next_nodes { PKT_CLS_NEXT_PKT_DROP, PKT_CLS_NEXT_IP4_LOOKUP, PKT_CLS_NEXT_IP6_LOOKUP, + PKT_CLS_NEXT_IP4_LOOKUP_FIB, PKT_CLS_NEXT_MAX, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 06/12] app/graph: add IP4 lookup mode command 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (4 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 05/12] node: add next node in packet classification Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 07/12] fib: move macro to header file Ankur Dwivedi ` (6 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a command to setup lookup mode for IP4 packets. By default the LPM mode is used. FIB can be given as a lookup mode by specifying the mode in CLI file. When FIB is given as lookup mode, the next node of packet classification node is updated to use IP4 lookup fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- app/graph/commands.list | 1 + app/graph/ip4_route.c | 34 ++++++++++++++++++++++++++++++---- app/graph/l3fwd.c | 12 ++++++++++++ app/graph/module_api.h | 7 +++++++ doc/guides/tools/graph.rst | 12 ++++++++---- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/app/graph/commands.list b/app/graph/commands.list index c027f73b0e..7a1bf0c708 100644 --- a/app/graph/commands.list +++ b/app/graph/commands.list @@ -23,6 +23,7 @@ ethdev_rx map port <STRING>dev queue <UINT32>qid core <UINT32>core_id # Port-Que help ethdev_rx # Print help on ethdev_rx commands ipv4_lookup route add ipv4 <IPv4>ip netmask <IPv4>mask via <IPv4>via_ip # Add IPv4 route to LPM table +ipv4_lookup mode <STRING>lkup_mode # Set IPv4 lookup mode help ipv4_lookup # Print help on ipv4_lookup commands ipv6_lookup route add ipv6 <IPv6>ip netmask <IPv6>mask via <IPv6>via_ip # Add IPv6 route to LPM6 table diff --git a/app/graph/ip4_route.c b/app/graph/ip4_route.c index 48ea912597..9af2c26078 100644 --- a/app/graph/ip4_route.c +++ b/app/graph/ip4_route.c @@ -18,8 +18,13 @@ static const char cmd_ipv4_lookup_help[] = "ipv4_lookup route add ipv4 <ip> netmask <mask> via <ip>"; +static const char +cmd_ipv4_lookup_mode_help[] = "ipv4_lookup mode <lpm|fib>"; + struct ip4_route route4 = TAILQ_HEAD_INITIALIZER(route4); +enum ip4_lookup_mode ip4_lookup_m = IP4_LOOKUP_LPM; + void route_ip4_list_clean(void) { @@ -62,6 +67,7 @@ route4_rewirte_table_update(struct route_ipv4_config *ipv4route) { uint8_t depth; int portid; + int rc; portid = ethdev_portid_by_ip4(ipv4route->via, ipv4route->netmask); if (portid < 0) { @@ -71,8 +77,14 @@ route4_rewirte_table_update(struct route_ipv4_config *ipv4route) depth = convert_netmask_to_depth(ipv4route->netmask); - return rte_node_ip4_route_add(ipv4route->ip, depth, portid, - RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + if (ip4_lookup_m == IP4_LOOKUP_FIB) + rc = rte_node_ip4_fib_route_add(ipv4route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + else + rc = rte_node_ip4_route_add(ipv4route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + + return rc; } static int @@ -134,9 +146,9 @@ cmd_help_ipv4_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struc len = strlen(conn->msg_out); conn->msg_out += len; - snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", "--------------------------- ipv4_lookup command help ---------------------------", - cmd_ipv4_lookup_help); + cmd_ipv4_lookup_help, cmd_ipv4_lookup_mode_help); len = strlen(conn->msg_out); conn->msg_out_len_max -= len; @@ -158,3 +170,17 @@ cmd_ipv4_lookup_route_add_ipv4_parsed(void *parsed_result, __rte_unused struct c if (rc < 0) printf(MSG_CMD_FAIL, res->ipv4_lookup); } + +void +cmd_ipv4_lookup_mode_parsed(void *parsed_result, __rte_unused struct cmdline *cl, + void *data __rte_unused) +{ + struct cmd_ipv4_lookup_mode_result *res = parsed_result; + + if (!strcmp(res->lkup_mode, "lpm")) + ip4_lookup_m = IP4_LOOKUP_LPM; + else if (!strcmp(res->lkup_mode, "fib")) + ip4_lookup_m = IP4_LOOKUP_FIB; + else + printf(MSG_CMD_FAIL, res->ipv4_lookup); +} diff --git a/app/graph/l3fwd.c b/app/graph/l3fwd.c index a2648df27d..cb64e66026 100644 --- a/app/graph/l3fwd.c +++ b/app/graph/l3fwd.c @@ -53,6 +53,18 @@ l3fwd_pattern_configure(void) graph_conf.num_pkt_to_capture = pcap_pkts_count; graph_conf.pcap_filename = strdup(pcap_file); + if (ip4_lookup_m == IP4_LOOKUP_FIB) { + const char *fib_n = "ip4_lookup_fib"; + const char *lpm_n = "ip4_lookup"; + rte_node_t pkt_cls; +#define IP4_LKUP_ACTIVE_EDGE 1 +#define IP4_LKUP_INACTIVE_EDGE 3 + + pkt_cls = rte_node_from_name("pkt_cls"); + rte_node_edge_update(pkt_cls, IP4_LKUP_ACTIVE_EDGE, &fib_n, 1); + rte_node_edge_update(pkt_cls, IP4_LKUP_INACTIVE_EDGE, &lpm_n, 1); + } + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { rte_graph_t graph_id; rte_edge_t i; diff --git a/app/graph/module_api.h b/app/graph/module_api.h index b872872dc1..b8188d30d5 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -27,6 +27,13 @@ extern volatile bool force_quit; extern struct conn *conn; +enum ip4_lookup_mode { + IP4_LOOKUP_LPM, + IP4_LOOKUP_FIB +}; + +extern enum ip4_lookup_mode ip4_lookup_m; + bool app_graph_stats_enabled(void); bool app_graph_exit(void); diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index d8c147d73e..2caf441591 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -235,10 +235,14 @@ file to express the requested use case configuration. | | | message. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | | ipv4_lookup route add ipv4 <ip> | | Command to add a route into | :ref:`3 <scopes>` | Yes | - | | netmask <mask> via <ip> | | ``ipv4_lookup`` LPM table. It is| | | - | | | needed if user wishes to route | | | - | | | the packets based on LPM lookup | | | - | | | table. | | | + | | netmask <mask> via <ip> | | ``ipv4_lookup`` LPM table or | | | + | | | FIB. It is needed if user wishes| | | + | | | to route the packets based on | | | + | | | LPM lookup table or FIB. | | | + +--------------------------------------+-----------------------------------+-------------------+----------+ + | | ipv4_lookup mode <lpm|fib> | | Command to set ipv4 lookup mode | :ref:`1 <scopes>` | Yes | + | | | to either LPM or FIB. By default| | | + | | | the lookup mode is LPM. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | help ipv4_lookup | | Command to dump ``ipv4_lookup`` | :ref:`2 <scopes>` | Yes | | | | help message. | | | -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 07/12] fib: move macro to header file 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (5 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 06/12] app/graph: add IP4 lookup mode command Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 08/12] node: add IP6 lookup FIB node Ankur Dwivedi ` (5 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Moves the macro FIB6_NAMESIZE to header file and rename it to RTE_FIB6_NAMESIZE. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/fib/rte_fib6.c | 11 ++++------- lib/fib/rte_fib6.h | 3 +++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/fib/rte_fib6.c b/lib/fib/rte_fib6.c index 00647bdfa4..93a1c7197b 100644 --- a/lib/fib/rte_fib6.c +++ b/lib/fib/rte_fib6.c @@ -28,9 +28,6 @@ static struct rte_tailq_elem rte_fib6_tailq = { }; EAL_REGISTER_TAILQ(rte_fib6_tailq) -/* Maximum length of a FIB name. */ -#define FIB6_NAMESIZE 64 - #if defined(RTE_LIBRTE_FIB_DEBUG) #define FIB6_RETURN_IF_TRUE(cond, retval) do { \ if (cond) \ @@ -41,7 +38,7 @@ EAL_REGISTER_TAILQ(rte_fib6_tailq) #endif struct rte_fib6 { - char name[FIB6_NAMESIZE]; + char name[RTE_FIB6_NAMESIZE]; enum rte_fib6_type type; /**< Type of FIB struct */ struct rte_rib6 *rib; /**< RIB helper datastructure */ void *dp; /**< pointer to the dataplane struct*/ @@ -157,7 +154,7 @@ RTE_EXPORT_SYMBOL(rte_fib6_create) struct rte_fib6 * rte_fib6_create(const char *name, int socket_id, struct rte_fib6_conf *conf) { - char mem_name[FIB6_NAMESIZE]; + char mem_name[RTE_FIB6_NAMESIZE]; int ret; struct rte_fib6 *fib = NULL; struct rte_rib6 *rib = NULL; @@ -190,7 +187,7 @@ rte_fib6_create(const char *name, int socket_id, struct rte_fib6_conf *conf) /* guarantee there's no existing */ TAILQ_FOREACH(te, fib_list, next) { fib = (struct rte_fib6 *)te->data; - if (strncmp(name, fib->name, FIB6_NAMESIZE) == 0) + if (strncmp(name, fib->name, RTE_FIB6_NAMESIZE) == 0) break; } fib = NULL; @@ -261,7 +258,7 @@ rte_fib6_find_existing(const char *name) rte_mcfg_tailq_read_lock(); TAILQ_FOREACH(te, fib_list, next) { fib = (struct rte_fib6 *) te->data; - if (strncmp(name, fib->name, FIB6_NAMESIZE) == 0) + if (strncmp(name, fib->name, RTE_FIB6_NAMESIZE) == 0) break; } rte_mcfg_tailq_read_unlock(); diff --git a/lib/fib/rte_fib6.h b/lib/fib/rte_fib6.h index 42e6138708..625df1fa6b 100644 --- a/lib/fib/rte_fib6.h +++ b/lib/fib/rte_fib6.h @@ -28,6 +28,9 @@ extern "C" { /** Maximum depth value possible for IPv6 FIB. */ #define RTE_FIB6_MAXDEPTH (RTE_DEPRECATED(RTE_FIB6_MAXDEPTH) RTE_IPV6_MAX_DEPTH) +/* Maximum length of a FIB name. */ +#define RTE_FIB6_NAMESIZE 64 + struct rte_fib6; struct rte_rib6; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 08/12] node: add IP6 lookup FIB node 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (6 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 07/12] fib: move macro to header file Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 09/12] node: add IP6 FIB route add Ankur Dwivedi ` (4 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a lookup FIB node for IP6. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 124 ++++++++++++++++++++++++++++++++++++++ lib/node/meson.build | 1 + 2 files changed, 125 insertions(+) create mode 100644 lib/node/ip6_lookup_fib.c diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c new file mode 100644 index 0000000000..317cb53d7b --- /dev/null +++ b/lib/node/ip6_lookup_fib.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2025 Marvell. + */ + +#include <rte_errno.h> +#include <rte_ether.h> +#include <rte_fib6.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> + +#include "rte_node_ip6_api.h" + +#include "node_private.h" + +/* IP6 Lookup FIB global data struct */ +struct ip6_lookup_fib_node_main { + struct rte_fib6 *fib6[RTE_MAX_NUMA_NODES]; +}; + +struct ip6_lookup_fib_node_ctx { + /* Socket's FIB6 */ + struct rte_fib6 *fib6; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +static struct ip6_lookup_fib_node_main ip6_lookup_fib_nm; + +#define FIB6_MAX_ROUTES (1 << 16) +#define FIB6_NUM_TBL8 (1 << 15) +#define FIB6_DEFAULT_NH 999 + +#define IP6_LOOKUP_FIB_NODE(ctx) \ + (((struct ip6_lookup_fib_node_ctx *)ctx)->fib6) + +#define IP6_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ + (((struct ip6_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) + +static int +setup_fib6(unsigned int socket) +{ + struct ip6_lookup_fib_node_main *nm = &ip6_lookup_fib_nm; + struct rte_fib6_conf conf; + char s[RTE_FIB6_NAMESIZE]; + + /* One fib6 per socket */ + if (nm->fib6[socket]) + return 0; + + conf.type = RTE_FIB6_TRIE; + conf.default_nh = FIB6_DEFAULT_NH; + conf.max_routes = FIB6_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.trie.nh_sz = RTE_FIB6_TRIE_4B; + conf.trie.num_tbl8 = FIB6_NUM_TBL8; + snprintf(s, sizeof(s), "IPV6_LOOKUP_FIB_%u", socket); + nm->fib6[socket] = rte_fib6_create(s, socket, &conf); + if (nm->fib6[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +ip6_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + static uint8_t init_once; + unsigned int socket; + uint16_t lcore_id; + int rc; + + RTE_BUILD_BUG_ON(sizeof(struct ip6_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + /* Setup FIB6 for all sockets */ + RTE_LCORE_FOREACH(lcore_id) + { + socket = rte_lcore_to_socket_id(lcore_id); + rc = setup_fib6(socket); + if (rc) { + node_err("ip6_lookup_fib", + "Failed to setup fib6 for sock %u, rc=%d", socket, rc); + return rc; + } + } + init_once = 1; + } + + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ + IP6_LOOKUP_FIB_NODE(node->ctx) = ip6_lookup_fib_nm.fib6[graph->socket]; + IP6_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + + node_dbg("ip6_lookup_fib", "Initialized ip6_lookup_fib node"); + + return 0; +} + +static struct rte_node_xstats ip6_lookup_fib_xstats = { + .nb_xstats = 1, + .xstat_desc = { + [0] = "ip6_lookup_fib_error", + }, +}; + +static struct rte_node_register ip6_lookup_fib_node = { + .name = "ip6_lookup_fib", + + .init = ip6_lookup_fib_node_init, + .xstats = &ip6_lookup_fib_xstats, + + .nb_edges = RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_IP6_LOOKUP_NEXT_REWRITE] = "ip6_rewrite", + [RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip6_lookup_fib_node); diff --git a/lib/node/meson.build b/lib/node/meson.build index d2011c8f56..70216a1a69 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -17,6 +17,7 @@ sources = files( 'ip4_reassembly.c', 'ip4_rewrite.c', 'ip6_lookup.c', + 'ip6_lookup_fib.c', 'ip6_rewrite.c', 'kernel_rx.c', 'kernel_tx.c', -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 09/12] node: add IP6 FIB route add 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (7 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 08/12] node: add IP6 lookup FIB node Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 10/12] node: add process callback for IP6 FIB Ankur Dwivedi ` (3 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a public function to add IP6 route to FIB. The applications should call this function to add IP6 routes to FIB. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 34 ++++++++++++++++++++++++++++++++++ lib/node/rte_node_ip6_api.h | 19 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c index 317cb53d7b..caf3e9d1fa 100644 --- a/lib/node/ip6_lookup_fib.c +++ b/lib/node/ip6_lookup_fib.c @@ -2,6 +2,9 @@ * Copyright(C) 2025 Marvell. */ +#include <arpa/inet.h> + +#include <eal_export.h> #include <rte_errno.h> #include <rte_ether.h> #include <rte_fib6.h> @@ -37,6 +40,37 @@ static struct ip6_lookup_fib_node_main ip6_lookup_fib_nm; #define IP6_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ (((struct ip6_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip6_fib_route_add, 25.07) +int +rte_node_ip6_fib_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + uint8_t socket; + uint32_t val; + int ret; + + inet_ntop(AF_INET6, ip, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip6_lookup_fib", "FIB6: Adding route %s / %d nh (0x%x)", abuf, depth, val); + + for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { + if (!ip6_lookup_fib_nm.fib6[socket]) + continue; + + ret = rte_fib6_add(ip6_lookup_fib_nm.fib6[socket], ip, depth, val); + if (ret < 0) { + node_err("ip6_lookup_fib", + "Unable to add entry %s / %d nh (%x) to FIB on sock %d, rc=%d", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + static int setup_fib6(unsigned int socket) { diff --git a/lib/node/rte_node_ip6_api.h b/lib/node/rte_node_ip6_api.h index 2875bc981a..e6f997a9c5 100644 --- a/lib/node/rte_node_ip6_api.h +++ b/lib/node/rte_node_ip6_api.h @@ -71,6 +71,25 @@ __rte_experimental int rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Add IPv6 route to FIB. + * + * @param ip + * IPv6 address of route to be added. + * @param depth + * Depth of the rule to be added. + * @param next_hop + * Next hop id of the rule result to be added. + * @param next_node + * Next node to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip6_fib_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 10/12] node: add process callback for IP6 FIB 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (8 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 09/12] node: add IP6 FIB route add Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 11/12] node: add next node in packet classification Ankur Dwivedi ` (2 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds the process callback function for ip6_lookup_fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 158 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c index caf3e9d1fa..6ad975dddb 100644 --- a/lib/node/ip6_lookup_fib.c +++ b/lib/node/ip6_lookup_fib.c @@ -40,6 +40,163 @@ static struct ip6_lookup_fib_node_main ip6_lookup_fib_nm; #define IP6_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ (((struct ip6_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +static uint16_t +ip6_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + struct rte_fib6 *fib = IP6_LOOKUP_FIB_NODE(node->ctx); + const int dyn = IP6_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx); + struct rte_ipv6_addr ip[nb_objs]; + struct rte_ipv6_hdr *ipv6_hdr; + uint64_t next_hop[nb_objs]; + uint16_t lookup_err = 0; + void **to_next, **from; + uint16_t last_spec = 0; + rte_edge_t next_index; + uint16_t n_left_from; + uint16_t held = 0; + uint32_t drop_nh; + uint16_t next; + int i, rc; + + /* Speculative next */ + next_index = RTE_NODE_IP6_LOOKUP_NEXT_REWRITE; + /* Drop node */ + drop_nh = ((uint32_t)RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP) << 16; + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + for (i = OBJS_PER_CLINE; i < RTE_GRAPH_BURST_SIZE; i += OBJS_PER_CLINE) + rte_prefetch0(&objs[i]); + +#if RTE_GRAPH_BURST_SIZE > 64 + for (i = 0; i < 4 && i < n_left_from; i++) { + rte_prefetch0(pkts[i]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, + sizeof(struct rte_ether_hdr))); + } +#endif + + i = 0; + while (n_left_from >= 4) { +#if RTE_GRAPH_BURST_SIZE > 64 + if (likely(n_left_from > 7)) { + rte_prefetch0(pkts[4]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[5]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[6]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(pkts[7]); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, + sizeof(struct rte_ether_hdr))); + } +#endif + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + pkts += 4; + n_left_from -= 4; + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf1 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf2 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf3 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + } + while (n_left_from > 0) { + mbuf0 = pkts[0]; + pkts += 1; + n_left_from -= 1; + + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + } + + rc = rte_fib6_lookup_bulk(fib, ip, next_hop, nb_objs); + if (unlikely(rc != 0)) + return 0; + + for (i = 0; i < nb_objs; i++) { + if (unlikely(next_hop[i] == FIB6_DEFAULT_NH)) { + next_hop[i] = drop_nh; + lookup_err += 1; + } + + mbuf0 = (struct rte_mbuf *)objs[i]; + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; + next = (uint16_t)(next_hop[i] >> 16); + + if (unlikely(next_index ^ next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + } + + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + + return nb_objs; +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip6_fib_route_add, 25.07) int rte_node_ip6_fib_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop, @@ -143,6 +300,7 @@ static struct rte_node_xstats ip6_lookup_fib_xstats = { }; static struct rte_node_register ip6_lookup_fib_node = { + .process = ip6_lookup_fib_node_process, .name = "ip6_lookup_fib", .init = ip6_lookup_fib_node_init, -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 11/12] node: add next node in packet classification 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (9 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 10/12] node: add process callback for IP6 FIB Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 12/12] app/graph: add IP6 lookup mode command Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi The ip6_lookup_fib is added as next node in packet classification. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/pkt_cls.c | 1 + lib/node/pkt_cls_priv.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index 3bd0ec0bbc..56bd5176b2 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -233,6 +233,7 @@ struct rte_node_register pkt_cls_node = { [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", [PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", [PKT_CLS_NEXT_IP4_LOOKUP_FIB] = "ip4_lookup_fib", + [PKT_CLS_NEXT_IP6_LOOKUP_FIB] = "ip6_lookup_fib", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/pkt_cls_priv.h b/lib/node/pkt_cls_priv.h index 5d24ec0fbd..c3b753a6a4 100644 --- a/lib/node/pkt_cls_priv.h +++ b/lib/node/pkt_cls_priv.h @@ -15,6 +15,7 @@ enum pkt_cls_next_nodes { PKT_CLS_NEXT_IP4_LOOKUP, PKT_CLS_NEXT_IP6_LOOKUP, PKT_CLS_NEXT_IP4_LOOKUP_FIB, + PKT_CLS_NEXT_IP6_LOOKUP_FIB, PKT_CLS_NEXT_MAX, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v1 12/12] app/graph: add IP6 lookup mode command 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (10 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 11/12] node: add next node in packet classification Ankur Dwivedi @ 2025-04-15 12:10 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-04-15 12:10 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, Ankur Dwivedi Adds a command to setup lookup mode for IP6 packets. By default LPM mode is used. FIB can be given as a lookup mode by specifying the mode in CLI file. When FIB is given as lookup mode, the next node of packet classification node is updated to use IP6 lookup fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- app/graph/commands.list | 1 + app/graph/ip6_route.c | 33 +++++++++++++++++++++++++++++---- app/graph/l3fwd.c | 12 ++++++++++++ app/graph/module_api.h | 6 ++++++ doc/guides/tools/graph.rst | 12 ++++++++---- 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/app/graph/commands.list b/app/graph/commands.list index 7a1bf0c708..ffdab4fc97 100644 --- a/app/graph/commands.list +++ b/app/graph/commands.list @@ -27,6 +27,7 @@ ipv4_lookup mode <STRING>lkup_mode # Set IPv4 lookup mode help ipv4_lookup # Print help on ipv4_lookup commands ipv6_lookup route add ipv6 <IPv6>ip netmask <IPv6>mask via <IPv6>via_ip # Add IPv6 route to LPM6 table +ipv6_lookup mode <STRING>lkup_mode # Set IPv6 lookup mode help ipv6_lookup # Print help on ipv6_lookup commands neigh add ipv4 <IPv4>ip <STRING>mac # Add static neighbour for IPv4 diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c index ec53239b06..14c0c83638 100644 --- a/app/graph/ip6_route.c +++ b/app/graph/ip6_route.c @@ -19,8 +19,13 @@ static const char cmd_ipv6_lookup_help[] = "ipv6_lookup route add ipv6 <ip> netmask <mask> via <ip>"; +static const char +cmd_ipv6_lookup_mode_help[] = "ipv6_lookup mode <lpm|fib>"; + struct ip6_route route6 = TAILQ_HEAD_INITIALIZER(route6); +enum ip6_lookup_mode ip6_lookup_m = IP6_LOOKUP_LPM; + void route_ip6_list_clean(void) { @@ -49,6 +54,7 @@ route6_rewirte_table_update(struct route_ipv6_config *ipv6route) { uint8_t depth; int portid; + int rc; portid = ethdev_portid_by_ip6(&ipv6route->gateway, &ipv6route->mask); if (portid < 0) { @@ -57,9 +63,14 @@ route6_rewirte_table_update(struct route_ipv6_config *ipv6route) } depth = rte_ipv6_mask_depth(&ipv6route->mask); - return rte_node_ip6_route_add(&ipv6route->ip, depth, portid, - RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + if (ip6_lookup_m == IP6_LOOKUP_FIB) + rc = rte_node_ip6_fib_route_add(&ipv6route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + else + rc = rte_node_ip6_route_add(&ipv6route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + return rc; } static int @@ -120,9 +131,9 @@ cmd_help_ipv6_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struc len = strlen(conn->msg_out); conn->msg_out += len; - snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", "--------------------------- ipv6_lookup command help ---------------------------", - cmd_ipv6_lookup_help); + cmd_ipv6_lookup_help, cmd_ipv6_lookup_mode_help); len = strlen(conn->msg_out); conn->msg_out_len_max -= len; @@ -144,3 +155,17 @@ cmd_ipv6_lookup_route_add_ipv6_parsed(void *parsed_result, __rte_unused struct c if (rc) printf(MSG_CMD_FAIL, res->ipv6_lookup); } + +void +cmd_ipv6_lookup_mode_parsed(void *parsed_result, __rte_unused struct cmdline *cl, + void *data __rte_unused) +{ + struct cmd_ipv6_lookup_mode_result *res = parsed_result; + + if (!strcmp(res->lkup_mode, "lpm")) + ip6_lookup_m = IP6_LOOKUP_LPM; + else if (!strcmp(res->lkup_mode, "fib")) + ip6_lookup_m = IP6_LOOKUP_FIB; + else + printf(MSG_CMD_FAIL, res->ipv6_lookup); +} diff --git a/app/graph/l3fwd.c b/app/graph/l3fwd.c index cb64e66026..3c9f8d2f8b 100644 --- a/app/graph/l3fwd.c +++ b/app/graph/l3fwd.c @@ -65,6 +65,18 @@ l3fwd_pattern_configure(void) rte_node_edge_update(pkt_cls, IP4_LKUP_INACTIVE_EDGE, &lpm_n, 1); } + if (ip6_lookup_m == IP6_LOOKUP_FIB) { + const char *fib6_n = "ip6_lookup_fib"; + const char *lpm6_n = "ip6_lookup"; + rte_node_t pkt_cls; +#define IP6_LKUP_ACTIVE_EDGE 2 +#define IP6_LKUP_INACTIVE_EDGE 4 + + pkt_cls = rte_node_from_name("pkt_cls"); + rte_node_edge_update(pkt_cls, IP6_LKUP_ACTIVE_EDGE, &fib6_n, 1); + rte_node_edge_update(pkt_cls, IP6_LKUP_INACTIVE_EDGE, &lpm6_n, 1); + } + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { rte_graph_t graph_id; rte_edge_t i; diff --git a/app/graph/module_api.h b/app/graph/module_api.h index b8188d30d5..5e3a384cb0 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -32,7 +32,13 @@ enum ip4_lookup_mode { IP4_LOOKUP_FIB }; +enum ip6_lookup_mode { + IP6_LOOKUP_LPM, + IP6_LOOKUP_FIB +}; + extern enum ip4_lookup_mode ip4_lookup_m; +extern enum ip6_lookup_mode ip6_lookup_m; bool app_graph_stats_enabled(void); bool app_graph_exit(void); diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 2caf441591..dd525f6037 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -248,10 +248,14 @@ file to express the requested use case configuration. | | | help message. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | | ipv6_lookup route add ipv6 <ip> | | Command to add a route into | :ref:`3 <scopes>` | Yes | - | | netmask <mask> via <ip> | | ``ipv6_lookup`` LPM table. It is| | | - | | | needed if user wishes to route | | | - | | | the packets based on LPM6 lookup| | | - | | | table. | | | + | | netmask <mask> via <ip> | | ``ipv6_lookup`` LPM table or. | | | + | | | FIB. It is needed if user wishes| | | + | | | to route the packets based on | | | + | | | LPM6 lookup table or FIB. | | | + +--------------------------------------+-----------------------------------+-------------------+----------+ + | | ipv6_lookup mode <lpm|fib> | | Command to set ipv6 lookup mode | :ref:`1 <scopes>` | Yes | + | | | to either LPM or FIB. By default| | | + | | | the lookup mode is LPM. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | help ipv6_lookup | | Command to dump ``ipv6_lookup`` | :ref:`2 <scopes>` | Yes | | | | help message. | | | -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 00/13] add lookup fib nodes in graph library 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi ` (11 preceding siblings ...) 2025-04-15 12:10 ` [PATCH v1 12/12] app/graph: add IP6 lookup mode command Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 01/13] fib: move macro to header file Ankur Dwivedi ` (12 more replies) 12 siblings, 13 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi This patch series adds two inbuilt nodes ip4_lookup_fib and ip6_lookup_fib in graph library. These nodes uses the existing Forwarding Information Base (FIB) library to create FIB, to do route addition and route lookup. Two new commands (for ipv4 and ipv6) for providing the lookup mode is added in the dpdk-graph application. fib or lpm can be given as lookup mode. If these new lookup mode commands are not given, the dpdk-graph uses lpm (Longest Prefix Match) or lpm6 by default. If fib is given as lookup mode then the ip4_lookup_fib or ip6_lookup_fib nodes are used by the application. v2: - Fixed build failure in DPDK CI. - Changed the prefetch code in process functions. Also removed the prefetch of mbuf obj as it was not improving performance. - Added code to control fib configuration from dpdk-graph application. - Added the packet classification next nodes id in public header file, so that they can be used by library and application. - Changed the macro FIB_DEFAULT_NH to point to pkt drop node. Ankur Dwivedi (13): fib: move macro to header file node: add IP4 lookup FIB node node: add IP4 FIB route add node: add process callback for IP4 FIB node: move next nodes to public header file node: add next node in packet classification app/graph: add IP4 lookup mode command fib: move macro to header file node: add IP6 lookup FIB node node: add IP6 FIB route add node: add process callback for IP6 FIB node: add next node in packet classification app/graph: add IP6 lookup mode command app/graph/commands.list | 2 + app/graph/ip4_route.c | 34 +++- app/graph/ip6_route.c | 33 +++- app/graph/l3fwd.c | 70 +++++++ app/graph/module_api.h | 13 ++ doc/guides/tools/graph.rst | 24 ++- lib/fib/rte_fib.c | 3 - lib/fib/rte_fib.h | 3 + lib/fib/rte_fib6.c | 11 +- lib/fib/rte_fib6.h | 3 + lib/node/ip4_lookup_fib.c | 332 ++++++++++++++++++++++++++++++++ lib/node/ip6_lookup_fib.c | 322 +++++++++++++++++++++++++++++++ lib/node/meson.build | 5 +- lib/node/pkt_cls.c | 35 ++-- lib/node/pkt_cls_priv.h | 7 - lib/node/rte_node_ip4_api.h | 34 ++++ lib/node/rte_node_ip6_api.h | 34 ++++ lib/node/rte_node_pkt_cls_api.h | 39 ++++ 18 files changed, 954 insertions(+), 50 deletions(-) create mode 100644 lib/node/ip4_lookup_fib.c create mode 100644 lib/node/ip6_lookup_fib.c create mode 100644 lib/node/rte_node_pkt_cls_api.h -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 01/13] fib: move macro to header file 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 02/13] node: add IP4 lookup FIB node Ankur Dwivedi ` (11 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Moves RTE_FIB_NAMESIZE to header file, in order to use it outside the fib library. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/fib/rte_fib.c | 3 --- lib/fib/rte_fib.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fib/rte_fib.c b/lib/fib/rte_fib.c index 2c05d46500..184210f380 100644 --- a/lib/fib/rte_fib.c +++ b/lib/fib/rte_fib.c @@ -28,9 +28,6 @@ static struct rte_tailq_elem rte_fib_tailq = { }; EAL_REGISTER_TAILQ(rte_fib_tailq) -/* Maximum length of a FIB name. */ -#define RTE_FIB_NAMESIZE 64 - #if defined(RTE_LIBRTE_FIB_DEBUG) #define FIB_RETURN_IF_TRUE(cond, retval) do { \ if (cond) \ diff --git a/lib/fib/rte_fib.h b/lib/fib/rte_fib.h index 53f04b8049..874bf1688b 100644 --- a/lib/fib/rte_fib.h +++ b/lib/fib/rte_fib.h @@ -27,6 +27,9 @@ extern "C" { struct rte_fib; struct rte_rib; +/* Maximum length of a FIB name. */ +#define RTE_FIB_NAMESIZE 64 + /** Maximum depth value possible for IPv4 FIB. */ #define RTE_FIB_MAXDEPTH 32 -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 02/13] node: add IP4 lookup FIB node 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 01/13] fib: move macro to header file Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 03/13] node: add IP4 FIB route add Ankur Dwivedi ` (10 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a lookup FIB node for IP4. Adds a public function to do fib configuration from application. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 141 ++++++++++++++++++++++++++++++++++++ lib/node/meson.build | 3 +- lib/node/rte_node_ip4_api.h | 15 ++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 lib/node/ip4_lookup_fib.c diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c new file mode 100644 index 0000000000..977d97b713 --- /dev/null +++ b/lib/node/ip4_lookup_fib.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2025 Marvell. + */ + +#include <eal_export.h> +#include <rte_errno.h> +#include <rte_ether.h> +#include <rte_fib.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> + +#include "rte_node_ip4_api.h" + +#include "node_private.h" + +/* IP4 Lookup global data struct */ +struct ip4_lookup_fib_node_main { + struct rte_fib *fib[RTE_MAX_NUMA_NODES]; +}; + +struct ip4_lookup_fib_node_ctx { + /* Socket's FIB */ + struct rte_fib *fib; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; + +#define FIB_DEFAULT_MAX_ROUTES (UINT16_MAX) +#define FIB_DEFAULT_NUM_TBL8 (UINT16_MAX / 2) +#define FIB_DEFAULT_NH (RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP << 16) + +#define IP4_LOOKUP_NODE_FIB(ctx) \ + (((struct ip4_lookup_fib_node_ctx *)ctx)->fib) + +#define IP4_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ + (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_create, 25.07) +int +rte_node_ip4_fib_create(int socket, struct rte_fib_conf *conf) +{ + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; + char s[RTE_FIB_NAMESIZE]; + + /* One fib per socket */ + if (nm->fib[socket]) + return 0; + + conf->default_nh = FIB_DEFAULT_NH; + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); + nm->fib[socket] = rte_fib_create(s, socket, conf); + if (nm->fib[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +setup_fib(int socket) +{ + struct ip4_lookup_fib_node_main *nm = &ip4_lookup_fib_nm; + struct rte_fib_conf conf; + char s[RTE_FIB_NAMESIZE]; + + /* One fib per socket */ + if (nm->fib[socket]) + return 0; + + conf.type = RTE_FIB_DIR24_8; + conf.default_nh = FIB_DEFAULT_NH; + conf.max_routes = FIB_DEFAULT_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; + conf.dir24_8.num_tbl8 = FIB_DEFAULT_NUM_TBL8; + conf.flags = 0; + snprintf(s, sizeof(s), "IPV4_LOOKUP_FIB_%d", socket); + nm->fib[socket] = rte_fib_create(s, socket, &conf); + if (nm->fib[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +ip4_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + static uint8_t init_once; + int rc; + + RTE_BUILD_BUG_ON(sizeof(struct ip4_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + init_once = 1; + } + + rc = setup_fib(graph->socket); + if (rc) { + node_err("ip4_lookup_fib", "Failed to setup fib for sock %u, rc=%d", + graph->socket, rc); + return rc; + } + + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ + IP4_LOOKUP_NODE_FIB(node->ctx) = ip4_lookup_fib_nm.fib[graph->socket]; + IP4_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + + node_dbg("ip4_lookup_fib", "Initialized ip4_lookup_fib node"); + + return 0; +} + +static struct rte_node_xstats ip4_lookup_fib_xstats = { + .nb_xstats = 1, + .xstat_desc = { + [0] = "ip4_lookup_fib_error", + }, +}; + +static struct rte_node_register ip4_lookup_fib_node = { + .name = "ip4_lookup_fib", + + .init = ip4_lookup_fib_node_init, + .xstats = &ip4_lookup_fib_xstats, + + .nb_edges = RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_IP4_LOOKUP_NEXT_IP4_LOCAL] = "ip4_local", + [RTE_NODE_IP4_LOOKUP_NEXT_REWRITE] = "ip4_rewrite", + [RTE_NODE_IP4_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip4_lookup_fib_node); diff --git a/lib/node/meson.build b/lib/node/meson.build index 0bed97a96c..d2011c8f56 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -13,6 +13,7 @@ sources = files( 'ethdev_tx.c', 'ip4_local.c', 'ip4_lookup.c', + 'ip4_lookup_fib.c', 'ip4_reassembly.c', 'ip4_rewrite.c', 'ip6_lookup.c', @@ -34,4 +35,4 @@ headers = files( # Strict-aliasing rules are violated by uint8_t[] to context size casts. cflags += '-fno-strict-aliasing' -deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag'] +deps += ['graph', 'mbuf', 'lpm', 'ethdev', 'mempool', 'cryptodev', 'ip_frag', 'fib'] diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 950751a525..1dac7a4936 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -18,6 +18,7 @@ #include <rte_common.h> #include <rte_compat.h> +#include <rte_fib.h> #include <rte_graph.h> #ifdef __cplusplus @@ -117,6 +118,20 @@ int rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, __rte_experimental int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, uint16_t cnt); +/** + * Create ipv4 FIB. + * + * @param socket + * NUMA socket for FIB memory allocation. + * @param conf + * Structure containing FIB configuration. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_fib_create(int socket, struct rte_fib_conf *conf); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 03/13] node: add IP4 FIB route add 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 01/13] fib: move macro to header file Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 02/13] node: add IP4 lookup FIB node Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 04/13] node: add process callback for IP4 FIB Ankur Dwivedi ` (9 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a public function to add IP4 route to FIB. The applications should call this function to add IP4 routes to FIB. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 37 +++++++++++++++++++++++++++++++++++++ lib/node/rte_node_ip4_api.h | 19 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c index 977d97b713..f300266c00 100644 --- a/lib/node/ip4_lookup_fib.c +++ b/lib/node/ip4_lookup_fib.c @@ -2,6 +2,8 @@ * Copyright(C) 2025 Marvell. */ +#include <arpa/inet.h> + #include <eal_export.h> #include <rte_errno.h> #include <rte_ether.h> @@ -58,6 +60,41 @@ rte_node_ip4_fib_create(int socket, struct rte_fib_conf *conf) return 0; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_route_add, 25.07) +int +rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip4_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + unsigned int nb_sockets; + struct in_addr in; + uint8_t socket; + uint32_t val; + int ret; + + nb_sockets = rte_socket_count(); + in.s_addr = htonl(ip); + inet_ntop(AF_INET, &in, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip4_lookup_fib", "FIB: Adding route %s / %d nh (0x%x)", abuf, depth, val); + + for (socket = 0; socket < nb_sockets; socket++) { + if (!ip4_lookup_fib_nm.fib[socket]) + continue; + + ret = rte_fib_add(ip4_lookup_fib_nm.fib[socket], ip, depth, val); + if (ret < 0) { + node_err("ip4_lookup_fib", + "Unable to add entry %s / %d nh (%x) to FIB on sock %d, rc=%d", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + static int setup_fib(int socket) { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 1dac7a4936..4d75c5f874 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -132,6 +132,25 @@ int rte_node_ip4_reassembly_configure(struct rte_node_ip4_reassembly_cfg *cfg, u __rte_experimental int rte_node_ip4_fib_create(int socket, struct rte_fib_conf *conf); +/** + * Add ipv4 route to FIB. + * + * @param ip + * IP address of route to be added. + * @param depth + * Depth of the rule to be added. + * @param next_hop + * Next hop id of the rule result to be added. + * @param next_node + * Next node to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip4_fib_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip4_lookup_next next_node); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 04/13] node: add process callback for IP4 FIB 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (2 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 03/13] node: add IP4 FIB route add Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 05/13] node: move next nodes to public header file Ankur Dwivedi ` (8 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds the process callback function for ip4_lookup_fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip4_lookup_fib.c | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/lib/node/ip4_lookup_fib.c b/lib/node/ip4_lookup_fib.c index f300266c00..f9a5c5aa5a 100644 --- a/lib/node/ip4_lookup_fib.c +++ b/lib/node/ip4_lookup_fib.c @@ -40,6 +40,159 @@ static struct ip4_lookup_fib_node_main ip4_lookup_fib_nm; #define IP4_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ (((struct ip4_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +static uint16_t +ip4_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + const int dyn = IP4_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx); + struct rte_fib *fib = IP4_LOOKUP_NODE_FIB(node->ctx); + uint64_t next_hop[RTE_GRAPH_BURST_SIZE]; + uint32_t ip[RTE_GRAPH_BURST_SIZE]; + struct rte_ipv4_hdr *ipv4_hdr; + uint16_t lookup_err = 0; + void **to_next, **from; + uint16_t last_spec = 0; + rte_edge_t next_index; + uint16_t n_left_from; + uint16_t held = 0; + uint16_t next; + int i; + + /* Speculative next */ + next_index = RTE_NODE_IP4_LOOKUP_NEXT_REWRITE; + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + for (i = 0; i < 4 && i < n_left_from; i++) + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, + sizeof(struct rte_ether_hdr))); + + i = 0; + while (n_left_from >= 4) { + if (likely(n_left_from > 7)) { + + /* Prefetch next-next mbufs */ + if (likely(n_left_from > 11)) { + rte_prefetch0(pkts[8]); + rte_prefetch0(pkts[9]); + rte_prefetch0(pkts[10]); + rte_prefetch0(pkts[11]); + } + + /* Prefetch next mbuf data */ + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, + sizeof(struct rte_ether_hdr))); + } + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + pkts += 4; + n_left_from -= 4; + /* Extract DIP of mbuf0 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf1 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf1, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf2 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf2, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + + /* Extract DIP of mbuf3 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf3, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + } + while (n_left_from > 0) { + mbuf0 = pkts[0]; + pkts += 1; + n_left_from -= 1; + + /* Extract DIP of mbuf0 */ + ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv4_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract cksum, ttl as ipv4 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->cksum = ipv4_hdr->hdr_checksum; + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv4_hdr->time_to_live; + + ip[i++] = rte_be_to_cpu_32(ipv4_hdr->dst_addr); + } + + rte_fib_lookup_bulk(fib, ip, next_hop, nb_objs); + + for (i = 0; i < nb_objs; i++) { + mbuf0 = (struct rte_mbuf *)objs[i]; + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; + next = (uint16_t)(next_hop[i] >> 16); + + if (unlikely(next_index ^ next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + + if (unlikely(next_hop[i] == FIB_DEFAULT_NH)) + lookup_err += 1; + } + + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + + return nb_objs; +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip4_fib_create, 25.07) int rte_node_ip4_fib_create(int socket, struct rte_fib_conf *conf) @@ -162,6 +315,7 @@ static struct rte_node_xstats ip4_lookup_fib_xstats = { }; static struct rte_node_register ip4_lookup_fib_node = { + .process = ip4_lookup_fib_node_process, .name = "ip4_lookup_fib", .init = ip4_lookup_fib_node_init, -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 05/13] node: move next nodes to public header file 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (3 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 04/13] node: add process callback for IP4 FIB Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 06/13] node: add next node in packet classification Ankur Dwivedi ` (7 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Moves the next nodes of packet classification node to a public header files, so that it can be used from applications. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/meson.build | 1 + lib/node/pkt_cls.c | 33 +++++++++++++++-------------- lib/node/pkt_cls_priv.h | 7 ------- lib/node/rte_node_pkt_cls_api.h | 37 +++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 lib/node/rte_node_pkt_cls_api.h diff --git a/lib/node/meson.build b/lib/node/meson.build index d2011c8f56..8112cf7f5b 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -30,6 +30,7 @@ headers = files( 'rte_node_eth_api.h', 'rte_node_ip4_api.h', 'rte_node_ip6_api.h', + 'rte_node_pkt_cls_api.h', 'rte_node_udp4_input_api.h', ) diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index 9d21b7f307..5d6409fdbf 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -9,36 +9,37 @@ #include "pkt_cls_priv.h" #include "node_private.h" +#include "rte_node_pkt_cls_api.h" /* Next node for each ptype, default is '0' is "pkt_drop" */ static const alignas(RTE_CACHE_LINE_SIZE) uint8_t p_nxt[256] = { - [RTE_PTYPE_L3_IPV4] = PKT_CLS_NEXT_IP4_LOOKUP, + [RTE_PTYPE_L3_IPV4] = RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, - [RTE_PTYPE_L3_IPV4_EXT] = PKT_CLS_NEXT_IP4_LOOKUP, + [RTE_PTYPE_L3_IPV4_EXT] = RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, - [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN] = PKT_CLS_NEXT_IP4_LOOKUP, + [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN] = RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, [RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L2_ETHER] = - PKT_CLS_NEXT_IP4_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, [RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L2_ETHER] = - PKT_CLS_NEXT_IP4_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, [RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] = - PKT_CLS_NEXT_IP4_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, - [RTE_PTYPE_L3_IPV6] = PKT_CLS_NEXT_IP6_LOOKUP, + [RTE_PTYPE_L3_IPV6] = RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, - [RTE_PTYPE_L3_IPV6_EXT] = PKT_CLS_NEXT_IP6_LOOKUP, + [RTE_PTYPE_L3_IPV6_EXT] = RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, - [RTE_PTYPE_L3_IPV6_EXT_UNKNOWN] = PKT_CLS_NEXT_IP6_LOOKUP, + [RTE_PTYPE_L3_IPV6_EXT_UNKNOWN] = RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, - [RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L2_ETHER] = PKT_CLS_NEXT_IP6_LOOKUP, + [RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L2_ETHER] = RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, - [RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L2_ETHER] = PKT_CLS_NEXT_IP6_LOOKUP, + [RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L2_ETHER] = RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, [RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L2_ETHER] = - PKT_CLS_NEXT_IP6_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, }; static uint16_t @@ -226,12 +227,12 @@ struct rte_node_register pkt_cls_node = { .process = pkt_cls_node_process, .name = "pkt_cls", - .nb_edges = PKT_CLS_NEXT_MAX, + .nb_edges = RTE_NODE_PKT_CLS_NEXT_MAX, .next_nodes = { /* Pkt drop node starts at '0' */ - [PKT_CLS_NEXT_PKT_DROP] = "pkt_drop", - [PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", - [PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", + [RTE_NODE_PKT_CLS_NEXT_PKT_DROP] = "pkt_drop", + [RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", + [RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/pkt_cls_priv.h b/lib/node/pkt_cls_priv.h index 16135807a1..63c26cae2a 100644 --- a/lib/node/pkt_cls_priv.h +++ b/lib/node/pkt_cls_priv.h @@ -10,11 +10,4 @@ struct pkt_cls_node_ctx { uint16_t l2l3_type; }; -enum pkt_cls_next_nodes { - PKT_CLS_NEXT_PKT_DROP, - PKT_CLS_NEXT_IP4_LOOKUP, - PKT_CLS_NEXT_IP6_LOOKUP, - PKT_CLS_NEXT_MAX, -}; - #endif /* __INCLUDE_PKT_CLS_PRIV_H__ */ diff --git a/lib/node/rte_node_pkt_cls_api.h b/lib/node/rte_node_pkt_cls_api.h new file mode 100644 index 0000000000..36276db63c --- /dev/null +++ b/lib/node/rte_node_pkt_cls_api.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2025 Marvell. + */ + +#ifndef __INCLUDE_RTE_NODE_PKT_CLS_API_H__ +#define __INCLUDE_RTE_NODE_PKT_CLS_API_H__ + +/** + * @file rte_node_pkt_cls_api.h + * + * @warning + * @b EXPERIMENTAL: + * All functions in this file may be changed or removed without prior notice. + * + * This API allows to do control path functions of pkt_cls node. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Packet classification (pkt_cls) next nodes. + */ + +enum rte_node_pkt_cls_next { + RTE_NODE_PKT_CLS_NEXT_PKT_DROP, + RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_MAX, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_RTE_NODE_PKT_CLS_API_H__ */ -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 06/13] node: add next node in packet classification 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (4 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 05/13] node: move next nodes to public header file Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 07/13] app/graph: add IP4 lookup mode command Ankur Dwivedi ` (6 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi The ip4_lookup_fib is added as next node in packet classification. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/pkt_cls.c | 1 + lib/node/rte_node_pkt_cls_api.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index 5d6409fdbf..f6e76989bc 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -233,6 +233,7 @@ struct rte_node_register pkt_cls_node = { [RTE_NODE_PKT_CLS_NEXT_PKT_DROP] = "pkt_drop", [RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", [RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", + [RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB] = "ip4_lookup_fib", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/rte_node_pkt_cls_api.h b/lib/node/rte_node_pkt_cls_api.h index 36276db63c..8f935bebbe 100644 --- a/lib/node/rte_node_pkt_cls_api.h +++ b/lib/node/rte_node_pkt_cls_api.h @@ -27,6 +27,7 @@ enum rte_node_pkt_cls_next { RTE_NODE_PKT_CLS_NEXT_PKT_DROP, RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, + RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB, RTE_NODE_PKT_CLS_NEXT_MAX, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 07/13] app/graph: add IP4 lookup mode command 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (5 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 06/13] node: add next node in packet classification Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 08/13] fib: move macro to header file Ankur Dwivedi ` (5 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a command to setup lookup mode for IP4 packets. By default the LPM mode is used. FIB can be given as a lookup mode by specifying the mode in CLI file. When FIB is given as lookup mode, the next node of packet classification node is updated to use IP4 lookup fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- app/graph/commands.list | 1 + app/graph/ip4_route.c | 34 ++++++++++++++++++++++++++++++---- app/graph/l3fwd.c | 36 ++++++++++++++++++++++++++++++++++++ app/graph/module_api.h | 7 +++++++ doc/guides/tools/graph.rst | 12 ++++++++---- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/app/graph/commands.list b/app/graph/commands.list index c027f73b0e..7a1bf0c708 100644 --- a/app/graph/commands.list +++ b/app/graph/commands.list @@ -23,6 +23,7 @@ ethdev_rx map port <STRING>dev queue <UINT32>qid core <UINT32>core_id # Port-Que help ethdev_rx # Print help on ethdev_rx commands ipv4_lookup route add ipv4 <IPv4>ip netmask <IPv4>mask via <IPv4>via_ip # Add IPv4 route to LPM table +ipv4_lookup mode <STRING>lkup_mode # Set IPv4 lookup mode help ipv4_lookup # Print help on ipv4_lookup commands ipv6_lookup route add ipv6 <IPv6>ip netmask <IPv6>mask via <IPv6>via_ip # Add IPv6 route to LPM6 table diff --git a/app/graph/ip4_route.c b/app/graph/ip4_route.c index 48ea912597..9af2c26078 100644 --- a/app/graph/ip4_route.c +++ b/app/graph/ip4_route.c @@ -18,8 +18,13 @@ static const char cmd_ipv4_lookup_help[] = "ipv4_lookup route add ipv4 <ip> netmask <mask> via <ip>"; +static const char +cmd_ipv4_lookup_mode_help[] = "ipv4_lookup mode <lpm|fib>"; + struct ip4_route route4 = TAILQ_HEAD_INITIALIZER(route4); +enum ip4_lookup_mode ip4_lookup_m = IP4_LOOKUP_LPM; + void route_ip4_list_clean(void) { @@ -62,6 +67,7 @@ route4_rewirte_table_update(struct route_ipv4_config *ipv4route) { uint8_t depth; int portid; + int rc; portid = ethdev_portid_by_ip4(ipv4route->via, ipv4route->netmask); if (portid < 0) { @@ -71,8 +77,14 @@ route4_rewirte_table_update(struct route_ipv4_config *ipv4route) depth = convert_netmask_to_depth(ipv4route->netmask); - return rte_node_ip4_route_add(ipv4route->ip, depth, portid, - RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + if (ip4_lookup_m == IP4_LOOKUP_FIB) + rc = rte_node_ip4_fib_route_add(ipv4route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + else + rc = rte_node_ip4_route_add(ipv4route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + + return rc; } static int @@ -134,9 +146,9 @@ cmd_help_ipv4_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struc len = strlen(conn->msg_out); conn->msg_out += len; - snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", "--------------------------- ipv4_lookup command help ---------------------------", - cmd_ipv4_lookup_help); + cmd_ipv4_lookup_help, cmd_ipv4_lookup_mode_help); len = strlen(conn->msg_out); conn->msg_out_len_max -= len; @@ -158,3 +170,17 @@ cmd_ipv4_lookup_route_add_ipv4_parsed(void *parsed_result, __rte_unused struct c if (rc < 0) printf(MSG_CMD_FAIL, res->ipv4_lookup); } + +void +cmd_ipv4_lookup_mode_parsed(void *parsed_result, __rte_unused struct cmdline *cl, + void *data __rte_unused) +{ + struct cmd_ipv4_lookup_mode_result *res = parsed_result; + + if (!strcmp(res->lkup_mode, "lpm")) + ip4_lookup_m = IP4_LOOKUP_LPM; + else if (!strcmp(res->lkup_mode, "fib")) + ip4_lookup_m = IP4_LOOKUP_FIB; + else + printf(MSG_CMD_FAIL, res->ipv4_lookup); +} diff --git a/app/graph/l3fwd.c b/app/graph/l3fwd.c index a2648df27d..48dff9fa07 100644 --- a/app/graph/l3fwd.c +++ b/app/graph/l3fwd.c @@ -15,9 +15,28 @@ #include <rte_graph_worker.h> #include <rte_lcore.h> #include <rte_node_eth_api.h> +#include <rte_node_ip4_api.h> +#include <rte_node_pkt_cls_api.h> #include "module_api.h" +static int +setup_fib(int socket) +{ + struct rte_fib_conf conf; + +#define FIB_MAX_ROUTES (UINT16_MAX) +#define FIB_NUM_TBL8 (UINT16_MAX / 2) + conf.type = RTE_FIB_DIR24_8; + conf.max_routes = FIB_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B; + conf.dir24_8.num_tbl8 = FIB_NUM_TBL8; + conf.flags = 0; + + return rte_node_ip4_fib_create(socket, &conf); +} + static int l3fwd_pattern_configure(void) { @@ -53,6 +72,16 @@ l3fwd_pattern_configure(void) graph_conf.num_pkt_to_capture = pcap_pkts_count; graph_conf.pcap_filename = strdup(pcap_file); + if (ip4_lookup_m == IP4_LOOKUP_FIB) { + const char *fib_n = "ip4_lookup_fib"; + const char *lpm_n = "ip4_lookup"; + rte_node_t pkt_cls; + + pkt_cls = rte_node_from_name("pkt_cls"); + rte_node_edge_update(pkt_cls, RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, &fib_n, 1); + rte_node_edge_update(pkt_cls, RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB, &lpm_n, 1); + } + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { rte_graph_t graph_id; rte_edge_t i; @@ -78,6 +107,13 @@ l3fwd_pattern_configure(void) snprintf(qconf->name, sizeof(qconf->name), "worker_%u", lcore_id); + if (ip4_lookup_m == IP4_LOOKUP_FIB) { + rc = setup_fib(graph_conf.socket_id); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to setup fib for socket %u\n", + graph_conf.socket_id); + } + graph_id = rte_graph_create(qconf->name, &graph_conf); if (graph_id == RTE_GRAPH_ID_INVALID) rte_exit(EXIT_FAILURE, diff --git a/app/graph/module_api.h b/app/graph/module_api.h index b872872dc1..b8188d30d5 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -27,6 +27,13 @@ extern volatile bool force_quit; extern struct conn *conn; +enum ip4_lookup_mode { + IP4_LOOKUP_LPM, + IP4_LOOKUP_FIB +}; + +extern enum ip4_lookup_mode ip4_lookup_m; + bool app_graph_stats_enabled(void); bool app_graph_exit(void); diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index d8c147d73e..2caf441591 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -235,10 +235,14 @@ file to express the requested use case configuration. | | | message. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | | ipv4_lookup route add ipv4 <ip> | | Command to add a route into | :ref:`3 <scopes>` | Yes | - | | netmask <mask> via <ip> | | ``ipv4_lookup`` LPM table. It is| | | - | | | needed if user wishes to route | | | - | | | the packets based on LPM lookup | | | - | | | table. | | | + | | netmask <mask> via <ip> | | ``ipv4_lookup`` LPM table or | | | + | | | FIB. It is needed if user wishes| | | + | | | to route the packets based on | | | + | | | LPM lookup table or FIB. | | | + +--------------------------------------+-----------------------------------+-------------------+----------+ + | | ipv4_lookup mode <lpm|fib> | | Command to set ipv4 lookup mode | :ref:`1 <scopes>` | Yes | + | | | to either LPM or FIB. By default| | | + | | | the lookup mode is LPM. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | help ipv4_lookup | | Command to dump ``ipv4_lookup`` | :ref:`2 <scopes>` | Yes | | | | help message. | | | -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 08/13] fib: move macro to header file 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (6 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 07/13] app/graph: add IP4 lookup mode command Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 09/13] node: add IP6 lookup FIB node Ankur Dwivedi ` (4 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Moves the macro FIB6_NAMESIZE to header file and rename it to RTE_FIB6_NAMESIZE. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/fib/rte_fib6.c | 11 ++++------- lib/fib/rte_fib6.h | 3 +++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/fib/rte_fib6.c b/lib/fib/rte_fib6.c index 00647bdfa4..93a1c7197b 100644 --- a/lib/fib/rte_fib6.c +++ b/lib/fib/rte_fib6.c @@ -28,9 +28,6 @@ static struct rte_tailq_elem rte_fib6_tailq = { }; EAL_REGISTER_TAILQ(rte_fib6_tailq) -/* Maximum length of a FIB name. */ -#define FIB6_NAMESIZE 64 - #if defined(RTE_LIBRTE_FIB_DEBUG) #define FIB6_RETURN_IF_TRUE(cond, retval) do { \ if (cond) \ @@ -41,7 +38,7 @@ EAL_REGISTER_TAILQ(rte_fib6_tailq) #endif struct rte_fib6 { - char name[FIB6_NAMESIZE]; + char name[RTE_FIB6_NAMESIZE]; enum rte_fib6_type type; /**< Type of FIB struct */ struct rte_rib6 *rib; /**< RIB helper datastructure */ void *dp; /**< pointer to the dataplane struct*/ @@ -157,7 +154,7 @@ RTE_EXPORT_SYMBOL(rte_fib6_create) struct rte_fib6 * rte_fib6_create(const char *name, int socket_id, struct rte_fib6_conf *conf) { - char mem_name[FIB6_NAMESIZE]; + char mem_name[RTE_FIB6_NAMESIZE]; int ret; struct rte_fib6 *fib = NULL; struct rte_rib6 *rib = NULL; @@ -190,7 +187,7 @@ rte_fib6_create(const char *name, int socket_id, struct rte_fib6_conf *conf) /* guarantee there's no existing */ TAILQ_FOREACH(te, fib_list, next) { fib = (struct rte_fib6 *)te->data; - if (strncmp(name, fib->name, FIB6_NAMESIZE) == 0) + if (strncmp(name, fib->name, RTE_FIB6_NAMESIZE) == 0) break; } fib = NULL; @@ -261,7 +258,7 @@ rte_fib6_find_existing(const char *name) rte_mcfg_tailq_read_lock(); TAILQ_FOREACH(te, fib_list, next) { fib = (struct rte_fib6 *) te->data; - if (strncmp(name, fib->name, FIB6_NAMESIZE) == 0) + if (strncmp(name, fib->name, RTE_FIB6_NAMESIZE) == 0) break; } rte_mcfg_tailq_read_unlock(); diff --git a/lib/fib/rte_fib6.h b/lib/fib/rte_fib6.h index 42e6138708..625df1fa6b 100644 --- a/lib/fib/rte_fib6.h +++ b/lib/fib/rte_fib6.h @@ -28,6 +28,9 @@ extern "C" { /** Maximum depth value possible for IPv6 FIB. */ #define RTE_FIB6_MAXDEPTH (RTE_DEPRECATED(RTE_FIB6_MAXDEPTH) RTE_IPV6_MAX_DEPTH) +/* Maximum length of a FIB name. */ +#define RTE_FIB6_NAMESIZE 64 + struct rte_fib6; struct rte_rib6; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 09/13] node: add IP6 lookup FIB node 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (7 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 08/13] fib: move macro to header file Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 10/13] node: add IP6 FIB route add Ankur Dwivedi ` (3 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a lookup FIB node for IP6. Adds a public function to do fib configuration from application. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 139 ++++++++++++++++++++++++++++++++++++ lib/node/meson.build | 1 + lib/node/rte_node_ip6_api.h | 15 ++++ 3 files changed, 155 insertions(+) create mode 100644 lib/node/ip6_lookup_fib.c diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c new file mode 100644 index 0000000000..a4f9f53644 --- /dev/null +++ b/lib/node/ip6_lookup_fib.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2025 Marvell. + */ + +#include <eal_export.h> +#include <rte_errno.h> +#include <rte_ether.h> +#include <rte_fib6.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_ip.h> + +#include "rte_node_ip6_api.h" + +#include "node_private.h" + +/* IP6 Lookup FIB global data struct */ +struct ip6_lookup_fib_node_main { + struct rte_fib6 *fib6[RTE_MAX_NUMA_NODES]; +}; + +struct ip6_lookup_fib_node_ctx { + /* Socket's FIB6 */ + struct rte_fib6 *fib6; + /* Dynamic offset to mbuf priv1 */ + int mbuf_priv1_off; +}; + +static struct ip6_lookup_fib_node_main ip6_lookup_fib_nm; + +#define FIB6_DEFAULT_MAX_ROUTES (UINT16_MAX) +#define FIB6_DEFAULT_NUM_TBL8 (UINT16_MAX / 2) +#define FIB6_DEFAULT_NH (RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP << 16) + +#define IP6_LOOKUP_FIB_NODE(ctx) \ + (((struct ip6_lookup_fib_node_ctx *)ctx)->fib6) + +#define IP6_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ + (((struct ip6_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip6_fib_create, 25.07) +int +rte_node_ip6_fib_create(int socket, struct rte_fib6_conf *conf) +{ + struct ip6_lookup_fib_node_main *nm = &ip6_lookup_fib_nm; + char s[RTE_FIB6_NAMESIZE]; + + /* One fib6 per socket */ + if (nm->fib6[socket]) + return 0; + + conf->default_nh = FIB6_DEFAULT_NH; + snprintf(s, sizeof(s), "IPV6_LOOKUP_FIB_%u", socket); + nm->fib6[socket] = rte_fib6_create(s, socket, conf); + if (nm->fib6[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +setup_fib6(int socket) +{ + struct ip6_lookup_fib_node_main *nm = &ip6_lookup_fib_nm; + struct rte_fib6_conf conf; + char s[RTE_FIB6_NAMESIZE]; + + /* One fib6 per socket */ + if (nm->fib6[socket]) + return 0; + + conf.type = RTE_FIB6_TRIE; + conf.default_nh = FIB6_DEFAULT_NH; + conf.max_routes = FIB6_DEFAULT_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.trie.nh_sz = RTE_FIB6_TRIE_4B; + conf.trie.num_tbl8 = FIB6_DEFAULT_NUM_TBL8; + snprintf(s, sizeof(s), "IPV6_LOOKUP_FIB_%u", socket); + nm->fib6[socket] = rte_fib6_create(s, socket, &conf); + if (nm->fib6[socket] == NULL) + return -rte_errno; + + return 0; +} + +static int +ip6_lookup_fib_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + static uint8_t init_once; + int rc; + + RTE_BUILD_BUG_ON(sizeof(struct ip6_lookup_fib_node_ctx) > RTE_NODE_CTX_SZ); + + if (!init_once) { + node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( + &node_mbuf_priv1_dynfield_desc); + if (node_mbuf_priv1_dynfield_offset < 0) + return -rte_errno; + + init_once = 1; + } + + rc = setup_fib6(graph->socket); + if (rc) { + node_err("ip6_lookup_fib", "Failed to setup fib6 for sock %u, rc=%d", + graph->socket, rc); + return rc; + } + + /* Update socket's FIB and mbuf dyn priv1 offset in node ctx */ + IP6_LOOKUP_FIB_NODE(node->ctx) = ip6_lookup_fib_nm.fib6[graph->socket]; + IP6_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + + node_dbg("ip6_lookup_fib", "Initialized ip6_lookup_fib node"); + + return 0; +} + +static struct rte_node_xstats ip6_lookup_fib_xstats = { + .nb_xstats = 1, + .xstat_desc = { + [0] = "ip6_lookup_fib_error", + }, +}; + +static struct rte_node_register ip6_lookup_fib_node = { + .name = "ip6_lookup_fib", + + .init = ip6_lookup_fib_node_init, + .xstats = &ip6_lookup_fib_xstats, + + .nb_edges = RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP + 1, + .next_nodes = { + [RTE_NODE_IP6_LOOKUP_NEXT_REWRITE] = "ip6_rewrite", + [RTE_NODE_IP6_LOOKUP_NEXT_PKT_DROP] = "pkt_drop", + }, +}; + +RTE_NODE_REGISTER(ip6_lookup_fib_node); diff --git a/lib/node/meson.build b/lib/node/meson.build index 8112cf7f5b..5ff52a2c44 100644 --- a/lib/node/meson.build +++ b/lib/node/meson.build @@ -17,6 +17,7 @@ sources = files( 'ip4_reassembly.c', 'ip4_rewrite.c', 'ip6_lookup.c', + 'ip6_lookup_fib.c', 'ip6_rewrite.c', 'kernel_rx.c', 'kernel_tx.c', diff --git a/lib/node/rte_node_ip6_api.h b/lib/node/rte_node_ip6_api.h index 2875bc981a..1d2b190724 100644 --- a/lib/node/rte_node_ip6_api.h +++ b/lib/node/rte_node_ip6_api.h @@ -17,6 +17,7 @@ */ #include <rte_common.h> #include <rte_compat.h> +#include <rte_fib6.h> #include <rte_ip6.h> #ifdef __cplusplus @@ -71,6 +72,20 @@ __rte_experimental int rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port); +/** + * Create ipv6 FIB. + * + * @param socket + * NUMA socket for FIB memory allocation. + * @param conf + * Structure containing FIB configuration. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip6_fib_create(int socket, struct rte_fib6_conf *conf); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 10/13] node: add IP6 FIB route add 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (8 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 09/13] node: add IP6 lookup FIB node Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 11/13] node: add process callback for IP6 FIB Ankur Dwivedi ` (2 subsequent siblings) 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a public function to add IP6 route to FIB. The applications should call this function to add IP6 routes to FIB. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 35 +++++++++++++++++++++++++++++++++++ lib/node/rte_node_ip6_api.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c index a4f9f53644..b510452ad8 100644 --- a/lib/node/ip6_lookup_fib.c +++ b/lib/node/ip6_lookup_fib.c @@ -2,6 +2,8 @@ * Copyright(C) 2025 Marvell. */ +#include <arpa/inet.h> + #include <eal_export.h> #include <rte_errno.h> #include <rte_ether.h> @@ -58,6 +60,39 @@ rte_node_ip6_fib_create(int socket, struct rte_fib6_conf *conf) return 0; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip6_fib_route_add, 25.07) +int +rte_node_ip6_fib_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node) +{ + char abuf[INET6_ADDRSTRLEN]; + unsigned int nb_sockets; + uint8_t socket; + uint32_t val; + int ret; + + nb_sockets = rte_socket_count(); + inet_ntop(AF_INET6, ip, abuf, sizeof(abuf)); + /* Embedded next node id into 24 bit next hop */ + val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1); + node_dbg("ip6_lookup_fib", "FIB6: Adding route %s / %d nh (0x%x)", abuf, depth, val); + + for (socket = 0; socket < nb_sockets; socket++) { + if (!ip6_lookup_fib_nm.fib6[socket]) + continue; + + ret = rte_fib6_add(ip6_lookup_fib_nm.fib6[socket], ip, depth, val); + if (ret < 0) { + node_err("ip6_lookup_fib", + "Unable to add entry %s / %d nh (%x) to FIB on sock %d, rc=%d", + abuf, depth, val, socket, ret); + return ret; + } + } + + return 0; +} + static int setup_fib6(int socket) { diff --git a/lib/node/rte_node_ip6_api.h b/lib/node/rte_node_ip6_api.h index 1d2b190724..31089b35fc 100644 --- a/lib/node/rte_node_ip6_api.h +++ b/lib/node/rte_node_ip6_api.h @@ -86,6 +86,25 @@ int rte_node_ip6_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, __rte_experimental int rte_node_ip6_fib_create(int socket, struct rte_fib6_conf *conf); +/** + * Add IPv6 route to FIB. + * + * @param ip + * IPv6 address of route to be added. + * @param depth + * Depth of the rule to be added. + * @param next_hop + * Next hop id of the rule result to be added. + * @param next_node + * Next node to redirect traffic to. + * + * @return + * 0 on success, negative otherwise. + */ +__rte_experimental +int rte_node_ip6_fib_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop, + enum rte_node_ip6_lookup_next next_node); + #ifdef __cplusplus } #endif -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 11/13] node: add process callback for IP6 FIB 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (9 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 10/13] node: add IP6 FIB route add Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 12/13] node: add next node in packet classification Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 13/13] app/graph: add IP6 lookup mode command Ankur Dwivedi 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds the process callback function for ip6_lookup_fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/ip6_lookup_fib.c | 148 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/lib/node/ip6_lookup_fib.c b/lib/node/ip6_lookup_fib.c index b510452ad8..3df61890e9 100644 --- a/lib/node/ip6_lookup_fib.c +++ b/lib/node/ip6_lookup_fib.c @@ -40,6 +40,153 @@ static struct ip6_lookup_fib_node_main ip6_lookup_fib_nm; #define IP6_LOOKUP_FIB_NODE_PRIV1_OFF(ctx) \ (((struct ip6_lookup_fib_node_ctx *)ctx)->mbuf_priv1_off) +static uint16_t +ip6_lookup_fib_node_process(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; + const int dyn = IP6_LOOKUP_FIB_NODE_PRIV1_OFF(node->ctx); + struct rte_fib6 *fib = IP6_LOOKUP_FIB_NODE(node->ctx); + struct rte_ipv6_addr ip[RTE_GRAPH_BURST_SIZE] = { 0 }; + uint64_t next_hop[RTE_GRAPH_BURST_SIZE]; + struct rte_ipv6_hdr *ipv6_hdr; + uint16_t lookup_err = 0; + void **to_next, **from; + uint16_t last_spec = 0; + rte_edge_t next_index; + uint16_t n_left_from; + uint16_t held = 0; + uint16_t next; + int i; + + /* Speculative next */ + next_index = RTE_NODE_IP6_LOOKUP_NEXT_REWRITE; + + pkts = (struct rte_mbuf **)objs; + from = objs; + n_left_from = nb_objs; + + /* Get stream for the speculated next node */ + to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + for (i = 0; i < 4 && i < n_left_from; i++) + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], void *, + sizeof(struct rte_ether_hdr))); + + i = 0; + while (n_left_from >= 4) { + if (likely(n_left_from > 7)) { + + /* Prefetch next-next mbufs */ + if (likely(n_left_from > 11)) { + rte_prefetch0(pkts[8]); + rte_prefetch0(pkts[9]); + rte_prefetch0(pkts[10]); + rte_prefetch0(pkts[11]); + } + + /* Prefetch next mbuf data */ + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[4], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[5], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[6], void *, + sizeof(struct rte_ether_hdr))); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[7], void *, + sizeof(struct rte_ether_hdr))); + } + + mbuf0 = pkts[0]; + mbuf1 = pkts[1]; + mbuf2 = pkts[2]; + mbuf3 = pkts[3]; + pkts += 4; + n_left_from -= 4; + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf1 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf2 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + + /* Extract DIP of mbuf3 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + } + while (n_left_from > 0) { + mbuf0 = pkts[0]; + pkts += 1; + n_left_from -= 1; + + /* Extract DIP of mbuf0 */ + ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf0, struct rte_ipv6_hdr *, + sizeof(struct rte_ether_hdr)); + /* Extract hop_limits as ipv6 hdr is in cache */ + node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits; + + ip[i++] = ipv6_hdr->dst_addr; + } + + rte_fib6_lookup_bulk(fib, ip, next_hop, nb_objs); + + for (i = 0; i < nb_objs; i++) { + mbuf0 = (struct rte_mbuf *)objs[i]; + node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop[i]; + next = (uint16_t)(next_hop[i] >> 16); + + if (unlikely(next_index ^ next)) { + /* Copy things successfully speculated till now */ + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + from += last_spec; + to_next += last_spec; + held += last_spec; + last_spec = 0; + + rte_node_enqueue_x1(graph, node, next, from[0]); + from += 1; + } else { + last_spec += 1; + } + + if (unlikely(next_hop[i] == FIB6_DEFAULT_NH)) + lookup_err += 1; + } + + /* !!! Home run !!! */ + if (likely(last_spec == nb_objs)) { + rte_node_next_stream_move(graph, node, next_index); + return nb_objs; + } + + NODE_INCREMENT_XSTAT_ID(node, 0, lookup_err != 0, lookup_err); + held += last_spec; + rte_memcpy(to_next, from, last_spec * sizeof(from[0])); + rte_node_next_stream_put(graph, node, next_index, held); + + return nb_objs; +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_node_ip6_fib_create, 25.07) int rte_node_ip6_fib_create(int socket, struct rte_fib6_conf *conf) @@ -159,6 +306,7 @@ static struct rte_node_xstats ip6_lookup_fib_xstats = { }; static struct rte_node_register ip6_lookup_fib_node = { + .process = ip6_lookup_fib_node_process, .name = "ip6_lookup_fib", .init = ip6_lookup_fib_node_init, -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 12/13] node: add next node in packet classification 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (10 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 11/13] node: add process callback for IP6 FIB Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 13/13] app/graph: add IP6 lookup mode command Ankur Dwivedi 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi The ip6_lookup_fib is added as next node in packet classification. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- lib/node/pkt_cls.c | 1 + lib/node/rte_node_pkt_cls_api.h | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/node/pkt_cls.c b/lib/node/pkt_cls.c index f6e76989bc..ca323ea573 100644 --- a/lib/node/pkt_cls.c +++ b/lib/node/pkt_cls.c @@ -234,6 +234,7 @@ struct rte_node_register pkt_cls_node = { [RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP] = "ip4_lookup", [RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP] = "ip6_lookup", [RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB] = "ip4_lookup_fib", + [RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP_FIB] = "ip6_lookup_fib", }, }; RTE_NODE_REGISTER(pkt_cls_node); diff --git a/lib/node/rte_node_pkt_cls_api.h b/lib/node/rte_node_pkt_cls_api.h index 8f935bebbe..cf617d6985 100644 --- a/lib/node/rte_node_pkt_cls_api.h +++ b/lib/node/rte_node_pkt_cls_api.h @@ -28,6 +28,7 @@ enum rte_node_pkt_cls_next { RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP, RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB, + RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP_FIB, RTE_NODE_PKT_CLS_NEXT_MAX, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 13/13] app/graph: add IP6 lookup mode command 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi ` (11 preceding siblings ...) 2025-05-09 6:44 ` [PATCH v2 12/13] node: add next node in packet classification Ankur Dwivedi @ 2025-05-09 6:44 ` Ankur Dwivedi 12 siblings, 0 replies; 36+ messages in thread From: Ankur Dwivedi @ 2025-05-09 6:44 UTC (permalink / raw) To: dev Cc: jerinj, vladimir.medvedkin, ndabilpuram, pbhagavatula, skori, rkudurumalla, nsaxena, Ankur Dwivedi Adds a command to setup lookup mode for IP6 packets. By default LPM mode is used. FIB can be given as a lookup mode by specifying the mode in CLI file. When FIB is given as lookup mode, the next node of packet classification node is updated to use IP6 lookup fib node. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- app/graph/commands.list | 1 + app/graph/ip6_route.c | 33 +++++++++++++++++++++++++++++---- app/graph/l3fwd.c | 34 ++++++++++++++++++++++++++++++++++ app/graph/module_api.h | 6 ++++++ doc/guides/tools/graph.rst | 12 ++++++++---- 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/app/graph/commands.list b/app/graph/commands.list index 7a1bf0c708..ffdab4fc97 100644 --- a/app/graph/commands.list +++ b/app/graph/commands.list @@ -27,6 +27,7 @@ ipv4_lookup mode <STRING>lkup_mode # Set IPv4 lookup mode help ipv4_lookup # Print help on ipv4_lookup commands ipv6_lookup route add ipv6 <IPv6>ip netmask <IPv6>mask via <IPv6>via_ip # Add IPv6 route to LPM6 table +ipv6_lookup mode <STRING>lkup_mode # Set IPv6 lookup mode help ipv6_lookup # Print help on ipv6_lookup commands neigh add ipv4 <IPv4>ip <STRING>mac # Add static neighbour for IPv4 diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c index ec53239b06..14c0c83638 100644 --- a/app/graph/ip6_route.c +++ b/app/graph/ip6_route.c @@ -19,8 +19,13 @@ static const char cmd_ipv6_lookup_help[] = "ipv6_lookup route add ipv6 <ip> netmask <mask> via <ip>"; +static const char +cmd_ipv6_lookup_mode_help[] = "ipv6_lookup mode <lpm|fib>"; + struct ip6_route route6 = TAILQ_HEAD_INITIALIZER(route6); +enum ip6_lookup_mode ip6_lookup_m = IP6_LOOKUP_LPM; + void route_ip6_list_clean(void) { @@ -49,6 +54,7 @@ route6_rewirte_table_update(struct route_ipv6_config *ipv6route) { uint8_t depth; int portid; + int rc; portid = ethdev_portid_by_ip6(&ipv6route->gateway, &ipv6route->mask); if (portid < 0) { @@ -57,9 +63,14 @@ route6_rewirte_table_update(struct route_ipv6_config *ipv6route) } depth = rte_ipv6_mask_depth(&ipv6route->mask); - return rte_node_ip6_route_add(&ipv6route->ip, depth, portid, - RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + if (ip6_lookup_m == IP6_LOOKUP_FIB) + rc = rte_node_ip6_fib_route_add(&ipv6route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + else + rc = rte_node_ip6_route_add(&ipv6route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + return rc; } static int @@ -120,9 +131,9 @@ cmd_help_ipv6_lookup_parsed(__rte_unused void *parsed_result, __rte_unused struc len = strlen(conn->msg_out); conn->msg_out += len; - snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", "--------------------------- ipv6_lookup command help ---------------------------", - cmd_ipv6_lookup_help); + cmd_ipv6_lookup_help, cmd_ipv6_lookup_mode_help); len = strlen(conn->msg_out); conn->msg_out_len_max -= len; @@ -144,3 +155,17 @@ cmd_ipv6_lookup_route_add_ipv6_parsed(void *parsed_result, __rte_unused struct c if (rc) printf(MSG_CMD_FAIL, res->ipv6_lookup); } + +void +cmd_ipv6_lookup_mode_parsed(void *parsed_result, __rte_unused struct cmdline *cl, + void *data __rte_unused) +{ + struct cmd_ipv6_lookup_mode_result *res = parsed_result; + + if (!strcmp(res->lkup_mode, "lpm")) + ip6_lookup_m = IP6_LOOKUP_LPM; + else if (!strcmp(res->lkup_mode, "fib")) + ip6_lookup_m = IP6_LOOKUP_FIB; + else + printf(MSG_CMD_FAIL, res->ipv6_lookup); +} diff --git a/app/graph/l3fwd.c b/app/graph/l3fwd.c index 48dff9fa07..fe25e43da8 100644 --- a/app/graph/l3fwd.c +++ b/app/graph/l3fwd.c @@ -16,6 +16,7 @@ #include <rte_lcore.h> #include <rte_node_eth_api.h> #include <rte_node_ip4_api.h> +#include <rte_node_ip6_api.h> #include <rte_node_pkt_cls_api.h> #include "module_api.h" @@ -37,6 +38,22 @@ setup_fib(int socket) return rte_node_ip4_fib_create(socket, &conf); } +static int +setup_fib6(int socket) +{ + struct rte_fib6_conf conf; + +#define FIB6_MAX_ROUTES (UINT16_MAX) +#define FIB6_NUM_TBL8 (UINT16_MAX / 2) + conf.type = RTE_FIB6_TRIE; + conf.max_routes = FIB6_MAX_ROUTES; + conf.rib_ext_sz = 0; + conf.trie.nh_sz = RTE_FIB6_TRIE_4B; + conf.trie.num_tbl8 = FIB6_NUM_TBL8; + + return rte_node_ip6_fib_create(socket, &conf); +} + static int l3fwd_pattern_configure(void) { @@ -82,6 +99,16 @@ l3fwd_pattern_configure(void) rte_node_edge_update(pkt_cls, RTE_NODE_PKT_CLS_NEXT_IP4_LOOKUP_FIB, &lpm_n, 1); } + if (ip6_lookup_m == IP6_LOOKUP_FIB) { + const char *fib6_n = "ip6_lookup_fib"; + const char *lpm6_n = "ip6_lookup"; + rte_node_t pkt_cls; + + pkt_cls = rte_node_from_name("pkt_cls"); + rte_node_edge_update(pkt_cls, RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP, &fib6_n, 1); + rte_node_edge_update(pkt_cls, RTE_NODE_PKT_CLS_NEXT_IP6_LOOKUP_FIB, &lpm6_n, 1); + } + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { rte_graph_t graph_id; rte_edge_t i; @@ -114,6 +141,13 @@ l3fwd_pattern_configure(void) graph_conf.socket_id); } + if (ip6_lookup_m == IP6_LOOKUP_FIB) { + rc = setup_fib6(graph_conf.socket_id); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to setup fib6 for socket %u\n", + graph_conf.socket_id); + } + graph_id = rte_graph_create(qconf->name, &graph_conf); if (graph_id == RTE_GRAPH_ID_INVALID) rte_exit(EXIT_FAILURE, diff --git a/app/graph/module_api.h b/app/graph/module_api.h index b8188d30d5..5e3a384cb0 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -32,7 +32,13 @@ enum ip4_lookup_mode { IP4_LOOKUP_FIB }; +enum ip6_lookup_mode { + IP6_LOOKUP_LPM, + IP6_LOOKUP_FIB +}; + extern enum ip4_lookup_mode ip4_lookup_m; +extern enum ip6_lookup_mode ip6_lookup_m; bool app_graph_stats_enabled(void); bool app_graph_exit(void); diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 2caf441591..dd525f6037 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -248,10 +248,14 @@ file to express the requested use case configuration. | | | help message. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | | ipv6_lookup route add ipv6 <ip> | | Command to add a route into | :ref:`3 <scopes>` | Yes | - | | netmask <mask> via <ip> | | ``ipv6_lookup`` LPM table. It is| | | - | | | needed if user wishes to route | | | - | | | the packets based on LPM6 lookup| | | - | | | table. | | | + | | netmask <mask> via <ip> | | ``ipv6_lookup`` LPM table or. | | | + | | | FIB. It is needed if user wishes| | | + | | | to route the packets based on | | | + | | | LPM6 lookup table or FIB. | | | + +--------------------------------------+-----------------------------------+-------------------+----------+ + | | ipv6_lookup mode <lpm|fib> | | Command to set ipv6 lookup mode | :ref:`1 <scopes>` | Yes | + | | | to either LPM or FIB. By default| | | + | | | the lookup mode is LPM. | | | +--------------------------------------+-----------------------------------+-------------------+----------+ | help ipv6_lookup | | Command to dump ``ipv6_lookup`` | :ref:`2 <scopes>` | Yes | | | | help message. | | | -- 2.25.1 ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2025-05-09 6:46 UTC | newest] Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-04-15 12:10 [PATCH v1 00/12] add lookup fib nodes in graph library Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 01/12] fib: move macro to header file Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 02/12] node: add IP4 lookup FIB node Ankur Dwivedi 2025-04-16 7:32 ` Nitin Saxena 2025-04-16 10:26 ` [EXTERNAL] " Ankur Dwivedi 2025-04-16 9:34 ` Medvedkin, Vladimir 2025-04-16 10:07 ` [EXTERNAL] " Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 03/12] node: add IP4 FIB route add Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 04/12] node: add process callback for IP4 FIB Ankur Dwivedi 2025-04-16 7:54 ` Nitin Saxena 2025-04-16 12:54 ` Medvedkin, Vladimir 2025-04-18 7:38 ` [EXTERNAL] " Ankur Dwivedi 2025-04-19 18:14 ` Vladimir Medvedkin 2025-04-23 9:46 ` Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 05/12] node: add next node in packet classification Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 06/12] app/graph: add IP4 lookup mode command Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 07/12] fib: move macro to header file Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 08/12] node: add IP6 lookup FIB node Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 09/12] node: add IP6 FIB route add Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 10/12] node: add process callback for IP6 FIB Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 11/12] node: add next node in packet classification Ankur Dwivedi 2025-04-15 12:10 ` [PATCH v1 12/12] app/graph: add IP6 lookup mode command Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 00/13] add lookup fib nodes in graph library Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 01/13] fib: move macro to header file Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 02/13] node: add IP4 lookup FIB node Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 03/13] node: add IP4 FIB route add Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 04/13] node: add process callback for IP4 FIB Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 05/13] node: move next nodes to public header file Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 06/13] node: add next node in packet classification Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 07/13] app/graph: add IP4 lookup mode command Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 08/13] fib: move macro to header file Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 09/13] node: add IP6 lookup FIB node Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 10/13] node: add IP6 FIB route add Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 11/13] node: add process callback for IP6 FIB Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 12/13] node: add next node in packet classification Ankur Dwivedi 2025-05-09 6:44 ` [PATCH v2 13/13] app/graph: add IP6 lookup mode command Ankur Dwivedi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).