DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd
@ 2021-02-18 12:15 Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                   ` (5 more replies)
  0 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
The flag '-F' has been added to the applications options to allow
the user to use this lookup method.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 488 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +---
 examples/l3fwd/main.c                   |  43 ++-
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 717 insertions(+), 76 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-02-18 12:15 ` Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-02-18 12:15 ` Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-02-18 12:15 ` Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
The flag '-F' has been added to the applications options to allow
the user to specify that l3fwd uses FIB as its lookup method.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/Makefile      |  2 +-
 examples/l3fwd/l3fwd.h       | 27 ++++++++++++++--
 examples/l3fwd/l3fwd_event.c |  9 ++++++
 examples/l3fwd/l3fwd_event.h |  1 +
 examples/l3fwd/l3fwd_fib.c   | 60 ++++++++++++++++++++++++++++++++++++
 examples/l3fwd/main.c        | 43 +++++++++++++++++++-------
 examples/l3fwd/meson.build   |  4 +--
 7 files changed, 129 insertions(+), 17 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..6881b49478 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,10 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
 static int l3fwd_lpm_on;
 static int l3fwd_em_on;
+static int l3fwd_fib_on;
 
 /* Global variables. */
 
@@ -162,10 +163,19 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
@@ -173,6 +183,9 @@ setup_l3fwd_lookup_tables(void)
 	/* Setup HASH lookup functions. */
 	if (l3fwd_em_on)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (l3fwd_fib_on)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -292,6 +305,7 @@ print_usage(const char *prgname)
 		"  -P : Enable promiscuous mode\n"
 		"  -E : Enable exact match\n"
 		"  -L : Enable longest prefix match (default)\n"
+		"  -F : Enable forwarding information base\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -492,6 +506,7 @@ static const char short_options[] =
 	"P"   /* promiscuous */
 	"L"   /* enable long prefix match */
 	"E"   /* enable exact match */
+	"F"   /* forwarding information base */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
 			l3fwd_lpm_on = 1;
 			break;
 
+		case 'F':
+			l3fwd_fib_on = 1;
+			break;
+
 		/* long options */
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
@@ -686,9 +705,9 @@ parse_args(int argc, char **argv)
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
+	/* If more than 1 of LPM, EM and FIB are selected, return error. */
+	if ((l3fwd_lpm_on + l3fwd_em_on + l3fwd_fib_on) > 1) {
+		fprintf(stderr, "LPM, EM and FIB are mutually exclusive, select only one\n");
 		return -1;
 	}
 
@@ -711,14 +730,14 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
+	if (!l3fwd_lpm_on && !l3fwd_em_on && !l3fwd_fib_on) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, default LPM on\n");
 		l3fwd_lpm_on = 1;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
 	if (l3fwd_lpm_on) {
@@ -780,7 +799,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1221,6 +1240,8 @@ main(int argc, char **argv)
 		l3fwd_event_resource_setup(&port_conf);
 		if (l3fwd_em_on)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (l3fwd_fib_on)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                   ` (2 preceding siblings ...)
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-02-18 12:15 ` Conor Walsh
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 440 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 434 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..b45b20e06a 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,487 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#include "l3fwd_sse.h"
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+l3fwd_fib_parse_packet(struct rte_mbuf *mbuf,
+		       uint32_t *ipv4, uint32_t *ipv4_cnt,
+		       uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		       uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+l3fwd_fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+			uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_reassem = 0, ipv6_reassem = 0;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+					       i + FIB_PREFETCH_OFFSET],
+					       void *));
+		l3fwd_fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		l3fwd_fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				    ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				     ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i]) {
+			if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv4[ipv4_reassem];
+			else
+				hops[i] = portid;
+			ipv4_reassem++;
+		} else {
+			if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv6[ipv6_reassem];
+			else
+				hops[i] = portid;
+			ipv6_reassem++;
+		}
+	}
+
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+				   US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+			" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+			lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+						 MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			l3fwd_fib_send_packets(nb_rx, pkts_burst,
+					       portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		 const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+		evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_reassem, ipv6_reassem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+						 events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_reassem = 0;
+		ipv6_reassem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+						i + FIB_PREFETCH_OFFSET].mbuf,
+						void *));
+
+			l3fwd_fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			l3fwd_fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					    ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					     ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i]) {
+				if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv4[ipv4_reassem];
+				ipv4_reassem++;
+			} else {
+				if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv6[ipv6_reassem];
+				ipv6_reassem++;
+			}
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+						events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+				&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+					  abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                   ` (3 preceding siblings ...)
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-02-18 12:15 ` Conor Walsh
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 12:15 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 8 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..266e1eb810 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -55,6 +55,7 @@ The application has a number of command line options::
                              [-P]
                              [-E]
                              [-L]
+                             [-F]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -78,6 +79,8 @@ Where,
 
 * ``-L:`` Optional, enable longest prefix match.
 
+* ``-F:`` Optional, enable forwarding information base.
+
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
 * ``--eth-dest=X,MM:MM:MM:MM:MM:MM:`` Optional, ethernet destination for port X.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                   ` (4 preceding siblings ...)
  2021-02-18 12:15 ` [dpdk-dev] [PATCH 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-02-18 15:20 ` Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                     ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
The flag '-F' has been added to the applications options to allow
the user to use this lookup method.

---

v2: added socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 489 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +---
 examples/l3fwd/main.c                   |  43 ++-
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 718 insertions(+), 76 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-02-18 15:20   ` Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-02-18 15:20   ` Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-02-18 15:20   ` Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
The flag '-F' has been added to the applications options to allow
the user to specify that l3fwd uses FIB as its lookup method.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/Makefile      |  2 +-
 examples/l3fwd/l3fwd.h       | 27 ++++++++++++++--
 examples/l3fwd/l3fwd_event.c |  9 ++++++
 examples/l3fwd/l3fwd_event.h |  1 +
 examples/l3fwd/l3fwd_fib.c   | 60 ++++++++++++++++++++++++++++++++++++
 examples/l3fwd/main.c        | 43 +++++++++++++++++++-------
 examples/l3fwd/meson.build   |  4 +--
 7 files changed, 129 insertions(+), 17 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..6881b49478 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,10 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
 static int l3fwd_lpm_on;
 static int l3fwd_em_on;
+static int l3fwd_fib_on;
 
 /* Global variables. */
 
@@ -162,10 +163,19 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
@@ -173,6 +183,9 @@ setup_l3fwd_lookup_tables(void)
 	/* Setup HASH lookup functions. */
 	if (l3fwd_em_on)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (l3fwd_fib_on)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -292,6 +305,7 @@ print_usage(const char *prgname)
 		"  -P : Enable promiscuous mode\n"
 		"  -E : Enable exact match\n"
 		"  -L : Enable longest prefix match (default)\n"
+		"  -F : Enable forwarding information base\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -492,6 +506,7 @@ static const char short_options[] =
 	"P"   /* promiscuous */
 	"L"   /* enable long prefix match */
 	"E"   /* enable exact match */
+	"F"   /* forwarding information base */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
 			l3fwd_lpm_on = 1;
 			break;
 
+		case 'F':
+			l3fwd_fib_on = 1;
+			break;
+
 		/* long options */
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
@@ -686,9 +705,9 @@ parse_args(int argc, char **argv)
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
+	/* If more than 1 of LPM, EM and FIB are selected, return error. */
+	if ((l3fwd_lpm_on + l3fwd_em_on + l3fwd_fib_on) > 1) {
+		fprintf(stderr, "LPM, EM and FIB are mutually exclusive, select only one\n");
 		return -1;
 	}
 
@@ -711,14 +730,14 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
+	if (!l3fwd_lpm_on && !l3fwd_em_on && !l3fwd_fib_on) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, default LPM on\n");
 		l3fwd_lpm_on = 1;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
 	if (l3fwd_lpm_on) {
@@ -780,7 +799,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1221,6 +1240,8 @@ main(int argc, char **argv)
 		l3fwd_event_resource_setup(&port_conf);
 		if (l3fwd_em_on)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (l3fwd_fib_on)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                     ` (2 preceding siblings ...)
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-02-18 15:20   ` Conor Walsh
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 441 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 435 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..3e6ed7bc34 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,488 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#include "l3fwd_sse.h"
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+l3fwd_fib_parse_packet(struct rte_mbuf *mbuf,
+		       uint32_t *ipv4, uint32_t *ipv4_cnt,
+		       uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		       uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+l3fwd_fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+			uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_reassem = 0, ipv6_reassem = 0;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+					       i + FIB_PREFETCH_OFFSET],
+					       void *));
+		l3fwd_fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		l3fwd_fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				    ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				     ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i]) {
+			if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv4[ipv4_reassem];
+			else
+				hops[i] = portid;
+			ipv4_reassem++;
+		} else {
+			if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv6[ipv6_reassem];
+			else
+				hops[i] = portid;
+			ipv6_reassem++;
+		}
+	}
+
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+				   US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+			" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+			lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+						 MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			l3fwd_fib_send_packets(nb_rx, pkts_burst,
+					       portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		 const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+		evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_reassem, ipv6_reassem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+						 events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_reassem = 0;
+		ipv6_reassem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+						i + FIB_PREFETCH_OFFSET].mbuf,
+						void *));
+
+			l3fwd_fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			l3fwd_fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					    ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					     ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i]) {
+				if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv4[ipv4_reassem];
+				ipv4_reassem++;
+			} else {
+				if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv6[ipv6_reassem];
+				ipv6_reassem++;
+			}
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+						events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+				&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+					  abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v2 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                     ` (3 preceding siblings ...)
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-02-18 15:20   ` Conor Walsh
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-18 15:20 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 8 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..266e1eb810 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -55,6 +55,7 @@ The application has a number of command line options::
                              [-P]
                              [-E]
                              [-L]
+                             [-F]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -78,6 +79,8 @@ Where,
 
 * ``-L:`` Optional, enable longest prefix match.
 
+* ``-F:`` Optional, enable forwarding information base.
+
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
 * ``--eth-dest=X,MM:MM:MM:MM:MM:MM:`` Optional, ethernet destination for port X.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                     ` (4 preceding siblings ...)
  2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-02-19 15:09   ` Conor Walsh
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                       ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
The flag '-F' has been added to the applications options to allow
the user to use this lookup method.

---

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 523 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/main.c                   |  43 +-
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 752 insertions(+), 76 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-02-19 15:09     ` Conor Walsh
  2021-03-08 10:41       ` Medvedkin, Vladimir
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                       ` (4 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-02-19 15:09     ` Conor Walsh
  2021-03-02 16:20       ` Ananyev, Konstantin
  2021-03-08 10:42       ` Medvedkin, Vladimir
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                       ` (3 subsequent siblings)
  5 siblings, 2 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-02-19 15:09     ` Conor Walsh
  2021-03-02 16:22       ` Ananyev, Konstantin
                         ` (2 more replies)
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                       ` (2 subsequent siblings)
  5 siblings, 3 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
The flag '-F' has been added to the applications options to allow
the user to specify that l3fwd uses FIB as its lookup method.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/Makefile      |  2 +-
 examples/l3fwd/l3fwd.h       | 27 ++++++++++++++--
 examples/l3fwd/l3fwd_event.c |  9 ++++++
 examples/l3fwd/l3fwd_event.h |  1 +
 examples/l3fwd/l3fwd_fib.c   | 60 ++++++++++++++++++++++++++++++++++++
 examples/l3fwd/main.c        | 43 +++++++++++++++++++-------
 examples/l3fwd/meson.build   |  4 +--
 7 files changed, 129 insertions(+), 17 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..6881b49478 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,10 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
 static int l3fwd_lpm_on;
 static int l3fwd_em_on;
+static int l3fwd_fib_on;
 
 /* Global variables. */
 
@@ -162,10 +163,19 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
@@ -173,6 +183,9 @@ setup_l3fwd_lookup_tables(void)
 	/* Setup HASH lookup functions. */
 	if (l3fwd_em_on)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (l3fwd_fib_on)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -292,6 +305,7 @@ print_usage(const char *prgname)
 		"  -P : Enable promiscuous mode\n"
 		"  -E : Enable exact match\n"
 		"  -L : Enable longest prefix match (default)\n"
+		"  -F : Enable forwarding information base\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -492,6 +506,7 @@ static const char short_options[] =
 	"P"   /* promiscuous */
 	"L"   /* enable long prefix match */
 	"E"   /* enable exact match */
+	"F"   /* forwarding information base */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
 			l3fwd_lpm_on = 1;
 			break;
 
+		case 'F':
+			l3fwd_fib_on = 1;
+			break;
+
 		/* long options */
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
@@ -686,9 +705,9 @@ parse_args(int argc, char **argv)
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
+	/* If more than 1 of LPM, EM and FIB are selected, return error. */
+	if ((l3fwd_lpm_on + l3fwd_em_on + l3fwd_fib_on) > 1) {
+		fprintf(stderr, "LPM, EM and FIB are mutually exclusive, select only one\n");
 		return -1;
 	}
 
@@ -711,14 +730,14 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
+	if (!l3fwd_lpm_on && !l3fwd_em_on && !l3fwd_fib_on) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, default LPM on\n");
 		l3fwd_lpm_on = 1;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
 	if (l3fwd_lpm_on) {
@@ -780,7 +799,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1221,6 +1240,8 @@ main(int argc, char **argv)
 		l3fwd_event_resource_setup(&port_conf);
 		if (l3fwd_em_on)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (l3fwd_fib_on)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                       ` (2 preceding siblings ...)
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-02-19 15:09     ` Conor Walsh
  2021-03-02 16:21       ` Ananyev, Konstantin
                         ` (2 more replies)
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 3 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 475 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 469 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..d5b9a4eae4 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,522 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+			 || defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		       uint32_t *ipv4, uint32_t *ipv4_cnt,
+		       uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		       uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+			struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	for (j = 0; j < nb_tx; j++)
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+			uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_reassem = 0, ipv6_reassem = 0;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+					       i + FIB_PREFETCH_OFFSET],
+					       void *));
+		fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				       &type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				    ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				     ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i]) {
+			if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv4[ipv4_reassem];
+			else
+				hops[i] = portid;
+			ipv4_reassem++;
+		} else {
+			if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+				hops[i] = (uint16_t)hopsv6[ipv6_reassem];
+			else
+				hops[i] = portid;
+			ipv6_reassem++;
+		}
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+				   US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+			" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+			lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+						 MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,
+					       portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		 const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+		evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_reassem, ipv6_reassem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+						 events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_reassem = 0;
+		ipv6_reassem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+						i + FIB_PREFETCH_OFFSET].mbuf,
+						void *));
+
+			fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+								 0);
+
+			fib_parse_packet(events[i].mbuf,
+					       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					       ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					       &type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					    ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					     ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i]) {
+				if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv4[ipv4_reassem];
+				ipv4_reassem++;
+			} else {
+				if (hopsv6[ipv6_reassem] != FIB_DEFAULT_HOP)
+					events[i].mbuf->port =
+						(uint16_t)hopsv6[ipv6_reassem];
+				ipv6_reassem++;
+			}
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+						events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+					l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+				&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+				"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+				i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+					  abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v3 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                       ` (3 preceding siblings ...)
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-02-19 15:09     ` Conor Walsh
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-02-19 15:09 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 103 ++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 8 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..266e1eb810 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -55,6 +55,7 @@ The application has a number of command line options::
                              [-P]
                              [-E]
                              [-L]
+                             [-F]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -78,6 +79,8 @@ Where,
 
 * ``-L:`` Optional, enable longest prefix match.
 
+* ``-F:`` Optional, enable forwarding information base.
+
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
 * ``--eth-dest=X,MM:MM:MM:MM:MM:MM:`` Optional, ethernet destination for port X.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-03-02 16:20       ` Ananyev, Konstantin
  2021-03-08 10:42       ` Medvedkin, Vladimir
  1 sibling, 0 replies; 77+ messages in thread
From: Ananyev, Konstantin @ 2021-03-02 16:20 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Medvedkin, Vladimir
  Cc: dev

> 
> To prevent code duplication from the addition of lookup methods
> the routes specified in lpm should be moved to a common header.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>  examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
>  examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
>  2 files changed, 65 insertions(+), 57 deletions(-)
>  create mode 100644 examples/l3fwd/l3fwd_common_route.h
> 
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-03-02 16:21       ` Ananyev, Konstantin
  2021-03-03 11:52       ` Burakov, Anatoly
  2021-03-08 10:43       ` Medvedkin, Vladimir
  2 siblings, 0 replies; 77+ messages in thread
From: Ananyev, Konstantin @ 2021-03-02 16:21 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Medvedkin, Vladimir
  Cc: dev


> 
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>  examples/l3fwd/l3fwd_fib.c | 475 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 469 insertions(+), 6 deletions(-)
> 
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-03-02 16:22       ` Ananyev, Konstantin
  2021-03-03 11:36       ` Burakov, Anatoly
  2021-03-08 10:42       ` Medvedkin, Vladimir
  2 siblings, 0 replies; 77+ messages in thread
From: Ananyev, Konstantin @ 2021-03-02 16:22 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Medvedkin, Vladimir
  Cc: dev

> 
> The purpose of this commit is to add the necessary function calls
> and supporting infrastructure to allow the Forwarding Information Base
> (FIB) library to be integrated into the l3fwd sample app.
> The flag '-F' has been added to the applications options to allow
> the user to specify that l3fwd uses FIB as its lookup method.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
  2021-03-02 16:22       ` Ananyev, Konstantin
@ 2021-03-03 11:36       ` Burakov, Anatoly
  2021-03-08 15:13         ` Walsh, Conor
  2021-03-08 10:42       ` Medvedkin, Vladimir
  2 siblings, 1 reply; 77+ messages in thread
From: Burakov, Anatoly @ 2021-03-03 11:36 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, vladimir.medvedkin
  Cc: dev

On 19-Feb-21 3:09 PM, Conor Walsh wrote:
> The purpose of this commit is to add the necessary function calls
> and supporting infrastructure to allow the Forwarding Information Base
> (FIB) library to be integrated into the l3fwd sample app.
> The flag '-F' has been added to the applications options to allow
> the user to specify that l3fwd uses FIB as its lookup method.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>   examples/l3fwd/Makefile      |  2 +-
>   examples/l3fwd/l3fwd.h       | 27 ++++++++++++++--
>   examples/l3fwd/l3fwd_event.c |  9 ++++++
>   examples/l3fwd/l3fwd_event.h |  1 +
>   examples/l3fwd/l3fwd_fib.c   | 60 ++++++++++++++++++++++++++++++++++++
>   examples/l3fwd/main.c        | 43 +++++++++++++++++++-------
>   examples/l3fwd/meson.build   |  4 +--
>   7 files changed, 129 insertions(+), 17 deletions(-)
>   create mode 100644 examples/l3fwd/l3fwd_fib.c
> 
> diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
> index 7e70bbd826..5f7baffbf7 100644
> --- a/examples/l3fwd/Makefile
> +++ b/examples/l3fwd/Makefile
> @@ -5,7 +5,7 @@
>   APP = l3fwd
>   
>   # all source are stored in SRCS-y
> -SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
> +SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
>   SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
>   
>   # Build using pkg-config variables if possible
> diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
> index 2cf06099e0..a808d60247 100644
> --- a/examples/l3fwd/l3fwd.h
> +++ b/examples/l3fwd/l3fwd.h
> @@ -1,5 +1,5 @@
>   /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright(c) 2010-2016 Intel Corporation
> + * Copyright(c) 2010-2021 Intel Corporation
>    */
>   
>   #ifndef __L3_FWD_H__
> @@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
>   int
>   init_mem(uint16_t portid, unsigned int nb_mbuf);
>   
> -/* Function pointers for LPM or EM functionality. */
> +/* Function pointers for LPM, EM or FIB functionality. */
>   void
>   setup_lpm(const int socketid);
>   
>   void
>   setup_hash(const int socketid);
>   
> +void
> +setup_fib(const int socketid);
> +
>   int
>   em_check_ptype(int portid);
>   
> @@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
>   int
>   lpm_main_loop(__rte_unused void *dummy);
>   
> +int
> +fib_main_loop(__rte_unused void *dummy);
> +
>   int
>   lpm_event_main_loop_tx_d(__rte_unused void *dummy);
>   int
> @@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
>   int
>   em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
>   
> +int
> +fib_event_main_loop_tx_d(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_q(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
> +
>   
> -/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
> +/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
>   void *
>   em_get_ipv4_l3fwd_lookup_struct(const int socketid);
>   
> @@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
>   void *
>   lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
>   
> +void *
> +fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
> +
> +void *
> +fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
> +
>   #endif  /* __L3_FWD_H__ */
> diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
> index 4d31593a0a..961860ea18 100644
> --- a/examples/l3fwd/l3fwd_event.c
> +++ b/examples/l3fwd/l3fwd_event.c
> @@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
>   		[1][0] = em_event_main_loop_tx_q,
>   		[1][1] = em_event_main_loop_tx_q_burst,
>   	};
> +	const event_loop_cb fib_event_loop[2][2] = {
> +		[0][0] = fib_event_main_loop_tx_d,
> +		[0][1] = fib_event_main_loop_tx_d_burst,
> +		[1][0] = fib_event_main_loop_tx_q,
> +		[1][1] = fib_event_main_loop_tx_q_burst,
> +	};
>   	uint32_t event_queue_cfg;
>   	int ret;
>   
> @@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
>   
>   	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
>   						       [evt_rsrc->has_burst];
> +
> +	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
> +						       [evt_rsrc->has_burst];
>   }
> diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
> index 0e46164170..3ad1902ab5 100644
> --- a/examples/l3fwd/l3fwd_event.h
> +++ b/examples/l3fwd/l3fwd_event.h
> @@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
>   	adapter_setup_cb adapter_setup;
>   	event_loop_cb lpm_event_loop;
>   	event_loop_cb em_event_loop;
> +	event_loop_cb fib_event_loop;
>   };
>   
>   struct l3fwd_event_resources {
> diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
> new file mode 100644
> index 0000000000..0a2d02db2f
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_fib.c
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Intel Corporation
> + */
> +
> +#include <rte_fib.h>
> +#include <rte_fib6.h>
> +
> +#include "l3fwd.h"
> +#include "l3fwd_event.h"
> +#include "l3fwd_common_route.h"
> +
> +/* Main fib processing loop. */
> +int
> +fib_main_loop(__rte_unused void *dummy)
> +{
> +	return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_d(__rte_unused void *dummy)
> +{
> +	return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
> +{
> +	return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_q(__rte_unused void *dummy)
> +{
> +	return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
> +{
> +	return 0;
> +}
> +
> +/* Function to setup fib. */
> +void
> +setup_fib(__rte_unused const int socketid)
> +{}
> +
> +/* Return ipv4 fib lookup struct. */
> +void *
> +fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> +	return 0;
> +}
> +
> +/* Return ipv6 fib lookup struct. */
> +void *
> +fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> +	return 0;
> +}
> diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
> index bb49e5faff..6881b49478 100644
> --- a/examples/l3fwd/main.c
> +++ b/examples/l3fwd/main.c
> @@ -1,5 +1,5 @@
>   /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright(c) 2010-2016 Intel Corporation
> + * Copyright(c) 2010-2021 Intel Corporation
>    */
>   
>   #include <stdio.h>
> @@ -60,9 +60,10 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
>   /**< Ports set in promiscuous mode off by default. */
>   static int promiscuous_on;
>   
> -/* Select Longest-Prefix or Exact match. */
> +/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
>   static int l3fwd_lpm_on;
>   static int l3fwd_em_on;
> +static int l3fwd_fib_on;
>   
>   /* Global variables. */
>   
> @@ -162,10 +163,19 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
>   	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
>   };
>   
> +static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
> +	.setup                  = setup_fib,
> +	.check_ptype            = lpm_check_ptype,
> +	.cb_parse_ptype         = lpm_cb_parse_ptype,
> +	.main_loop              = fib_main_loop,
> +	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
> +	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
> +};
> +
>   /*
>    * Setup lookup methods for forwarding.
> - * Currently exact-match and longest-prefix-match
> - * are supported ones.
> + * Currently exact-match, longest-prefix-match and forwarding information
> + * base are the supported ones.
>    */
>   static void
>   setup_l3fwd_lookup_tables(void)
> @@ -173,6 +183,9 @@ setup_l3fwd_lookup_tables(void)
>   	/* Setup HASH lookup functions. */
>   	if (l3fwd_em_on)
>   		l3fwd_lkp = l3fwd_em_lkp;
> +	/* Setup FIB lookup functions. */
> +	else if (l3fwd_fib_on)
> +		l3fwd_lkp = l3fwd_fib_lkp;
>   	/* Setup LPM lookup functions. */
>   	else
>   		l3fwd_lkp = l3fwd_lpm_lkp;
> @@ -292,6 +305,7 @@ print_usage(const char *prgname)
>   		"  -P : Enable promiscuous mode\n"
>   		"  -E : Enable exact match\n"
>   		"  -L : Enable longest prefix match (default)\n"
> +		"  -F : Enable forwarding information base\n"
>   		"  --config (port,queue,lcore): Rx queue configuration\n"
>   		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
>   		"  --enable-jumbo: Enable jumbo frames\n"
> @@ -492,6 +506,7 @@ static const char short_options[] =
>   	"P"   /* promiscuous */
>   	"L"   /* enable long prefix match */
>   	"E"   /* enable exact match */
> +	"F"   /* forwarding information base */
>   	;
>   
>   #define CMD_LINE_OPT_CONFIG "config"
> @@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
>   			l3fwd_lpm_on = 1;
>   			break;
>   
> +		case 'F':
> +			l3fwd_fib_on = 1;
> +			break;
> +
>   		/* long options */

IMO this necessitates creating an enum instead of a set of mutually 
exclusive binary switches. For example:

enum L3FWD_LOOKUP_MODE {
     L3FWD_LOOKUP_DEFAULT,
     L3FWD_LOOKUP_LPM,
     L3FWD_LOOKUP_EM,
     L3FWD_LOOKUP_FIB
};
static enum L3FWD_LOOKUP_MODE lookup_mode;

...

case 'F':
     if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
         RTE_LOG(ERR, L3FWD, "Only one lookup mode is allowed at a time!");
         return -1;
     }
     lookup_mode = L3FWD_LOOKUP_FIB;
     break;
...

Additionally, i really think this '-E'/'-L'/'-F' business is silly and 
it would be better to have something like "--lookup=exact|lpm|fib", and 
leave the old -E/-L options for backwards compatibility.

-- 
Thanks,
Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
  2021-03-02 16:21       ` Ananyev, Konstantin
@ 2021-03-03 11:52       ` Burakov, Anatoly
  2021-03-08 15:35         ` Walsh, Conor
  2021-03-08 10:43       ` Medvedkin, Vladimir
  2 siblings, 1 reply; 77+ messages in thread
From: Burakov, Anatoly @ 2021-03-03 11:52 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, vladimir.medvedkin
  Cc: dev

On 19-Feb-21 3:09 PM, Conor Walsh wrote:
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---

<snip>

> +			 || defined RTE_ARCH_PPC_64
> +#define FIB_SEND_MULTI
> +#endif
> +
> +static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
> +static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
> +
> +/* Parse packet type and ip address. */
> +static inline void
> +fib_parse_packet(struct rte_mbuf *mbuf,
> +		       uint32_t *ipv4, uint32_t *ipv4_cnt,
> +		       uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
> +		       uint32_t *ipv6_cnt, uint8_t *ip_type)

Nitpicking, but here and in a bunch of other places, the indentation is 
quite odd :)

<snip>

> +
> +/* Bulk parse, fib lookup and send. */
> +static inline void
> +fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
> +			uint16_t portid, struct lcore_conf *qconf)
> +{
> +	uint32_t ipv4_arr[nb_rx];
> +	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
> +	uint16_t hops[nb_rx];
> +	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
> +	uint8_t type_arr[nb_rx];
> +	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
> +	uint32_t ipv4_reassem = 0, ipv6_reassem = 0;

I don't quite follow the naming here - this looks like it's 
"reassembling" something but i don't see any IP reassembly going on? 
Artifacts of copy-paste?

> +	int32_t i;
> +
> +	/* Prefetch first packets. */
> +	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
> +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
> +
> +	/* Parse packet info and prefetch. */
> +	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
> +		/* Prefetch packet. */
> +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
> +					       i + FIB_PREFETCH_OFFSET],
> +					       void *));
> +		fib_parse_packet(pkts_burst[i],
> +				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
> +				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
> +				       &type_arr[i]);
> +	}
> +
> +	/* Parse remaining packet info. */
> +	for (; i < nb_rx; i++)
> +		fib_parse_packet(pkts_burst[i],
> +				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
> +				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
> +				       &type_arr[i]);
> +
> +	/* Lookup IPv4 hops if IPv4 packets are present. */
> +	if (likely(ipv4_cnt > 0))
> +		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
> +				    ipv4_arr, hopsv4, ipv4_cnt);
> +
> +	/* Lookup IPv6 hops if IPv6 packets are present. */
> +	if (ipv6_cnt > 0)
> +		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
> +				     ipv6_arr, hopsv6, ipv6_cnt);
> +
> +	/* Add IPv4 and IPv6 hops to one array depending on type. */
> +	for (i = 0; i < nb_rx; i++) {
> +		if (type_arr[i]) {
> +			if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
> +				hops[i] = (uint16_t)hopsv4[ipv4_reassem];
> +			else
> +				hops[i] = portid;
> +			ipv4_reassem++;

Nitpicking, but could be made slightly more concise and readable:

const uint16_t nh = (uint16_t)hopsv4[ipv4_reassem++];
hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;

Same for IPv6.

-- 
Thanks,
Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-03-08 10:41       ` Medvedkin, Vladimir
  0 siblings, 0 replies; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-08 10:41 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Ananyev, Konstantin
  Cc: dev



On 19/02/2021 15:09, Walsh, Conor wrote:
> The IPv6 subnets used were not within the 2001:200::/48 subnet
> Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID
> 
> Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>   examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
>   1 file changed, 16 insertions(+), 10 deletions(-)
> 
> diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
> index 3dcf1fef18..1cfaf36572 100644
> --- a/examples/l3fwd/l3fwd_lpm.c
> +++ b/examples/l3fwd/l3fwd_lpm.c
> @@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
>   uint8_t  if_out;
>   };
> 
> -/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
> +/*
> + * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
> + * 198.18.{0-7}.0/24 = Port {0-7}
> + */
>   static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
>   {RTE_IPV4(198, 18, 0, 0), 24, 0},
>   {RTE_IPV4(198, 18, 1, 0), 24, 1},
> @@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
>   {RTE_IPV4(198, 18, 7, 0), 24, 7},
>   };
> 
> -/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
> +/*
> + * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
> + * 2001:200:0:{0-7}::/64 = Port {0-7}
> + */
>   static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
> +{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
> +{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
> +{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
> +{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
> +{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
> +{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
> +{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
> +{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
>   };
> 
>   #define IPV4_L3FWD_LPM_MAX_RULES         1024
> --
> 2.25.1
> 

Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>

-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
  2021-03-02 16:20       ` Ananyev, Konstantin
@ 2021-03-08 10:42       ` Medvedkin, Vladimir
  1 sibling, 0 replies; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-08 10:42 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Ananyev, Konstantin
  Cc: dev



On 19/02/2021 15:09, Walsh, Conor wrote:
> To prevent code duplication from the addition of lookup methods
> the routes specified in lpm should be moved to a common header.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>   examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
>   examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
>   2 files changed, 65 insertions(+), 57 deletions(-)
>   create mode 100644 examples/l3fwd/l3fwd_common_route.h
> 
> diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
> new file mode 100644
> index 0000000000..7f0125a8a5
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_common_route.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Intel Corporation
> + */
> +
> +#include <stdint.h>
> +#include <rte_ip.h>
> +
> +struct ipv4_l3fwd_common_route {
> +uint32_t ip;
> +uint8_t  depth;
> +uint8_t  if_out;
> +};
> +
> +struct ipv6_l3fwd_common_route {
> +uint8_t ip[16];
> +uint8_t  depth;
> +uint8_t  if_out;
> +};
> +
> +/*
> + * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
> + * 198.18.{0-7}.0/24 = Port {0-7}
> + */
> +static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
> +{RTE_IPV4(198, 18, 0, 0), 24, 0},
> +{RTE_IPV4(198, 18, 1, 0), 24, 1},
> +{RTE_IPV4(198, 18, 2, 0), 24, 2},
> +{RTE_IPV4(198, 18, 3, 0), 24, 3},
> +{RTE_IPV4(198, 18, 4, 0), 24, 4},
> +{RTE_IPV4(198, 18, 5, 0), 24, 5},
> +{RTE_IPV4(198, 18, 6, 0), 24, 6},
> +{RTE_IPV4(198, 18, 7, 0), 24, 7},
> +};
> +
> +/*
> + * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
> + * 2001:200:0:{0-7}::/64 = Port {0-7}
> + */
> +static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
> +{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
> +{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
> +{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
> +{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
> +{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
> +{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
> +{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
> +{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
> +};
> diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
> index 1cfaf36572..818cf717d1 100644
> --- a/examples/l3fwd/l3fwd_lpm.c
> +++ b/examples/l3fwd/l3fwd_lpm.c
> @@ -30,47 +30,7 @@
>   #include "l3fwd.h"
>   #include "l3fwd_event.h"
> 
> -struct ipv4_l3fwd_lpm_route {
> -uint32_t ip;
> -uint8_t  depth;
> -uint8_t  if_out;
> -};
> -
> -struct ipv6_l3fwd_lpm_route {
> -uint8_t ip[16];
> -uint8_t  depth;
> -uint8_t  if_out;
> -};
> -
> -/*
> - * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
> - * 198.18.{0-7}.0/24 = Port {0-7}
> - */
> -static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
> -{RTE_IPV4(198, 18, 0, 0), 24, 0},
> -{RTE_IPV4(198, 18, 1, 0), 24, 1},
> -{RTE_IPV4(198, 18, 2, 0), 24, 2},
> -{RTE_IPV4(198, 18, 3, 0), 24, 3},
> -{RTE_IPV4(198, 18, 4, 0), 24, 4},
> -{RTE_IPV4(198, 18, 5, 0), 24, 5},
> -{RTE_IPV4(198, 18, 6, 0), 24, 6},
> -{RTE_IPV4(198, 18, 7, 0), 24, 7},
> -};
> -
> -/*
> - * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
> - * 2001:200:0:{0-7}::/64 = Port {0-7}
> - */
> -static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
> -{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
> -{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
> -{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
> -{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
> -{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
> -{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
> -{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
> -{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
> -};
> +#include "l3fwd_common_route.h"
> 
>   #define IPV4_L3FWD_LPM_MAX_RULES         1024
>   #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
> @@ -485,18 +445,18 @@ setup_lpm(const int socketid)
>   socketid);
> 
>   /* populate the LPM table */
> -for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
> +for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
>   struct in_addr in;
> 
>   /* skip unused ports */
> -if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
> +if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
>   enabled_port_mask) == 0)
>   continue;
> 
>   ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
> -ipv4_l3fwd_lpm_route_array[i].ip,
> -ipv4_l3fwd_lpm_route_array[i].depth,
> -ipv4_l3fwd_lpm_route_array[i].if_out);
> +ipv4_l3fwd_common_route_array[i].ip,
> +ipv4_l3fwd_common_route_array[i].depth,
> +ipv4_l3fwd_common_route_array[i].if_out);
> 
>   if (ret < 0) {
>   rte_exit(EXIT_FAILURE,
> @@ -504,11 +464,11 @@ setup_lpm(const int socketid)
>   i, socketid);
>   }
> 
> -in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
> +in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
>   printf("LPM: Adding route %s / %d (%d)\n",
>          inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
> -ipv4_l3fwd_lpm_route_array[i].depth,
> -ipv4_l3fwd_lpm_route_array[i].if_out);
> +ipv4_l3fwd_common_route_array[i].depth,
> +ipv4_l3fwd_common_route_array[i].if_out);
>   }
> 
>   /* create the LPM6 table */
> @@ -525,17 +485,17 @@ setup_lpm(const int socketid)
>   socketid);
> 
>   /* populate the LPM table */
> -for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
> +for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
> 
>   /* skip unused ports */
> -if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
> +if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
>   enabled_port_mask) == 0)
>   continue;
> 
>   ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
> -ipv6_l3fwd_lpm_route_array[i].ip,
> -ipv6_l3fwd_lpm_route_array[i].depth,
> -ipv6_l3fwd_lpm_route_array[i].if_out);
> +ipv6_l3fwd_common_route_array[i].ip,
> +ipv6_l3fwd_common_route_array[i].depth,
> +ipv6_l3fwd_common_route_array[i].if_out);
> 
>   if (ret < 0) {
>   rte_exit(EXIT_FAILURE,
> @@ -544,10 +504,10 @@ setup_lpm(const int socketid)
>   }
> 
>   printf("LPM: Adding route %s / %d (%d)\n",
> -       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
> +       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
>    abuf, sizeof(abuf)),
> -       ipv6_l3fwd_lpm_route_array[i].depth,
> -       ipv6_l3fwd_lpm_route_array[i].if_out);
> +       ipv6_l3fwd_common_route_array[i].depth,
> +       ipv6_l3fwd_common_route_array[i].if_out);
>   }
>   }
> 
> --
> 2.25.1
> 

Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>

-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
  2021-03-02 16:22       ` Ananyev, Konstantin
  2021-03-03 11:36       ` Burakov, Anatoly
@ 2021-03-08 10:42       ` Medvedkin, Vladimir
  2 siblings, 0 replies; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-08 10:42 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Ananyev, Konstantin
  Cc: dev



On 19/02/2021 15:09, Walsh, Conor wrote:
> The purpose of this commit is to add the necessary function calls
> and supporting infrastructure to allow the Forwarding Information Base
> (FIB) library to be integrated into the l3fwd sample app.
> The flag '-F' has been added to the applications options to allow
> the user to specify that l3fwd uses FIB as its lookup method.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>   examples/l3fwd/Makefile      |  2 +-
>   examples/l3fwd/l3fwd.h       | 27 ++++++++++++++--
>   examples/l3fwd/l3fwd_event.c |  9 ++++++
>   examples/l3fwd/l3fwd_event.h |  1 +
>   examples/l3fwd/l3fwd_fib.c   | 60 ++++++++++++++++++++++++++++++++++++
>   examples/l3fwd/main.c        | 43 +++++++++++++++++++-------
>   examples/l3fwd/meson.build   |  4 +--
>   7 files changed, 129 insertions(+), 17 deletions(-)
>   create mode 100644 examples/l3fwd/l3fwd_fib.c
> 
> diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
> index 7e70bbd826..5f7baffbf7 100644
> --- a/examples/l3fwd/Makefile
> +++ b/examples/l3fwd/Makefile
> @@ -5,7 +5,7 @@
>   APP = l3fwd
> 
>   # all source are stored in SRCS-y
> -SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
> +SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
>   SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
> 
>   # Build using pkg-config variables if possible
> diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
> index 2cf06099e0..a808d60247 100644
> --- a/examples/l3fwd/l3fwd.h
> +++ b/examples/l3fwd/l3fwd.h
> @@ -1,5 +1,5 @@
>   /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright(c) 2010-2016 Intel Corporation
> + * Copyright(c) 2010-2021 Intel Corporation
>    */
> 
>   #ifndef __L3_FWD_H__
> @@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
>   int
>   init_mem(uint16_t portid, unsigned int nb_mbuf);
> 
> -/* Function pointers for LPM or EM functionality. */
> +/* Function pointers for LPM, EM or FIB functionality. */
>   void
>   setup_lpm(const int socketid);
> 
>   void
>   setup_hash(const int socketid);
> 
> +void
> +setup_fib(const int socketid);
> +
>   int
>   em_check_ptype(int portid);
> 
> @@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
>   int
>   lpm_main_loop(__rte_unused void *dummy);
> 
> +int
> +fib_main_loop(__rte_unused void *dummy);
> +
>   int
>   lpm_event_main_loop_tx_d(__rte_unused void *dummy);
>   int
> @@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
>   int
>   em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
> 
> +int
> +fib_event_main_loop_tx_d(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_q(__rte_unused void *dummy);
> +int
> +fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
> +
> 
> -/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
> +/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
>   void *
>   em_get_ipv4_l3fwd_lookup_struct(const int socketid);
> 
> @@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
>   void *
>   lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
> 
> +void *
> +fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
> +
> +void *
> +fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
> +
>   #endif  /* __L3_FWD_H__ */
> diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
> index 4d31593a0a..961860ea18 100644
> --- a/examples/l3fwd/l3fwd_event.c
> +++ b/examples/l3fwd/l3fwd_event.c
> @@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
>   [1][0] = em_event_main_loop_tx_q,
>   [1][1] = em_event_main_loop_tx_q_burst,
>   };
> +const event_loop_cb fib_event_loop[2][2] = {
> +[0][0] = fib_event_main_loop_tx_d,
> +[0][1] = fib_event_main_loop_tx_d_burst,
> +[1][0] = fib_event_main_loop_tx_q,
> +[1][1] = fib_event_main_loop_tx_q_burst,
> +};
>   uint32_t event_queue_cfg;
>   int ret;
> 
> @@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
> 
>   evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
>          [evt_rsrc->has_burst];
> +
> +evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
> +       [evt_rsrc->has_burst];
>   }
> diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
> index 0e46164170..3ad1902ab5 100644
> --- a/examples/l3fwd/l3fwd_event.h
> +++ b/examples/l3fwd/l3fwd_event.h
> @@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
>   adapter_setup_cb adapter_setup;
>   event_loop_cb lpm_event_loop;
>   event_loop_cb em_event_loop;
> +event_loop_cb fib_event_loop;
>   };
> 
>   struct l3fwd_event_resources {
> diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
> new file mode 100644
> index 0000000000..0a2d02db2f
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_fib.c
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Intel Corporation
> + */
> +
> +#include <rte_fib.h>
> +#include <rte_fib6.h>
> +
> +#include "l3fwd.h"
> +#include "l3fwd_event.h"
> +#include "l3fwd_common_route.h"
> +
> +/* Main fib processing loop. */
> +int
> +fib_main_loop(__rte_unused void *dummy)
> +{
> +return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_d(__rte_unused void *dummy)
> +{
> +return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
> +{
> +return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_q(__rte_unused void *dummy)
> +{
> +return 0;
> +}
> +
> +int __rte_noinline
> +fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
> +{
> +return 0;
> +}
> +
> +/* Function to setup fib. */
> +void
> +setup_fib(__rte_unused const int socketid)
> +{}
> +
> +/* Return ipv4 fib lookup struct. */
> +void *
> +fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> +return 0;
> +}
> +
> +/* Return ipv6 fib lookup struct. */
> +void *
> +fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> +return 0;
> +}
> diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
> index bb49e5faff..6881b49478 100644
> --- a/examples/l3fwd/main.c
> +++ b/examples/l3fwd/main.c
> @@ -1,5 +1,5 @@
>   /* SPDX-License-Identifier: BSD-3-Clause
> - * Copyright(c) 2010-2016 Intel Corporation
> + * Copyright(c) 2010-2021 Intel Corporation
>    */
> 
>   #include <stdio.h>
> @@ -60,9 +60,10 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
>   /**< Ports set in promiscuous mode off by default. */
>   static int promiscuous_on;
> 
> -/* Select Longest-Prefix or Exact match. */
> +/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
>   static int l3fwd_lpm_on;
>   static int l3fwd_em_on;
> +static int l3fwd_fib_on;
> 
>   /* Global variables. */
> 
> @@ -162,10 +163,19 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
>   .get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
>   };
> 
> +static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
> +.setup                  = setup_fib,
> +.check_ptype            = lpm_check_ptype,
> +.cb_parse_ptype         = lpm_cb_parse_ptype,
> +.main_loop              = fib_main_loop,
> +.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
> +.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
> +};
> +
>   /*
>    * Setup lookup methods for forwarding.
> - * Currently exact-match and longest-prefix-match
> - * are supported ones.
> + * Currently exact-match, longest-prefix-match and forwarding information
> + * base are the supported ones.
>    */
>   static void
>   setup_l3fwd_lookup_tables(void)
> @@ -173,6 +183,9 @@ setup_l3fwd_lookup_tables(void)
>   /* Setup HASH lookup functions. */
>   if (l3fwd_em_on)
>   l3fwd_lkp = l3fwd_em_lkp;
> +/* Setup FIB lookup functions. */
> +else if (l3fwd_fib_on)
> +l3fwd_lkp = l3fwd_fib_lkp;
>   /* Setup LPM lookup functions. */
>   else
>   l3fwd_lkp = l3fwd_lpm_lkp;
> @@ -292,6 +305,7 @@ print_usage(const char *prgname)
>   "  -P : Enable promiscuous mode\n"
>   "  -E : Enable exact match\n"
>   "  -L : Enable longest prefix match (default)\n"
> +"  -F : Enable forwarding information base\n"
>   "  --config (port,queue,lcore): Rx queue configuration\n"
>   "  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
>   "  --enable-jumbo: Enable jumbo frames\n"
> @@ -492,6 +506,7 @@ static const char short_options[] =
>   "P"   /* promiscuous */
>   "L"   /* enable long prefix match */
>   "E"   /* enable exact match */
> +"F"   /* forwarding information base */
>   ;
> 
>   #define CMD_LINE_OPT_CONFIG "config"
> @@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
>   l3fwd_lpm_on = 1;
>   break;
> 
> +case 'F':
> +l3fwd_fib_on = 1;
> +break;
> +
>   /* long options */
>   case CMD_LINE_OPT_CONFIG_NUM:
>   ret = parse_config(optarg);
> @@ -686,9 +705,9 @@ parse_args(int argc, char **argv)
>   }
>   }
> 
> -/* If both LPM and EM are selected, return error. */
> -if (l3fwd_lpm_on && l3fwd_em_on) {
> -fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
> +/* If more than 1 of LPM, EM and FIB are selected, return error. */
> +if ((l3fwd_lpm_on + l3fwd_em_on + l3fwd_fib_on) > 1) {
> +fprintf(stderr, "LPM, EM and FIB are mutually exclusive, select only one\n");
>   return -1;
>   }
> 
> @@ -711,14 +730,14 @@ parse_args(int argc, char **argv)
>    * Nothing is selected, pick longest-prefix match
>    * as default match.
>    */
> -if (!l3fwd_lpm_on && !l3fwd_em_on) {
> -fprintf(stderr, "LPM or EM none selected, default LPM on\n");
> +if (!l3fwd_lpm_on && !l3fwd_em_on && !l3fwd_fib_on) {
> +fprintf(stderr, "Neither LPM, EM, or FIB selected, default LPM on\n");
>   l3fwd_lpm_on = 1;
>   }
> 
>   /*
>    * ipv6 and hash flags are valid only for
> - * exact macth, reset them to default for
> + * exact match, reset them to default for
>    * longest-prefix match.
>    */
>   if (l3fwd_lpm_on) {
> @@ -780,7 +799,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
>   printf("Allocated mbuf pool on socket %d\n",
>   socketid);
> 
> -/* Setup either LPM or EM(f.e Hash). But, only once per
> +/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
>    * available socket.
>    */
>   if (!lkp_per_socket[socketid]) {
> @@ -1221,6 +1240,8 @@ main(int argc, char **argv)
>   l3fwd_event_resource_setup(&port_conf);
>   if (l3fwd_em_on)
>   l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
> +else if (l3fwd_fib_on)
> +l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
>   else
>   l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
>   l3fwd_event_service_setup();
> diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
> index 7d72b1b365..2e5d1d34f2 100644
> --- a/examples/l3fwd/meson.build
> +++ b/examples/l3fwd/meson.build
> @@ -7,8 +7,8 @@
>   # DPDK instance, use 'make'
> 
>   allow_experimental_apis = true
> -deps += ['hash', 'lpm', 'eventdev']
> +deps += ['hash', 'lpm', 'fib', 'eventdev']
>   sources = files(
> -'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
> +'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
>   'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
>   )
> --
> 2.25.1
> 

Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>

-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
  2021-03-02 16:21       ` Ananyev, Konstantin
  2021-03-03 11:52       ` Burakov, Anatoly
@ 2021-03-08 10:43       ` Medvedkin, Vladimir
  2021-03-08 17:20         ` Walsh, Conor
  2 siblings, 1 reply; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-08 10:43 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Ananyev, Konstantin
  Cc: dev

Hi Conor,

Please see comment below

On 19/02/2021 15:09, Walsh, Conor wrote:
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> ---
>   examples/l3fwd/l3fwd_fib.c | 475 ++++++++++++++++++++++++++++++++++++-
>   1 file changed, 469 insertions(+), 6 deletions(-)
> 
> diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
> index 0a2d02db2f..d5b9a4eae4 100644
> --- a/examples/l3fwd/l3fwd_fib.c
> +++ b/examples/l3fwd/l3fwd_fib.c
> @@ -2,59 +2,522 @@
>    * Copyright(c) 2021 Intel Corporation
>    */
> 
> +
> +/*
> + * If the machine does not have SSE, NEON or PPC 64 then the packets
> + * are sent one at a time using send_single_packet()
> + */
> +#if !defined FIB_SEND_MULTI
> +static inline void
> +fib_send_single(int nb_tx, struct lcore_conf *qconf,
> +struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
> +{
> +int32_t j;
> +for (j = 0; j < nb_tx; j++)
> +send_single_packet(qconf, pkts_burst[j], hops[j]);
> +}

I think in fib_send_single() you need to implement the same 
functionality as in send_packets_multi, such as mac swap and 
rfc1812_process()


> +#endif
> +
> +/* Bulk parse, fib lookup and send. */
> +static inline void
> +fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
> +uint16_t portid, struct lcore_conf *qconf)
> +{
> +
> +#if defined FIB_SEND_MULTI
> +send_packets_multi(qconf, pkts_burst, hops, nb_rx);
> +#else
> +fib_send_single(nb_rx, qconf, pkts_burst, hops);
> +#endif
> +}
> +
> --
> 2.25.1
> 

-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure
  2021-03-03 11:36       ` Burakov, Anatoly
@ 2021-03-08 15:13         ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-03-08 15:13 UTC (permalink / raw)
  To: Burakov, Anatoly, jerinj, stephen, Iremonger, Bernard, Ananyev,
	Konstantin, Medvedkin, Vladimir
  Cc: dev

<snip>
> >   #define CMD_LINE_OPT_CONFIG "config"
> > @@ -596,6 +611,10 @@ parse_args(int argc, char **argv)
> >   			l3fwd_lpm_on = 1;
> >   			break;
> >
> > +		case 'F':
> > +			l3fwd_fib_on = 1;
> > +			break;
> > +
> >   		/* long options */
> 

Hi Anatoly,
Thanks for your feedback responses inline below.

> IMO this necessitates creating an enum instead of a set of mutually
> exclusive binary switches. For example:
> 
> enum L3FWD_LOOKUP_MODE {
>      L3FWD_LOOKUP_DEFAULT,
>      L3FWD_LOOKUP_LPM,
>      L3FWD_LOOKUP_EM,
>      L3FWD_LOOKUP_FIB
> };
> static enum L3FWD_LOOKUP_MODE lookup_mode;

I agree I have added this to the v4 of the patchset.

> 
> ...
> 
> case 'F':
>      if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
>          RTE_LOG(ERR, L3FWD, "Only one lookup mode is allowed at a time!");
>          return -1;
>      }
>      lookup_mode = L3FWD_LOOKUP_FIB;
>      break;
> ...
> 
> Additionally, i really think this '-E'/'-L'/'-F' business is silly and
> it would be better to have something like "--lookup=exact|lpm|fib", and
> leave the old -E/-L options for backwards compatibility.

I have also added the above to v4 of the patchset, which will be released soon.
These changes should make it easier to use for users if more lookup methods are added to l3fwd.

Thanks,
Conor.

> 
> --
> Thanks,
> Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-03 11:52       ` Burakov, Anatoly
@ 2021-03-08 15:35         ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-03-08 15:35 UTC (permalink / raw)
  To: Burakov, Anatoly, jerinj, stephen, Iremonger, Bernard, Ananyev,
	Konstantin, Medvedkin, Vladimir
  Cc: dev

> From: Burakov, Anatoly <anatoly.burakov@intel.com>
> Sent: Wednesday 3 March 2021 11:53
> To: Walsh, Conor <conor.walsh@intel.com>; jerinj@marvell.com;
> stephen@networkplumber.org; Iremonger, Bernard
> <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Medvedkin, Vladimir
> <vladimir.medvedkin@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB
> lookup method
> 
> On 19-Feb-21 3:09 PM, Conor Walsh wrote:
> > This patch implements the Forwarding Information Base (FIB) library
> > in l3fwd using the function calls and infrastructure introduced in
> > the previous patch.
> >
> > Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> > ---
> 
> <snip>
> 
> > +			 || defined RTE_ARCH_PPC_64
> > +#define FIB_SEND_MULTI
> > +#endif
> > +
> > +static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
> > +static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
> > +
> > +/* Parse packet type and ip address. */
> > +static inline void
> > +fib_parse_packet(struct rte_mbuf *mbuf,
> > +		       uint32_t *ipv4, uint32_t *ipv4_cnt,
> > +		       uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
> > +		       uint32_t *ipv6_cnt, uint8_t *ip_type)
> 
> Nitpicking, but here and in a bunch of other places, the indentation is
> quite odd :)

Hi Anatoly,
I have corrected the indentation issues in the v4 of the patchset.

> 
> <snip>
> 
> > +
> > +/* Bulk parse, fib lookup and send. */
> > +static inline void
> > +fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
> > +			uint16_t portid, struct lcore_conf *qconf)
> > +{
> > +	uint32_t ipv4_arr[nb_rx];
> > +	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
> > +	uint16_t hops[nb_rx];
> > +	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
> > +	uint8_t type_arr[nb_rx];
> > +	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
> > +	uint32_t ipv4_reassem = 0, ipv6_reassem = 0;
> 
> I don't quite follow the naming here - this looks like it's
> "reassembling" something but i don't see any IP reassembly going on?
> Artifacts of copy-paste?

For FIB lookups the packets need to be split into ipv4 and ipv6.
These lookups create separate arrays of 'hops' for ipv4 and ipv6 which need to be assembled into a single 'hops' array.
I use ipv4_reassem And ipv6_reassem as counters for this purpose.
To try and avoid confusion I have renamed them as follows ipv4_reassem -> ipv4_arr_assem and ipv6_reassem -> ipv6_arr_assem in v4.

> 
> > +	int32_t i;
> > +
> > +	/* Prefetch first packets. */
> > +	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
> > +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
> > +
> > +	/* Parse packet info and prefetch. */
> > +	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
> > +		/* Prefetch packet. */
> > +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
> > +					       i + FIB_PREFETCH_OFFSET],
> > +					       void *));
> > +		fib_parse_packet(pkts_burst[i],
> > +				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
> > +				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
> > +				       &type_arr[i]);
> > +	}
> > +
> > +	/* Parse remaining packet info. */
> > +	for (; i < nb_rx; i++)
> > +		fib_parse_packet(pkts_burst[i],
> > +				       &ipv4_arr[ipv4_cnt], &ipv4_cnt,
> > +				       ipv6_arr[ipv6_cnt], &ipv6_cnt,
> > +				       &type_arr[i]);
> > +
> > +	/* Lookup IPv4 hops if IPv4 packets are present. */
> > +	if (likely(ipv4_cnt > 0))
> > +		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
> > +				    ipv4_arr, hopsv4, ipv4_cnt);
> > +
> > +	/* Lookup IPv6 hops if IPv6 packets are present. */
> > +	if (ipv6_cnt > 0)
> > +		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
> > +				     ipv6_arr, hopsv6, ipv6_cnt);
> > +
> > +	/* Add IPv4 and IPv6 hops to one array depending on type. */
> > +	for (i = 0; i < nb_rx; i++) {
> > +		if (type_arr[i]) {
> > +			if (hopsv4[ipv4_reassem] != FIB_DEFAULT_HOP)
> > +				hops[i] = (uint16_t)hopsv4[ipv4_reassem];
> > +			else
> > +				hops[i] = portid;
> > +			ipv4_reassem++;
> 
> Nitpicking, but could be made slightly more concise and readable:
> 
> const uint16_t nh = (uint16_t)hopsv4[ipv4_reassem++];
> hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
> 
> Same for IPv6.

I have changed this in the v4 of the patchset which will be released soon.

Thanks,
Conor.

> 
> --
> Thanks,
> Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-08 10:43       ` Medvedkin, Vladimir
@ 2021-03-08 17:20         ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-03-08 17:20 UTC (permalink / raw)
  To: Medvedkin, Vladimir, jerinj, stephen, Iremonger, Bernard,
	Ananyev, Konstantin
  Cc: dev

> Hi Conor,
> 
> Please see comment below
> 

<snip>

> > +/*
> > + * If the machine does not have SSE, NEON or PPC 64 then the packets
> > + * are sent one at a time using send_single_packet()
> > + */
> > +#if !defined FIB_SEND_MULTI
> > +static inline void
> > +fib_send_single(int nb_tx, struct lcore_conf *qconf,
> > +struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
> > +{
> > +int32_t j;
> > +for (j = 0; j < nb_tx; j++)
> > +send_single_packet(qconf, pkts_burst[j], hops[j]);
> > +}
> 
> I think in fib_send_single() you need to implement the same
> functionality as in send_packets_multi, such as mac swap and
> rfc1812_process()

Hi Vladimir,

Thanks for the feedback.
I have implemented rfc1812 and mac swapping in fib_send_single for v4 of the patchset which I will release soon after testing.

Thanks,
Conor.

> 
<snip>
> 
> --
> Regards,
> Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                       ` (4 preceding siblings ...)
  2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-03-11 12:01     ` Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                         ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

---

v4:
    - Changed individual switches for lookup methods to an enum for all lookup methods
    - Removed '-F' and introduced '--lookup' flag to select lookup methods
    - Fixed indentation issues
    - Renamed some variables for increased clarity
    - Minor changes to some logic for readability
    - Implemented MAC updating for FIB on non-SSE machines
    - Implemented RFC1812 for FIB on non-SSE machines
    - Added checks to ensure desired port is within portmask

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 113 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 530 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/main.c                   | 107 +++--
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 811 insertions(+), 98 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-03-11 12:01       ` Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-03-11 12:01       ` Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 3/5] examples/l3fwd: add FIB infrastructure
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-03-11 12:01       ` Conor Walsh
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/Makefile      |   2 +-
 examples/l3fwd/l3fwd.h       |  27 ++++++++-
 examples/l3fwd/l3fwd_event.c |   9 +++
 examples/l3fwd/l3fwd_event.h |   1 +
 examples/l3fwd/l3fwd_fib.c   |  60 ++++++++++++++++++++
 examples/l3fwd/main.c        | 107 ++++++++++++++++++++++++++---------
 examples/l3fwd/meson.build   |   4 +-
 7 files changed, 176 insertions(+), 34 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..3f48895e87 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,14 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
-static int l3fwd_lpm_on;
-static int l3fwd_em_on;
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
+enum L3FWD_LOOKUP_MODE {
+	L3FWD_LOOKUP_DEFAULT,
+	L3FWD_LOOKUP_LPM,
+	L3FWD_LOOKUP_EM,
+	L3FWD_LOOKUP_FIB
+};
+static enum L3FWD_LOOKUP_MODE lookup_mode;
 
 /* Global variables. */
 
@@ -162,17 +167,29 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
 {
 	/* Setup HASH lookup functions. */
-	if (l3fwd_em_on)
+	if (lookup_mode == L3FWD_LOOKUP_EM)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (lookup_mode == L3FWD_LOOKUP_FIB)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -286,12 +303,13 @@ print_usage(const char *prgname)
 		" [--parse-ptype]"
 		" [--per-port-pool]"
 		" [--mode]"
-		" [--eventq-sched]\n\n"
+		" [--eventq-sched]"
+		" [--lookup]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
-		"  -E : Enable exact match\n"
-		"  -L : Enable longest prefix match (default)\n"
+		"  -E : Enable exact match, legacy flag please use --lookup=em instead\n"
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -310,7 +328,10 @@ print_usage(const char *prgname)
 		"                  Valid only if --mode=eventdev\n"
 		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
 		"                    Default: 1\n"
-		"                    Valid only if --mode=eventdev\n\n",
+		"                    Valid only if --mode=eventdev\n"
+		"  --lookup: Select the lookup method\n"
+		"            Default: lpm\n"
+		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (First Information Base)\n\n",
 		prgname);
 }
 
@@ -485,13 +506,32 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
 	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
 }
 
+static void
+parse_lookup(const char *optarg)
+{
+	if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+		rte_exit(EXIT_FAILURE,
+				"Only one lookup mode is allowed at a time!\n");
+	}
+	if (!strcmp(optarg, "em"))
+		lookup_mode = L3FWD_LOOKUP_EM;
+	else if (!strcmp(optarg, "lpm"))
+		lookup_mode = L3FWD_LOOKUP_LPM;
+	else if (!strcmp(optarg, "fib"))
+		lookup_mode = L3FWD_LOOKUP_FIB;
+	else {
+		rte_exit(EXIT_FAILURE,
+				"Invalid --lookup option! Accepted options: em, lpm, fib\n");
+	}
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
 	"p:"  /* portmask */
 	"P"   /* promiscuous */
-	"L"   /* enable long prefix match */
-	"E"   /* enable exact match */
+	"L"   /* legacy enable long prefix match */
+	"E"   /* legacy enable exact match */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -505,6 +545,7 @@ static const char short_options[] =
 #define CMD_LINE_OPT_MODE "mode"
 #define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched"
 #define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs"
+#define CMD_LINE_OPT_LOOKUP "lookup"
 enum {
 	/* long options mapped to a short option */
 
@@ -522,6 +563,7 @@ enum {
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
 	CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM,
+	CMD_LINE_OPT_LOOKUP_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -537,6 +579,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
 	{CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0,
 					CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM},
+	{CMD_LINE_OPT_LOOKUP, 1, 0, CMD_LINE_OPT_LOOKUP_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -589,11 +632,19 @@ parse_args(int argc, char **argv)
 			break;
 
 		case 'E':
-			l3fwd_em_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_EM;
 			break;
 
 		case 'L':
-			l3fwd_lpm_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_LPM;
 			break;
 
 		/* long options */
@@ -680,18 +731,16 @@ parse_args(int argc, char **argv)
 			eth_rx_q = 1;
 			break;
 
+		case CMD_LINE_OPT_LOOKUP_NUM:
+			parse_lookup(optarg);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
-		return -1;
-	}
-
 	if (evt_rsrc->enabled && lcore_params) {
 		fprintf(stderr, "lcore config is not valid when event mode is selected\n");
 		return -1;
@@ -711,17 +760,17 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
-		l3fwd_lpm_on = 1;
+	if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
+		lookup_mode = L3FWD_LOOKUP_LPM;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
-	if (l3fwd_lpm_on) {
+	if (lookup_mode == L3FWD_LOOKUP_LPM) {
 		ipv6 = 0;
 		hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 	}
@@ -780,7 +829,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1219,8 +1268,10 @@ main(int argc, char **argv)
 	/* Configure eventdev parameters if user has requested */
 	if (evt_rsrc->enabled) {
 		l3fwd_event_resource_setup(&port_conf);
-		if (l3fwd_em_on)
+		if (lookup_mode == L3FWD_LOOKUP_EM)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (lookup_mode == L3FWD_LOOKUP_FIB)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                         ` (2 preceding siblings ...)
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-03-11 12:01       ` Conor Walsh
  2021-03-12 18:56         ` Medvedkin, Vladimir
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 482 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 476 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..976fa60c80 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,529 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+		|| defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		uint32_t *ipv4, uint32_t *ipv4_cnt,
+		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	struct rte_ether_hdr *eth_hdr;
+
+	for (j = 0; j < nb_tx; j++) {
+		/* Run rfc1812 if packet is ipv4 and checks enabled. */
+#if defined DO_RFC_1812_CHECKS
+		rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
+				pkts_burst[j], struct rte_ether_hdr *) + 1),
+				&hops[j], pkts_burst[j]->packet_type);
+#endif
+
+		/* Set MAC addresses. */
+		eth_hdr = rte_pktmbuf_mtod(pkts_burst[j],
+				struct rte_ether_hdr *);
+		*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[hops[j]];
+		rte_ether_addr_copy(&ports_eth_addr[hops[j]],
+				&eth_hdr->s_addr);
+
+		/* Send single packet. */
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+	}
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+		uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
+	uint16_t nh;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+				i + FIB_PREFETCH_OFFSET], void *));
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i])
+			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+		else
+			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+		hops[i] = (nh != FIB_DEFAULT_HOP && nh <= RTE_MAX_ETHPORTS &&
+			(enabled_port_mask & 1 << nh) != 0) ? nh : portid;
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+			US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+				" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+				lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+					MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+			evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint16_t nh;
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_arr_assem, ipv6_arr_assem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+				events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_arr_assem = 0;
+		ipv6_arr_assem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+					i + FIB_PREFETCH_OFFSET].mbuf,
+					void *));
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i])
+				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+			else
+				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+			if (nh != FIB_DEFAULT_HOP && nh <= RTE_MAX_ETHPORTS &&
+					(enabled_port_mask & 1 << nh) != 0)
+				events[i].mbuf->port = nh;
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+					events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+			&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+				"Unable to create the l3fwd FIB table on socket %d\n",
+				socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+				abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v4 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                         ` (3 preceding siblings ...)
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-03-11 12:01       ` Conor Walsh
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-11 12:01 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 113 +++++++++++++++++++++---
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..d5892bdcf8 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -53,8 +53,7 @@ The application has a number of command line options::
 
     ./dpdk-l3fwd [EAL options] -- -p PORTMASK
                              [-P]
-                             [-E]
-                             [-L]
+                             [--lookup LOOKUP_METHOD]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -66,6 +65,8 @@ The application has a number of command line options::
                              [--mode]
                              [--eventq-sched]
                              [--event-eth-rxqs]
+                             [-E]
+                             [-L]
 
 Where,
 
@@ -74,9 +75,7 @@ Where,
 * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
   Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
 
-* ``-E:`` Optional, enable exact match.
-
-* ``-L:`` Optional, enable longest prefix match.
+* ``--lookup:`` Optional, Select the lookup method. Accepted options ``em`` (Exact Match), ``lpm`` (Longest Prefix Match), ``fib`` (Forwarding Information Base). Default is ``lpm``.
 
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
@@ -102,6 +101,10 @@ Where,
 
 * ``--event-eth-rxqs:`` Optional, Number of ethernet RX queues per device. Only valid if --mode=eventdev.
 
+* ``-E:`` Optional, enable exact match, legacy flag please use ``--lookup=em`` instead.
+
+* ``-L:`` Optional, enable longest prefix match, legacy flag please use ``--lookup=lpm`` instead.
+
 
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-03-12 18:56         ` Medvedkin, Vladimir
  2021-03-15 10:21           ` Walsh, Conor
  0 siblings, 1 reply; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-12 18:56 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, anatoly.burakov
  Cc: dev

Hi Conor,

see comment inlined

On 11/03/2021 12:01, Conor Walsh wrote:
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
>   examples/l3fwd/l3fwd_fib.c | 482 ++++++++++++++++++++++++++++++++++++-
>   1 file changed, 476 insertions(+), 6 deletions(-)
> 

<snip>

> +/* Bulk parse, fib lookup and send. */
> +static inline void
> +fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
> +		uint16_t portid, struct lcore_conf *qconf)
> +{
> +	uint32_t ipv4_arr[nb_rx];
> +	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
> +	uint16_t hops[nb_rx];
> +	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
> +	uint8_t type_arr[nb_rx];
> +	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
> +	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
> +	uint16_t nh;
> +	int32_t i;
> +
> +	/* Prefetch first packets. */
> +	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
> +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
> +
> +	/* Parse packet info and prefetch. */
> +	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
> +		/* Prefetch packet. */
> +		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
> +				i + FIB_PREFETCH_OFFSET], void *));
> +		fib_parse_packet(pkts_burst[i],
> +				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
> +				ipv6_arr[ipv6_cnt], &ipv6_cnt,
> +				&type_arr[i]);
> +	}
> +
> +	/* Parse remaining packet info. */
> +	for (; i < nb_rx; i++)
> +		fib_parse_packet(pkts_burst[i],
> +				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
> +				ipv6_arr[ipv6_cnt], &ipv6_cnt,
> +				&type_arr[i]);
> +
> +	/* Lookup IPv4 hops if IPv4 packets are present. */
> +	if (likely(ipv4_cnt > 0))
> +		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
> +				ipv4_arr, hopsv4, ipv4_cnt);
> +
> +	/* Lookup IPv6 hops if IPv6 packets are present. */
> +	if (ipv6_cnt > 0)
> +		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
> +				ipv6_arr, hopsv6, ipv6_cnt);
> +
> +	/* Add IPv4 and IPv6 hops to one array depending on type. */
> +	for (i = 0; i < nb_rx; i++) {
> +		if (type_arr[i])
> +			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
> +		else
> +			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
> +		hops[i] = (nh != FIB_DEFAULT_HOP && nh <= RTE_MAX_ETHPORTS &&
> +			(enabled_port_mask & 1 << nh) != 0) ? nh : portid;

I think you can get rid of
"nh <= RTE_MAX_ETHPORTS && (enabled_port_mask & 1 << nh) != 0"
because it can be controlled during initialization when installing 
routes to the table. So you can check it just before rte_fib_add() and 
install FIB_DEFAULT_HOP if needed.

Apart from that LGTM.


> +	}
> +
> +#if defined FIB_SEND_MULTI
> +	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
> +#else
> +	fib_send_single(nb_rx, qconf, pkts_burst, hops);
> +#endif
> +}
> +

<snip>

> 

-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-12 18:56         ` Medvedkin, Vladimir
@ 2021-03-15 10:21           ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-03-15 10:21 UTC (permalink / raw)
  To: Medvedkin, Vladimir, jerinj, stephen, Iremonger, Bernard,
	Ananyev, Konstantin, Burakov, Anatoly
  Cc: dev

Hi Vladimir,

<snip>

> > +	/* Add IPv4 and IPv6 hops to one array depending on type. */
> > +	for (i = 0; i < nb_rx; i++) {
> > +		if (type_arr[i])
> > +			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
> > +		else
> > +			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
> > +		hops[i] = (nh != FIB_DEFAULT_HOP && nh <=
> RTE_MAX_ETHPORTS &&
> > +			(enabled_port_mask & 1 << nh) != 0) ? nh : portid;
> 
> I think you can get rid of
> "nh <= RTE_MAX_ETHPORTS && (enabled_port_mask & 1 << nh) != 0"
> because it can be controlled during initialization when installing
> routes to the table. So you can check it just before rte_fib_add() and
> install FIB_DEFAULT_HOP if needed.

I will change this ternary to: hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
I will also update the event code to match this.

> 
> Apart from that LGTM.

I will push a v5 with this change.

Thanks,
Conor.

> 
> 
> > +	}
> > +
> > +#if defined FIB_SEND_MULTI
> > +	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
> > +#else
> > +	fib_send_single(nb_rx, qconf, pkts_burst, hops);
> > +#endif
> > +}
> > +
> 
> <snip>
> 
> >
> 
> --
> Regards,
> Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                         ` (4 preceding siblings ...)
  2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-03-15 11:34       ` Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                           ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

---

v5:
    - Removed runtime checks to ensure desired port is within portmask,
      unused ports are still removed during setup

v4:
    - Changed individual switches for lookup methods to an
      enum for all lookup methods
    - Removed '-F' and introduced '--lookup' flag to select lookup methods
    - Fixed indentation issues
    - Renamed some variables for increased clarity
    - Minor changes to some logic for readability
    - Implemented MAC updating for FIB on non-SSE machines
    - Implemented RFC1812 for FIB on non-SSE machines
    - Added checks to ensure desired port is within portmask

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 113 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 528 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/main.c                   | 107 +++--
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 809 insertions(+), 98 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-03-15 11:34         ` Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                           ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-03-15 11:34         ` Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                           ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-03-15 11:34         ` Conor Walsh
  2021-04-01 11:20           ` Burakov, Anatoly
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                           ` (2 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/Makefile      |   2 +-
 examples/l3fwd/l3fwd.h       |  27 ++++++++-
 examples/l3fwd/l3fwd_event.c |   9 +++
 examples/l3fwd/l3fwd_event.h |   1 +
 examples/l3fwd/l3fwd_fib.c   |  60 ++++++++++++++++++++
 examples/l3fwd/main.c        | 107 ++++++++++++++++++++++++++---------
 examples/l3fwd/meson.build   |   4 +-
 7 files changed, 176 insertions(+), 34 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..3f48895e87 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,14 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
-static int l3fwd_lpm_on;
-static int l3fwd_em_on;
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
+enum L3FWD_LOOKUP_MODE {
+	L3FWD_LOOKUP_DEFAULT,
+	L3FWD_LOOKUP_LPM,
+	L3FWD_LOOKUP_EM,
+	L3FWD_LOOKUP_FIB
+};
+static enum L3FWD_LOOKUP_MODE lookup_mode;
 
 /* Global variables. */
 
@@ -162,17 +167,29 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
 {
 	/* Setup HASH lookup functions. */
-	if (l3fwd_em_on)
+	if (lookup_mode == L3FWD_LOOKUP_EM)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (lookup_mode == L3FWD_LOOKUP_FIB)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -286,12 +303,13 @@ print_usage(const char *prgname)
 		" [--parse-ptype]"
 		" [--per-port-pool]"
 		" [--mode]"
-		" [--eventq-sched]\n\n"
+		" [--eventq-sched]"
+		" [--lookup]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
-		"  -E : Enable exact match\n"
-		"  -L : Enable longest prefix match (default)\n"
+		"  -E : Enable exact match, legacy flag please use --lookup=em instead\n"
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -310,7 +328,10 @@ print_usage(const char *prgname)
 		"                  Valid only if --mode=eventdev\n"
 		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
 		"                    Default: 1\n"
-		"                    Valid only if --mode=eventdev\n\n",
+		"                    Valid only if --mode=eventdev\n"
+		"  --lookup: Select the lookup method\n"
+		"            Default: lpm\n"
+		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (First Information Base)\n\n",
 		prgname);
 }
 
@@ -485,13 +506,32 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
 	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
 }
 
+static void
+parse_lookup(const char *optarg)
+{
+	if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+		rte_exit(EXIT_FAILURE,
+				"Only one lookup mode is allowed at a time!\n");
+	}
+	if (!strcmp(optarg, "em"))
+		lookup_mode = L3FWD_LOOKUP_EM;
+	else if (!strcmp(optarg, "lpm"))
+		lookup_mode = L3FWD_LOOKUP_LPM;
+	else if (!strcmp(optarg, "fib"))
+		lookup_mode = L3FWD_LOOKUP_FIB;
+	else {
+		rte_exit(EXIT_FAILURE,
+				"Invalid --lookup option! Accepted options: em, lpm, fib\n");
+	}
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
 	"p:"  /* portmask */
 	"P"   /* promiscuous */
-	"L"   /* enable long prefix match */
-	"E"   /* enable exact match */
+	"L"   /* legacy enable long prefix match */
+	"E"   /* legacy enable exact match */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -505,6 +545,7 @@ static const char short_options[] =
 #define CMD_LINE_OPT_MODE "mode"
 #define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched"
 #define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs"
+#define CMD_LINE_OPT_LOOKUP "lookup"
 enum {
 	/* long options mapped to a short option */
 
@@ -522,6 +563,7 @@ enum {
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
 	CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM,
+	CMD_LINE_OPT_LOOKUP_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -537,6 +579,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
 	{CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0,
 					CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM},
+	{CMD_LINE_OPT_LOOKUP, 1, 0, CMD_LINE_OPT_LOOKUP_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -589,11 +632,19 @@ parse_args(int argc, char **argv)
 			break;
 
 		case 'E':
-			l3fwd_em_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_EM;
 			break;
 
 		case 'L':
-			l3fwd_lpm_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_LPM;
 			break;
 
 		/* long options */
@@ -680,18 +731,16 @@ parse_args(int argc, char **argv)
 			eth_rx_q = 1;
 			break;
 
+		case CMD_LINE_OPT_LOOKUP_NUM:
+			parse_lookup(optarg);
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
-		return -1;
-	}
-
 	if (evt_rsrc->enabled && lcore_params) {
 		fprintf(stderr, "lcore config is not valid when event mode is selected\n");
 		return -1;
@@ -711,17 +760,17 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
-		l3fwd_lpm_on = 1;
+	if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
+		lookup_mode = L3FWD_LOOKUP_LPM;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
-	if (l3fwd_lpm_on) {
+	if (lookup_mode == L3FWD_LOOKUP_LPM) {
 		ipv6 = 0;
 		hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 	}
@@ -780,7 +829,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1219,8 +1268,10 @@ main(int argc, char **argv)
 	/* Configure eventdev parameters if user has requested */
 	if (evt_rsrc->enabled) {
 		l3fwd_event_resource_setup(&port_conf);
-		if (l3fwd_em_on)
+		if (lookup_mode == L3FWD_LOOKUP_EM)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (lookup_mode == L3FWD_LOOKUP_FIB)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                           ` (2 preceding siblings ...)
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-03-15 11:34         ` Conor Walsh
  2021-03-16 18:46           ` Medvedkin, Vladimir
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 480 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 474 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..a58b933f83 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,527 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+		|| defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		uint32_t *ipv4, uint32_t *ipv4_cnt,
+		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	struct rte_ether_hdr *eth_hdr;
+
+	for (j = 0; j < nb_tx; j++) {
+		/* Run rfc1812 if packet is ipv4 and checks enabled. */
+#if defined DO_RFC_1812_CHECKS
+		rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
+				pkts_burst[j], struct rte_ether_hdr *) + 1),
+				&hops[j], pkts_burst[j]->packet_type);
+#endif
+
+		/* Set MAC addresses. */
+		eth_hdr = rte_pktmbuf_mtod(pkts_burst[j],
+				struct rte_ether_hdr *);
+		*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[hops[j]];
+		rte_ether_addr_copy(&ports_eth_addr[hops[j]],
+				&eth_hdr->s_addr);
+
+		/* Send single packet. */
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+	}
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+		uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
+	uint16_t nh;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+				i + FIB_PREFETCH_OFFSET], void *));
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i])
+			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+		else
+			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+		hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+			US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+				" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+				lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+					MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+			evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint16_t nh;
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_arr_assem, ipv6_arr_assem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+				events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_arr_assem = 0;
+		ipv6_arr_assem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+					i + FIB_PREFETCH_OFFSET].mbuf,
+					void *));
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i])
+				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+			else
+				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+			if (nh != FIB_DEFAULT_HOP)
+				events[i].mbuf->port = nh;
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+					events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+			&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+				"Unable to create the l3fwd FIB table on socket %d\n",
+				socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+				abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                           ` (3 preceding siblings ...)
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-03-15 11:34         ` Conor Walsh
  2021-03-18 19:45           ` Mcnamara, John
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-03-15 11:34 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 113 +++++++++++++++++++++---
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..d5892bdcf8 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -53,8 +53,7 @@ The application has a number of command line options::
 
     ./dpdk-l3fwd [EAL options] -- -p PORTMASK
                              [-P]
-                             [-E]
-                             [-L]
+                             [--lookup LOOKUP_METHOD]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -66,6 +65,8 @@ The application has a number of command line options::
                              [--mode]
                              [--eventq-sched]
                              [--event-eth-rxqs]
+                             [-E]
+                             [-L]
 
 Where,
 
@@ -74,9 +75,7 @@ Where,
 * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
   Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
 
-* ``-E:`` Optional, enable exact match.
-
-* ``-L:`` Optional, enable longest prefix match.
+* ``--lookup:`` Optional, Select the lookup method. Accepted options ``em`` (Exact Match), ``lpm`` (Longest Prefix Match), ``fib`` (Forwarding Information Base). Default is ``lpm``.
 
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
@@ -102,6 +101,10 @@ Where,
 
 * ``--event-eth-rxqs:`` Optional, Number of ethernet RX queues per device. Only valid if --mode=eventdev.
 
+* ``-E:`` Optional, enable exact match, legacy flag please use ``--lookup=em`` instead.
+
+* ``-L:`` Optional, enable longest prefix match, legacy flag please use ``--lookup=lpm`` instead.
+
 
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-03-16 18:46           ` Medvedkin, Vladimir
  0 siblings, 0 replies; 77+ messages in thread
From: Medvedkin, Vladimir @ 2021-03-16 18:46 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, anatoly.burakov
  Cc: dev



On 15/03/2021 11:34, Conor Walsh wrote:
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> ---
>   examples/l3fwd/l3fwd_fib.c | 480 ++++++++++++++++++++++++++++++++++++-
>   1 file changed, 474 insertions(+), 6 deletions(-)
>

<snip>

> 

Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
-- 
Regards,
Vladimir

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-03-18 19:45           ` Mcnamara, John
  0 siblings, 0 replies; 77+ messages in thread
From: Mcnamara, John @ 2021-03-18 19:45 UTC (permalink / raw)
  To: Walsh, Conor, jerinj, stephen, Iremonger, Bernard, Ananyev,
	Konstantin, Medvedkin, Vladimir, Burakov, Anatoly
  Cc: dev, Walsh, Conor



> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Conor Walsh
> Sent: Monday, March 15, 2021 11:35 AM
> To: jerinj@marvell.com; stephen@networkplumber.org; Iremonger, Bernard
> <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Medvedkin, Vladimir
> <vladimir.medvedkin@intel.com>; Burakov, Anatoly
> <anatoly.burakov@intel.com>
> Cc: dev@dpdk.org; Walsh, Conor <conor.walsh@intel.com>
> Subject: [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update
> documentation for FIB

For the doc section of the patch:

Acked-by: John McNamara <john.mcnamara@intel.com>


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-04-01 11:20           ` Burakov, Anatoly
  2021-04-01 12:59             ` Walsh, Conor
  0 siblings, 1 reply; 77+ messages in thread
From: Burakov, Anatoly @ 2021-04-01 11:20 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, vladimir.medvedkin
  Cc: dev

On 15-Mar-21 11:34 AM, Conor Walsh wrote:
> The purpose of this commit is to add the necessary function calls
> and supporting infrastructure to allow the Forwarding Information Base
> (FIB) library to be integrated into the l3fwd sample app.
> Instead of adding an individual flag for FIB, a new flag '--lookup' has
> been added that allows the user to select their desired lookup method.
> The flags '-E' and '-L' have been retained for backwards compatibility.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---

<snip>

> @@ -310,7 +328,10 @@ print_usage(const char *prgname)
>   		"                  Valid only if --mode=eventdev\n"
>   		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
>   		"                    Default: 1\n"
> -		"                    Valid only if --mode=eventdev\n\n",
> +		"                    Valid only if --mode=eventdev\n"
> +		"  --lookup: Select the lookup method\n"
> +		"            Default: lpm\n"
> +		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (First Information Base)\n\n",

Isn't it Forward Information Base?

>   		prgname);
>   }
>   
> @@ -485,13 +506,32 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
>   	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
>   }
>   
> +static void
> +parse_lookup(const char *optarg)
> +{
> +	if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> +		rte_exit(EXIT_FAILURE,
> +				"Only one lookup mode is allowed at a time!\n");
> +	}
> +	if (!strcmp(optarg, "em"))
> +		lookup_mode = L3FWD_LOOKUP_EM;
> +	else if (!strcmp(optarg, "lpm"))
> +		lookup_mode = L3FWD_LOOKUP_LPM;
> +	else if (!strcmp(optarg, "fib"))
> +		lookup_mode = L3FWD_LOOKUP_FIB;
> +	else {
> +		rte_exit(EXIT_FAILURE,
> +				"Invalid --lookup option! Accepted options: em, lpm, fib\n");
> +	}
> +}
> +

I don't think having rte_exit() calls inside a parsing function is good 
practice. The check at the beginning of the function can be done in 
optarg switch (like you have for E and L switches), while the latter can 
be replaced with a RTE_LOG(ERR, ...) and a return -1, which can be 
checked by the caller.

Once the above is fixed,

Acked-by: Anatoly Burako <anatoly.burakov@intel.com>

-- 
Thanks,
Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-01 11:20           ` Burakov, Anatoly
@ 2021-04-01 12:59             ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-04-01 12:59 UTC (permalink / raw)
  To: Burakov, Anatoly, jerinj, stephen, Iremonger, Bernard, Ananyev,
	Konstantin, Medvedkin, Vladimir
  Cc: dev

<snip>
> 
> > @@ -310,7 +328,10 @@ print_usage(const char *prgname)
> >   		"                  Valid only if --mode=eventdev\n"
> >   		"  --event-eth-rxqs: Number of ethernet RX queues per
> device.\n"
> >   		"                    Default: 1\n"
> > -		"                    Valid only if --mode=eventdev\n\n",
> > +		"                    Valid only if --mode=eventdev\n"
> > +		"  --lookup: Select the lookup method\n"
> > +		"            Default: lpm\n"
> > +		"            Accepted: em (Exact Match), lpm (Longest Prefix
> Match), fib (First Information Base)\n\n",
> 
> Isn't it Forward Information Base?

Hi Anatoly,
It's Forwarding Information Base, I will correct this.

> 
> >   		prgname);
> >   }
> >
> > @@ -485,13 +506,32 @@ parse_event_eth_rx_queues(const char
> *eth_rx_queues)
> >   	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
> >   }
> >
> > +static void
> > +parse_lookup(const char *optarg)
> > +{
> > +	if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> > +		rte_exit(EXIT_FAILURE,
> > +				"Only one lookup mode is allowed at a
> time!\n");
> > +	}
> > +	if (!strcmp(optarg, "em"))
> > +		lookup_mode = L3FWD_LOOKUP_EM;
> > +	else if (!strcmp(optarg, "lpm"))
> > +		lookup_mode = L3FWD_LOOKUP_LPM;
> > +	else if (!strcmp(optarg, "fib"))
> > +		lookup_mode = L3FWD_LOOKUP_FIB;
> > +	else {
> > +		rte_exit(EXIT_FAILURE,
> > +				"Invalid --lookup option! Accepted options:
> em, lpm, fib\n");
> > +	}
> > +}
> > +
> 
> I don't think having rte_exit() calls inside a parsing function is good
> practice. The check at the beginning of the function can be done in
> optarg switch (like you have for E and L switches), while the latter can
> be replaced with a RTE_LOG(ERR, ...) and a return -1, which can be
> checked by the caller.

I will modify the patch in line with this comment too.

> 
> Once the above is fixed,
> 
> Acked-by: Anatoly Burako <anatoly.burakov@intel.com>

Thanks for your feedback and ack I will make the changes and push a v6 of the patchset.
Conor.

> 
> --
> Thanks,
> Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                           ` (4 preceding siblings ...)
  2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-04-02 10:52         ` Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                             ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

---

v6:
    - rte_exit no longer used within parse_lookup, exiting due to
      incorrect config is now handled the same as the other config options
    - Corrected a typo within print usage
    - Moved -E and -L to the bottom of print usage as they are
      now legacy flags

v5:
    - Removed runtime checks to ensure desired port is within portmask,
      unused ports are still removed during setup

v4:
    - Changed individual switches for lookup methods to an
      enum for all lookup methods
    - Removed '-F' and introduced '--lookup' flag to select lookup methods
    - Fixed indentation issues
    - Renamed some variables for increased clarity
    - Minor changes to some logic for readability
    - Implemented MAC updating for FIB on non-SSE machines
    - Implemented RFC1812 for FIB on non-SSE machines
    - Added checks to ensure desired port is within portmask

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 113 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 528 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/main.c                   | 114 +++--
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 814 insertions(+), 100 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-04-02 10:52           ` Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                             ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-04-02 10:52           ` Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                             ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-04-02 10:52           ` Conor Walsh
  2021-04-02 16:34             ` Burakov, Anatoly
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                             ` (2 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Anatoly Burako <anatoly.burakov@intel.com>
---
 examples/l3fwd/Makefile      |   2 +-
 examples/l3fwd/l3fwd.h       |  27 ++++++++-
 examples/l3fwd/l3fwd_event.c |   9 +++
 examples/l3fwd/l3fwd_event.h |   1 +
 examples/l3fwd/l3fwd_fib.c   |  60 ++++++++++++++++++
 examples/l3fwd/main.c        | 114 ++++++++++++++++++++++++++---------
 examples/l3fwd/meson.build   |   4 +-
 7 files changed, 181 insertions(+), 36 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..a1c8cbf341 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,14 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
-static int l3fwd_lpm_on;
-static int l3fwd_em_on;
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
+enum L3FWD_LOOKUP_MODE {
+	L3FWD_LOOKUP_DEFAULT,
+	L3FWD_LOOKUP_LPM,
+	L3FWD_LOOKUP_EM,
+	L3FWD_LOOKUP_FIB
+};
+static enum L3FWD_LOOKUP_MODE lookup_mode;
 
 /* Global variables. */
 
@@ -162,17 +167,29 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
 {
 	/* Setup HASH lookup functions. */
-	if (l3fwd_em_on)
+	if (lookup_mode == L3FWD_LOOKUP_EM)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (lookup_mode == L3FWD_LOOKUP_FIB)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -275,8 +292,7 @@ print_usage(const char *prgname)
 	fprintf(stderr, "%s [EAL options] --"
 		" -p PORTMASK"
 		" [-P]"
-		" [-E]"
-		" [-L]"
+		" [--lookup]"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--enable-jumbo [--max-pkt-len PKTLEN]]"
@@ -286,12 +302,15 @@ print_usage(const char *prgname)
 		" [--parse-ptype]"
 		" [--per-port-pool]"
 		" [--mode]"
-		" [--eventq-sched]\n\n"
+		" [--eventq-sched]"
+		" [-E]"
+		" [-L]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
-		"  -E : Enable exact match\n"
-		"  -L : Enable longest prefix match (default)\n"
+		"  --lookup: Select the lookup method\n"
+		"            Default: lpm\n"
+		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (Forwarding Information Base)\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -310,7 +329,9 @@ print_usage(const char *prgname)
 		"                  Valid only if --mode=eventdev\n"
 		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
 		"                    Default: 1\n"
-		"                    Valid only if --mode=eventdev\n\n",
+		"                    Valid only if --mode=eventdev\n"
+		"  -E : Enable exact match, legacy flag please use --lookup=em instead\n"
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n\n",
 		prgname);
 }
 
@@ -485,13 +506,27 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
 	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
 }
 
+static int
+parse_lookup(const char *optarg)
+{
+	if (!strcmp(optarg, "em"))
+		lookup_mode = L3FWD_LOOKUP_EM;
+	else if (!strcmp(optarg, "lpm"))
+		lookup_mode = L3FWD_LOOKUP_LPM;
+	else if (!strcmp(optarg, "fib"))
+		lookup_mode = L3FWD_LOOKUP_FIB;
+	else
+		return -1;
+	return 0;
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
 	"p:"  /* portmask */
 	"P"   /* promiscuous */
-	"L"   /* enable long prefix match */
-	"E"   /* enable exact match */
+	"L"   /* legacy enable long prefix match */
+	"E"   /* legacy enable exact match */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -505,6 +540,7 @@ static const char short_options[] =
 #define CMD_LINE_OPT_MODE "mode"
 #define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched"
 #define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs"
+#define CMD_LINE_OPT_LOOKUP "lookup"
 enum {
 	/* long options mapped to a short option */
 
@@ -522,6 +558,7 @@ enum {
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
 	CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM,
+	CMD_LINE_OPT_LOOKUP_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -537,6 +574,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
 	{CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0,
 					CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM},
+	{CMD_LINE_OPT_LOOKUP, 1, 0, CMD_LINE_OPT_LOOKUP_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -589,11 +627,19 @@ parse_args(int argc, char **argv)
 			break;
 
 		case 'E':
-			l3fwd_em_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_EM;
 			break;
 
 		case 'L':
-			l3fwd_lpm_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_LPM;
 			break;
 
 		/* long options */
@@ -680,18 +726,24 @@ parse_args(int argc, char **argv)
 			eth_rx_q = 1;
 			break;
 
+		case CMD_LINE_OPT_LOOKUP_NUM:
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			ret = parse_lookup(optarg);
+			if (ret) {
+				fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib\n");
+				return -1;
+			}
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
-		return -1;
-	}
-
 	if (evt_rsrc->enabled && lcore_params) {
 		fprintf(stderr, "lcore config is not valid when event mode is selected\n");
 		return -1;
@@ -711,17 +763,17 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
-		l3fwd_lpm_on = 1;
+	if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
+		lookup_mode = L3FWD_LOOKUP_LPM;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
-	if (l3fwd_lpm_on) {
+	if (lookup_mode == L3FWD_LOOKUP_LPM) {
 		ipv6 = 0;
 		hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 	}
@@ -780,7 +832,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1219,8 +1271,10 @@ main(int argc, char **argv)
 	/* Configure eventdev parameters if user has requested */
 	if (evt_rsrc->enabled) {
 		l3fwd_event_resource_setup(&port_conf);
-		if (l3fwd_em_on)
+		if (lookup_mode == L3FWD_LOOKUP_EM)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (lookup_mode == L3FWD_LOOKUP_FIB)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 4/5] examples/l3fwd: implement FIB lookup method
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                             ` (2 preceding siblings ...)
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-04-02 10:52           ` Conor Walsh
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 480 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 474 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..a58b933f83 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,527 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+		|| defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		uint32_t *ipv4, uint32_t *ipv4_cnt,
+		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	struct rte_ether_hdr *eth_hdr;
+
+	for (j = 0; j < nb_tx; j++) {
+		/* Run rfc1812 if packet is ipv4 and checks enabled. */
+#if defined DO_RFC_1812_CHECKS
+		rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
+				pkts_burst[j], struct rte_ether_hdr *) + 1),
+				&hops[j], pkts_burst[j]->packet_type);
+#endif
+
+		/* Set MAC addresses. */
+		eth_hdr = rte_pktmbuf_mtod(pkts_burst[j],
+				struct rte_ether_hdr *);
+		*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[hops[j]];
+		rte_ether_addr_copy(&ports_eth_addr[hops[j]],
+				&eth_hdr->s_addr);
+
+		/* Send single packet. */
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+	}
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+		uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
+	uint16_t nh;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+				i + FIB_PREFETCH_OFFSET], void *));
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i])
+			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+		else
+			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+		hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+			US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+				" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+				lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+					MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+			evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint16_t nh;
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_arr_assem, ipv6_arr_assem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+				events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_arr_assem = 0;
+		ipv6_arr_assem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+					i + FIB_PREFETCH_OFFSET].mbuf,
+					void *));
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i])
+				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+			else
+				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+			if (nh != FIB_DEFAULT_HOP)
+				events[i].mbuf->port = nh;
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+					events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+			&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+				"Unable to create the l3fwd FIB table on socket %d\n",
+				socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+				abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v6 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                             ` (3 preceding siblings ...)
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-04-02 10:52           ` Conor Walsh
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-02 10:52 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov
  Cc: dev, Conor Walsh, John McNamara

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 113 +++++++++++++++++++++---
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..d5892bdcf8 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -53,8 +53,7 @@ The application has a number of command line options::
 
     ./dpdk-l3fwd [EAL options] -- -p PORTMASK
                              [-P]
-                             [-E]
-                             [-L]
+                             [--lookup LOOKUP_METHOD]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -66,6 +65,8 @@ The application has a number of command line options::
                              [--mode]
                              [--eventq-sched]
                              [--event-eth-rxqs]
+                             [-E]
+                             [-L]
 
 Where,
 
@@ -74,9 +75,7 @@ Where,
 * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
   Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
 
-* ``-E:`` Optional, enable exact match.
-
-* ``-L:`` Optional, enable longest prefix match.
+* ``--lookup:`` Optional, Select the lookup method. Accepted options ``em`` (Exact Match), ``lpm`` (Longest Prefix Match), ``fib`` (Forwarding Information Base). Default is ``lpm``.
 
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
@@ -102,6 +101,10 @@ Where,
 
 * ``--event-eth-rxqs:`` Optional, Number of ethernet RX queues per device. Only valid if --mode=eventdev.
 
+* ``-E:`` Optional, enable exact match, legacy flag please use ``--lookup=em`` instead.
+
+* ``-L:`` Optional, enable longest prefix match, legacy flag please use ``--lookup=lpm`` instead.
+
 
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-04-02 16:34             ` Burakov, Anatoly
  2021-04-06 11:05               ` Walsh, Conor
  0 siblings, 1 reply; 77+ messages in thread
From: Burakov, Anatoly @ 2021-04-02 16:34 UTC (permalink / raw)
  To: Conor Walsh, jerinj, stephen, bernard.iremonger,
	konstantin.ananyev, vladimir.medvedkin
  Cc: dev

On 02-Apr-21 11:52 AM, Conor Walsh wrote:
> The purpose of this commit is to add the necessary function calls
> and supporting infrastructure to allow the Forwarding Information Base
> (FIB) library to be integrated into the l3fwd sample app.
> Instead of adding an individual flag for FIB, a new flag '--lookup' has
> been added that allows the user to select their desired lookup method.
> The flags '-E' and '-L' have been retained for backwards compatibility.
> 
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> Acked-by: Anatoly Burako <anatoly.burakov@intel.com>
> ---

Burakov*

>   			break;
>   
>   		case 'L':
> -			l3fwd_lpm_on = 1;
> +			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> +				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
> +				return -1;
> +			}
> +			lookup_mode = L3FWD_LOOKUP_LPM;
>   			break;
>   
>   		/* long options */
> @@ -680,18 +726,24 @@ parse_args(int argc, char **argv)
>   			eth_rx_q = 1;
>   			break;
>   
> +		case CMD_LINE_OPT_LOOKUP_NUM:
> +			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> +				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
> +				return -1;
> +			}
> +			ret = parse_lookup(optarg);
> +			if (ret) {
> +				fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib\n");

Nitpicking, but i would have preferred having this log in the 
parse_lookup(), because if we add one more lookup method, you'd only 
have to modify one function (together with the log message), rather than 
two. However, this works too :)

-- 
Thanks,
Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-02 16:34             ` Burakov, Anatoly
@ 2021-04-06 11:05               ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-04-06 11:05 UTC (permalink / raw)
  To: Burakov, Anatoly, jerinj, stephen, Iremonger, Bernard, Ananyev,
	Konstantin, Medvedkin, Vladimir
  Cc: dev

<snip>

> > Acked-by: Anatoly Burako <anatoly.burakov@intel.com>
> > ---
> 
> Burakov*

Sorry about that!

> 
> >   			break;
> >
> >   		case 'L':
> > -			l3fwd_lpm_on = 1;
> > +			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> > +				fprintf(stderr, "Only one lookup mode is
> allowed at a time!\n");
> > +				return -1;
> > +			}
> > +			lookup_mode = L3FWD_LOOKUP_LPM;
> >   			break;
> >
> >   		/* long options */
> > @@ -680,18 +726,24 @@ parse_args(int argc, char **argv)
> >   			eth_rx_q = 1;
> >   			break;
> >
> > +		case CMD_LINE_OPT_LOOKUP_NUM:
> > +			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
> > +				fprintf(stderr, "Only one lookup mode is
> allowed at a time!\n");
> > +				return -1;
> > +			}
> > +			ret = parse_lookup(optarg);
> > +			if (ret) {
> > +				fprintf(stderr, "Invalid lookup option!
> Accepted options: em, lpm, fib\n");
> 
> Nitpicking, but i would have preferred having this log in the
> parse_lookup(), because if we add one more lookup method, you'd only
> have to modify one function (together with the log message), rather than
> two. However, this works too :)

I will push a v7 with this change.
Thanks again,
Conor.

> 
> --
> Thanks,
> Anatoly

^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                             ` (4 preceding siblings ...)
  2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-04-06 11:11           ` Conor Walsh
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                               ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

---

v7:
    - Error log for invalid lookup method now runs within the parse_lookup
      function for better maintainability

v6:
    - rte_exit no longer used within parse_lookup, exiting due to
      incorrect config is now handled the same as the other config options
    - Corrected a typo within print usage
    - Moved -E and -L to the bottom of print usage as they are
      now legacy flags

v5:
    - Removed runtime checks to ensure desired port is within portmask,
      unused ports are still removed during setup

v4:
    - Changed individual switches for lookup methods to an
      enum for all lookup methods
    - Removed '-F' and introduced '--lookup' flag to select lookup methods
    - Fixed indentation issues
    - Renamed some variables for increased clarity
    - Minor changes to some logic for readability
    - Implemented MAC updating for FIB on non-SSE machines
    - Implemented RFC1812 for FIB on non-SSE machines
    - Added checks to ensure desired port is within portmask

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/sample_app_ug/l3_forward.rst | 113 ++++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_common_route.h     |  48 +++
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 528 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/main.c                   | 119 ++++--
 examples/l3fwd/meson.build              |   4 +-
 10 files changed, 819 insertions(+), 100 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h
 create mode 100644 examples/l3fwd/l3fwd_fib.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-04-06 11:11             ` Conor Walsh
  2021-04-14 20:59               ` David Marchand
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                               ` (4 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

The IPv6 subnets used were not within the 2001:200::/48 subnet
Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-04-06 11:11             ` Conor Walsh
  2021-04-15 14:38               ` David Marchand
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                               ` (3 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
 2 files changed, 65 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_common_route.h

diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
new file mode 100644
index 0000000000..7f0125a8a5
--- /dev/null
+++ b/examples/l3fwd/l3fwd_common_route.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <rte_ip.h>
+
+struct ipv4_l3fwd_common_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_common_route {
+	uint8_t ip[16];
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..818cf717d1 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_common_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_common_route_array[i].depth,
+		       ipv6_l3fwd_common_route_array[i].if_out);
 	}
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-04-06 11:11             ` Conor Walsh
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                               ` (2 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 examples/l3fwd/Makefile      |   2 +-
 examples/l3fwd/l3fwd.h       |  27 +++++++-
 examples/l3fwd/l3fwd_event.c |   9 +++
 examples/l3fwd/l3fwd_event.h |   1 +
 examples/l3fwd/l3fwd_fib.c   |  60 ++++++++++++++++++
 examples/l3fwd/main.c        | 119 ++++++++++++++++++++++++++---------
 examples/l3fwd/meson.build   |   4 +-
 7 files changed, 186 insertions(+), 36 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index 7e70bbd826..5f7baffbf7 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..0a2d02db2f
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_common_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..e22869ae9c 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -60,9 +60,14 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
-static int l3fwd_lpm_on;
-static int l3fwd_em_on;
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
+enum L3FWD_LOOKUP_MODE {
+	L3FWD_LOOKUP_DEFAULT,
+	L3FWD_LOOKUP_LPM,
+	L3FWD_LOOKUP_EM,
+	L3FWD_LOOKUP_FIB
+};
+static enum L3FWD_LOOKUP_MODE lookup_mode;
 
 /* Global variables. */
 
@@ -162,17 +167,29 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
 {
 	/* Setup HASH lookup functions. */
-	if (l3fwd_em_on)
+	if (lookup_mode == L3FWD_LOOKUP_EM)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (lookup_mode == L3FWD_LOOKUP_FIB)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -275,8 +292,7 @@ print_usage(const char *prgname)
 	fprintf(stderr, "%s [EAL options] --"
 		" -p PORTMASK"
 		" [-P]"
-		" [-E]"
-		" [-L]"
+		" [--lookup]"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--enable-jumbo [--max-pkt-len PKTLEN]]"
@@ -286,12 +302,15 @@ print_usage(const char *prgname)
 		" [--parse-ptype]"
 		" [--per-port-pool]"
 		" [--mode]"
-		" [--eventq-sched]\n\n"
+		" [--eventq-sched]"
+		" [-E]"
+		" [-L]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
-		"  -E : Enable exact match\n"
-		"  -L : Enable longest prefix match (default)\n"
+		"  --lookup: Select the lookup method\n"
+		"            Default: lpm\n"
+		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (Forwarding Information Base)\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -310,7 +329,9 @@ print_usage(const char *prgname)
 		"                  Valid only if --mode=eventdev\n"
 		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
 		"                    Default: 1\n"
-		"                    Valid only if --mode=eventdev\n\n",
+		"                    Valid only if --mode=eventdev\n"
+		"  -E : Enable exact match, legacy flag please use --lookup=em instead\n"
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n\n",
 		prgname);
 }
 
@@ -485,13 +506,29 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
 	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
 }
 
+static int
+parse_lookup(const char *optarg)
+{
+	if (!strcmp(optarg, "em"))
+		lookup_mode = L3FWD_LOOKUP_EM;
+	else if (!strcmp(optarg, "lpm"))
+		lookup_mode = L3FWD_LOOKUP_LPM;
+	else if (!strcmp(optarg, "fib"))
+		lookup_mode = L3FWD_LOOKUP_FIB;
+	else {
+		fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib\n");
+		return -1;
+	}
+	return 0;
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
 	"p:"  /* portmask */
 	"P"   /* promiscuous */
-	"L"   /* enable long prefix match */
-	"E"   /* enable exact match */
+	"L"   /* legacy enable long prefix match */
+	"E"   /* legacy enable exact match */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -505,6 +542,7 @@ static const char short_options[] =
 #define CMD_LINE_OPT_MODE "mode"
 #define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched"
 #define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs"
+#define CMD_LINE_OPT_LOOKUP "lookup"
 enum {
 	/* long options mapped to a short option */
 
@@ -522,6 +560,7 @@ enum {
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
 	CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM,
+	CMD_LINE_OPT_LOOKUP_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -537,6 +576,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
 	{CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0,
 					CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM},
+	{CMD_LINE_OPT_LOOKUP, 1, 0, CMD_LINE_OPT_LOOKUP_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -589,11 +629,19 @@ parse_args(int argc, char **argv)
 			break;
 
 		case 'E':
-			l3fwd_em_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_EM;
 			break;
 
 		case 'L':
-			l3fwd_lpm_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_LPM;
 			break;
 
 		/* long options */
@@ -680,18 +728,27 @@ parse_args(int argc, char **argv)
 			eth_rx_q = 1;
 			break;
 
+		case CMD_LINE_OPT_LOOKUP_NUM:
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			ret = parse_lookup(optarg);
+			/*
+			 * If parse_lookup was passed an invalid lookup type
+			 * then return -1. Error log included within
+			 * parse_lookup for simplicity.
+			 */
+			if (ret)
+				return -1;
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
-		return -1;
-	}
-
 	if (evt_rsrc->enabled && lcore_params) {
 		fprintf(stderr, "lcore config is not valid when event mode is selected\n");
 		return -1;
@@ -711,17 +768,17 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
-		l3fwd_lpm_on = 1;
+	if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
+		lookup_mode = L3FWD_LOOKUP_LPM;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
-	if (l3fwd_lpm_on) {
+	if (lookup_mode == L3FWD_LOOKUP_LPM) {
 		ipv6 = 0;
 		hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 	}
@@ -780,7 +837,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1219,8 +1276,10 @@ main(int argc, char **argv)
 	/* Configure eventdev parameters if user has requested */
 	if (evt_rsrc->enabled) {
 		l3fwd_event_resource_setup(&port_conf);
-		if (l3fwd_em_on)
+		if (lookup_mode == L3FWD_LOOKUP_EM)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (lookup_mode == L3FWD_LOOKUP_FIB)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                               ` (2 preceding siblings ...)
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-04-06 11:11             ` Conor Walsh
  2021-04-15 14:42               ` David Marchand
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 1 reply; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 480 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 474 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 0a2d02db2f..a58b933f83 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,527 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_common_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+		|| defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		uint32_t *ipv4, uint32_t *ipv4_cnt,
+		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	struct rte_ether_hdr *eth_hdr;
+
+	for (j = 0; j < nb_tx; j++) {
+		/* Run rfc1812 if packet is ipv4 and checks enabled. */
+#if defined DO_RFC_1812_CHECKS
+		rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
+				pkts_burst[j], struct rte_ether_hdr *) + 1),
+				&hops[j], pkts_burst[j]->packet_type);
+#endif
+
+		/* Set MAC addresses. */
+		eth_hdr = rte_pktmbuf_mtod(pkts_burst[j],
+				struct rte_ether_hdr *);
+		*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[hops[j]];
+		rte_ether_addr_copy(&ports_eth_addr[hops[j]],
+				&eth_hdr->s_addr);
+
+		/* Send single packet. */
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+	}
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+		uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
+	uint16_t nh;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+				i + FIB_PREFETCH_OFFSET], void *));
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i])
+			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+		else
+			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+		hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+			US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+				" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+				lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+					MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+			evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint16_t nh;
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_arr_assem, ipv6_arr_assem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+				events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_arr_assem = 0;
+		ipv6_arr_assem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+					i + FIB_PREFETCH_OFFSET].mbuf,
+					void *));
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i])
+				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+			else
+				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+			if (nh != FIB_DEFAULT_HOP)
+				events[i].mbuf->port = nh;
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+					events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_common_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_common_route_array[i].ip,
+			ipv4_l3fwd_common_route_array[i].depth,
+			ipv4_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_common_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_common_route_array[i].depth,
+				ipv4_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_common_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+			&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+				"Unable to create the l3fwd FIB table on socket %d\n",
+				socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_common_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_common_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_common_route_array[i].ip,
+			ipv6_l3fwd_common_route_array[i].depth,
+			ipv6_l3fwd_common_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_common_route_array[i].ip,
+				abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_common_route_array[i].depth,
+				ipv6_l3fwd_common_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_common_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                               ` (3 preceding siblings ...)
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-04-06 11:11             ` Conor Walsh
  2021-04-15 14:43               ` David Marchand
  2021-04-15 14:59               ` David Marchand
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  5 siblings, 2 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-06 11:11 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 doc/guides/sample_app_ug/l3_forward.rst | 113 +++++++++++++++++++++---
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..d5892bdcf8 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -53,8 +53,7 @@ The application has a number of command line options::
 
     ./dpdk-l3fwd [EAL options] -- -p PORTMASK
                              [-P]
-                             [-E]
-                             [-L]
+                             [--lookup LOOKUP_METHOD]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -66,6 +65,8 @@ The application has a number of command line options::
                              [--mode]
                              [--eventq-sched]
                              [--event-eth-rxqs]
+                             [-E]
+                             [-L]
 
 Where,
 
@@ -74,9 +75,7 @@ Where,
 * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
   Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
 
-* ``-E:`` Optional, enable exact match.
-
-* ``-L:`` Optional, enable longest prefix match.
+* ``--lookup:`` Optional, Select the lookup method. Accepted options ``em`` (Exact Match), ``lpm`` (Longest Prefix Match), ``fib`` (Forwarding Information Base). Default is ``lpm``.
 
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
@@ -102,6 +101,10 @@ Where,
 
 * ``--event-eth-rxqs:`` Optional, Number of ethernet RX queues per device. Only valid if --mode=eventdev.
 
+* ``-E:`` Optional, enable exact match, legacy flag please use ``--lookup=em`` instead.
+
+* ``-L:`` Optional, enable longest prefix match, legacy flag please use ``--lookup=lpm`` instead.
+
 
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
@@ -290,6 +293,61 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from a global array.
+
+.. code-block:: c
+
+    #if (APP_LOOKUP_METHOD == APP_LOOKUP_FIB)
+
+    void
+    setup_fib(const int socketid)
+    {
+        unsigned int i;
+        int ret;
+        char s[64];
+
+        /* create the FIB table */
+
+        snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+
+        ipv4_l3fwd_fib_lookup_struct[socketid] = rte_fib_create(s, socketid, IPV4_L3FWD_FIB_MAX_RULES);
+
+        if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+            rte_exit(EXIT_FAILURE, "Unable to create the l3fwd FIB table on socket %d\n", socketid);
+
+        /* populate the FIB table */
+
+        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
+            struct in_addr in;
+
+            /* skip unused ports */
+            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)
+                continue;
+
+            ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+                ipv4_l3fwd_fib_route_array[i].ip,
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+
+            if (ret < 0) {
+                rte_exit(EXIT_FAILURE, "Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+                        i, socketid);
+            }
+
+            in.s_addr = htonl(ipv4_l3fwd_fib_route_array[i].ip);
+            printf("FIB: Adding route %s / %d (%d)\n",
+                inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
+                ipv4_l3fwd_fib_route_array[i].depth,
+                ipv4_l3fwd_fib_route_array[i].if_out);
+        }
+
+        /* ipv6 omitted from this example for brevity */
+    }
+    #endif
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +438,35 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not have separate functions for single
+and bulk lookups. ``rte_fib_lookup_bulk`` is used for ipv4 lookups and ``rte_fib6_lookup_bulk`` for ipv6.
+An example of a FIB lookup function can be seen below:
+
+.. code-block:: c
+
+    static inline uint16_t
+    fib_get_ipv4_dst_ports(struct rte_fib *ipv4_l3fwd_lookup_struct, uint32_t *ipv4_addrs, uint64_t *next_hops, uint16_t portid, int nb_pkts)
+    {
+        uint16_t hops[nb_pkts];
+
+        rte_fib_lookup_bulk(ipv4_l3fwd_lookup_struct, ipv4_addrs, next_hops, nb_pkts);
+
+        /*
+         * If FIB has returned its default value for an unknown IP address set it to the portid supplied.
+         * FIB uses uint64_t for hops but l3fwd uses uint16_t so the values are cast.
+         */
+
+        for (i = 0; i < nb_pkts; i++)
+            (next_hops[i]==FIB_DEFAULT_HOP) ? (hops[i] = (uint16_t)portid) : (hops[i] = (uint16_t)next_hop[i]);
+
+        return hops;
+    }
+
+    /* IPv6 example omitted for brevity */
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-04-14 20:59               ` David Marchand
  2021-04-15  8:44                 ` Walsh, Conor
  0 siblings, 1 reply; 77+ messages in thread
From: David Marchand @ 2021-04-14 20:59 UTC (permalink / raw)
  To: Conor Walsh, Ananyev, Konstantin, Vladimir Medvedkin
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Burakov, Anatoly, Mcnamara, John, dev

On Tue, Apr 6, 2021 at 1:11 PM Conor Walsh <conor.walsh@intel.com> wrote:
>
> The IPv6 subnets used were not within the 2001:200::/48 subnet

{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
etc...

Err... all those subnets were exactly == 2001:200::/48.
Is the issue that the example needs *separate* subnets taken from
within 2001:200::/48 ?


> Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID
>
> Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")

And this looks like a Cc: stable@dpdk.org candidate.

>
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>


-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-14 20:59               ` David Marchand
@ 2021-04-15  8:44                 ` Walsh, Conor
  2021-04-15 14:31                   ` David Marchand
  0 siblings, 1 reply; 77+ messages in thread
From: Walsh, Conor @ 2021-04-15  8:44 UTC (permalink / raw)
  To: David Marchand, Ananyev, Konstantin, Medvedkin, Vladimir
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Burakov, Anatoly, Mcnamara, John, dev

<snip>

> >
> > The IPv6 subnets used were not within the 2001:200::/48 subnet
> 
> {{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
> {{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
> etc...
> 
> Err... all those subnets were exactly == 2001:200::/48.
> Is the issue that the example needs *separate* subnets taken from
> within 2001:200::/48 ?

Hi David,
As it is ATM any IP with that range will match for all the rules for the 8 ports and the application cannot differentiate between them and it just returns the traffic to sender.
After this change the ports can be individually matched using the smaller /64 ranges for each port which are still within the given /48 subnet range (RFC5180).

> 
> 
> > Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID
> >
> > Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")
> 
> And this looks like a Cc: stable@dpdk.org candidate.

I can send a v8 and CC stable if you think that’s needed.
Thanks,
Conor.

> 
> >
> > Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> > Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> 
> 
> --
> David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-15  8:44                 ` Walsh, Conor
@ 2021-04-15 14:31                   ` David Marchand
  2021-04-15 15:18                     ` Walsh, Conor
  0 siblings, 1 reply; 77+ messages in thread
From: David Marchand @ 2021-04-15 14:31 UTC (permalink / raw)
  To: Walsh, Conor
  Cc: Ananyev, Konstantin, Medvedkin, Vladimir,
	Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Burakov, Anatoly, Mcnamara, John, dev

On Thu, Apr 15, 2021 at 10:44 AM Walsh, Conor <conor.walsh@intel.com> wrote:
>
> <snip>
>
> > >
> > > The IPv6 subnets used were not within the 2001:200::/48 subnet
> >
> > {{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
> > {{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
> > etc...
> >
> > Err... all those subnets were exactly == 2001:200::/48.
> > Is the issue that the example needs *separate* subnets taken from
> > within 2001:200::/48 ?
>
> Hi David,
> As it is ATM any IP with that range will match for all the rules for the 8 ports and the application cannot differentiate between them and it just returns the traffic to sender.
> After this change the ports can be individually matched using the smaller /64 ranges for each port which are still within the given /48 subnet range (RFC5180).

Ok, thanks for confirming, could you update the commitlog to make it clear?

>
> >
> >
> > > Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID
> > >
> > > Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")
> >
> > And this looks like a Cc: stable@dpdk.org candidate.
>
> I can send a v8 and CC stable if you think that’s needed.

Yes please.
I was waiting to look at the rest of the series, I have some comments
that will require a v8 (from my pov).


-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-04-15 14:38               ` David Marchand
  0 siblings, 0 replies; 77+ messages in thread
From: David Marchand @ 2021-04-15 14:38 UTC (permalink / raw)
  To: Conor Walsh
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Ananyev, Konstantin, Vladimir Medvedkin, Burakov, Anatoly,
	Mcnamara, John, dev

On Tue, Apr 6, 2021 at 1:11 PM Conor Walsh <conor.walsh@intel.com> wrote:
>
> To prevent code duplication from the addition of lookup methods
> the routes specified in lpm should be moved to a common header.
>
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
>  examples/l3fwd/l3fwd_common_route.h | 48 +++++++++++++++++++
>  examples/l3fwd/l3fwd_lpm.c          | 74 +++++++----------------------
>  2 files changed, 65 insertions(+), 57 deletions(-)
>  create mode 100644 examples/l3fwd/l3fwd_common_route.h
>
> diff --git a/examples/l3fwd/l3fwd_common_route.h b/examples/l3fwd/l3fwd_common_route.h
> new file mode 100644
> index 0000000000..7f0125a8a5
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_common_route.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2021 Intel Corporation
> + */
> +
> +#include <stdint.h>
> +#include <rte_ip.h>
> +
> +struct ipv4_l3fwd_common_route {

Why "common" ? ipv4_l3fwd_route is enough.
Plus, this is what we reference in the doc.

doc/guides/sample_app_ug/l3_forward.rst:            if ((1 <<
ipv4_l3fwd_route_array[i].if_out & enabled_port_mask) == 0)
doc/guides/sample_app_ug/l3_forward.rst:            ret =
rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid],
ipv4_l3fwd_route_array[i].ip,
doc/guides/sample_app_ug/l3_forward.rst:
     ipv4_l3fwd_route_array[i].depth,
ipv4_l3fwd_route_array[i].if_out);
doc/guides/sample_app_ug/l3_forward.rst:
(unsigned)ipv4_l3fwd_route_array[i].ip,
ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out);


> +       uint32_t ip;
> +       uint8_t  depth;
> +       uint8_t  if_out;
> +};



> +
> +struct ipv6_l3fwd_common_route {
> +       uint8_t ip[16];
> +       uint8_t  depth;

Unneeded double space.


> +       uint8_t  if_out;
> +};
> +
> +/*
> + * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
> + * 198.18.{0-7}.0/24 = Port {0-7}
> + */
> +static const struct ipv4_l3fwd_common_route ipv4_l3fwd_common_route_array[] = {
> +       {RTE_IPV4(198, 18, 0, 0), 24, 0},
> +       {RTE_IPV4(198, 18, 1, 0), 24, 1},
> +       {RTE_IPV4(198, 18, 2, 0), 24, 2},
> +       {RTE_IPV4(198, 18, 3, 0), 24, 3},
> +       {RTE_IPV4(198, 18, 4, 0), 24, 4},
> +       {RTE_IPV4(198, 18, 5, 0), 24, 5},
> +       {RTE_IPV4(198, 18, 6, 0), 24, 6},
> +       {RTE_IPV4(198, 18, 7, 0), 24, 7},
> +};

With static symbols, we end up with duplicating info in lpm / fib.
$ nm build/examples/dpdk-l3fwd |grep ipv4_l3fwd_common_route_array
000000000100c260 r ipv4_l3fwd_common_route_array
000000000100c4c0 r ipv4_l3fwd_common_route_array

You can declare global symbols in a common header, and define them in main.c.


> +
> +/*
> + * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
> + * 2001:200:0:{0-7}::/64 = Port {0-7}
> + */
> +static const struct ipv6_l3fwd_common_route ipv6_l3fwd_common_route_array[] = {
> +       {{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
> +       {{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
> +       {{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
> +       {{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
> +       {{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
> +       {{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
> +       {{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
> +       {{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
> +};


-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-04-15 14:42               ` David Marchand
  0 siblings, 0 replies; 77+ messages in thread
From: David Marchand @ 2021-04-15 14:42 UTC (permalink / raw)
  To: Conor Walsh
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Ananyev, Konstantin, Vladimir Medvedkin, Burakov, Anatoly,
	Mcnamara, John, dev

On Tue, Apr 6, 2021 at 1:11 PM Conor Walsh <conor.walsh@intel.com> wrote:
>
> This patch implements the Forwarding Information Base (FIB) library
> in l3fwd using the function calls and infrastructure introduced in
> the previous patch.

This probably helped for reviews, but I will squash this into the
previous patches + the documentation before pushing.

>
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>



-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-04-15 14:43               ` David Marchand
  2021-04-15 14:59               ` David Marchand
  1 sibling, 0 replies; 77+ messages in thread
From: David Marchand @ 2021-04-15 14:43 UTC (permalink / raw)
  To: Conor Walsh
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Ananyev, Konstantin, Vladimir Medvedkin, Burakov, Anatoly,
	Mcnamara, John, dev

On Tue, Apr 6, 2021 at 1:11 PM Conor Walsh <conor.walsh@intel.com> wrote:
>
> The purpose of this patch is to update the l3fwd user guide to include
> the changes proposed in this patchset.
>
> Signed-off-by: Conor Walsh <conor.walsh@intel.com>
> Acked-by: John McNamara <john.mcnamara@intel.com>
> ---
>  doc/guides/sample_app_ug/l3_forward.rst | 113 +++++++++++++++++++++---

Please, add a bullet in the release notes.
Thanks.



-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-04-15 14:43               ` David Marchand
@ 2021-04-15 14:59               ` David Marchand
  1 sibling, 0 replies; 77+ messages in thread
From: David Marchand @ 2021-04-15 14:59 UTC (permalink / raw)
  To: Conor Walsh
  Cc: Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Ananyev, Konstantin, Vladimir Medvedkin, Burakov, Anatoly,
	Mcnamara, John, dev

On Tue, Apr 6, 2021 at 1:11 PM Conor Walsh <conor.walsh@intel.com> wrote:
> +        /* populate the FIB table */
> +
> +        for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) {
> +            struct in_addr in;
> +
> +            /* skip unused ports */
> +            if ((1 << ipv4_l3fwd_fib_route_array[i].if_out & enabled_port_mask) == 0)


Little extra comment, this code is not using the same variables as the code.

Pasting all this code in the documentation does not help, I would just
remove it and/or reference the code example to avoid doc and example
being out of sync in the future.


> +                continue;
> +


-- 
David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-15 14:31                   ` David Marchand
@ 2021-04-15 15:18                     ` Walsh, Conor
  0 siblings, 0 replies; 77+ messages in thread
From: Walsh, Conor @ 2021-04-15 15:18 UTC (permalink / raw)
  To: David Marchand
  Cc: Ananyev, Konstantin, Medvedkin, Vladimir,
	Jerin Jacob Kollanukkaran, Stephen Hemminger, Iremonger, Bernard,
	Burakov, Anatoly, Mcnamara, John, dev

<snip>

> > > > The IPv6 subnets used were not within the 2001:200::/48 subnet
> > >
> > > {{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
> > > {{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
> > > etc...
> > >
> > > Err... all those subnets were exactly == 2001:200::/48.
> > > Is the issue that the example needs *separate* subnets taken from
> > > within 2001:200::/48 ?
> >
> > Hi David,
> > As it is ATM any IP with that range will match for all the rules for the 8 ports
> and the application cannot differentiate between them and it just returns
> the traffic to sender.
> > After this change the ports can be individually matched using the smaller
> /64 ranges for each port which are still within the given /48 subnet range
> (RFC5180).
> 
> Ok, thanks for confirming, could you update the commitlog to make it clear?

Hi David,

Thanks for your feedback on this patch and the other patches in the series, I will address them in v8.

Thanks,
Conor.

> 
> >
> > >
> > >
> > > > Changed to 2001:200:0:{0-7}::/64 where 0-7 is the port ID
> > > >
> > > > Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")
> > >
> > > And this looks like a Cc: stable@dpdk.org candidate.
> >
> > I can send a v8 and CC stable if you think that’s needed.
> 
> Yes please.
> I was waiting to look at the rest of the series, I have some comments
> that will require a v8 (from my pov).
> 
> 
> --
> David Marchand


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                               ` (4 preceding siblings ...)
  2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-04-16 17:19             ` Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
                                 ` (5 more replies)
  5 siblings, 6 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh

Currently the l3fwd sample app supports LPM and EM lookup methods this
patchset implements the FIB library as another lookup method for l3fwd.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

---
v8:
    - Updated commit log to better explain why subnets needed to be changed
    - Changed the suffix on _common_route varibles to just _route
    - Corrected spacing issue
    - Route array symbols now only appear in binary once
    - Added notice to release notes
    - Removed large c blocks from doc and replaced with includes

v7:
    - Error log for invalid lookup method now runs within the parse_lookup
      function for better maintainability

v6:
    - rte_exit no longer used within parse_lookup, exiting due to
      incorrect config is now handled the same as the other config options
    - Corrected a typo within print usage
    - Moved -E and -L to the bottom of print usage as they are
      now legacy flags

v5:
    - Removed runtime checks to ensure desired port is within portmask,
      unused ports are still removed during setup

v4:
    - Changed individual switches for lookup methods to an
      enum for all lookup methods
    - Removed '-F' and introduced '--lookup' flag to select lookup methods
    - Fixed indentation issues
    - Renamed some variables for increased clarity
    - Minor changes to some logic for readability
    - Implemented MAC updating for FIB on non-SSE machines
    - Implemented RFC1812 for FIB on non-SSE machines
    - Added checks to ensure desired port is within portmask

v3: add support for NEON, PPC 64 and machines that do not support SSE,
    NEON or PPC 64.

v2: added the socket header file to fix FreeBSD build.

Conor Walsh (5):
  examples/l3fwd: fix LPM IPv6 subnets
  examples/l3fwd: move l3fwd routes to common header
  examples/l3fwd: add FIB infrastructure
  examples/l3fwd: implement FIB lookup method
  doc/guides/l3_forward: update documentation for FIB

 doc/guides/rel_notes/release_21_05.rst  |   5 +
 doc/guides/sample_app_ug/l3_forward.rst |  50 ++-
 examples/l3fwd/Makefile                 |   2 +-
 examples/l3fwd/l3fwd.h                  |  27 +-
 examples/l3fwd/l3fwd_event.c            |   9 +
 examples/l3fwd/l3fwd_event.h            |   1 +
 examples/l3fwd/l3fwd_fib.c              | 528 ++++++++++++++++++++++++
 examples/l3fwd/l3fwd_lpm.c              |  68 +--
 examples/l3fwd/l3fwd_route.h            |  19 +
 examples/l3fwd/main.c                   | 150 +++++--
 examples/l3fwd/meson.build              |   4 +-
 11 files changed, 763 insertions(+), 100 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c
 create mode 100644 examples/l3fwd/l3fwd_route.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 1/5] examples/l3fwd: fix LPM IPv6 subnets
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
@ 2021-04-16 17:19               ` Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
                                 ` (4 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh, stable

Any IP within the 2001:200::/48 subnet will match all the routes given
instead of 1 individual route and the application cannot
differentiate between them.
The change in this patch allows the ports to be individually matched using
smaller /64 ranges for each port. These smaller subnet ranges are still
within the 2001:200::/48 subnet range set aside for benchmarking
in RFC5180.
l3fwd will now use 2001:200:0:{0-7}::/64 where 0-7 is the port ID for IPv6.

Fixes: 37afe381bde4 ("examples/l3fwd: use reserved IP addresses")
CC: stable@dpdk.org

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 3dcf1fef18..1cfaf36572 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -42,7 +42,10 @@ struct ipv6_l3fwd_lpm_route {
 	uint8_t  if_out;
 };
 
-/* 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735). */
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
 static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 0, 0), 24, 0},
 	{RTE_IPV4(198, 18, 1, 0), 24, 1},
@@ -54,16 +57,19 @@ static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
-/* 2001:0200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180) */
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
 static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, 48, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 48, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0}, 48, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0}, 48, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0}, 48, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0}, 48, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0}, 48, 7},
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
 };
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 2/5] examples/l3fwd: move l3fwd routes to common header
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
@ 2021-04-16 17:19               ` Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
                                 ` (3 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh

To prevent code duplication from the addition of lookup methods
the routes specified in lpm should be moved to a common header.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_lpm.c   | 74 +++++++++---------------------------
 examples/l3fwd/l3fwd_route.h | 19 +++++++++
 examples/l3fwd/main.c        | 31 +++++++++++++++
 3 files changed, 67 insertions(+), 57 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_route.h

diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 1cfaf36572..351cc91a11 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -30,47 +30,7 @@
 #include "l3fwd.h"
 #include "l3fwd_event.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
-	uint8_t  depth;
-	uint8_t  if_out;
-};
-
-/*
- * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
- * 198.18.{0-7}.0/24 = Port {0-7}
- */
-static const struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{RTE_IPV4(198, 18, 0, 0), 24, 0},
-	{RTE_IPV4(198, 18, 1, 0), 24, 1},
-	{RTE_IPV4(198, 18, 2, 0), 24, 2},
-	{RTE_IPV4(198, 18, 3, 0), 24, 3},
-	{RTE_IPV4(198, 18, 4, 0), 24, 4},
-	{RTE_IPV4(198, 18, 5, 0), 24, 5},
-	{RTE_IPV4(198, 18, 6, 0), 24, 6},
-	{RTE_IPV4(198, 18, 7, 0), 24, 7},
-};
-
-/*
- * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
- * 2001:200:0:{0-7}::/64 = Port {0-7}
- */
-static const struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
-	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
-	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
-	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
-	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
-	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
-};
+#include "l3fwd_route.h"
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
@@ -485,18 +445,18 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv4_l3fwd_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_route_array[i].ip,
+			ipv4_l3fwd_route_array[i].depth,
+			ipv4_l3fwd_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -504,11 +464,11 @@ setup_lpm(const int socketid)
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
+		in.s_addr = htonl(ipv4_l3fwd_route_array[i].ip);
 		printf("LPM: Adding route %s / %d (%d)\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			ipv4_l3fwd_route_array[i].depth,
+			ipv4_l3fwd_route_array[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -525,17 +485,17 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_lpm_route_array); i++) {
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		if ((1 << ipv6_l3fwd_route_array[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_lpm_route_array[i].ip,
-			ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			ipv6_l3fwd_route_array[i].ip,
+			ipv6_l3fwd_route_array[i].depth,
+			ipv6_l3fwd_route_array[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -544,10 +504,10 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_lpm_route_array[i].ip,
+		       inet_ntop(AF_INET6, ipv6_l3fwd_route_array[i].ip,
 				 abuf, sizeof(abuf)),
-		       ipv6_l3fwd_lpm_route_array[i].depth,
-		       ipv6_l3fwd_lpm_route_array[i].if_out);
+		       ipv6_l3fwd_route_array[i].depth,
+		       ipv6_l3fwd_route_array[i].if_out);
 	}
 }
 
diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h
new file mode 100644
index 0000000000..89f8634443
--- /dev/null
+++ b/examples/l3fwd/l3fwd_route.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+struct ipv4_l3fwd_route {
+	uint32_t ip;
+	uint8_t  depth;
+	uint8_t  if_out;
+};
+
+struct ipv6_l3fwd_route {
+	uint8_t ip[16];
+	uint8_t depth;
+	uint8_t if_out;
+};
+
+extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[8];
+
+extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[8];
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index bb49e5faff..355064a1c7 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -47,6 +47,7 @@
 
 #include "l3fwd.h"
 #include "l3fwd_event.h"
+#include "l3fwd_route.h"
 
 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_LCORE
 #define MAX_RX_QUEUE_PER_PORT 128
@@ -162,6 +163,36 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+/*
+ * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
+ * 198.18.{0-7}.0/24 = Port {0-7}
+ */
+const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = {
+	{RTE_IPV4(198, 18, 0, 0), 24, 0},
+	{RTE_IPV4(198, 18, 1, 0), 24, 1},
+	{RTE_IPV4(198, 18, 2, 0), 24, 2},
+	{RTE_IPV4(198, 18, 3, 0), 24, 3},
+	{RTE_IPV4(198, 18, 4, 0), 24, 4},
+	{RTE_IPV4(198, 18, 5, 0), 24, 5},
+	{RTE_IPV4(198, 18, 6, 0), 24, 6},
+	{RTE_IPV4(198, 18, 7, 0), 24, 7},
+};
+
+/*
+ * 2001:200::/48 is IANA reserved range for IPv6 benchmarking (RFC5180).
+ * 2001:200:0:{0-7}::/64 = Port {0-7}
+ */
+const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
+	{{32, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 0},
+	{{32, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 1},
+	{{32, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+	{{32, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+	{{32, 1, 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 4},
+	{{32, 1, 2, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 5},
+	{{32, 1, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 6},
+	{{32, 1, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 7},
+};
+
 /*
  * Setup lookup methods for forwarding.
  * Currently exact-match and longest-prefix-match
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 3/5] examples/l3fwd: add FIB infrastructure
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
@ 2021-04-16 17:19               ` Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
                                 ` (2 subsequent siblings)
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh

The purpose of this commit is to add the necessary function calls
and supporting infrastructure to allow the Forwarding Information Base
(FIB) library to be integrated into the l3fwd sample app.
Instead of adding an individual flag for FIB, a new flag '--lookup' has
been added that allows the user to select their desired lookup method.
The flags '-E' and '-L' have been retained for backwards compatibility.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 examples/l3fwd/Makefile      |   2 +-
 examples/l3fwd/l3fwd.h       |  27 +++++++-
 examples/l3fwd/l3fwd_event.c |   9 +++
 examples/l3fwd/l3fwd_event.h |   1 +
 examples/l3fwd/l3fwd_fib.c   |  60 ++++++++++++++++++
 examples/l3fwd/main.c        | 119 ++++++++++++++++++++++++++---------
 examples/l3fwd/meson.build   |   4 +-
 7 files changed, 186 insertions(+), 36 deletions(-)
 create mode 100644 examples/l3fwd/l3fwd_fib.c

diff --git a/examples/l3fwd/Makefile b/examples/l3fwd/Makefile
index ff3930c42b..2381a215f0 100644
--- a/examples/l3fwd/Makefile
+++ b/examples/l3fwd/Makefile
@@ -5,7 +5,7 @@
 APP = l3fwd
 
 # all source are stored in SRCS-y
-SRCS-y := main.c l3fwd_lpm.c l3fwd_em.c l3fwd_event.c
+SRCS-y := main.c l3fwd_lpm.c l3fwd_fib.c l3fwd_em.c l3fwd_event.c
 SRCS-y += l3fwd_event_generic.c l3fwd_event_internal_port.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 2cf06099e0..a808d60247 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #ifndef __L3_FWD_H__
@@ -180,13 +180,16 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
-/* Function pointers for LPM or EM functionality. */
+/* Function pointers for LPM, EM or FIB functionality. */
 void
 setup_lpm(const int socketid);
 
 void
 setup_hash(const int socketid);
 
+void
+setup_fib(const int socketid);
+
 int
 em_check_ptype(int portid);
 
@@ -207,6 +210,9 @@ em_main_loop(__rte_unused void *dummy);
 int
 lpm_main_loop(__rte_unused void *dummy);
 
+int
+fib_main_loop(__rte_unused void *dummy);
+
 int
 lpm_event_main_loop_tx_d(__rte_unused void *dummy);
 int
@@ -225,8 +231,17 @@ em_event_main_loop_tx_q(__rte_unused void *dummy);
 int
 em_event_main_loop_tx_q_burst(__rte_unused void *dummy);
 
+int
+fib_event_main_loop_tx_d(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q(__rte_unused void *dummy);
+int
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy);
+
 
-/* Return ipv4/ipv6 fwd lookup struct for LPM or EM. */
+/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
 void *
 em_get_ipv4_l3fwd_lookup_struct(const int socketid);
 
@@ -239,4 +254,10 @@ lpm_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 lpm_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void *
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
+
+void *
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_event.c b/examples/l3fwd/l3fwd_event.c
index 4d31593a0a..961860ea18 100644
--- a/examples/l3fwd/l3fwd_event.c
+++ b/examples/l3fwd/l3fwd_event.c
@@ -227,6 +227,12 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 		[1][0] = em_event_main_loop_tx_q,
 		[1][1] = em_event_main_loop_tx_q_burst,
 	};
+	const event_loop_cb fib_event_loop[2][2] = {
+		[0][0] = fib_event_main_loop_tx_d,
+		[0][1] = fib_event_main_loop_tx_d_burst,
+		[1][0] = fib_event_main_loop_tx_q,
+		[1][1] = fib_event_main_loop_tx_q_burst,
+	};
 	uint32_t event_queue_cfg;
 	int ret;
 
@@ -264,4 +270,7 @@ l3fwd_event_resource_setup(struct rte_eth_conf *port_conf)
 
 	evt_rsrc->ops.em_event_loop = em_event_loop[evt_rsrc->tx_mode_q]
 						       [evt_rsrc->has_burst];
+
+	evt_rsrc->ops.fib_event_loop = fib_event_loop[evt_rsrc->tx_mode_q]
+						       [evt_rsrc->has_burst];
 }
diff --git a/examples/l3fwd/l3fwd_event.h b/examples/l3fwd/l3fwd_event.h
index 0e46164170..3ad1902ab5 100644
--- a/examples/l3fwd/l3fwd_event.h
+++ b/examples/l3fwd/l3fwd_event.h
@@ -55,6 +55,7 @@ struct l3fwd_event_setup_ops {
 	adapter_setup_cb adapter_setup;
 	event_loop_cb lpm_event_loop;
 	event_loop_cb em_event_loop;
+	event_loop_cb fib_event_loop;
 };
 
 struct l3fwd_event_resources {
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
new file mode 100644
index 0000000000..eb5bc2de5b
--- /dev/null
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#include "l3fwd.h"
+#include "l3fwd_event.h"
+#include "l3fwd_route.h"
+
+/* Main fib processing loop. */
+int
+fib_main_loop(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+int __rte_noinline
+fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
+{
+	return 0;
+}
+
+/* Function to setup fib. */
+void
+setup_fib(__rte_unused const int socketid)
+{}
+
+/* Return ipv4 fib lookup struct. */
+void *
+fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
+
+/* Return ipv6 fib lookup struct. */
+void *
+fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+{
+	return 0;
+}
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 355064a1c7..74413052b0 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
+ * Copyright(c) 2010-2021 Intel Corporation
  */
 
 #include <stdio.h>
@@ -61,9 +61,14 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 /**< Ports set in promiscuous mode off by default. */
 static int promiscuous_on;
 
-/* Select Longest-Prefix or Exact match. */
-static int l3fwd_lpm_on;
-static int l3fwd_em_on;
+/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
+enum L3FWD_LOOKUP_MODE {
+	L3FWD_LOOKUP_DEFAULT,
+	L3FWD_LOOKUP_LPM,
+	L3FWD_LOOKUP_EM,
+	L3FWD_LOOKUP_FIB
+};
+static enum L3FWD_LOOKUP_MODE lookup_mode;
 
 /* Global variables. */
 
@@ -163,6 +168,15 @@ static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
 };
 
+static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.setup                  = setup_fib,
+	.check_ptype            = lpm_check_ptype,
+	.cb_parse_ptype         = lpm_cb_parse_ptype,
+	.main_loop              = fib_main_loop,
+	.get_ipv4_lookup_struct = fib_get_ipv4_l3fwd_lookup_struct,
+	.get_ipv6_lookup_struct = fib_get_ipv6_l3fwd_lookup_struct,
+};
+
 /*
  * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
  * 198.18.{0-7}.0/24 = Port {0-7}
@@ -195,15 +209,18 @@ const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
 
 /*
  * Setup lookup methods for forwarding.
- * Currently exact-match and longest-prefix-match
- * are supported ones.
+ * Currently exact-match, longest-prefix-match and forwarding information
+ * base are the supported ones.
  */
 static void
 setup_l3fwd_lookup_tables(void)
 {
 	/* Setup HASH lookup functions. */
-	if (l3fwd_em_on)
+	if (lookup_mode == L3FWD_LOOKUP_EM)
 		l3fwd_lkp = l3fwd_em_lkp;
+	/* Setup FIB lookup functions. */
+	else if (lookup_mode == L3FWD_LOOKUP_FIB)
+		l3fwd_lkp = l3fwd_fib_lkp;
 	/* Setup LPM lookup functions. */
 	else
 		l3fwd_lkp = l3fwd_lpm_lkp;
@@ -306,8 +323,7 @@ print_usage(const char *prgname)
 	fprintf(stderr, "%s [EAL options] --"
 		" -p PORTMASK"
 		" [-P]"
-		" [-E]"
-		" [-L]"
+		" [--lookup]"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
 		" [--enable-jumbo [--max-pkt-len PKTLEN]]"
@@ -317,12 +333,15 @@ print_usage(const char *prgname)
 		" [--parse-ptype]"
 		" [--per-port-pool]"
 		" [--mode]"
-		" [--eventq-sched]\n\n"
+		" [--eventq-sched]"
+		" [-E]"
+		" [-L]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
-		"  -E : Enable exact match\n"
-		"  -L : Enable longest prefix match (default)\n"
+		"  --lookup: Select the lookup method\n"
+		"            Default: lpm\n"
+		"            Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (Forwarding Information Base)\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
 		"  --enable-jumbo: Enable jumbo frames\n"
@@ -341,7 +360,9 @@ print_usage(const char *prgname)
 		"                  Valid only if --mode=eventdev\n"
 		"  --event-eth-rxqs: Number of ethernet RX queues per device.\n"
 		"                    Default: 1\n"
-		"                    Valid only if --mode=eventdev\n\n",
+		"                    Valid only if --mode=eventdev\n"
+		"  -E : Enable exact match, legacy flag please use --lookup=em instead\n"
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n\n",
 		prgname);
 }
 
@@ -516,13 +537,29 @@ parse_event_eth_rx_queues(const char *eth_rx_queues)
 	evt_rsrc->eth_rx_queues = num_eth_rx_queues;
 }
 
+static int
+parse_lookup(const char *optarg)
+{
+	if (!strcmp(optarg, "em"))
+		lookup_mode = L3FWD_LOOKUP_EM;
+	else if (!strcmp(optarg, "lpm"))
+		lookup_mode = L3FWD_LOOKUP_LPM;
+	else if (!strcmp(optarg, "fib"))
+		lookup_mode = L3FWD_LOOKUP_FIB;
+	else {
+		fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib\n");
+		return -1;
+	}
+	return 0;
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
 	"p:"  /* portmask */
 	"P"   /* promiscuous */
-	"L"   /* enable long prefix match */
-	"E"   /* enable exact match */
+	"L"   /* legacy enable long prefix match */
+	"E"   /* legacy enable exact match */
 	;
 
 #define CMD_LINE_OPT_CONFIG "config"
@@ -536,6 +573,7 @@ static const char short_options[] =
 #define CMD_LINE_OPT_MODE "mode"
 #define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched"
 #define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs"
+#define CMD_LINE_OPT_LOOKUP "lookup"
 enum {
 	/* long options mapped to a short option */
 
@@ -553,6 +591,7 @@ enum {
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
 	CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM,
+	CMD_LINE_OPT_LOOKUP_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -568,6 +607,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM},
 	{CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0,
 					CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM},
+	{CMD_LINE_OPT_LOOKUP, 1, 0, CMD_LINE_OPT_LOOKUP_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -620,11 +660,19 @@ parse_args(int argc, char **argv)
 			break;
 
 		case 'E':
-			l3fwd_em_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_EM;
 			break;
 
 		case 'L':
-			l3fwd_lpm_on = 1;
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			lookup_mode = L3FWD_LOOKUP_LPM;
 			break;
 
 		/* long options */
@@ -711,18 +759,27 @@ parse_args(int argc, char **argv)
 			eth_rx_q = 1;
 			break;
 
+		case CMD_LINE_OPT_LOOKUP_NUM:
+			if (lookup_mode != L3FWD_LOOKUP_DEFAULT) {
+				fprintf(stderr, "Only one lookup mode is allowed at a time!\n");
+				return -1;
+			}
+			ret = parse_lookup(optarg);
+			/*
+			 * If parse_lookup was passed an invalid lookup type
+			 * then return -1. Error log included within
+			 * parse_lookup for simplicity.
+			 */
+			if (ret)
+				return -1;
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
 		}
 	}
 
-	/* If both LPM and EM are selected, return error. */
-	if (l3fwd_lpm_on && l3fwd_em_on) {
-		fprintf(stderr, "LPM and EM are mutually exclusive, select only one\n");
-		return -1;
-	}
-
 	if (evt_rsrc->enabled && lcore_params) {
 		fprintf(stderr, "lcore config is not valid when event mode is selected\n");
 		return -1;
@@ -742,17 +799,17 @@ parse_args(int argc, char **argv)
 	 * Nothing is selected, pick longest-prefix match
 	 * as default match.
 	 */
-	if (!l3fwd_lpm_on && !l3fwd_em_on) {
-		fprintf(stderr, "LPM or EM none selected, default LPM on\n");
-		l3fwd_lpm_on = 1;
+	if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
+		fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
+		lookup_mode = L3FWD_LOOKUP_LPM;
 	}
 
 	/*
 	 * ipv6 and hash flags are valid only for
-	 * exact macth, reset them to default for
+	 * exact match, reset them to default for
 	 * longest-prefix match.
 	 */
-	if (l3fwd_lpm_on) {
+	if (lookup_mode == L3FWD_LOOKUP_LPM) {
 		ipv6 = 0;
 		hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 	}
@@ -811,7 +868,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 				printf("Allocated mbuf pool on socket %d\n",
 					socketid);
 
-			/* Setup either LPM or EM(f.e Hash). But, only once per
+			/* Setup LPM, EM(f.e Hash) or FIB. But, only once per
 			 * available socket.
 			 */
 			if (!lkp_per_socket[socketid]) {
@@ -1250,8 +1307,10 @@ main(int argc, char **argv)
 	/* Configure eventdev parameters if user has requested */
 	if (evt_rsrc->enabled) {
 		l3fwd_event_resource_setup(&port_conf);
-		if (l3fwd_em_on)
+		if (lookup_mode == L3FWD_LOOKUP_EM)
 			l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop;
+		else if (lookup_mode == L3FWD_LOOKUP_FIB)
+			l3fwd_lkp.main_loop = evt_rsrc->ops.fib_event_loop;
 		else
 			l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop;
 		l3fwd_event_service_setup();
diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
index 7d72b1b365..2e5d1d34f2 100644
--- a/examples/l3fwd/meson.build
+++ b/examples/l3fwd/meson.build
@@ -7,8 +7,8 @@
 # DPDK instance, use 'make'
 
 allow_experimental_apis = true
-deps += ['hash', 'lpm', 'eventdev']
+deps += ['hash', 'lpm', 'fib', 'eventdev']
 sources = files(
-	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_event.c',
+	'l3fwd_em.c', 'l3fwd_lpm.c', 'l3fwd_fib.c', 'l3fwd_event.c',
 	'l3fwd_event_internal_port.c', 'l3fwd_event_generic.c', 'main.c'
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 4/5] examples/l3fwd: implement FIB lookup method
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                                 ` (2 preceding siblings ...)
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
@ 2021-04-16 17:19               ` Conor Walsh
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
  2021-04-20 18:28               ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Thomas Monjalon
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh

This patch implements the Forwarding Information Base (FIB) library
in l3fwd using the function calls and infrastructure introduced in
the previous patch.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/l3fwd/l3fwd_fib.c | 480 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 474 insertions(+), 6 deletions(-)

diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index eb5bc2de5b..c7d7689a94 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -2,59 +2,527 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
 #include <rte_fib.h>
 #include <rte_fib6.h>
 
 #include "l3fwd.h"
+#if defined RTE_ARCH_X86
+#include "l3fwd_sse.h"
+#elif defined __ARM_NEON
+#include "l3fwd_neon.h"
+#elif defined RTE_ARCH_PPC_64
+#include "l3fwd_altivec.h"
+#endif
 #include "l3fwd_event.h"
 #include "l3fwd_route.h"
 
+/* Configure how many packets ahead to prefetch for fib. */
+#define FIB_PREFETCH_OFFSET 4
+
+/* A non-existent portid is needed to denote a default hop for fib. */
+#define FIB_DEFAULT_HOP 999
+
+/*
+ * If the machine has SSE, NEON or PPC 64 then multiple packets
+ * can be sent at once if not only single packets will be sent
+ */
+#if defined RTE_ARCH_X86 || defined __ARM_NEON \
+		|| defined RTE_ARCH_PPC_64
+#define FIB_SEND_MULTI
+#endif
+
+static struct rte_fib *ipv4_l3fwd_fib_lookup_struct[NB_SOCKETS];
+static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
+
+/* Parse packet type and ip address. */
+static inline void
+fib_parse_packet(struct rte_mbuf *mbuf,
+		uint32_t *ipv4, uint32_t *ipv4_cnt,
+		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		uint32_t *ipv6_cnt, uint8_t *ip_type)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+
+	eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+	/* IPv4 */
+	if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+		*ipv4 = rte_be_to_cpu_32(ipv4_hdr->dst_addr);
+		/* Store type of packet in type_arr (IPv4=1, IPv6=0). */
+		*ip_type = 1;
+		(*ipv4_cnt)++;
+	}
+	/* IPv6 */
+	else {
+		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
+		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		*ip_type = 0;
+		(*ipv6_cnt)++;
+	}
+}
+
+/*
+ * If the machine does not have SSE, NEON or PPC 64 then the packets
+ * are sent one at a time using send_single_packet()
+ */
+#if !defined FIB_SEND_MULTI
+static inline void
+fib_send_single(int nb_tx, struct lcore_conf *qconf,
+		struct rte_mbuf **pkts_burst, uint16_t hops[nb_tx])
+{
+	int32_t j;
+	struct rte_ether_hdr *eth_hdr;
+
+	for (j = 0; j < nb_tx; j++) {
+		/* Run rfc1812 if packet is ipv4 and checks enabled. */
+#if defined DO_RFC_1812_CHECKS
+		rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
+				pkts_burst[j], struct rte_ether_hdr *) + 1),
+				&hops[j], pkts_burst[j]->packet_type);
+#endif
+
+		/* Set MAC addresses. */
+		eth_hdr = rte_pktmbuf_mtod(pkts_burst[j],
+				struct rte_ether_hdr *);
+		*(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[hops[j]];
+		rte_ether_addr_copy(&ports_eth_addr[hops[j]],
+				&eth_hdr->s_addr);
+
+		/* Send single packet. */
+		send_single_packet(qconf, pkts_burst[j], hops[j]);
+	}
+}
+#endif
+
+/* Bulk parse, fib lookup and send. */
+static inline void
+fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
+		uint16_t portid, struct lcore_conf *qconf)
+{
+	uint32_t ipv4_arr[nb_rx];
+	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint16_t hops[nb_rx];
+	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
+	uint8_t type_arr[nb_rx];
+	uint32_t ipv4_cnt = 0, ipv6_cnt = 0;
+	uint32_t ipv4_arr_assem = 0, ipv6_arr_assem = 0;
+	uint16_t nh;
+	int32_t i;
+
+	/* Prefetch first packets. */
+	for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_rx; i++)
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i], void *));
+
+	/* Parse packet info and prefetch. */
+	for (i = 0; i < (nb_rx - FIB_PREFETCH_OFFSET); i++) {
+		/* Prefetch packet. */
+		rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[
+				i + FIB_PREFETCH_OFFSET], void *));
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+	}
+
+	/* Parse remaining packet info. */
+	for (; i < nb_rx; i++)
+		fib_parse_packet(pkts_burst[i],
+				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&type_arr[i]);
+
+	/* Lookup IPv4 hops if IPv4 packets are present. */
+	if (likely(ipv4_cnt > 0))
+		rte_fib_lookup_bulk(qconf->ipv4_lookup_struct,
+				ipv4_arr, hopsv4, ipv4_cnt);
+
+	/* Lookup IPv6 hops if IPv6 packets are present. */
+	if (ipv6_cnt > 0)
+		rte_fib6_lookup_bulk(qconf->ipv6_lookup_struct,
+				ipv6_arr, hopsv6, ipv6_cnt);
+
+	/* Add IPv4 and IPv6 hops to one array depending on type. */
+	for (i = 0; i < nb_rx; i++) {
+		if (type_arr[i])
+			nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+		else
+			nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+		hops[i] = nh != FIB_DEFAULT_HOP ? nh : portid;
+	}
+
+#if defined FIB_SEND_MULTI
+	send_packets_multi(qconf, pkts_burst, hops, nb_rx);
+#else
+	fib_send_single(nb_rx, qconf, pkts_burst, hops);
+#endif
+}
+
 /* Main fib processing loop. */
 int
 fib_main_loop(__rte_unused void *dummy)
 {
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	unsigned int lcore_id;
+	uint64_t prev_tsc, diff_tsc, cur_tsc;
+	int i, nb_rx;
+	uint16_t portid;
+	uint8_t queueid;
+	struct lcore_conf *qconf;
+	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
+			US_PER_S * BURST_TX_DRAIN_US;
+
+	prev_tsc = 0;
+
+	lcore_id = rte_lcore_id();
+	qconf = &lcore_conf[lcore_id];
+
+	if (qconf->n_rx_queue == 0) {
+		RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
+		return 0;
+	}
+
+	RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
+
+	for (i = 0; i < qconf->n_rx_queue; i++) {
+
+		portid = qconf->rx_queue_list[i].port_id;
+		queueid = qconf->rx_queue_list[i].queue_id;
+		RTE_LOG(INFO, L3FWD,
+				" -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
+				lcore_id, portid, queueid);
+	}
+
+	while (!force_quit) {
+
+		cur_tsc = rte_rdtsc();
+
+		/* TX burst queue drain. */
+		diff_tsc = cur_tsc - prev_tsc;
+		if (unlikely(diff_tsc > drain_tsc)) {
+
+			for (i = 0; i < qconf->n_tx_port; ++i) {
+				portid = qconf->tx_port_id[i];
+				if (qconf->tx_mbufs[portid].len == 0)
+					continue;
+				send_burst(qconf,
+					qconf->tx_mbufs[portid].len,
+					portid);
+				qconf->tx_mbufs[portid].len = 0;
+			}
+
+			prev_tsc = cur_tsc;
+		}
+
+		/* Read packet from RX queues. */
+		for (i = 0; i < qconf->n_rx_queue; ++i) {
+			portid = qconf->rx_queue_list[i].port_id;
+			queueid = qconf->rx_queue_list[i].queue_id;
+			nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst,
+					MAX_PKT_BURST);
+			if (nb_rx == 0)
+				continue;
+
+			/* Use fib to lookup port IDs and transmit them. */
+			fib_send_packets(nb_rx, pkts_burst,	portid, qconf);
+		}
+	}
+
 	return 0;
 }
 
+/* One eventdev loop for single and burst using fib. */
+static __rte_always_inline void
+fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
+		const uint8_t flags)
+{
+	const int event_p_id = l3fwd_get_free_event_port(evt_rsrc);
+	const uint8_t tx_q_id = evt_rsrc->evq.event_q_id[
+			evt_rsrc->evq.nb_queues - 1];
+	const uint8_t event_d_id = evt_rsrc->event_d_id;
+	const uint16_t deq_len = evt_rsrc->deq_depth;
+	struct rte_event events[MAX_PKT_BURST];
+	struct lcore_conf *lconf;
+	unsigned int lcore_id;
+	int nb_enq, nb_deq, i;
+
+	uint32_t ipv4_arr[MAX_PKT_BURST];
+	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
+	uint16_t nh;
+	uint8_t type_arr[MAX_PKT_BURST];
+	uint32_t ipv4_cnt, ipv6_cnt;
+	uint32_t ipv4_arr_assem, ipv6_arr_assem;
+
+	if (event_p_id < 0)
+		return;
+
+	lcore_id = rte_lcore_id();
+
+	lconf = &lcore_conf[lcore_id];
+
+	RTE_LOG(INFO, L3FWD, "entering %s on lcore %u\n", __func__, lcore_id);
+
+	while (!force_quit) {
+		/* Read events from RX queues. */
+		nb_deq = rte_event_dequeue_burst(event_d_id, event_p_id,
+				events, deq_len, 0);
+		if (nb_deq == 0) {
+			rte_pause();
+			continue;
+		}
+
+		/* Reset counters. */
+		ipv4_cnt = 0;
+		ipv6_cnt = 0;
+		ipv4_arr_assem = 0;
+		ipv6_arr_assem = 0;
+
+		/* Prefetch first packets. */
+		for (i = 0; i < FIB_PREFETCH_OFFSET && i < nb_deq; i++)
+			rte_prefetch0(rte_pktmbuf_mtod(events[i].mbuf, void *));
+
+		/* Parse packet info and prefetch. */
+		for (i = 0; i < (nb_deq - FIB_PREFETCH_OFFSET); i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			/* Prefetch packet. */
+			rte_prefetch0(rte_pktmbuf_mtod(events[
+					i + FIB_PREFETCH_OFFSET].mbuf,
+					void *));
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Parse remaining packet info. */
+		for (; i < nb_deq; i++) {
+			if (flags & L3FWD_EVENT_TX_ENQ) {
+				events[i].queue_id = tx_q_id;
+				events[i].op = RTE_EVENT_OP_FORWARD;
+			}
+
+			if (flags & L3FWD_EVENT_TX_DIRECT)
+				rte_event_eth_tx_adapter_txq_set(events[i].mbuf,
+						0);
+
+			fib_parse_packet(events[i].mbuf,
+					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
+					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&type_arr[i]);
+		}
+
+		/* Lookup IPv4 hops if IPv4 packets are present. */
+		if (likely(ipv4_cnt > 0))
+			rte_fib_lookup_bulk(lconf->ipv4_lookup_struct,
+					ipv4_arr, hopsv4, ipv4_cnt);
+
+		/* Lookup IPv6 hops if IPv6 packets are present. */
+		if (ipv6_cnt > 0)
+			rte_fib6_lookup_bulk(lconf->ipv6_lookup_struct,
+					ipv6_arr, hopsv6, ipv6_cnt);
+
+		/* Assign ports looked up in fib depending on IPv4 or IPv6 */
+		for (i = 0; i < nb_deq; i++) {
+			if (type_arr[i])
+				nh = (uint16_t)hopsv4[ipv4_arr_assem++];
+			else
+				nh = (uint16_t)hopsv6[ipv6_arr_assem++];
+			if (nh != FIB_DEFAULT_HOP)
+				events[i].mbuf->port = nh;
+		}
+
+		if (flags & L3FWD_EVENT_TX_ENQ) {
+			nb_enq = rte_event_enqueue_burst(event_d_id, event_p_id,
+					events, nb_deq);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_enqueue_burst(event_d_id,
+						event_p_id, events + nb_enq,
+						nb_deq - nb_enq);
+		}
+
+		if (flags & L3FWD_EVENT_TX_DIRECT) {
+			nb_enq = rte_event_eth_tx_adapter_enqueue(event_d_id,
+					event_p_id, events, nb_deq, 0);
+			while (nb_enq < nb_deq && !force_quit)
+				nb_enq += rte_event_eth_tx_adapter_enqueue(
+						event_d_id, event_p_id,
+						events + nb_enq,
+						nb_deq - nb_enq, 0);
+		}
+	}
+}
+
 int __rte_noinline
 fib_event_main_loop_tx_d(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_d_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_DIRECT);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 int __rte_noinline
 fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 {
+	struct l3fwd_event_resources *evt_rsrc =
+			l3fwd_get_eventdev_rsrc();
+
+	fib_event_loop(evt_rsrc, L3FWD_EVENT_TX_ENQ);
 	return 0;
 }
 
 /* Function to setup fib. */
 void
-setup_fib(__rte_unused const int socketid)
-{}
+setup_fib(const int socketid)
+{
+	struct rte_fib6_conf config;
+	struct rte_fib_conf config_ipv4;
+	unsigned int i;
+	int ret;
+	char s[64];
+	char abuf[INET6_ADDRSTRLEN];
+
+	/* Create the fib IPv4 table. */
+	config_ipv4.type = RTE_FIB_DIR24_8;
+	config_ipv4.max_routes = (1 << 16);
+	config_ipv4.default_nh = FIB_DEFAULT_HOP;
+	config_ipv4.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+	config_ipv4.dir24_8.num_tbl8 = (1 << 15);
+	snprintf(s, sizeof(s), "IPV4_L3FWD_FIB_%d", socketid);
+	ipv4_l3fwd_fib_lookup_struct[socketid] =
+			rte_fib_create(s, socketid, &config_ipv4);
+	if (ipv4_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+			"Unable to create the l3fwd FIB table on socket %d\n",
+			socketid);
+
+	/* Populate the fib ipv4 table. */
+	for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
+		struct in_addr in;
+
+		/* Skip unused ports. */
+		if ((1 << ipv4_l3fwd_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid],
+			ipv4_l3fwd_route_array[i].ip,
+			ipv4_l3fwd_route_array[i].depth,
+			ipv4_l3fwd_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		in.s_addr = htonl(ipv4_l3fwd_route_array[i].ip);
+		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv4_l3fwd_route_array[i].depth,
+				ipv4_l3fwd_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv4 route added to port %d\n",
+				ipv4_l3fwd_route_array[i].if_out);
+		}
+	}
+
+	/* Create the fib IPv6 table. */
+	snprintf(s, sizeof(s), "IPV6_L3FWD_FIB_%d", socketid);
+
+	config.type = RTE_FIB6_TRIE;
+	config.max_routes = (1 << 16) - 1;
+	config.default_nh = FIB_DEFAULT_HOP;
+	config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+	config.trie.num_tbl8 = (1 << 15);
+	ipv6_l3fwd_fib_lookup_struct[socketid] = rte_fib6_create(s, socketid,
+			&config);
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL)
+		rte_exit(EXIT_FAILURE,
+				"Unable to create the l3fwd FIB table on socket %d\n",
+				socketid);
+
+	/* Populate the fib IPv6 table. */
+	for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
+
+		/* Skip unused ports. */
+		if ((1 << ipv6_l3fwd_route_array[i].if_out &
+				enabled_port_mask) == 0)
+			continue;
+
+		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
+			ipv6_l3fwd_route_array[i].ip,
+			ipv6_l3fwd_route_array[i].depth,
+			ipv6_l3fwd_route_array[i].if_out);
+
+		if (ret < 0) {
+			rte_exit(EXIT_FAILURE,
+					"Unable to add entry %u to the l3fwd FIB table on socket %d\n",
+					i, socketid);
+		}
+
+		if (inet_ntop(AF_INET6, ipv6_l3fwd_route_array[i].ip,
+				abuf, sizeof(abuf)) != NULL) {
+			printf("FIB: Adding route %s / %d (%d)\n",
+				abuf,
+				ipv6_l3fwd_route_array[i].depth,
+				ipv6_l3fwd_route_array[i].if_out);
+		} else {
+			printf("FIB: IPv6 route added to port %d\n",
+				ipv6_l3fwd_route_array[i].if_out);
+		}
+	}
+}
 
 /* Return ipv4 fib lookup struct. */
 void *
-fib_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv4_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv4_l3fwd_fib_lookup_struct[socketid];
 }
 
 /* Return ipv6 fib lookup struct. */
 void *
-fib_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
+fib_get_ipv6_l3fwd_lookup_struct(const int socketid)
 {
-	return 0;
+	return ipv6_l3fwd_fib_lookup_struct[socketid];
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* [dpdk-dev] [PATCH v8 5/5] doc/guides/l3_forward: update documentation for FIB
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                                 ` (3 preceding siblings ...)
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
@ 2021-04-16 17:19               ` Conor Walsh
  2021-04-20 18:28               ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Thomas Monjalon
  5 siblings, 0 replies; 77+ messages in thread
From: Conor Walsh @ 2021-04-16 17:19 UTC (permalink / raw)
  To: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand
  Cc: dev, Conor Walsh

The purpose of this patch is to update the l3fwd user guide to include
the changes proposed in this patchset.

Signed-off-by: Conor Walsh <conor.walsh@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
---
 doc/guides/rel_notes/release_21_05.rst  |  5 +++
 doc/guides/sample_app_ug/l3_forward.rst | 50 ++++++++++++++++++-------
 2 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst
index 2e3bf5c95a..7f558ed1c5 100644
--- a/doc/guides/rel_notes/release_21_05.rst
+++ b/doc/guides/rel_notes/release_21_05.rst
@@ -174,6 +174,11 @@ New Features
   * Added command to display Rx queue used descriptor count.
     ``show port (port_id) rxq (queue_id) desc used count``
 
+* **Added support for the FIB lookup method in the l3fwd example app.**
+
+  Previously the l3fwd sample app only supported LPM and EM lookup methods,
+  the app now supports the Forwarding Information Base (FIB) lookup method.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index e7875f8dcd..9263a6d942 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -11,7 +11,7 @@ The application performs L3 forwarding.
 Overview
 --------
 
-The application demonstrates the use of the hash and LPM libraries in the DPDK
+The application demonstrates the use of the hash, LPM and FIB libraries in DPDK
 to implement packet forwarding using poll or event mode PMDs for packet I/O.
 The initialization and run-time paths are very similar to those of the
 :doc:`l2_forward_real_virtual` and :doc:`l2_forward_event`.
@@ -22,7 +22,7 @@ decision is made based on information read from the input packet.
 Eventdev can optionally use S/W or H/W (if supported by platform) scheduler
 implementation for packet I/O based on run time parameters.
 
-The lookup method is either hash-based or LPM-based and is selected at run time. When the selected lookup method is hash-based,
+The lookup method is hash-based, LPM-based or FIB-based and is selected at run time. When the selected lookup method is hash-based,
 a hash object is used to emulate the flow classification stage.
 The hash object is used in correlation with a flow table to map each input packet to its flow at runtime.
 
@@ -30,14 +30,14 @@ The hash lookup key is represented by a DiffServ 5-tuple composed of the followi
 Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port.
 The ID of the output interface for the input packet is read from the identified flow table entry.
 The set of flows used by the application is statically configured and loaded into the hash at initialization time.
-When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets.
-The LPM object is used as the routing table to identify the next hop for each input packet at runtime.
+When the selected lookup method is LPM or FIB based, an LPM or FIB object is used to emulate the forwarding stage for IPv4 packets.
+The LPM or FIB object is used as the routing table to identify the next hop for each input packet at runtime.
 
-The LPM lookup key is represented by the Destination IP Address field read from the input packet.
-The ID of the output interface for the input packet is the next hop returned by the LPM lookup.
-The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time.
+The LPM and FIB lookup keys are represented by the Destination IP Address field read from the input packet.
+The ID of the output interface for the input packet is the next hop returned by the LPM or FIB lookup.
+The set of LPM and FIB rules used by the application is statically configured and loaded into the LPM or FIB object at initialization time.
 
-In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
+In the sample application, hash-based and FIB-based forwarding supports both IPv4 and IPv6. LPM-based forwarding supports IPv4 only.
 
 Compiling the Application
 -------------------------
@@ -53,8 +53,7 @@ The application has a number of command line options::
 
     ./dpdk-l3fwd [EAL options] -- -p PORTMASK
                              [-P]
-                             [-E]
-                             [-L]
+                             [--lookup LOOKUP_METHOD]
                              --config(port,queue,lcore)[,(port,queue,lcore)]
                              [--eth-dest=X,MM:MM:MM:MM:MM:MM]
                              [--enable-jumbo [--max-pkt-len PKTLEN]]
@@ -66,6 +65,8 @@ The application has a number of command line options::
                              [--mode]
                              [--eventq-sched]
                              [--event-eth-rxqs]
+                             [-E]
+                             [-L]
 
 Where,
 
@@ -74,9 +75,7 @@ Where,
 * ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
   Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
 
-* ``-E:`` Optional, enable exact match.
-
-* ``-L:`` Optional, enable longest prefix match.
+* ``--lookup:`` Optional, Select the lookup method. Accepted options ``em`` (Exact Match), ``lpm`` (Longest Prefix Match), ``fib`` (Forwarding Information Base). Default is ``lpm``.
 
 * ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.
 
@@ -102,6 +101,10 @@ Where,
 
 * ``--event-eth-rxqs:`` Optional, Number of ethernet RX queues per device. Only valid if --mode=eventdev.
 
+* ``-E:`` Optional, enable exact match, legacy flag please use ``--lookup=em`` instead.
+
+* ``-L:`` Optional, enable longest prefix match, legacy flag please use ``--lookup=lpm`` instead.
+
 
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
@@ -290,6 +293,19 @@ The LPM object is created and loaded with the pre-configured entries read from a
     }
     #endif
 
+FIB Initialization
+~~~~~~~~~~~~~~~~~~
+
+The FIB object is created and loaded with the pre-configured entries read from
+a global array. The abridged code snippet below shows the FIB initialization
+for IPv4, the full setup function including the IPv6 setup can be seen in
+the app code.
+
+.. literalinclude:: ../../../examples/l3fwd/l3fwd_fib.c
+    :language: c
+    :start-after: Function to setup fib.
+    :end-before: Create the fib IPv6 table.
+
 Packet Forwarding for Hash-based Lookups
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -380,6 +396,14 @@ for LPM-based lookups is done by the get_ipv4_dst_port() function below:
         return ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid);
     }
 
+Packet Forwarding for FIB-based Lookups
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The FIB library was designed to process multiple packets at once, it does not
+have separate functions for single and bulk lookups. ``rte_fib_lookup_bulk``
+is used for IPv4 lookups and ``rte_fib6_lookup_bulk`` for IPv6.
+Various examples of these functions being used can be found in the sample app code.
+
 Eventdev Driver Initialization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Eventdev driver initialization is same as L2 forwarding eventdev application.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 77+ messages in thread

* Re: [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd
  2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
                                 ` (4 preceding siblings ...)
  2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
@ 2021-04-20 18:28               ` Thomas Monjalon
  5 siblings, 0 replies; 77+ messages in thread
From: Thomas Monjalon @ 2021-04-20 18:28 UTC (permalink / raw)
  To: Conor Walsh
  Cc: jerinj, stephen, bernard.iremonger, konstantin.ananyev,
	vladimir.medvedkin, anatoly.burakov, john.mcnamara,
	david.marchand, dev

16/04/2021 19:19, Conor Walsh:
> Conor Walsh (5):
>   examples/l3fwd: fix LPM IPv6 subnets
>   examples/l3fwd: move l3fwd routes to common header
>   examples/l3fwd: add FIB infrastructure
>   examples/l3fwd: implement FIB lookup method
>   doc/guides/l3_forward: update documentation for FIB

Applied, thanks

Note: doc patch was squashed in 2 last patches,
and doc lines are more logically wrapped.




^ permalink raw reply	[flat|nested] 77+ messages in thread

end of thread, other threads:[~2021-04-20 18:28 UTC | newest]

Thread overview: 77+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-18 12:15 [dpdk-dev] [PATCH 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-02-18 12:15 ` [dpdk-dev] [PATCH 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-02-18 12:15 ` [dpdk-dev] [PATCH 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-02-18 12:15 ` [dpdk-dev] [PATCH 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-02-18 12:15 ` [dpdk-dev] [PATCH 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-02-18 12:15 ` [dpdk-dev] [PATCH 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-02-18 15:20 ` [dpdk-dev] [PATCH v2 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-02-18 15:20   ` [dpdk-dev] [PATCH v2 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-02-19 15:09   ` [dpdk-dev] [PATCH v3 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-03-08 10:41       ` Medvedkin, Vladimir
2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-03-02 16:20       ` Ananyev, Konstantin
2021-03-08 10:42       ` Medvedkin, Vladimir
2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-03-02 16:22       ` Ananyev, Konstantin
2021-03-03 11:36       ` Burakov, Anatoly
2021-03-08 15:13         ` Walsh, Conor
2021-03-08 10:42       ` Medvedkin, Vladimir
2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-03-02 16:21       ` Ananyev, Konstantin
2021-03-03 11:52       ` Burakov, Anatoly
2021-03-08 15:35         ` Walsh, Conor
2021-03-08 10:43       ` Medvedkin, Vladimir
2021-03-08 17:20         ` Walsh, Conor
2021-02-19 15:09     ` [dpdk-dev] [PATCH v3 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-03-11 12:01     ` [dpdk-dev] [PATCH v4 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-03-12 18:56         ` Medvedkin, Vladimir
2021-03-15 10:21           ` Walsh, Conor
2021-03-11 12:01       ` [dpdk-dev] [PATCH v4 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-03-15 11:34       ` [dpdk-dev] [PATCH v5 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-04-01 11:20           ` Burakov, Anatoly
2021-04-01 12:59             ` Walsh, Conor
2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-03-16 18:46           ` Medvedkin, Vladimir
2021-03-15 11:34         ` [dpdk-dev] [PATCH v5 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-03-18 19:45           ` Mcnamara, John
2021-04-02 10:52         ` [dpdk-dev] [PATCH v6 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-04-02 16:34             ` Burakov, Anatoly
2021-04-06 11:05               ` Walsh, Conor
2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-04-02 10:52           ` [dpdk-dev] [PATCH v6 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-04-06 11:11           ` [dpdk-dev] [PATCH v7 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-04-14 20:59               ` David Marchand
2021-04-15  8:44                 ` Walsh, Conor
2021-04-15 14:31                   ` David Marchand
2021-04-15 15:18                     ` Walsh, Conor
2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-04-15 14:38               ` David Marchand
2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-04-15 14:42               ` David Marchand
2021-04-06 11:11             ` [dpdk-dev] [PATCH v7 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-04-15 14:43               ` David Marchand
2021-04-15 14:59               ` David Marchand
2021-04-16 17:19             ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Conor Walsh
2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 1/5] examples/l3fwd: fix LPM IPv6 subnets Conor Walsh
2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 2/5] examples/l3fwd: move l3fwd routes to common header Conor Walsh
2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 3/5] examples/l3fwd: add FIB infrastructure Conor Walsh
2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 4/5] examples/l3fwd: implement FIB lookup method Conor Walsh
2021-04-16 17:19               ` [dpdk-dev] [PATCH v8 5/5] doc/guides/l3_forward: update documentation for FIB Conor Walsh
2021-04-20 18:28               ` [dpdk-dev] [PATCH v8 0/5] examples/l3fwd: add FIB lookup method to l3fwd Thomas Monjalon

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