DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ankur Dwivedi <adwivedi@marvell.com>
To: Akhil Goyal <akhil.goyal@nxp.com>
Cc: "praveen.shetty@intel.com" <praveen.shetty@intel.com>,
	"konstantin.ananyev@intel.com" <konstantin.ananyev@intel.com>,
	"radu.nicolau@intel.com" <radu.nicolau@intel.com>,
	Anoob Joseph <anoobj@marvell.com>, "dev@dpdk.org" <dev@dpdk.org>,
	Ankur Dwivedi <adwivedi@marvell.com>
Subject: Re: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: enable rte_flow based packet distribution
Date: Tue, 14 Jul 2020 09:28:21 +0000	[thread overview]
Message-ID: <DM5PR1801MB18841E7898B738005A5AEDA0DD610@DM5PR1801MB1884.namprd18.prod.outlook.com> (raw)
In-Reply-To: <1591780136-15113-1-git-send-email-adwivedi@marvell.com>

Hi Akhil,

Can you please review this patch?

Thanks
Ankur

>-----Original Message-----
>From: Ankur Dwivedi <adwivedi@marvell.com>
>Sent: Wednesday, June 10, 2020 2:39 PM
>To: dev@dpdk.org
>Cc: praveen.shetty@intel.com; konstantin.ananyev@intel.com;
>radu.nicolau@intel.com; akhil.goyal@nxp.com; Anoob Joseph
><anoobj@marvell.com>; Ankur Dwivedi <adwivedi@marvell.com>
>Subject: [PATCH v2] examples/ipsec-secgw: enable rte_flow based packet
>distribution
>
>From: Anoob Joseph <anoobj@marvell.com>
>
>RTE_FLOW API allows hardware parsing and steering of packets to specific
>queues which helps in distributing ingress traffic across various cores.
>Adding 'flow' rules allows user to specify the distribution required.
>
>Signed-off-by: Anoob Joseph <anoobj@marvell.com>
>---
>v2:
>* Removed Change-Id
>
> doc/guides/sample_app_ug/ipsec_secgw.rst |  78 ++++++++-
> examples/ipsec-secgw/Makefile            |   1 +
> examples/ipsec-secgw/flow.c              | 285
>+++++++++++++++++++++++++++++++
> examples/ipsec-secgw/flow.h              |  15 ++
> examples/ipsec-secgw/ipsec-secgw.c       |   3 +
> examples/ipsec-secgw/ipsec-secgw.h       |   7 +
> examples/ipsec-secgw/ipsec.h             |   7 -
> examples/ipsec-secgw/meson.build         |  15 +-
> examples/ipsec-secgw/parser.c            |  46 +++++
> examples/ipsec-secgw/parser.h            |   7 +-
> 10 files changed, 450 insertions(+), 14 deletions(-)  create mode 100644
>examples/ipsec-secgw/flow.c  create mode 100644 examples/ipsec-
>secgw/flow.h
>
>diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
>b/doc/guides/sample_app_ug/ipsec_secgw.rst
>index 81c5d43..434f484 100644
>--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
>+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
>@@ -348,7 +348,7 @@ Configurations
> --------------
>
> The following sections provide the syntax of configurations to initialize -your
>SP, SA, Routing and Neighbour tables.
>+your SP, SA, Routing, Flow and Neighbour tables.
> Configurations shall be specified in the configuration file to be passed to  the
>application. The file is then parsed by the application. The successful  parsing
>will result in the appropriate rules being applied to the tables @@ -369,7
>+369,7 @@ General rule syntax
>
> The parse treats one line in the configuration file as one configuration  item
>(unless the line concatenation symbol exists). Every configuration -item shall
>follow the syntax of either SP, SA, Routing or Neighbour
>+item shall follow the syntax of either SP, SA, Routing, Flow or
>+Neighbour
> rules specified below.
>
> The configuration parser supports the following special symbols:
>@@ -808,6 +808,80 @@ Example SP rules:
>
>     rt ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 0
>
>+Flow rule syntax
>+^^^^^^^^^^^^^^^^
>+
>+Flow rule enables the usage of hardware classification capabilities to
>+match specific ingress traffic and redirect the packets to the
>+specified queue. This feature is optional and relies on hardware ``rte_flow``
>support.
>+
>+The flow rule syntax is shown as follows:
>+
>+.. code-block:: console
>+
>+    flow <ip_ver> <src_ip> <dst_ip> <port> <queue>
>+
>+
>+where each options means:
>+
>+``<ip_ver>``
>+
>+ * IP protocol version
>+
>+ * Optional: No
>+
>+ * Available options:
>+
>+   * *ipv4*: IP protocol version 4
>+   * *ipv6*: IP protocol version 6
>+
>+``<src_ip>``
>+
>+ * The source IP address and mask
>+
>+ * Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
>+
>+ * Syntax:
>+
>+   * *src X.X.X.X/Y* for IPv4
>+   * *src XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
>+
>+``<dst_ip>``
>+
>+ * The destination IP address and mask
>+
>+ * Optional: Yes, default address 0.0.0.0 and mask of 0 will be used
>+
>+ * Syntax:
>+
>+   * *dst X.X.X.X/Y* for IPv4
>+   * *dst XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/Y* for IPv6
>+
>+``<port>``
>+
>+ * The traffic input port id
>+
>+ * Optional: yes, default input port 0 will be used
>+
>+ * Syntax: *port X*
>+
>+``<queue>``
>+
>+ * The traffic input queue id
>+
>+ * Optional: yes, default input queue 0 will be used
>+
>+ * Syntax: *queue X*
>+
>+Example flow rules:
>+
>+.. code-block:: console
>+
>+    flow ipv4 dst 172.16.1.5/32 port 0 queue 0
>+
>+    flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1
>+ queue 0
>+
>+
> Neighbour rule syntax
> ^^^^^^^^^^^^^^^^^^^^^
>
>diff --git a/examples/ipsec-secgw/Makefile b/examples/ipsec-secgw/Makefile
>index c4a272a..dbae152 100644
>--- a/examples/ipsec-secgw/Makefile
>+++ b/examples/ipsec-secgw/Makefile
>@@ -18,6 +18,7 @@ SRCS-y += ipsec_process.c  SRCS-y += ipsec-secgw.c
>SRCS-y += ipsec_worker.c  SRCS-y += event_helper.c
>+SRCS-y += flow.c
>
> CFLAGS += -gdwarf-2
>
>diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c new
>file mode 100644 index 0000000..69f8405
>--- /dev/null
>+++ b/examples/ipsec-secgw/flow.c
>@@ -0,0 +1,285 @@
>+/* SPDX-License-Identifier: BSD-3-Clause
>+ * Copyright (C) 2020 Marvell International Ltd.
>+ */
>+
>+#include <stdio.h>
>+
>+#include <rte_common.h>
>+#include <rte_flow.h>
>+#include <rte_ip.h>
>+
>+#include "flow.h"
>+#include "ipsec-secgw.h"
>+#include "parser.h"
>+
>+#define FLOW_RULES_MAX 128
>+
>+struct flow_rule_entry {
>+	uint8_t is_ipv4;
>+	RTE_STD_C11
>+	union {
>+		struct {
>+			struct rte_flow_item_ipv4 spec;
>+			struct rte_flow_item_ipv4 mask;
>+		} ipv4;
>+		struct {
>+			struct rte_flow_item_ipv6 spec;
>+			struct rte_flow_item_ipv6 mask;
>+		} ipv6;
>+	};
>+	uint16_t port;
>+	uint16_t queue;
>+	struct rte_flow *flow;
>+} flow_rule_tbl[FLOW_RULES_MAX];
>+
>+int nb_flow_rule;
>+
>+static void
>+ipv4_hdr_print(struct rte_ipv4_hdr *hdr) {
>+	char a, b, c, d;
>+
>+	uint32_t_to_char(rte_bswap32(hdr->src_addr), &a, &b, &c, &d);
>+	printf("src: %3hhu.%3hhu.%3hhu.%3hhu \t", a, b, c, d);
>+
>+	uint32_t_to_char(rte_bswap32(hdr->dst_addr), &a, &b, &c, &d);
>+	printf("dst: %3hhu.%3hhu.%3hhu.%3hhu", a, b, c, d); }
>+
>+static int
>+ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token,
>+	      struct parse_status *status)
>+{
>+	struct in_addr ip;
>+	uint32_t depth;
>+
>+	APP_CHECK(parse_ipv4_addr(token, &ip, &depth) == 0, status,
>+		 "unrecognized input \"%s\", expect valid ipv4 addr", token);
>+	if (status->status < 0)
>+		return -1;
>+
>+	if (depth > 32)
>+		return -1;
>+
>+	memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip));
>+
>+	*spec = ip.s_addr;
>+	if (depth < 32)
>+		*mask = *mask << (32-depth);
>+
>+	return 0;
>+}
>+
>+static void
>+ipv6_hdr_print(struct rte_ipv6_hdr *hdr) {
>+	uint8_t *addr;
>+
>+	addr = hdr->src_addr;
>+	printf("src: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx \t",
>+	       (uint16_t)((addr[0] << 8) | addr[1]),
>+	       (uint16_t)((addr[2] << 8) | addr[3]),
>+	       (uint16_t)((addr[4] << 8) | addr[5]),
>+	       (uint16_t)((addr[6] << 8) | addr[7]),
>+	       (uint16_t)((addr[8] << 8) | addr[9]),
>+	       (uint16_t)((addr[10] << 8) | addr[11]),
>+	       (uint16_t)((addr[12] << 8) | addr[13]),
>+	       (uint16_t)((addr[14] << 8) | addr[15]));
>+
>+	addr = hdr->dst_addr;
>+	printf("dst: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx",
>+	       (uint16_t)((addr[0] << 8) | addr[1]),
>+	       (uint16_t)((addr[2] << 8) | addr[3]),
>+	       (uint16_t)((addr[4] << 8) | addr[5]),
>+	       (uint16_t)((addr[6] << 8) | addr[7]),
>+	       (uint16_t)((addr[8] << 8) | addr[9]),
>+	       (uint16_t)((addr[10] << 8) | addr[11]),
>+	       (uint16_t)((addr[12] << 8) | addr[13]),
>+	       (uint16_t)((addr[14] << 8) | addr[15])); }
>+
>+static int
>+ipv6_addr_cpy(uint8_t *spec, uint8_t *mask, char *token,
>+	      struct parse_status *status)
>+{
>+	struct in6_addr ip;
>+	uint32_t depth, i;
>+
>+	APP_CHECK(parse_ipv6_addr(token, &ip, &depth) == 0, status,
>+		"unrecognized input \"%s\", expect valid ipv6 address",
>token);
>+	if (status->status < 0)
>+		return -1;
>+
>+	memcpy(mask, &rte_flow_item_ipv6_mask.hdr.src_addr, sizeof(ip));
>+	memcpy(spec, ip.s6_addr, sizeof(struct in6_addr));
>+
>+	for (i = 0; i < depth && (i%8 <= sizeof(struct in6_addr)); i++)
>+		mask[i/8] &= ~(1 << (7-i%8));
>+
>+	return 0;
>+}
>+
>+void
>+parse_flow_tokens(char **tokens, uint32_t n_tokens,
>+		  struct parse_status *status)
>+{
>+	struct flow_rule_entry *rule;
>+	uint32_t ti;
>+
>+	if (nb_flow_rule >= FLOW_RULES_MAX) {
>+		printf("Too many flow rules\n");
>+		return;
>+	}
>+
>+	rule = &flow_rule_tbl[nb_flow_rule];
>+	memset(rule, 0, sizeof(*rule));
>+
>+	if (strcmp(tokens[0], "ipv4") == 0) {
>+		rule->is_ipv4 = 1;
>+	} else if (strcmp(tokens[0], "ipv6") == 0) {
>+		rule->is_ipv4 = 0;
>+	} else {
>+		APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]);
>+		return;
>+	}
>+
>+	for (ti = 1; ti < n_tokens; ti++) {
>+		if (strcmp(tokens[ti], "src") == 0) {
>+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>+			if (status->status < 0)
>+				return;
>+
>+			if (rule->is_ipv4) {
>+				if (ipv4_addr_cpy(&rule-
>>ipv4.spec.hdr.src_addr,
>+						  &rule-
>>ipv4.mask.hdr.src_addr,
>+						  tokens[ti], status))
>+					return;
>+			} else {
>+				if (ipv6_addr_cpy(rule-
>>ipv6.spec.hdr.src_addr,
>+						  rule-
>>ipv6.mask.hdr.src_addr,
>+						  tokens[ti], status))
>+					return;
>+			}
>+		}
>+		if (strcmp(tokens[ti], "dst") == 0) {
>+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>+			if (status->status < 0)
>+				return;
>+
>+			if (rule->is_ipv4) {
>+				if (ipv4_addr_cpy(&rule-
>>ipv4.spec.hdr.dst_addr,
>+						  &rule-
>>ipv4.mask.hdr.dst_addr,
>+						  tokens[ti], status))
>+					return;
>+			} else {
>+				if (ipv6_addr_cpy(rule-
>>ipv6.spec.hdr.dst_addr,
>+						  rule-
>>ipv6.mask.hdr.dst_addr,
>+						  tokens[ti], status))
>+					return;
>+			}
>+		}
>+
>+		if (strcmp(tokens[ti], "port") == 0) {
>+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>+			if (status->status < 0)
>+				return;
>+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
>+			if (status->status < 0)
>+				return;
>+
>+			rule->port = atoi(tokens[ti]);
>+
>+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>+			if (status->status < 0)
>+				return;
>+			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
>+			if (status->status < 0)
>+				return;
>+
>+			rule->queue = atoi(tokens[ti]);
>+		}
>+	}
>+
>+	nb_flow_rule++;
>+}
>+
>+#define MAX_RTE_FLOW_PATTERN (3)
>+#define MAX_RTE_FLOW_ACTIONS (2)
>+
>+static void
>+flow_init_single(struct flow_rule_entry *rule) {
>+	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {};
>+	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {};
>+	struct rte_flow_attr attr = {};
>+	struct rte_flow_error err;
>+	int ret;
>+
>+	attr.egress = 0;
>+	attr.ingress = 1;
>+
>+	action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
>+	action[0].conf = &(struct rte_flow_action_queue) {
>+				.index = rule->queue,
>+	};
>+	action[1].type = RTE_FLOW_ACTION_TYPE_END;
>+
>+	pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
>+
>+	if (rule->is_ipv4) {
>+		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
>+		pattern[1].spec = &rule->ipv4.spec;
>+		pattern[1].mask = &rule->ipv4.mask;
>+	} else {
>+		pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
>+		pattern[1].spec = &rule->ipv6.spec;
>+		pattern[1].mask = &rule->ipv6.mask;
>+	}
>+
>+	pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
>+
>+	ret = rte_flow_validate(rule->port, &attr, pattern, action, &err);
>+	if (ret < 0) {
>+		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n",
>err.message);
>+		return;
>+	}
>+
>+	rule->flow = rte_flow_create(rule->port, &attr, pattern, action, &err);
>+	if (rule->flow == NULL)
>+		RTE_LOG(ERR, IPSEC, "Flow creation return %s\n",
>err.message); }
>+
>+void
>+flow_init(void)
>+{
>+	struct flow_rule_entry *rule;
>+	int i;
>+
>+	for (i = 0; i < nb_flow_rule; i++) {
>+		rule = &flow_rule_tbl[i];
>+		flow_init_single(rule);
>+	}
>+
>+	for (i = 0; i < nb_flow_rule; i++) {
>+		rule = &flow_rule_tbl[i];
>+		if (rule->is_ipv4) {
>+			printf("Flow #%3d: spec ipv4 ", i);
>+			ipv4_hdr_print(&rule->ipv4.spec.hdr);
>+			printf("\n");
>+			printf("           mask ipv4 ");
>+			ipv4_hdr_print(&rule->ipv4.mask.hdr);
>+		} else {
>+			printf("Flow #%3d: spec ipv6 ", i);
>+			ipv6_hdr_print(&rule->ipv6.spec.hdr);
>+			printf("\n");
>+			printf("           mask ipv6 ");
>+			ipv6_hdr_print(&rule->ipv6.mask.hdr);
>+		}
>+
>+		printf("\tPort: %d, Queue: %d", rule->port, rule->queue);
>+
>+		if (rule->flow == NULL)
>+			printf(" [UNSUPPORTED]");
>+		printf("\n");
>+	}
>+}
>diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h new
>file mode 100644 index 0000000..1b1b477
>--- /dev/null
>+++ b/examples/ipsec-secgw/flow.h
>@@ -0,0 +1,15 @@
>+/* SPDX-License-Identifier: BSD-3-Clause
>+ * Copyright (C) 2020 Marvell International Ltd.
>+ */
>+
>+#ifndef _FLOW_H_
>+#define _FLOW_H_
>+
>+#include "parser.h"
>+
>+void parse_flow_tokens(char **tokens, uint32_t n_tokens,
>+		       struct parse_status *status);
>+
>+void flow_init(void);
>+
>+#endif /* _FLOW_H_ */
>diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
>secgw/ipsec-secgw.c
>index f777ce2..d19688d 100644
>--- a/examples/ipsec-secgw/ipsec-secgw.c
>+++ b/examples/ipsec-secgw/ipsec-secgw.c
>@@ -49,6 +49,7 @@
> #include <rte_ip_frag.h>
>
> #include "event_helper.h"
>+#include "flow.h"
> #include "ipsec.h"
> #include "ipsec_worker.h"
> #include "parser.h"
>@@ -2914,6 +2915,8 @@ struct lcore_conf {
> 		}
> 	}
>
>+	flow_init();
>+
> 	check_all_ports_link_status(enabled_port_mask);
>
> 	/* launch per-lcore init on every lcore */ diff --git a/examples/ipsec-
>secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
>index 4b53cb5..412d727 100644
>--- a/examples/ipsec-secgw/ipsec-secgw.h
>+++ b/examples/ipsec-secgw/ipsec-secgw.h
>@@ -34,6 +34,13 @@
> 	((uint64_t)(a) & 0xff))
> #endif
>
>+#define uint32_t_to_char(ip, a, b, c, d) do {\
>+		*a = (uint8_t)(ip >> 24 & 0xff);\
>+		*b = (uint8_t)(ip >> 16 & 0xff);\
>+		*c = (uint8_t)(ip >> 8 & 0xff);\
>+		*d = (uint8_t)(ip & 0xff);\
>+	} while (0)
>+
> #define ETHADDR(a, b, c, d, e, f) (__BYTES_TO_UINT64(a, b, c, d, e, f, 0, 0))
>
> struct traffic_type {
>diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
>index 2f69199..7031e28 100644
>--- a/examples/ipsec-secgw/ipsec.h
>+++ b/examples/ipsec-secgw/ipsec.h
>@@ -28,13 +28,6 @@
> #define IV_OFFSET		(sizeof(struct rte_crypto_op) + \
> 				sizeof(struct rte_crypto_sym_op))
>
>-#define uint32_t_to_char(ip, a, b, c, d) do {\
>-		*a = (uint8_t)(ip >> 24 & 0xff);\
>-		*b = (uint8_t)(ip >> 16 & 0xff);\
>-		*c = (uint8_t)(ip >> 8 & 0xff);\
>-		*d = (uint8_t)(ip & 0xff);\
>-	} while (0)
>-
> #define DEFAULT_MAX_CATEGORIES	1
>
> #define INVALID_SPI (0)
>diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-
>secgw/meson.build
>index f9ba2a2..d0373da 100644
>--- a/examples/ipsec-secgw/meson.build
>+++ b/examples/ipsec-secgw/meson.build
>@@ -9,6 +9,17 @@
> deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
>allow_experimental_apis = true  sources = files(
>-	'esp.c', 'event_helper.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
>-	'ipsec_worker.c', 'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
>+	'esp.c',
>+	'event_helper.c',
>+	'flow.c',
>+	'ipsec.c',
>+	'ipsec_process.c',
>+	'ipsec-secgw.c',
>+	'ipsec_worker.c',
>+	'parser.c',
>+	'rt.c',
>+	'sa.c',
>+	'sad.c',
>+	'sp4.c',
>+	'sp6.c'
> )
>diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
>index 65eb7e9..8f66660 100644
>--- a/examples/ipsec-secgw/parser.c
>+++ b/examples/ipsec-secgw/parser.c
>@@ -11,6 +11,7 @@
> #include <cmdline_socket.h>
> #include <cmdline.h>
>
>+#include "flow.h"
> #include "ipsec.h"
> #include "parser.h"
>
>@@ -484,6 +485,49 @@ struct cfg_rt_add_cfg_item {
> 	},
> };
>
>+/* flow add parse */
>+struct cfg_flow_add_cfg_item {
>+	cmdline_fixed_string_t flow_keyword;
>+	cmdline_multi_string_t multi_string;
>+};
>+
>+static void
>+cfg_flow_add_cfg_item_parsed(void *parsed_result,
>+	__rte_unused struct cmdline *cl, void *data) {
>+	struct cfg_flow_add_cfg_item *params = parsed_result;
>+	char *tokens[32];
>+	uint32_t n_tokens = RTE_DIM(tokens);
>+	struct parse_status *status = (struct parse_status *)data;
>+
>+	APP_CHECK(parse_tokenize_string(
>+		params->multi_string, tokens, &n_tokens) == 0,
>+		status, "too many arguments\n");
>+	if (status->status < 0)
>+		return;
>+
>+	parse_flow_tokens(tokens, n_tokens, status); }
>+
>+static cmdline_parse_token_string_t cfg_flow_add_flow_str =
>+	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
>+		flow_keyword, "flow");
>+
>+static cmdline_parse_token_string_t cfg_flow_add_multi_str =
>+	TOKEN_STRING_INITIALIZER(struct cfg_flow_add_cfg_item,
>multi_string,
>+		TOKEN_STRING_MULTI);
>+
>+cmdline_parse_inst_t cfg_flow_add_rule = {
>+	.f = cfg_flow_add_cfg_item_parsed,
>+	.data = NULL,
>+	.help_str = "",
>+	.tokens = {
>+		(void *) &cfg_flow_add_flow_str,
>+		(void *) &cfg_flow_add_multi_str,
>+		NULL,
>+	},
>+};
>+
> /* neigh add parse */
> struct cfg_neigh_add_item {
> 	cmdline_fixed_string_t neigh;
>@@ -538,6 +582,7 @@ struct cfg_neigh_add_item {
> 	(cmdline_parse_inst_t *)&cfg_sp_add_rule,
> 	(cmdline_parse_inst_t *)&cfg_sa_add_rule,
> 	(cmdline_parse_inst_t *)&cfg_rt_add_rule,
>+	(cmdline_parse_inst_t *)&cfg_flow_add_rule,
> 	(cmdline_parse_inst_t *)&cfg_neigh_add_rule,
> 	NULL,
> };
>@@ -564,6 +609,7 @@ struct cfg_neigh_add_item {
> 	cfg_sp_add_rule.data = &status;
> 	cfg_sa_add_rule.data = &status;
> 	cfg_rt_add_rule.data = &status;
>+	cfg_flow_add_rule.data = &status;
> 	cfg_neigh_add_rule.data = &status;
>
> 	do {
>diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
>index 6e764fe..a0ff7e1 100644
>--- a/examples/ipsec-secgw/parser.h
>+++ b/examples/ipsec-secgw/parser.h
>@@ -2,12 +2,13 @@
>  * Copyright(c) 2016 Intel Corporation
>  */
>
>+#ifndef __PARSER_H
>+#define __PARSER_H
>+
> #include <sys/types.h>
> #include <netinet/in.h>
> #include <netinet/ip.h>
>-
>-#ifndef __PARSER_H
>-#define __PARSER_H
>+#include <string.h>
>
> struct parse_status {
> 	int status;
>--
>1.9.3


  reply	other threads:[~2020-07-14  9:28 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-10  9:01 [dpdk-dev] [PATCH] " Ankur Dwivedi
2020-06-10  9:08 ` [dpdk-dev] [PATCH v2] " Ankur Dwivedi
2020-07-14  9:28   ` Ankur Dwivedi [this message]
2020-07-16 16:48     ` Akhil Goyal
2020-07-17 12:31   ` [dpdk-dev] [PATCH v3] " Ankur Dwivedi
2020-07-20  9:12     ` Akhil Goyal

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=DM5PR1801MB18841E7898B738005A5AEDA0DD610@DM5PR1801MB1884.namprd18.prod.outlook.com \
    --to=adwivedi@marvell.com \
    --cc=akhil.goyal@nxp.com \
    --cc=anoobj@marvell.com \
    --cc=dev@dpdk.org \
    --cc=konstantin.ananyev@intel.com \
    --cc=praveen.shetty@intel.com \
    --cc=radu.nicolau@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).