DPDK patches and discussions
 help / color / mirror / Atom feed
From: Sean Morrissey <sean.morrissey@intel.com>
Cc: dev@dpdk.org, Sean Morrissey <sean.morrissey@intel.com>,
	Konstantin Ananyev <konstantin.ananyev@intel.com>
Subject: [PATCH v5 1/2] examples/l3fwd: add config file support for LPM/FIB
Date: Fri,  4 Feb 2022 19:59:04 +0000	[thread overview]
Message-ID: <20220204195905.449192-2-sean.morrissey@intel.com> (raw)
In-Reply-To: <20220204195905.449192-1-sean.morrissey@intel.com>

Add support to define ipv4 and ipv6 forwarding tables
from reading from a config file for LPM and FIB,
with format similar to l3fwd-acl one.

Users can now use the default hardcoded route tables
or optionally config files. Default config files have
been provided for use with LPM and FIB.

Signed-off-by: Sean Morrissey <sean.morrissey@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 examples/l3fwd/l3fwd.h            |  41 ++++
 examples/l3fwd/l3fwd_em.c         |  13 ++
 examples/l3fwd/l3fwd_fib.c        |  50 ++---
 examples/l3fwd/l3fwd_lpm.c        | 315 ++++++++++++++++++++++++++++--
 examples/l3fwd/l3fwd_route.h      |  17 ++
 examples/l3fwd/lpm_default_v4.cfg |  17 ++
 examples/l3fwd/lpm_default_v6.cfg |  17 ++
 examples/l3fwd/main.c             |  68 ++++++-
 8 files changed, 495 insertions(+), 43 deletions(-)
 create mode 100644 examples/l3fwd/lpm_default_v4.cfg
 create mode 100644 examples/l3fwd/lpm_default_v6.cfg

diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 38ca19133c..4e1e0af033 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -58,6 +58,30 @@
 #endif
 #define HASH_ENTRY_NUMBER_DEFAULT	16
 
+/*Log file related character defs. */
+#define COMMENT_LEAD_CHAR	('#')
+#define ROUTE_LEAD_CHAR		('R')
+
+#define	IPV6_ADDR_LEN	16
+#define	IPV6_ADDR_U16	(IPV6_ADDR_LEN / sizeof(uint16_t))
+#define	IPV6_ADDR_U32	(IPV6_ADDR_LEN / sizeof(uint32_t))
+
+#define GET_CB_FIELD(in, fd, base, lim, dlm)	do {            \
+	unsigned long val;                                      \
+	char *end;                                              \
+	errno = 0;                                              \
+	val = strtoul((in), &end, (base));                      \
+	if (errno != 0 || end[0] != (dlm) || val > (lim))       \
+		return -EINVAL;                               \
+	(fd) = (typeof(fd))val;                                 \
+	(in) = end + 1;                                         \
+} while (0)
+
+struct parm_cfg {
+	const char *rule_ipv4_name;
+	const char *rule_ipv6_name;
+};
+
 struct mbuf_table {
 	uint16_t len;
 	struct rte_mbuf *m_table[MAX_PKT_BURST];
@@ -96,6 +120,8 @@ extern xmm_t val_eth[RTE_MAX_ETHPORTS];
 
 extern struct lcore_conf lcore_conf[RTE_MAX_LCORE];
 
+extern struct parm_cfg parm_config;
+
 /* Send burst of packets on an output interface */
 static inline int
 send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port)
@@ -183,6 +209,12 @@ int
 init_mem(uint16_t portid, unsigned int nb_mbuf);
 
 /* Function pointers for LPM, EM or FIB functionality. */
+void
+read_config_files_lpm(void);
+
+void
+read_config_files_em(void);
+
 void
 setup_lpm(const int socketid);
 
@@ -286,4 +318,13 @@ fib_get_ipv4_l3fwd_lookup_struct(const int socketid);
 void *
 fib_get_ipv6_l3fwd_lookup_struct(const int socketid);
 
+void
+em_free_routes(void);
+
+void
+lpm_free_routes(void);
+
+int
+is_bypass_line(const char *buff);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c
index 5cc4a4d979..9058e75a76 100644
--- a/examples/l3fwd/l3fwd_em.c
+++ b/examples/l3fwd/l3fwd_em.c
@@ -972,6 +972,19 @@ em_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy)
 	return 0;
 }
 
+/* Load rules from the input file */
+void
+read_config_files_em(void)
+{
+	/* Empty till config file support added to EM */
+}
+
+void
+em_free_routes(void)
+{
+	/* Empty till config file support added to EM */
+}
+
 /* Initialize exact match (hash) parameters. 8< */
 void
 setup_hash(const int socketid)
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 2110459cc3..6e0054b4cb 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -583,7 +583,7 @@ setup_fib(const int socketid)
 	struct rte_eth_dev_info dev_info;
 	struct rte_fib6_conf config;
 	struct rte_fib_conf config_ipv4;
-	unsigned int i;
+	int i;
 	int ret;
 	char s[64];
 	char abuf[INET6_ADDRSTRLEN];
@@ -603,37 +603,39 @@ setup_fib(const int socketid)
 			"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++) {
+	for (i = 0; i < route_num_v4; i++) {
 		struct in_addr in;
 
 		/* Skip unused ports. */
-		if ((1 << ipv4_l3fwd_route_array[i].if_out &
+		if ((1 << route_base_v4[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
-		rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
+		rte_eth_dev_info_get(route_base_v4[i].if_out,
 				     &dev_info);
 		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);
+			route_base_v4[i].ip,
+			route_base_v4[i].depth,
+			route_base_v4[i].if_out);
 
 		if (ret < 0) {
+			free(route_base_v4);
 			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);
+		in.s_addr = htonl(route_base_v4[i].ip);
 		if (inet_ntop(AF_INET, &in, abuf, sizeof(abuf)) != NULL) {
 			printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
-			       ipv4_l3fwd_route_array[i].depth,
-			       ipv4_l3fwd_route_array[i].if_out,
+			       route_base_v4[i].depth,
+			       route_base_v4[i].if_out,
 			       dev_info.device->name);
 		} else {
 			printf("FIB: IPv4 route added to port %d [%s]\n",
-			       ipv4_l3fwd_route_array[i].if_out,
+			       route_base_v4[i].if_out,
 			       dev_info.device->name);
 		}
 	}
@@ -650,41 +652,45 @@ setup_fib(const int socketid)
 	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)
+	if (ipv6_l3fwd_fib_lookup_struct[socketid] == NULL) {
+		free(route_base_v4);
 		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++) {
+	for (i = 0; i < route_num_v6; i++) {
 
 		/* Skip unused ports. */
-		if ((1 << ipv6_l3fwd_route_array[i].if_out &
+		if ((1 << route_base_v6[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
-		rte_eth_dev_info_get(ipv6_l3fwd_route_array[i].if_out,
+		rte_eth_dev_info_get(route_base_v6[i].if_out,
 				     &dev_info);
 		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);
+			route_base_v6[i].ip_8,
+			route_base_v6[i].depth,
+			route_base_v6[i].if_out);
 
 		if (ret < 0) {
+			free(route_base_v4);
+			free(route_base_v6);
 			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,
+		if (inet_ntop(AF_INET6, route_base_v6[i].ip_8,
 				abuf, sizeof(abuf)) != NULL) {
 			printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
-			       ipv6_l3fwd_route_array[i].depth,
-			       ipv6_l3fwd_route_array[i].if_out,
+			       route_base_v6[i].depth,
+			       route_base_v6[i].if_out,
 			       dev_info.device->name);
 		} else {
 			printf("FIB: IPv6 route added to port %d [%s]\n",
-			       ipv6_l3fwd_route_array[i].if_out,
+			       route_base_v6[i].if_out,
 			       dev_info.device->name);
 		}
 	}
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index a5b476ced3..9e24ad1e7e 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -39,6 +39,16 @@
 
 static struct rte_lpm *ipv4_l3fwd_lpm_lookup_struct[NB_SOCKETS];
 static struct rte_lpm6 *ipv6_l3fwd_lpm_lookup_struct[NB_SOCKETS];
+struct lpm_route_rule *route_base_v4;
+struct lpm_route_rule *route_base_v6;
+int route_num_v4;
+int route_num_v6;
+
+enum {
+	CB_FLD_DST_ADDR,
+	CB_FLD_IF_OUT,
+	CB_FLD_MAX
+};
 
 /* Performing LPM-based lookups. 8< */
 static inline uint16_t
@@ -139,6 +149,233 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
 #include "l3fwd_lpm.h"
 #endif
 
+static int
+parse_ipv6_addr_mask(char *token, uint32_t *ipv6, uint8_t *mask)
+{
+	char *sa, *sm, *sv;
+	const char *dlm =  "/";
+
+	sv = NULL;
+	sa = strtok_r(token, dlm, &sv);
+	if (sa == NULL)
+		return -EINVAL;
+	sm = strtok_r(NULL, dlm, &sv);
+	if (sm == NULL)
+		return -EINVAL;
+
+	if (inet_pton(AF_INET6, sa, ipv6) != 1)
+		return -EINVAL;
+
+	GET_CB_FIELD(sm, *mask, 0, 128, 0);
+	return 0;
+}
+
+static int
+parse_ipv4_addr_mask(char *token, uint32_t *ipv4, uint8_t *mask)
+{
+	char *sa, *sm, *sv;
+	const char *dlm =  "/";
+
+	sv = NULL;
+	sa = strtok_r(token, dlm, &sv);
+	if (sa == NULL)
+		return -EINVAL;
+	sm = strtok_r(NULL, dlm, &sv);
+	if (sm == NULL)
+		return -EINVAL;
+
+	if (inet_pton(AF_INET, sa, ipv4) != 1)
+		return -EINVAL;
+
+	GET_CB_FIELD(sm, *mask, 0, 32, 0);
+	*ipv4 = ntohl(*ipv4);
+	return 0;
+}
+
+static int
+lpm_parse_v6_net(char *in, uint32_t *v, uint8_t *mask_len)
+{
+	int32_t rc;
+
+	/* get address. */
+	rc = parse_ipv6_addr_mask(in, v, mask_len);
+
+	return rc;
+}
+
+static int
+lpm_parse_v6_rule(char *str, struct lpm_route_rule *v)
+{
+	int i, rc;
+	char *s, *sp, *in[CB_FLD_MAX];
+	static const char *dlm = " \t\n";
+	int dim = CB_FLD_MAX;
+	s = str;
+
+	for (i = 0; i != dim; i++, s = NULL) {
+		in[i] = strtok_r(s, dlm, &sp);
+		if (in[i] == NULL)
+			return -EINVAL;
+	}
+
+	rc = lpm_parse_v6_net(in[CB_FLD_DST_ADDR], v->ip_32, &v->depth);
+
+	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
+
+	return rc;
+}
+
+static int
+lpm_parse_v4_rule(char *str, struct lpm_route_rule *v)
+{
+	int i, rc;
+	char *s, *sp, *in[CB_FLD_MAX];
+	static const char *dlm = " \t\n";
+	int dim = CB_FLD_MAX;
+	s = str;
+
+	for (i = 0; i != dim; i++, s = NULL) {
+		in[i] = strtok_r(s, dlm, &sp);
+		if (in[i] == NULL)
+			return -EINVAL;
+	}
+
+	rc = parse_ipv4_addr_mask(in[CB_FLD_DST_ADDR], &v->ip, &v->depth);
+
+	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
+
+	return rc;
+}
+
+static int
+lpm_add_rules(const char *rule_path,
+		struct lpm_route_rule **proute_base,
+		int (*parser)(char *, struct lpm_route_rule *))
+{
+	struct lpm_route_rule *route_rules;
+	struct lpm_route_rule *next;
+	unsigned int route_num = 0;
+	unsigned int route_cnt = 0;
+	char buff[LINE_MAX];
+	FILE *fh;
+	unsigned int i = 0, rule_size = sizeof(*next);
+	int val;
+
+	*proute_base = NULL;
+	fh = fopen(rule_path, "rb");
+	if (fh == NULL)
+		return -EINVAL;
+
+	while ((fgets(buff, LINE_MAX, fh) != NULL)) {
+		if (buff[0] == ROUTE_LEAD_CHAR)
+			route_num++;
+	}
+
+	if (route_num == 0) {
+		fclose(fh);
+		return -EINVAL;
+	}
+
+	val = fseek(fh, 0, SEEK_SET);
+	if (val < 0) {
+		fclose(fh);
+		return -EINVAL;
+	}
+
+	route_rules = calloc(route_num, rule_size);
+
+	if (route_rules == NULL) {
+		fclose(fh);
+		return -EINVAL;
+	}
+
+	i = 0;
+	while (fgets(buff, LINE_MAX, fh) != NULL) {
+		i++;
+		if (is_bypass_line(buff))
+			continue;
+
+		char s = buff[0];
+
+		/* Route entry */
+		if (s == ROUTE_LEAD_CHAR)
+			next = &route_rules[route_cnt];
+
+		/* Illegal line */
+		else {
+			RTE_LOG(ERR, L3FWD,
+				"%s Line %u: should start with leading "
+				"char %c\n",
+				rule_path, i, ROUTE_LEAD_CHAR);
+			fclose(fh);
+			free(route_rules);
+			return -EINVAL;
+		}
+
+		if (parser(buff + 1, next) != 0) {
+			RTE_LOG(ERR, L3FWD,
+				"%s Line %u: parse rules error\n",
+				rule_path, i);
+			fclose(fh);
+			free(route_rules);
+			return -EINVAL;
+		}
+
+		route_cnt++;
+	}
+
+	fclose(fh);
+
+	*proute_base = route_rules;
+
+	return route_cnt;
+}
+
+static int
+lpm_add_default_v4_rules(void)
+{
+	/* populate the LPM IPv4 table */
+	unsigned int i, rule_size = sizeof(*route_base_v4);
+	route_num_v4 = RTE_DIM(ipv4_l3fwd_route_array);
+
+	route_base_v4 = calloc(route_num_v4, rule_size);
+
+	for (i = 0; i < (unsigned int)route_num_v4; i++) {
+		route_base_v4[i].ip = ipv4_l3fwd_route_array[i].ip;
+		route_base_v4[i].depth = ipv4_l3fwd_route_array[i].depth;
+		route_base_v4[i].if_out = ipv4_l3fwd_route_array[i].if_out;
+	}
+	return 0;
+}
+
+static int
+lpm_add_default_v6_rules(void)
+{
+	/* populate the LPM IPv6 table */
+	unsigned int i, rule_size = sizeof(*route_base_v6);
+	route_num_v6 = RTE_DIM(ipv6_l3fwd_route_array);
+
+	route_base_v6 = calloc(route_num_v6, rule_size);
+
+	for (i = 0; i < (unsigned int)route_num_v6; i++) {
+		*(route_base_v6[i].ip_8) = *(ipv6_l3fwd_route_array[i].ip);
+		route_base_v6[i].depth = ipv6_l3fwd_route_array[i].depth;
+		route_base_v6[i].if_out = ipv6_l3fwd_route_array[i].if_out;
+	}
+	return 0;
+}
+
+void
+lpm_free_routes(void)
+{
+	free(route_base_v4);
+	free(route_base_v6);
+	route_base_v4 = NULL;
+	route_base_v6 = NULL;
+	route_num_v4 = 0;
+	route_num_v6 = 0;
+}
+
 /* main processing loop */
 int
 lpm_main_loop(__rte_unused void *dummy)
@@ -548,13 +785,47 @@ lpm_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy)
 	return 0;
 }
 
+/* Load rules from the input file */
+void
+read_config_files_lpm(void)
+{
+	if (parm_config.rule_ipv4_name != NULL &&
+			parm_config.rule_ipv6_name != NULL) {
+		/* ipv4 check */
+		route_num_v4 = lpm_add_rules(parm_config.rule_ipv4_name,
+					&route_base_v4, &lpm_parse_v4_rule);
+		if (route_num_v4 < 0) {
+			lpm_free_routes();
+			rte_exit(EXIT_FAILURE, "Failed to add IPv4 rules\n");
+		}
+
+		/* ipv6 check */
+		route_num_v6 = lpm_add_rules(parm_config.rule_ipv6_name,
+					&route_base_v6, &lpm_parse_v6_rule);
+		if (route_num_v6 < 0) {
+			lpm_free_routes();
+			rte_exit(EXIT_FAILURE, "Failed to add IPv6 rules\n");
+		}
+	} else {
+		RTE_LOG(INFO, L3FWD, "Missing 1 or more rule files, using default instead\n");
+		if (lpm_add_default_v4_rules() < 0) {
+			lpm_free_routes();
+			rte_exit(EXIT_FAILURE, "Failed to add default IPv4 rules\n");
+		}
+		if (lpm_add_default_v6_rules() < 0) {
+			lpm_free_routes();
+			rte_exit(EXIT_FAILURE, "Failed to add default IPv6 rules\n");
+		}
+	}
+}
+
 void
 setup_lpm(const int socketid)
 {
 	struct rte_eth_dev_info dev_info;
 	struct rte_lpm6_config config;
 	struct rte_lpm_config config_ipv4;
-	unsigned i;
+	int i;
 	int ret;
 	char s[64];
 	char abuf[INET6_ADDRSTRLEN];
@@ -572,32 +843,33 @@ setup_lpm(const int socketid)
 			socketid);
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv4_l3fwd_route_array); i++) {
+	for (i = 0; i < route_num_v4; i++) {
 		struct in_addr in;
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_route_array[i].if_out &
+		if ((1 << route_base_v4[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
-		rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
+		rte_eth_dev_info_get(route_base_v4[i].if_out,
 				     &dev_info);
 		ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid],
-			ipv4_l3fwd_route_array[i].ip,
-			ipv4_l3fwd_route_array[i].depth,
-			ipv4_l3fwd_route_array[i].if_out);
+			route_base_v4[i].ip,
+			route_base_v4[i].depth,
+			route_base_v4[i].if_out);
 
 		if (ret < 0) {
+			lpm_free_routes();
 			rte_exit(EXIT_FAILURE,
 				"Unable to add entry %u to the l3fwd LPM table on socket %d\n",
 				i, socketid);
 		}
 
-		in.s_addr = htonl(ipv4_l3fwd_route_array[i].ip);
+		in.s_addr = htonl(route_base_v4[i].ip);
 		printf("LPM: Adding route %s / %d (%d) [%s]\n",
 		       inet_ntop(AF_INET, &in, abuf, sizeof(abuf)),
-		       ipv4_l3fwd_route_array[i].depth,
-		       ipv4_l3fwd_route_array[i].if_out, dev_info.device->name);
+		       route_base_v4[i].depth,
+		       route_base_v4[i].if_out, dev_info.device->name);
 	}
 
 	/* create the LPM6 table */
@@ -608,37 +880,40 @@ setup_lpm(const int socketid)
 	config.flags = 0;
 	ipv6_l3fwd_lpm_lookup_struct[socketid] = rte_lpm6_create(s, socketid,
 				&config);
-	if (ipv6_l3fwd_lpm_lookup_struct[socketid] == NULL)
+	if (ipv6_l3fwd_lpm_lookup_struct[socketid] == NULL) {
+		lpm_free_routes();
 		rte_exit(EXIT_FAILURE,
 			"Unable to create the l3fwd LPM table on socket %d\n",
 			socketid);
+	}
 
 	/* populate the LPM table */
-	for (i = 0; i < RTE_DIM(ipv6_l3fwd_route_array); i++) {
+	for (i = 0; i < route_num_v6; i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_route_array[i].if_out &
+		if ((1 << route_base_v6[i].if_out &
 				enabled_port_mask) == 0)
 			continue;
 
-		rte_eth_dev_info_get(ipv4_l3fwd_route_array[i].if_out,
+		rte_eth_dev_info_get(route_base_v6[i].if_out,
 				     &dev_info);
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			ipv6_l3fwd_route_array[i].ip,
-			ipv6_l3fwd_route_array[i].depth,
-			ipv6_l3fwd_route_array[i].if_out);
+			route_base_v6[i].ip_8,
+			route_base_v6[i].depth,
+			route_base_v6[i].if_out);
 
 		if (ret < 0) {
+			lpm_free_routes();
 			rte_exit(EXIT_FAILURE,
 				"Unable to add entry %u to the l3fwd LPM table on socket %d\n",
 				i, socketid);
 		}
 
 		printf("LPM: Adding route %s / %d (%d) [%s]\n",
-		       inet_ntop(AF_INET6, ipv6_l3fwd_route_array[i].ip, abuf,
+		       inet_ntop(AF_INET6, route_base_v6[i].ip_8, abuf,
 				 sizeof(abuf)),
-		       ipv6_l3fwd_route_array[i].depth,
-		       ipv6_l3fwd_route_array[i].if_out, dev_info.device->name);
+		       route_base_v6[i].depth,
+		       route_base_v6[i].if_out, dev_info.device->name);
 	}
 }
 
diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h
index c7eba06c4d..843ffbe9fa 100644
--- a/examples/l3fwd/l3fwd_route.h
+++ b/examples/l3fwd/l3fwd_route.h
@@ -14,6 +14,23 @@ struct ipv6_l3fwd_route {
 	uint8_t if_out;
 };
 
+struct lpm_route_rule {
+	union {
+		uint32_t ip;
+		union {
+			uint32_t ip_32[IPV6_ADDR_U32];
+			uint8_t ip_8[IPV6_ADDR_LEN];
+		};
+	};
+	uint8_t depth;
+	uint8_t if_out;
+};
+
+extern struct lpm_route_rule *route_base_v4;
+extern struct lpm_route_rule *route_base_v6;
+extern int route_num_v4;
+extern int route_num_v6;
+
 extern const struct ipv4_l3fwd_route ipv4_l3fwd_route_array[16];
 
 extern const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[16];
diff --git a/examples/l3fwd/lpm_default_v4.cfg b/examples/l3fwd/lpm_default_v4.cfg
new file mode 100644
index 0000000000..4db5597ed8
--- /dev/null
+++ b/examples/l3fwd/lpm_default_v4.cfg
@@ -0,0 +1,17 @@
+#Copy of hard-coded IPv4 FWD table for L3FWD LPM
+R198.18.0.0/24 0
+R198.18.1.0/24 1
+R198.18.2.0/24 2
+R198.18.3.0/24 3
+R198.18.4.0/24 4
+R198.18.5.0/24 5
+R198.18.6.0/24 6
+R198.18.7.0/24 7
+R198.18.8.0/24 8
+R198.18.9.0/24 9
+R198.18.10.0/24 10
+R198.18.11.0/24 11
+R198.18.12.0/24 12
+R198.18.13.0/24 13
+R198.18.14.0/24 14
+R198.18.15.0/24 15
diff --git a/examples/l3fwd/lpm_default_v6.cfg b/examples/l3fwd/lpm_default_v6.cfg
new file mode 100644
index 0000000000..c50233e0ba
--- /dev/null
+++ b/examples/l3fwd/lpm_default_v6.cfg
@@ -0,0 +1,17 @@
+#Copy of hard-coded IPv6 FWD table for L3FWD LPM
+R2001:0200:0000:0000:0000:0000:0000:0000/64 0
+R2001:0200:0000:0001:0000:0000:0000:0000/64 1
+R2001:0200:0000:0002:0000:0000:0000:0000/64 2
+R2001:0200:0000:0003:0000:0000:0000:0000/64 3
+R2001:0200:0000:0004:0000:0000:0000:0000/64 4
+R2001:0200:0000:0005:0000:0000:0000:0000/64 5
+R2001:0200:0000:0006:0000:0000:0000:0000/64 6
+R2001:0200:0000:0007:0000:0000:0000:0000/64 7
+R2001:0200:0000:0008:0000:0000:0000:0000/64 8
+R2001:0200:0000:0009:0000:0000:0000:0000/64 9
+R2001:0200:0000:000A:0000:0000:0000:0000/64 10
+R2001:0200:0000:000B:0000:0000:0000:0000/64 11
+R2001:0200:0000:000C:0000:0000:0000:0000/64 12
+R2001:0200:0000:000D:0000:0000:0000:0000/64 13
+R2001:0200:0000:000E:0000:0000:0000:0000/64 14
+R2001:0200:0000:000F:0000:0000:0000:0000/64 15
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index eb68ffc5aa..8383d8f095 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -94,6 +94,8 @@ uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
 
 struct lcore_conf lcore_conf[RTE_MAX_LCORE];
 
+struct parm_cfg parm_config;
+
 struct lcore_params {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -141,41 +143,49 @@ static struct rte_mempool *vector_pool[RTE_MAX_ETHPORTS];
 static uint8_t lkp_per_socket[NB_SOCKETS];
 
 struct l3fwd_lkp_mode {
+	void  (*read_config_files)(void);
 	void  (*setup)(int);
 	int   (*check_ptype)(int);
 	rte_rx_callback_fn cb_parse_ptype;
 	int   (*main_loop)(void *);
 	void* (*get_ipv4_lookup_struct)(int);
 	void* (*get_ipv6_lookup_struct)(int);
+	void  (*free_routes)(void);
 };
 
 static struct l3fwd_lkp_mode l3fwd_lkp;
 
 static struct l3fwd_lkp_mode l3fwd_em_lkp = {
+	.read_config_files		= read_config_files_em,
 	.setup                  = setup_hash,
 	.check_ptype		= em_check_ptype,
 	.cb_parse_ptype		= em_cb_parse_ptype,
 	.main_loop              = em_main_loop,
 	.get_ipv4_lookup_struct = em_get_ipv4_l3fwd_lookup_struct,
 	.get_ipv6_lookup_struct = em_get_ipv6_l3fwd_lookup_struct,
+	.free_routes			= em_free_routes,
 };
 
 static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
+	.read_config_files		= read_config_files_lpm,
 	.setup                  = setup_lpm,
 	.check_ptype		= lpm_check_ptype,
 	.cb_parse_ptype		= lpm_cb_parse_ptype,
 	.main_loop              = lpm_main_loop,
 	.get_ipv4_lookup_struct = lpm_get_ipv4_l3fwd_lookup_struct,
 	.get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
+	.free_routes			= lpm_free_routes,
 };
 
 static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
+	.read_config_files		= read_config_files_lpm,
 	.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,
+	.free_routes			= lpm_free_routes,
 };
 
 /*
@@ -224,6 +234,21 @@ const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
 	{{32, 1, 2, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 15},
 };
 
+/*
+ * API's called during initialization to setup ACL/EM/LPM rules.
+ */
+static void
+l3fwd_set_rule_ipv4_name(const char *optarg)
+{
+	parm_config.rule_ipv4_name = optarg;
+}
+
+static void
+l3fwd_set_rule_ipv6_name(const char *optarg)
+{
+	parm_config.rule_ipv6_name = optarg;
+}
+
 /*
  * Setup lookup methods for forwarding.
  * Currently exact-match, longest-prefix-match and forwarding information
@@ -339,6 +364,8 @@ print_usage(const char *prgname)
 {
 	fprintf(stderr, "%s [EAL options] --"
 		" -p PORTMASK"
+		"  --rule_ipv4=FILE"
+		"  --rule_ipv6=FILE"
 		" [-P]"
 		" [--lookup]"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -381,7 +408,10 @@ print_usage(const char *prgname)
 		"  --event-vector-size: Max vector size if event vectorization is enabled.\n"
 		"  --event-vector-tmo: Max timeout to form vector in nanoseconds if event vectorization is enabled\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",
+		"  -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n"
+		"  --rule_ipv4=FILE: Specify the ipv4 rules entries file.\n"
+		"                    Each rule occupies one line.\n"
+		"  --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n\n",
 		prgname);
 }
 
@@ -596,6 +626,8 @@ static const char short_options[] =
 #define CMD_LINE_OPT_ENABLE_VECTOR "event-vector"
 #define CMD_LINE_OPT_VECTOR_SIZE "event-vector-size"
 #define CMD_LINE_OPT_VECTOR_TMO_NS "event-vector-tmo"
+#define CMD_LINE_OPT_RULE_IPV4 "rule_ipv4"
+#define CMD_LINE_OPT_RULE_IPV6 "rule_ipv6"
 
 enum {
 	/* long options mapped to a short option */
@@ -610,6 +642,8 @@ enum {
 	CMD_LINE_OPT_MAX_PKT_LEN_NUM,
 	CMD_LINE_OPT_HASH_ENTRY_NUM_NUM,
 	CMD_LINE_OPT_PARSE_PTYPE_NUM,
+	CMD_LINE_OPT_RULE_IPV4_NUM,
+	CMD_LINE_OPT_RULE_IPV6_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
 	CMD_LINE_OPT_MODE_NUM,
 	CMD_LINE_OPT_EVENTQ_SYNC_NUM,
@@ -637,6 +671,8 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_ENABLE_VECTOR, 0, 0, CMD_LINE_OPT_ENABLE_VECTOR_NUM},
 	{CMD_LINE_OPT_VECTOR_SIZE, 1, 0, CMD_LINE_OPT_VECTOR_SIZE_NUM},
 	{CMD_LINE_OPT_VECTOR_TMO_NS, 1, 0, CMD_LINE_OPT_VECTOR_TMO_NS_NUM},
+	{CMD_LINE_OPT_RULE_IPV4,   1, 0, CMD_LINE_OPT_RULE_IPV4_NUM},
+	{CMD_LINE_OPT_RULE_IPV6,   1, 0, CMD_LINE_OPT_RULE_IPV6_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -791,6 +827,12 @@ parse_args(int argc, char **argv)
 		case CMD_LINE_OPT_VECTOR_TMO_NS_NUM:
 			evt_rsrc->vector_tmo_ns = strtoull(optarg, NULL, 10);
 			break;
+		case CMD_LINE_OPT_RULE_IPV4_NUM:
+			l3fwd_set_rule_ipv4_name(optarg);
+			break;
+		case CMD_LINE_OPT_RULE_IPV6_NUM:
+			l3fwd_set_rule_ipv6_name(optarg);
+			break;
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1358,6 +1400,24 @@ l3fwd_event_service_setup(void)
 	}
 }
 
+/* Bypass comment and empty lines */
+int
+is_bypass_line(const char *buff)
+{
+	int i = 0;
+
+	/* comment line */
+	if (buff[0] == COMMENT_LEAD_CHAR)
+		return 1;
+	/* empty line */
+	while (buff[i] != '\0') {
+		if (!isspace(buff[i]))
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -1395,6 +1455,9 @@ main(int argc, char **argv)
 	/* Setup function pointers for lookup method. */
 	setup_l3fwd_lookup_tables();
 
+	/* Add the config file rules */
+	l3fwd_lkp.read_config_files();
+
 	evt_rsrc->per_port_pool = per_port_pool;
 	evt_rsrc->pkt_pool = pktmbuf_pool;
 	evt_rsrc->vec_pool = vector_pool;
@@ -1501,6 +1564,9 @@ main(int argc, char **argv)
 		}
 	}
 
+	/* clean up config file routes */
+	l3fwd_lkp.free_routes();
+
 	/* clean up the EAL */
 	rte_eal_cleanup();
 
-- 
2.25.1


  reply	other threads:[~2022-02-04 19:59 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-16 15:01 [PATCH v1 0/2] Add config file support for l3fwd Sean Morrissey
2021-12-16 15:01 ` [PATCH v1 1/2] examples/l3fwd: add config file support for LPM/FIB Sean Morrissey
2021-12-16 15:01 ` [PATCH v1 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2021-12-20 11:08 ` [PATCH v2 0/2] Add config file support for l3fwd Sean Morrissey
2021-12-20 11:08   ` [PATCH v2 1/2] examples/l3fwd: add config file support for LPM/FIB Sean Morrissey
2021-12-20 15:42     ` Ananyev, Konstantin
2021-12-20 11:08   ` [PATCH v2 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2021-12-20 15:53     ` Ananyev, Konstantin
2021-12-21 12:30   ` [PATCH v3 0/2] Add config file support for l3fwd Sean Morrissey
2021-12-21 12:30     ` [PATCH v3 1/2] examples/l3fwd: add config file support for LPM/FIB Sean Morrissey
2021-12-21 12:30     ` [PATCH v3 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2022-01-10 14:00       ` Ananyev, Konstantin
2022-01-26 12:44     ` [PATCH v4 0/2] Add config file support for l3fwd Sean Morrissey
2022-01-26 12:44       ` [PATCH v4 1/2] examples/l3fwd: add config file support for LPM/FIB Sean Morrissey
2022-01-26 12:44       ` [PATCH v4 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2022-02-04 19:59       ` [PATCH v5 0/2] Add config file support for l3fwd Sean Morrissey
2022-02-04 19:59         ` Sean Morrissey [this message]
2022-02-08  2:21           ` [PATCH v5 1/2] examples/l3fwd: add config file support for LPM/FIB Han, YingyaX
2022-02-04 19:59         ` [PATCH v5 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2022-02-04 22:26         ` [PATCH v5 0/2] Add config file support for l3fwd Stephen Hemminger
2022-02-06 15:16           ` Ananyev, Konstantin
2022-02-08  3:04             ` Stephen Hemminger
2022-02-08 10:44               ` Ananyev, Konstantin
2022-02-08 16:15                 ` Medvedkin, Vladimir
2022-02-08 17:49                   ` Stephen Hemminger
2022-02-08 18:10                     ` Bruce Richardson
2022-02-09 12:00                     ` Ananyev, Konstantin
2022-02-09 13:54                       ` Bruce Richardson
2022-02-09 16:00                         ` Medvedkin, Vladimir
2022-02-22  9:59                       ` Thomas Monjalon
2022-02-22 10:39                         ` Ananyev, Konstantin
2022-02-22 13:46                           ` Thomas Monjalon
2022-02-22 15:13                             ` Ananyev, Konstantin
2022-02-22 16:48                               ` Thomas Monjalon
2022-02-24 11:06                                 ` Ananyev, Konstantin
2022-02-24 13:46                                   ` Thomas Monjalon
2022-02-24 13:58                                     ` Bruce Richardson
2022-02-25 10:36                                       ` Ananyev, Konstantin
2022-02-25 10:40                                         ` Bruce Richardson
2022-02-25 12:21                                           ` Ananyev, Konstantin
2022-02-25 12:50                                           ` Morten Brørup
2022-02-25  5:18                                     ` Honnappa Nagarahalli
2022-03-01 14:49         ` [PATCH v6 " Sean Morrissey
2022-03-01 14:49           ` [PATCH v6 1/2] examples/l3fwd: add config file support for LPM/FIB Sean Morrissey
2022-03-01 14:49           ` [PATCH v6 2/2] examples/l3fwd: add config file support for EM Sean Morrissey
2022-03-08  8:57           ` [PATCH v6 0/2] Add config file support for l3fwd Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220204195905.449192-2-sean.morrissey@intel.com \
    --to=sean.morrissey@intel.com \
    --cc=dev@dpdk.org \
    --cc=konstantin.ananyev@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).