DPDK patches and discussions
 help / color / mirror / Atom feed
* [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
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ 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] 16+ 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
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 16+ 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] 16+ 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
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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-15 12:10 ` [PATCH v1 05/12] node: add next node in packet classification Ankur Dwivedi
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 16+ 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] 16+ 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
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ 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] 16+ 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
  2025-04-15 12:10 ` [PATCH v1 12/12] app/graph: add IP6 lookup mode command Ankur Dwivedi
  11 siblings, 0 replies; 16+ 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] 16+ 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
  11 siblings, 0 replies; 16+ 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] 16+ 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
  11 siblings, 0 replies; 16+ 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] 16+ 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
  1 sibling, 0 replies; 16+ 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] 16+ 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
  0 siblings, 0 replies; 16+ 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] 16+ 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
  1 sibling, 0 replies; 16+ 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] 16+ messages in thread

end of thread, other threads:[~2025-04-16  9:35 UTC | newest]

Thread overview: 16+ 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  9:34   ` Medvedkin, Vladimir
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-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

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).