[dpdk-dev,v6,2/3] examples/l3fwd: add config file support for lpm

Message ID 1489179491-9401-3-git-send-email-rkerur@gmail.com (mailing list archive)
State Rejected, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch warning coding style issues

Commit Message

Ravi Kerur March 10, 2017, 8:58 p.m. UTC
  Add support to read from config file to build ipv4 and ipv6
longest prefix match forwarding tables.
---

v6:
	> Change commit message format.

v5:
	> Change is_bypass_line from inline to non-line.

v4:
	> No changes.

v3:
	> Fix additional checkpatch coding style issues.

v2:
	> Fix checkpatch warnings related to code
	> MACRO GET_CB_FIELD checkpatch warning not fixed

v1:
	> Remove static array configuration of Destination IP, MASK
		and IF_OUT for LPM and LPM6 config.
	> Add reading configuration from a file.
	> Format of configuration file is as follows
		#LPM route entries Dest-IP/Mask IF_OUT
		L1.1.1.0/24 0
		L2.1.1.0/24 1
		L3.1.1.0/24 2
		...

		#LPM6 route entries Dest-IP/Mask IF_OUT
		L1111:1111:1111:1111:0000:0000:0000:0000/48 0
		L2111:1111:1111:1111:0000:0000:0000:0000/48 1
		L3111:1111:1111:1111:0000:0000:0000:0000/48 2
		...

Signed-off-by: Ravi Kerur <rkerur@gmail.com>
---
 examples/l3fwd/l3fwd.h     |  28 +++++
 examples/l3fwd/l3fwd_acl.c |  39 +-----
 examples/l3fwd/l3fwd_acl.h |  29 -----
 examples/l3fwd/l3fwd_lpm.c | 308 +++++++++++++++++++++++++++++++++++++--------
 examples/l3fwd/main.c      |  47 ++++++-
 5 files changed, 332 insertions(+), 119 deletions(-)
  

Patch

diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 93e08f6..aa4bd25 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -94,6 +94,29 @@ 
 #define ACL_LEAD_CHAR		('@')
 #define ROUTE_LEAD_CHAR		('R')
 #define COMMENT_LEAD_CHAR	('#')
+#define LPM_LEAD_CHAR		('L')
+#define EM_LEAD_CHAR		('E')
+
+#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;
+	int scalar;
+};
 
 struct mbuf_table {
 	uint16_t len;
@@ -134,6 +157,8 @@  extern xmm_t val_eth[RTE_MAX_ETHPORTS];
 
 extern struct lcore_conf lcore_conf[RTE_MAX_LCORE];
 
+extern struct parm_cfg parm_config;
+
 extern int numa_on; /**< NUMA is enabled by default. */
 
 /* Send burst of packets on an output interface */
@@ -287,4 +312,7 @@  l3fwd_acl_set_rule_ipv6_name(const char *optarg);
 void
 l3fwd_acl_set_rule_ipv4_name(const char *optarg);
 
+int
+is_bypass_line(const char *buff);
+
 #endif  /* __L3_FWD_H__ */
diff --git a/examples/l3fwd/l3fwd_acl.c b/examples/l3fwd/l3fwd_acl.c
index 388b978..66ed23d 100644
--- a/examples/l3fwd/l3fwd_acl.c
+++ b/examples/l3fwd/l3fwd_acl.c
@@ -147,10 +147,6 @@  struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
 	},
 };
 
-#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))
-
 enum {
 	PROTO_FIELD_IPV6,
 	SRC1_FIELD_IPV6,
@@ -297,12 +293,6 @@  static struct {
 
 const char cb_port_delim[] = ":";
 
-static struct {
-	const char *rule_ipv4_name;
-	const char *rule_ipv6_name;
-	int scalar;
-} parm_config;
-
 /*
  * Print and dump ACL/Route rules functions are defined in
  * following header file.
@@ -316,27 +306,6 @@  static struct {
 #include "l3fwd_acl_scalar.h"
 
 /*
- * API's called during initialization to setup ACL rules.
- */
-void
-l3fwd_acl_set_rule_ipv4_name(const char *optarg)
-{
-	parm_config.rule_ipv4_name = optarg;
-}
-
-void
-l3fwd_acl_set_rule_ipv6_name(const char *optarg)
-{
-	parm_config.rule_ipv6_name = optarg;
-}
-
-void
-l3fwd_acl_set_scalar(void)
-{
-	parm_config.scalar = 1;
-}
-
-/*
  * Parses IPV6 address, exepcts the following format:
  * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit).
  */
@@ -566,7 +535,7 @@  parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata)
 }
 
 static int
-add_rules(const char *rule_path,
+acl_add_rules(const char *rule_path,
 		struct rte_acl_rule **proute_base,
 		unsigned int *proute_num,
 		struct rte_acl_rule **pacl_base,
@@ -764,8 +733,8 @@  setup_acl(const int socket_id __attribute__((unused)))
 
 	dump_acl_config();
 
-	/* Load  rules from the input file */
-	if (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,
+	/* Load rules from the input file */
+	if (acl_add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,
 			&route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4,
 			sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0)
 		rte_exit(EXIT_FAILURE, "Failed to add rules\n");
@@ -776,7 +745,7 @@  setup_acl(const int socket_id __attribute__((unused)))
 	acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4);
 	dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1);
 
-	if (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,
+	if (acl_add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,
 			&route_num_ipv6,
 			&acl_base_ipv6, &acl_num_ipv6,
 			sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0)
diff --git a/examples/l3fwd/l3fwd_acl.h b/examples/l3fwd/l3fwd_acl.h
index b79784b..da0b5a8 100644
--- a/examples/l3fwd/l3fwd_acl.h
+++ b/examples/l3fwd/l3fwd_acl.h
@@ -55,17 +55,6 @@ 
 #define MBUF_IPV6_2PROTO(m)	\
 	rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO)
 
-#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)
-
 /*
  * ACL rules should have higher priorities than route ones to ensure ACL rule
  * always be found when input packets have multi-matches in the database.
@@ -163,24 +152,6 @@  print_one_ipv6_rule(struct acl6_rule *rule, int extra)
 			rule->data.userdata);
 }
 
-/* Bypass comment and empty lines */
-static inline int
-is_bypass_line(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;
-}
-
 #ifdef L3FWDACL_DEBUG
 static inline void
 dump_acl4_rule(struct rte_mbuf *m, uint32_t sig)
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index ab31210..97f99cf 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -57,45 +57,24 @@ 
 
 #include "l3fwd.h"
 
-struct ipv4_l3fwd_lpm_route {
-	uint32_t ip;
-	uint8_t  depth;
-	uint8_t  if_out;
+enum {
+	CB_FLD_DST_ADDR,
+	CB_FLD_IF_OUT,
+	CB_FLD_MAX
 };
 
-struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[16];
+struct lpm_rule {
+	union {
+		uint32_t ip;
+		union {
+			uint32_t ip_32[4];
+			uint8_t ip_8[16];
+		};
+	};
 	uint8_t  depth;
 	uint8_t  if_out;
 };
 
-static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
-	{IPv4(1, 1, 1, 0), 24, 0},
-	{IPv4(2, 1, 1, 0), 24, 1},
-	{IPv4(3, 1, 1, 0), 24, 2},
-	{IPv4(4, 1, 1, 0), 24, 3},
-	{IPv4(5, 1, 1, 0), 24, 4},
-	{IPv4(6, 1, 1, 0), 24, 5},
-	{IPv4(7, 1, 1, 0), 24, 6},
-	{IPv4(8, 1, 1, 0), 24, 7},
-};
-
-static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 0},
-	{{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 1},
-	{{3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 2},
-	{{4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 3},
-	{{5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 4},
-	{{6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 5},
-	{{7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 6},
-	{{8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 7},
-};
-
-#define IPV4_L3FWD_LPM_NUM_ROUTES \
-	(sizeof(ipv4_l3fwd_lpm_route_array) / sizeof(ipv4_l3fwd_lpm_route_array[0]))
-#define IPV6_L3FWD_LPM_NUM_ROUTES \
-	(sizeof(ipv6_l3fwd_lpm_route_array) / sizeof(ipv6_l3fwd_lpm_route_array[0]))
-
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
 #define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
 #define IPV6_L3FWD_LPM_MAX_RULES         1024
@@ -110,6 +89,211 @@  struct rte_lpm6 *ipv6_l3fwd_lpm_lookup_struct[NB_SOCKETS];
 #include "l3fwd_lpm.h"
 #endif
 
+static int
+lpm_parse_v6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32],
+	char dlm)
+{
+	uint32_t addr[IPV6_ADDR_U16];
+
+	GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':');
+	GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm);
+
+	*end = in;
+
+	v[0] = (addr[0] << 16) + addr[1];
+	v[1] = (addr[2] << 16) + addr[3];
+	v[2] = (addr[4] << 16) + addr[5];
+	v[3] = (addr[6] << 16) + addr[7];
+
+	return 0;
+}
+
+static int
+lpm_parse_v6_net(const char *in, uint32_t *v, uint8_t *mask_len)
+{
+	int32_t rc;
+	const char *mp;
+	uint8_t m;
+	uint32_t tmp[4];
+
+	/* get address. */
+	rc = lpm_parse_v6_addr(in, &mp, v, '/');
+	if (rc != 0) {
+		RTE_LOG(ERR, L3FWD, "parse_v6_addr failed %d\n", rc);
+		return rc;
+	}
+
+	/* get mask. */
+	GET_CB_FIELD(mp, m, 0, sizeof(tmp) * CHAR_BIT, 0);
+	*mask_len = m;
+
+	return 0;
+}
+
+static int
+lpm_parse_v6_rule(char *str, struct lpm_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) {
+			RTE_LOG(ERR, L3FWD,
+				"\nparse_v6_rule strtok_r failed\n");
+			return -EINVAL;
+		}
+	}
+
+	rc = lpm_parse_v6_net(in[CB_FLD_DST_ADDR], v->ip_32, &v->depth);
+	if (rc != 0) {
+		RTE_LOG(ERR, L3FWD, "parse_v6_net failed\n");
+		return rc;
+	}
+
+	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
+
+	return 0;
+}
+
+static int
+lpm_parse_v4_net(const char *in, uint32_t *addr, uint8_t *mask_len)
+{
+	uint8_t a, b, c, d, m;
+
+	GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
+	GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
+	GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
+	GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
+	GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
+
+	addr[0] = IPv4(a, b, c, d);
+	*mask_len = m;
+
+	return 0;
+}
+
+static int
+lpm_parse_v4_rule(char *str, struct lpm_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_v4_net(in[CB_FLD_DST_ADDR], &v->ip, &v->depth);
+	if (rc != 0) {
+		RTE_LOG(ERR, L3FWD, "parse_v4_net failed %d\n", rc);
+		return rc;
+	}
+
+	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
+
+	return 0;
+}
+
+static int
+lpm_add_rules(const char *rule_path,
+		struct lpm_rule **proute_base,
+		unsigned int *proute_num,
+		int (*parser)(char *, struct lpm_rule *))
+{
+	uint8_t *route_rules;
+	struct lpm_rule *next;
+	unsigned int route_num = 0;
+	unsigned int route_cnt = 0;
+	char buff[LINE_MAX];
+	FILE *fh = fopen(rule_path, "rb");
+	unsigned int i = 0, rule_size = sizeof(*next);
+
+	if (fh == NULL)
+		rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
+			rule_path);
+
+	while ((fgets(buff, LINE_MAX, fh) != NULL)) {
+		if (buff[0] == LPM_LEAD_CHAR)
+			route_num++;
+	}
+
+	if (route_num == 0)
+		rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n",
+				rule_path);
+
+	fseek(fh, 0, SEEK_SET);
+
+	route_rules = calloc(route_num, rule_size);
+
+	if (route_rules == NULL)
+		rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n",
+			__func__);
+
+	i = 0;
+	while (fgets(buff, LINE_MAX, fh) != NULL) {
+		i++;
+
+		if (is_bypass_line(buff))
+			continue;
+
+		char s = buff[0];
+
+		/* Route entry */
+		if (s == LPM_LEAD_CHAR)
+			next = (struct lpm_rule *)
+				(route_rules + route_cnt * rule_size);
+
+		/* Illegal line */
+		else
+			rte_exit(EXIT_FAILURE,
+				"%s Line %u: should start with leading "
+				"char %c\n",
+				rule_path, i, LPM_LEAD_CHAR);
+
+		if (parser(buff + 1, next) != 0)
+			rte_exit(EXIT_FAILURE,
+				"%s Line %u: parse rules error\n",
+				rule_path, i);
+
+		route_cnt++;
+	}
+
+	fclose(fh);
+
+	*proute_base = (struct lpm_rule *)route_rules;
+	*proute_num = route_cnt;
+
+	return 0;
+}
+
+static int
+check_lpm_config(void)
+{
+	if (parm_config.rule_ipv4_name == NULL) {
+		RTE_LOG(ERR, L3FWD, "LPM IPv4 rule file not specified\n");
+		return -1;
+	} else if (parm_config.rule_ipv6_name == NULL) {
+		RTE_LOG(ERR, L3FWD, "LPM IPv6 rule file not specified\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /* main processing loop */
 int
 lpm_main_loop(__attribute__((unused)) void *dummy)
@@ -196,10 +380,16 @@  setup_lpm(const int socketid)
 {
 	struct rte_lpm6_config config;
 	struct rte_lpm_config config_ipv4;
+	struct lpm_rule *route_base_v4;
+	struct lpm_rule *route_base_v6;
+	unsigned int route_num_v4 = 0, route_num_v6 = 0;
 	unsigned i;
 	int ret;
 	char s[64];
 
+	if (check_lpm_config() != 0)
+		rte_exit(EXIT_FAILURE, "Failed to get valid LPM options\n");
+
 	/* create the LPM table */
 	config_ipv4.max_rules = IPV4_L3FWD_LPM_MAX_RULES;
 	config_ipv4.number_tbl8s = IPV4_L3FWD_LPM_NUMBER_TBL8S;
@@ -212,18 +402,25 @@  setup_lpm(const int socketid)
 			"Unable to create v4 LPM table on socket %d\n",
 			socketid);
 
+	/* Load rules from the input file */
+	if (lpm_add_rules(parm_config.rule_ipv4_name,
+		&route_base_v4, &route_num_v4,
+		&lpm_parse_v4_rule) < 0)
+		rte_exit(EXIT_FAILURE, "Failed to add lpm v4 rules\n");
+
 	/* populate the LPM table */
-	for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {
+	for (i = 0; i < route_num_v4; i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out &
-				enabled_port_mask) == 0)
+		if ((1 << route_base_v4[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);
+		ret = rte_lpm_add(
+			ipv4_l3fwd_lpm_lookup_struct[socketid],
+			route_base_v4[i].ip,
+			route_base_v4[i].depth,
+			route_base_v4[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -231,9 +428,9 @@  setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route 0x%08x / %d (%d)\n",
-			(unsigned)ipv4_l3fwd_lpm_route_array[i].ip,
-			ipv4_l3fwd_lpm_route_array[i].depth,
-			ipv4_l3fwd_lpm_route_array[i].if_out);
+			(unsigned int)route_base_v4[i].ip,
+			route_base_v4[i].depth,
+			route_base_v4[i].if_out);
 	}
 
 	/* create the LPM6 table */
@@ -249,18 +446,25 @@  setup_lpm(const int socketid)
 			"Unable to create v6 LPM table on socket %d\n",
 			socketid);
 
+	/* Load rules from the input file */
+	if (lpm_add_rules(parm_config.rule_ipv6_name,
+		&route_base_v6, &route_num_v6,
+		&lpm_parse_v6_rule) < 0)
+		rte_exit(EXIT_FAILURE, "Failed to add lpm v6 rules\n");
+
 	/* populate the LPM table */
-	for (i = 0; i < IPV6_L3FWD_LPM_NUM_ROUTES; i++) {
+	for (i = 0; i < route_num_v6; i++) {
 
 		/* skip unused ports */
-		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
-				enabled_port_mask) == 0)
+		if ((1 << route_base_v6[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);
+		ret = rte_lpm6_add(
+			ipv6_l3fwd_lpm_lookup_struct[socketid],
+			route_base_v6[i].ip_8,
+			route_base_v6[i].depth,
+			route_base_v6[i].if_out);
 
 		if (ret < 0) {
 			rte_exit(EXIT_FAILURE,
@@ -268,8 +472,8 @@  setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d)\n",
-			"IPV6", ipv6_l3fwd_lpm_route_array[i].depth,
-			ipv6_l3fwd_lpm_route_array[i].if_out);
+			"IPV6", route_base_v6[i].depth,
+			route_base_v6[i].if_out);
 	}
 }
 
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 65d792b..1098f78 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -126,6 +126,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 {
 	uint8_t port_id;
 	uint8_t queue_id;
@@ -212,6 +214,27 @@  static struct l3fwd_lkp_mode l3fwd_acl_lkp = {
 };
 
 /*
+ * API's called during initialization to setup ACL/LPM/EM 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;
+}
+
+static void
+l3fwd_set_scalar(void)
+{
+	parm_config.scalar = 1;
+}
+
+/*
  * Setup lookup methods for forwarding.
  * Currently exact-match and longest-prefix-match
  * are supported ones.
@@ -689,15 +712,15 @@  parse_args(int argc, char **argv)
 			break;
 
 		case CMD_LINE_OPT_RULE_IPV4:
-			l3fwd_acl_set_rule_ipv4_name(optarg);
+			l3fwd_set_rule_ipv4_name(optarg);
 			break;
 
 		case CMD_LINE_OPT_RULE_IPV6:
-			l3fwd_acl_set_rule_ipv6_name(optarg);
+			l3fwd_set_rule_ipv6_name(optarg);
 			break;
 
 		case CMD_LINE_OPT_SCALAR:
-			l3fwd_acl_set_scalar();
+			l3fwd_set_scalar();
 			break;
 
 		default:
@@ -895,6 +918,24 @@  prepare_ptype_parser(uint8_t portid, uint16_t queueid)
 	return 0;
 }
 
+/* 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)
 {