DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature
@ 2020-03-11 14:55 Praveen Shetty
  2020-03-12 11:00 ` Anoob Joseph
  2020-03-19 16:21 ` [dpdk-dev] [PATCH v2] " Praveen Shetty
  0 siblings, 2 replies; 26+ messages in thread
From: Praveen Shetty @ 2020-03-11 14:55 UTC (permalink / raw)
  To: dev, declan.doherty, bernard.iremonger, konstantin.ananyev

Modified Secuirty gateway application to support configuration of
flow director rule to direct inbound IPsec SA to a specified queue.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
 examples/ipsec-secgw/ep0.cfg       | 11 +++++
 examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h       | 11 +++++
 examples/ipsec-secgw/sa.c          | 50 +++++++++++++++++++++-
 5 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..c9f80e81b 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2 port_id 0 type lookaside-protocol-offload
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3 port_id 0 type lookaside-protocol-offload
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4799bc90c..132484422 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -166,7 +166,6 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
 	{NULL, 0, 0, 0}
 };
-
 /* mask of enabled ports */
 static uint32_t enabled_port_mask;
 static uint64_t enabled_cryptodev_mask = UINT64_MAX;
@@ -259,6 +258,30 @@ static struct rte_eth_conf port_conf = {
 	.txmode = {
 		.mq_mode = ETH_MQ_TX_NONE,
 	},
+	.fdir_conf = {
+	.mode = RTE_FDIR_MODE_NONE,
+	.pballoc = RTE_FDIR_PBALLOC_64K,
+	.status = RTE_FDIR_REPORT_STATUS,
+	.mask = {
+		.vlan_tci_mask = 0xFFEF,
+		.ipv4_mask     = {
+			.src_ip = 0xFFFFFFFF,
+			.dst_ip = 0xFFFFFFFF,
+		},
+		.ipv6_mask     = {
+			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+		},
+		.src_port_mask = 0xFFFF,
+		.dst_port_mask = 0xFFFF,
+		.mac_addr_byte_mask = 0xFF,
+		.tunnel_type_mask = 1,
+		.tunnel_id_mask = 0xFFFFFFFF,
+	},
+	.drop_queue = 127,
+	}
 };
 
 static struct socket_ctx socket_ctx[NB_SOCKETS];
@@ -1184,7 +1207,6 @@ main_loop(__attribute__((unused)) void *dummy)
 
 			if (nb_rx > 0)
 				process_pkts(qconf, pkts, nb_rx, portid);
-
 			/* dequeue and process completed crypto-ops */
 			if (UNPROTECTED_PORT(portid))
 				drain_inbound_crypto_queues(qconf,
@@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
 	}
 }
 
+int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_params(void)
 {
@@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
 			continue;
 
 		sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
+		/* check if FDIR is configured on the port */
+		if (check_fdir_configured(portid)) {
+			/* Enable FDIR */
+			port_conf.fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+			/* Disable RSS */
+			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
+			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+		}
 		port_init(portid, req_rx_offloads, req_tx_offloads);
 	}
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6e8120702..363809cfd 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		return 0; /* No Flow director rules for Egress traffic */
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode:");
+			return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
+				sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Validation failed\n");
+		return ret;
+	}
+	sa->flow = rte_flow_create(sa->fdir_portid,
+				&sa->attr, sa->pattern, sa->action,
+				&err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Creation failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 4f2fd6184..00147895a 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -46,6 +46,8 @@
 
 #define IP6_VERSION (6)
 
+#define IPV6_ADDR_LEN   16
+
 struct rte_crypto_xform;
 struct ipsec_xform;
 struct rte_mbuf;
@@ -138,6 +140,9 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint16_t fdir_portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
+int check_fdir_configured(uint16_t portid);
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 4822d6bda..9955dfcbe 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -20,6 +20,9 @@
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_ethdev_driver.h>
 
 #include "ipsec.h"
 #include "esp.h"
@@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -681,6 +685,25 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			rule->fdir_flag = 1;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_portid = atoi(tokens[ti]);
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_qid = atoi(tokens[ti]);
+			/* validating portid and queueid */
+			status_p = check_flow_params(rule->fdir_portid,
+					rule->fdir_qid);
+			if (status_p < 0) {
+				printf("port id %u / queue id %u is not valid\n",
+					rule->fdir_portid, rule->fdir_qid);
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -823,6 +846,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1153,7 +1179,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 		}
-
+		if (sa->fdir_flag &&
+			ips->type ==
+			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL &&
+			inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp flow failed\n");
+			}
 		print_one_sa_rule(sa, inbound);
 	}
 
@@ -1256,6 +1290,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa)
 	return rc;
 }
 
+int
+check_fdir_configured(uint16_t portid)
+{
+	struct ipsec_sa *sa = NULL;
+	uint32_t idx_sa = 0;
+
+	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
+		sa = &sa_in[idx_sa];
+		if (sa->fdir_portid == portid)
+			return sa->fdir_flag;
+	}
+	return 0;
+}
+
 /*
  * Initialise related rte_ipsec_sa object.
  */
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature
  2020-03-11 14:55 [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature Praveen Shetty
@ 2020-03-12 11:00 ` Anoob Joseph
       [not found]   ` <BN7PR11MB25310A9A6B9C3BE91A411AA29DFD0@BN7PR11MB2531.namprd11.prod.outlook.com>
  2020-03-19 16:21 ` [dpdk-dev] [PATCH v2] " Praveen Shetty
  1 sibling, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-03-12 11:00 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty, bernard.iremonger,
	konstantin.ananyev

Hi Praveen,

I do have some review comments on the code. Before that, can you give a brief overview of what is being targeted? My understanding is that the primary objective is to use rte_flow (or flow director) to redirect a specific flow(/SA) to a specific queue. Can you confirm?

Couple of questions,
1. I would assume the new option of "flow-direction" is optional and is determined per SA. In that case, can I assume that RSS would be active for the other flows (or SAs). Let's say, I just want to add a SA for which I would like to enable "flow-direction" but leave the rest as is. How is that handled?
2. I see that the changes are only applicable for LOOKASIDE_PROTOCOL. The same feature would be useful for other modes as well, right?
3. I'm not sure "flow-direction" is the right wording for the option. This is just specifying the "rx-queue" per SA. @Akhil, Konstantin, comments?

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> Sent: Wednesday, March 11, 2020 8:25 PM
> To: dev@dpdk.org; declan.doherty@intel.com; bernard.iremonger@intel.com;
> konstantin.ananyev@intel.com
> Subject: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director
> feature
> 
> Modified Secuirty gateway application to support configuration of flow director
> rule to direct inbound IPsec SA to a specified queue.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
>  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       | 11 +++++
>  examples/ipsec-secgw/sa.c          | 50 +++++++++++++++++++++-
>  5 files changed, 192 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
> index dfd4aca7d..c9f80e81b 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24
> sport 0:65535 dport 0:65535  sp ipv4 in esp protect 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
> @@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
> @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2 port_id 0 type
> +lookaside-protocol-offload
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa in
> 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3 port_id 0
> +type lookaside-protocol-offload
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 4799bc90c..132484422 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
>  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
>  	{NULL, 0, 0, 0}
>  };
> -
>  /* mask of enabled ports */
>  static uint32_t enabled_port_mask;
>  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6 +258,30
> @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6 @@
> main_loop(__attribute__((unused)) void *dummy)
> 
>  			if (nb_rx > 0)
>  				process_pkts(qconf, pkts, nb_rx, portid);
> -
>  			/* dequeue and process completed crypto-ops */
>  			if (UNPROTECTED_PORT(portid))
>  				drain_inbound_crypto_queues(qconf,
> @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
>  	}
>  }
> 
> +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_params(void)
>  {
> @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
>  			continue;
> 
>  		sa_check_offloads(portid, &req_rx_offloads,
> &req_tx_offloads);
> +		/* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}
>  		port_init(portid, req_rx_offloads, req_tx_offloads);
>  	}
> 
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index
> 6e8120702..363809cfd 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->fdir_portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 4f2fd6184..00147895a 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -46,6 +46,8 @@
> 
>  #define IP6_VERSION (6)
> 
> +#define IPV6_ADDR_LEN   16
> +
>  struct rte_crypto_xform;
>  struct ipsec_xform;
>  struct rte_mbuf;
> @@ -138,6 +140,9 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint16_t fdir_portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx,
> struct ipsec_sa *sa,  int  create_inline_session(struct socket_ctx *skt_ctx, struct
> ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int check_fdir_configured(uint16_t portid);
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index
> 4822d6bda..9955dfcbe 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -20,6 +20,9 @@
>  #include <rte_random.h>
>  #include <rte_ethdev.h>
>  #include <rte_malloc.h>
> +#include <rte_common.h>
> +#include <rte_string_fns.h>
> +#include <rte_ethdev_driver.h>
> 
>  #include "ipsec.h"
>  #include "esp.h"
> @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -681,6 +685,25 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_portid = atoi(tokens[ti]);
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->fdir_portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->fdir_portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> +846,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1153,7 +1179,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  				return -EINVAL;
>  			}
>  		}
> -
> +		if (sa->fdir_flag &&
> +			ips->type ==
> +			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
> &&
> +			inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");
> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1256,6 +1290,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct
> rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid)
> +{
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->fdir_portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* Re: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature
       [not found]       ` <BN7PR11MB2531ABDDAE26D1FD3B216E259DFD0@BN7PR11MB2531.namprd11.prod.outlook.com>
@ 2020-03-13  7:05         ` Shetty, Praveen
  2020-03-13 10:51           ` Anoob Joseph
  0 siblings, 1 reply; 26+ messages in thread
From: Shetty, Praveen @ 2020-03-13  7:05 UTC (permalink / raw)
  To: Anoob Joseph, Doherty, Declan, Ananyev, Konstantin, Iremonger,
	Bernard, dev

Hi Anoob,

Thank you.

Please see my answers below.

Regards,
Praveen

-----Original Message-----
From: Anoob Joseph <anoobj@marvell.com>
Sent: Thursday, March 12, 2020 4:31 PM
To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature

Hi Praveen,

I do have some review comments on the code. Before that, can you give a brief overview of what is being targeted? My understanding is that the primary objective is to use rte_flow (or flow director) to redirect a specific flow(/SA) to a specific queue. Can you confirm?

>>>> Yes, your understanding is correct, the main objective is to support load distribution in ipsec-secgw application.
>>>> flow director and RSS features are used achieve the load distribution.
>>>> flow director is used to redirect the specified inbound ipsec flow to a specified queue.

Couple of questions,
1. I would assume the new option of "flow-direction" is optional and is determined per SA. In that case, can I assume that RSS would be active for the other flows (or SAs). Let's say, I just want to add a SA for which I would like to enable "flow-direction" but leave the rest as is. How is that handled?

[Praveen]

>>>> We are using fdir_flag to differentiate the mix of SA's(SA's with and without flow-direction).
>>>> fdir_flag will be "set" for the SA which has configured with flow-direction option(SA rule syntax is extended to 	add new options  <action_type>  <portid>  <queueid> ).
>>>> flow creation is called only for the SA's with fdir_flag is set.

2. I see that the changes are only applicable for LOOKASIDE_PROTOCOL. The same feature would be useful for other modes as well, right?

[Praveen]
>>>>  We are adding this feature for i40e NIC and the  i40e NIC doesn't support either encryption or decryption, that's why we used only LOOKASIDE_PROTOCOL in this case.

3. I'm not sure "flow-direction" is the right wording for the option. This is just specifying the "rx-queue" per SA. @Akhil, Konstantin, comments?

 >>>> @Declan, @Konstantin ,  @Bernard, @Akhil  Could you please suggest a name on which we can all agree  upon?

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> Sent: Wednesday, March 11, 2020 8:25 PM
> To: dev@dpdk.org; declan.doherty@intel.com; 
> bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow 
> director feature
> 
> Modified Secuirty gateway application to support configuration of flow 
> director rule to direct inbound IPsec SA to a specified queue.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
>  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       | 11 +++++
>  examples/ipsec-secgw/sa.c          | 50 +++++++++++++++++++++-
>  5 files changed, 192 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg 
> b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..c9f80e81b 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst
> 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst
> 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst
> 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect
> 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 
> dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 
> sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst
> 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6 
> in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport
> 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key
> 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src
> 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2 port_id 0 type 
> +lookaside-protocol-offload
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa 
> in
> 126 cipher_algo aes-128-cbc cipher_key 
> 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3 port_id
> +0 type lookaside-protocol-offload
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> secgw/ipsec-secgw.c index 4799bc90c..132484422 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
>  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
>  	{NULL, 0, 0, 0}
>  };
> -
>  /* mask of enabled ports */
>  static uint32_t enabled_port_mask;
>  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6
> +258,30 @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6 
> @@
> main_loop(__attribute__((unused)) void *dummy)
> 
>  			if (nb_rx > 0)
>  				process_pkts(qconf, pkts, nb_rx, portid);
> -
>  			/* dequeue and process completed crypto-ops */
>  			if (UNPROTECTED_PORT(portid))
>  				drain_inbound_crypto_queues(qconf,
> @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
>  	}
>  }
> 
> +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_params(void)
>  {
> @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
>  			continue;
> 
>  		sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
> +		/* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}
>  		port_init(portid, req_rx_offloads, req_tx_offloads);
>  	}
> 
> diff --git a/examples/ipsec-secgw/ipsec.c 
> b/examples/ipsec-secgw/ipsec.c index 6e8120702..363809cfd 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx, 
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->fdir_portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h 
> b/examples/ipsec-secgw/ipsec.h index 4f2fd6184..00147895a 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -46,6 +46,8 @@
> 
>  #define IP6_VERSION (6)
> 
> +#define IPV6_ADDR_LEN   16
> +
>  struct rte_crypto_xform;
>  struct ipsec_xform;
>  struct rte_mbuf;
> @@ -138,6 +140,9 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint16_t fdir_portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx 
> *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct 
> socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int check_fdir_configured(uint16_t portid);
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> index 4822d6bda..9955dfcbe 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -20,6 +20,9 @@
>  #include <rte_random.h>
>  #include <rte_ethdev.h>
>  #include <rte_malloc.h>
> +#include <rte_common.h>
> +#include <rte_string_fns.h>
> +#include <rte_ethdev_driver.h>
> 
>  #include "ipsec.h"
>  #include "esp.h"
> @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -681,6 +685,25 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_portid = atoi(tokens[ti]);
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->fdir_portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->fdir_portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> +846,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1153,7 +1179,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const 
> struct ipsec_sa entries[],
>  				return -EINVAL;
>  			}
>  		}
> -
> +		if (sa->fdir_flag &&
> +			ips->type ==
> +			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
> &&
> +			inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");
> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1256,6 +1290,20 @@ fill_ipsec_session(struct rte_ipsec_session 
> *ss, struct rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid) {
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->fdir_portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* Re: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature
  2020-03-13  7:05         ` Shetty, Praveen
@ 2020-03-13 10:51           ` Anoob Joseph
  2020-03-13 12:21             ` Shetty, Praveen
  0 siblings, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-03-13 10:51 UTC (permalink / raw)
  To: Shetty, Praveen, Doherty, Declan, Ananyev, Konstantin, Iremonger,
	Bernard, dev

Hi Praveen,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Shetty, Praveen <praveen.shetty@intel.com>
> Sent: Friday, March 13, 2020 12:36 PM
> To: Anoob Joseph <anoobj@marvell.com>; Doherty, Declan
> <declan.doherty@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: [EXT] RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow
> director feature
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Anoob,
> 
> Thank you.
> 
> Please see my answers below.
> 
> Regards,
> Praveen
> 
> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Thursday, March 12, 2020 4:31 PM
> To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty,
> Declan <declan.doherty@intel.com>; Iremonger, Bernard
> <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director
> feature
> 
> Hi Praveen,
> 
> I do have some review comments on the code. Before that, can you give a brief
> overview of what is being targeted? My understanding is that the primary
> objective is to use rte_flow (or flow director) to redirect a specific flow(/SA) to a
> specific queue. Can you confirm?
> 
> >>>> Yes, your understanding is correct, the main objective is to support load
> distribution in ipsec-secgw application.
> >>>> flow director and RSS features are used achieve the load distribution.
> >>>> flow director is used to redirect the specified inbound ipsec flow to a
> specified queue.

[Anoob] May be update the commit description with some more such details. And I think it's better to use 'rte_flow' rather than flow director. I see that i40e PMD talks about flow director, but overall the feature is usage of rte_flow.
 
> 
> Couple of questions,
> 1. I would assume the new option of "flow-direction" is optional and is
> determined per SA. In that case, can I assume that RSS would be active for the
> other flows (or SAs). Let's say, I just want to add a SA for which I would like to
> enable "flow-direction" but leave the rest as is. How is that handled?
> 
> [Praveen]
> 
> >>>> We are using fdir_flag to differentiate the mix of SA's(SA's with and
> without flow-direction).
> >>>> fdir_flag will be "set" for the SA which has configured with flow-direction
> option(SA rule syntax is extended to 	add new options  <action_type>
> <portid>  <queueid> ).
> >>>> flow creation is called only for the SA's with fdir_flag is set.

[Anoob] I've few questions on this. I'll send this along with my code review.
 
> 
> 2. I see that the changes are only applicable for LOOKASIDE_PROTOCOL. The
> same feature would be useful for other modes as well, right?
> 
> [Praveen]
> >>>>  We are adding this feature for i40e NIC and the  i40e NIC doesn't support
> either encryption or decryption, that's why we used only
> LOOKASIDE_PROTOCOL in this case.

[Anoob] I meant LOOKASIDE_NONE (LOOKASIDE_CRYPTO) case. I would assume that can be early supported.

> 
> 3. I'm not sure "flow-direction" is the right wording for the option. This is just
> specifying the "rx-queue" per SA. @Akhil, Konstantin, comments?
> 
>  >>>> @Declan, @Konstantin ,  @Bernard, @Akhil  Could you please suggest a
> name on which we can all agree  upon?
> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> > Sent: Wednesday, March 11, 2020 8:25 PM
> > To: dev@dpdk.org; declan.doherty@intel.com;
> > bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> > Subject: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow
> > director feature
> >
> > Modified Secuirty gateway application to support configuration of flow
> > director rule to direct inbound IPsec SA to a specified queue.
> >
> > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > ---
> >  examples/ipsec-secgw/ep0.cfg       | 11 +++++
> >  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
> >  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
> >  examples/ipsec-secgw/ipsec.h       | 11 +++++
> >  examples/ipsec-secgw/sa.c          | 50 +++++++++++++++++++++-
> >  5 files changed, 192 insertions(+), 3 deletions(-)
> >
> > diff --git a/examples/ipsec-secgw/ep0.cfg
> > b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..c9f80e81b 100644
> > --- a/examples/ipsec-secgw/ep0.cfg
> > +++ b/examples/ipsec-secgw/ep0.cfg
> > @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst
> > 192.168.186.0/24 sport
> > 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst
> > 192.168.210.0/24 sport
> > 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst
> > 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect
> > 115 pri 1 dst
> > 192.168.210.0/24 sport 0:65535 dport 0:65535
> > +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535
> > +dport 0:65535
> >  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535
> > dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24
> > sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst
> > 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6
> > in esp protect 125 pri 1 dst
> > ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
> >  sport 0:65535 dport 0:65535
> >  sp ipv6 in esp protect 126 pri 1 dst
> > ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport
> > 0:65535
> > +sp ipv6 in esp protect 127 pri 1 dst
> > +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> > +0:65535
> >
> >  #SA rules
> >  sa out 5 cipher_algo aes-128-cbc cipher_key
> > 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> >
> >  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src
> > 172.16.2.6 dst
> > 172.16.1.6
> >
> > +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> > +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2 port_id 0 type
> > +lookaside-protocol-offload
> > +
> >  sa in 125 cipher_algo aes-128-cbc cipher_key
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa
> > in
> > 126 cipher_algo aes-128-cbc cipher_key
> > 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
> >  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> > 1111:1111:1111:1111:1111:1111:1111:6666
> >
> > +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> > +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> > +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3 port_id
> > +0 type lookaside-protocol-offload
> > +
> >  #Routing rules
> >  rt ipv4 dst 172.16.2.5/32 port 0
> >  rt ipv4 dst 172.16.2.6/32 port 1
> > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> > secgw/ipsec-secgw.c index 4799bc90c..132484422 100644
> > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
> >  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
> >  	{NULL, 0, 0, 0}
> >  };
> > -
> >  /* mask of enabled ports */
> >  static uint32_t enabled_port_mask;
> >  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6
> > +258,30 @@ static struct rte_eth_conf port_conf = {
> >  	.txmode = {
> >  		.mq_mode = ETH_MQ_TX_NONE,
> >  	},
> > +	.fdir_conf = {
> > +	.mode = RTE_FDIR_MODE_NONE,
> > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > +	.status = RTE_FDIR_REPORT_STATUS,
> > +	.mask = {
> > +		.vlan_tci_mask = 0xFFEF,
> > +		.ipv4_mask     = {
> > +			.src_ip = 0xFFFFFFFF,
> > +			.dst_ip = 0xFFFFFFFF,
> > +		},
> > +		.ipv6_mask     = {
> > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +		},
> > +		.src_port_mask = 0xFFFF,
> > +		.dst_port_mask = 0xFFFF,
> > +		.mac_addr_byte_mask = 0xFF,
> > +		.tunnel_type_mask = 1,
> > +		.tunnel_id_mask = 0xFFFFFFFF,
> > +	},
> > +	.drop_queue = 127,
> > +	}
> >  };
> >
> >  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6
> > @@
> > main_loop(__attribute__((unused)) void *dummy)
> >
> >  			if (nb_rx > 0)
> >  				process_pkts(qconf, pkts, nb_rx, portid);
> > -
> >  			/* dequeue and process completed crypto-ops */
> >  			if (UNPROTECTED_PORT(portid))
> >  				drain_inbound_crypto_queues(qconf,
> > @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
> >  	}
> >  }
> >
> > +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > +	uint16_t i;
> > +	uint16_t portid;
> > +	uint8_t queueid;
> > +
> > +	for (i = 0; i < nb_lcore_params; ++i) {
> > +		portid = lcore_params_array[i].port_id;
> > +		if (portid == fdir_portid) {
> > +			queueid = lcore_params_array[i].queue_id;
> > +			if (queueid == fdir_qid)
> > +				break;
> > +		}
> > +
> > +		if (i == nb_lcore_params - 1)
> > +			return -1;
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> >  static int32_t
> >  check_params(void)
> >  {
> > @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
> >  			continue;
> >
> >  		sa_check_offloads(portid, &req_rx_offloads,
> &req_tx_offloads);
> > +		/* check if FDIR is configured on the port */
> > +		if (check_fdir_configured(portid)) {
> > +			/* Enable FDIR */
> > +			port_conf.fdir_conf.mode =
> > RTE_FDIR_MODE_PERFECT;
> > +			/* Disable RSS */
> > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > +		}
> >  		port_init(portid, req_rx_offloads, req_tx_offloads);
> >  	}
> >
> > diff --git a/examples/ipsec-secgw/ipsec.c
> > b/examples/ipsec-secgw/ipsec.c index 6e8120702..363809cfd 100644
> > --- a/examples/ipsec-secgw/ipsec.c
> > +++ b/examples/ipsec-secgw/ipsec.c
> > @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> > struct ipsec_sa *sa,
> >  	return 0;
> >  }
> >
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > +	int ret = 0;
> > +	struct rte_flow_error err;
> > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > +		return 0; /* No Flow director rules for Egress traffic */
> > +	if (sa->flags == TRANSPORT) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"No Flow director rule for transport mode:");
> > +			return -1;
> > +	}
> > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > +	sa->action[0].conf =
> > +			&(struct rte_flow_action_queue){
> > +				.index = sa->fdir_qid,
> > +	};
> > +	sa->attr.egress = 0;
> > +	sa->attr.ingress = 1;
> > +	if (IS_IP6(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	} else if (IS_IP4(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	}
> > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > +
> > +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> > +				sa->pattern, sa->action,
> > +				&err);
> > +	if (ret < 0) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Validation failed\n");
> > +		return ret;
> > +	}
> > +	sa->flow = rte_flow_create(sa->fdir_portid,
> > +				&sa->attr, sa->pattern, sa->action,
> > +				&err);
> > +	if (!sa->flow) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Creation failed\n");
> > +		return -1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * queue crypto-ops into PMD queue.
> >   */
> > diff --git a/examples/ipsec-secgw/ipsec.h
> > b/examples/ipsec-secgw/ipsec.h index 4f2fd6184..00147895a 100644
> > --- a/examples/ipsec-secgw/ipsec.h
> > +++ b/examples/ipsec-secgw/ipsec.h
> > @@ -46,6 +46,8 @@
> >
> >  #define IP6_VERSION (6)
> >
> > +#define IPV6_ADDR_LEN   16
> > +
> >  struct rte_crypto_xform;
> >  struct ipsec_xform;
> >  struct rte_mbuf;
> > @@ -138,6 +140,9 @@ struct ipsec_sa {
> >  	};
> >  	enum rte_security_ipsec_sa_direction direction;
> >  	uint16_t portid;
> > +	uint16_t fdir_portid;
> > +	uint8_t fdir_qid;
> > +	uint8_t fdir_flag;
> >
> >  #define MAX_RTE_FLOW_PATTERN (4)
> >  #define MAX_RTE_FLOW_ACTIONS (3)
> > @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx
> > *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct
> > socket_ctx *skt_ctx, struct ipsec_sa *sa,
> >  		struct rte_ipsec_session *ips);
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > +
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> >
> > +int check_fdir_configured(uint16_t portid);
> >  #endif /* __IPSEC_H__ */
> > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> > index 4822d6bda..9955dfcbe 100644
> > --- a/examples/ipsec-secgw/sa.c
> > +++ b/examples/ipsec-secgw/sa.c
> > @@ -20,6 +20,9 @@
> >  #include <rte_random.h>
> >  #include <rte_ethdev.h>
> >  #include <rte_malloc.h>
> > +#include <rte_common.h>
> > +#include <rte_string_fns.h>
> > +#include <rte_ethdev_driver.h>
> >
> >  #include "ipsec.h"
> >  #include "esp.h"
> > @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	uint32_t type_p = 0;
> >  	uint32_t portid_p = 0;
> >  	uint32_t fallback_p = 0;
> > +	int16_t status_p = 0;
> >
> >  	if (strcmp(tokens[0], "in") == 0) {
> >  		ri = &nb_sa_in;
> > @@ -681,6 +685,25 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			fallback_p = 1;
> >  			continue;
> >  		}
> > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > +			rule->fdir_flag = 1;
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_portid = atoi(tokens[ti]);
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_qid = atoi(tokens[ti]);
> > +			/* validating portid and queueid */
> > +			status_p = check_flow_params(rule->fdir_portid,
> > +					rule->fdir_qid);
> > +			if (status_p < 0) {
> > +				printf("port id %u / queue id %u is not valid\n",
> > +					rule->fdir_portid, rule->fdir_qid);
> > +			}
> > +			continue;
> > +		}
> >
> >  		/* unrecognizeable input */
> >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> > +846,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
> >  			break;
> >  		}
> >  	}
> > +	if (sa->fdir_flag == 1)
> > +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> > +
> >  	printf("\n");
> >  }
> >
> > @@ -1153,7 +1179,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const
> > struct ipsec_sa entries[],
> >  				return -EINVAL;
> >  			}
> >  		}
> > -
> > +		if (sa->fdir_flag &&
> > +			ips->type ==
> > +			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
> > &&
> > +			inbound) {
> > +			rc = create_ipsec_esp_flow(sa);
> > +			if (rc != 0)
> > +				RTE_LOG(ERR, IPSEC_ESP,
> > +					"create_ipsec_esp flow failed\n");
> > +			}
> >  		print_one_sa_rule(sa, inbound);
> >  	}
> >
> > @@ -1256,6 +1290,20 @@ fill_ipsec_session(struct rte_ipsec_session
> > *ss, struct rte_ipsec_sa *sa)
> >  	return rc;
> >  }
> >
> > +int
> > +check_fdir_configured(uint16_t portid) {
> > +	struct ipsec_sa *sa = NULL;
> > +	uint32_t idx_sa = 0;
> > +
> > +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> > +		sa = &sa_in[idx_sa];
> > +		if (sa->fdir_portid == portid)
> > +			return sa->fdir_flag;
> > +	}
> > +	return 0;
> > +}
> > +
> >  /*
> >   * Initialise related rte_ipsec_sa object.
> >   */
> > --
> > 2.17.1


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

* Re: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature
  2020-03-13 10:51           ` Anoob Joseph
@ 2020-03-13 12:21             ` Shetty, Praveen
  0 siblings, 0 replies; 26+ messages in thread
From: Shetty, Praveen @ 2020-03-13 12:21 UTC (permalink / raw)
  To: Anoob Joseph, Doherty, Declan, Ananyev, Konstantin, Iremonger,
	Bernard, dev

Hi Anoob,

Please see my response inline.

Regards,
Praveen

-----Original Message-----
From: Anoob Joseph <anoobj@marvell.com> 
Sent: Friday, March 13, 2020 4:22 PM
To: Shetty, Praveen <praveen.shetty@intel.com>; Doherty, Declan <declan.doherty@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>; Iremonger, Bernard <bernard.iremonger@intel.com>; dev@dpdk.org
Subject: RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature

Hi Praveen,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Shetty, Praveen <praveen.shetty@intel.com>
> Sent: Friday, March 13, 2020 12:36 PM
> To: Anoob Joseph <anoobj@marvell.com>; Doherty, Declan 
> <declan.doherty@intel.com>; Ananyev, Konstantin 
> <konstantin.ananyev@intel.com>; Iremonger, Bernard 
> <bernard.iremonger@intel.com>; dev@dpdk.org
> Subject: [EXT] RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support 
> flow director feature
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Anoob,
> 
> Thank you.
> 
> Please see my answers below.
> 
> Regards,
> Praveen
> 
> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Thursday, March 12, 2020 4:31 PM
> To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, 
> Declan <declan.doherty@intel.com>; Iremonger, Bernard 
> <bernard.iremonger@intel.com>; Ananyev, Konstantin 
> <konstantin.ananyev@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow 
> director feature
> 
> Hi Praveen,
> 
> I do have some review comments on the code. Before that, can you give 
> a brief overview of what is being targeted? My understanding is that 
> the primary objective is to use rte_flow (or flow director) to 
> redirect a specific flow(/SA) to a specific queue. Can you confirm?
> 
> >>>> Yes, your understanding is correct, the main objective is to 
> >>>> support load
> distribution in ipsec-secgw application.
> >>>> flow director and RSS features are used achieve the load distribution.
> >>>> flow director is used to redirect the specified inbound ipsec 
> >>>> flow to a
> specified queue.

[Anoob] May be update the commit description with some more such details. And I think it's better to use 'rte_flow' rather than flow director. I see that i40e PMD talks about flow director, but overall the feature is usage of rte_flow.
 
[Praveen]  Yeah Sure , I will add more such details in v2. 
> 
> Couple of questions,
> 1. I would assume the new option of "flow-direction" is optional and 
> is determined per SA. In that case, can I assume that RSS would be 
> active for the other flows (or SAs). Let's say, I just want to add a 
> SA for which I would like to enable "flow-direction" but leave the rest as is. How is that handled?
> 
> [Praveen]
> 
> >>>> We are using fdir_flag to differentiate the mix of SA's(SA's with 
> >>>> and
> without flow-direction).
> >>>> fdir_flag will be "set" for the SA which has configured with 
> >>>> flow-direction
> option(SA rule syntax is extended to 	add new options  <action_type>
> <portid>  <queueid> ).
> >>>> flow creation is called only for the SA's with fdir_flag is set.

[Anoob] I've few questions on this. I'll send this along with my code review.
 
> 
> 2. I see that the changes are only applicable for LOOKASIDE_PROTOCOL. 
> The same feature would be useful for other modes as well, right?
> 
> [Praveen]
> >>>>  We are adding this feature for i40e NIC and the  i40e NIC 
> >>>> doesn't support
> either encryption or decryption, that's why we used only 
> LOOKASIDE_PROTOCOL in this case.

[Anoob] I meant LOOKASIDE_NONE (LOOKASIDE_CRYPTO) case. I would assume that can be early supported.

[Praveen]  Yes , it was a copy & paste error , what I meant was LOOKASIDE_NONE. Will fix this in v2.
 
> 
> 3. I'm not sure "flow-direction" is the right wording for the option. 
> This is just specifying the "rx-queue" per SA. @Akhil, Konstantin, comments?
> 
>  >>>> @Declan, @Konstantin ,  @Bernard, @Akhil  Could you please 
> suggest a name on which we can all agree  upon?
> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> > Sent: Wednesday, March 11, 2020 8:25 PM
> > To: dev@dpdk.org; declan.doherty@intel.com; 
> > bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> > Subject: [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow 
> > director feature
> >
> > Modified Secuirty gateway application to support configuration of 
> > flow director rule to direct inbound IPsec SA to a specified queue.
> >
> > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > ---
> >  examples/ipsec-secgw/ep0.cfg       | 11 +++++
> >  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
> >  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
> >  examples/ipsec-secgw/ipsec.h       | 11 +++++
> >  examples/ipsec-secgw/sa.c          | 50 +++++++++++++++++++++-
> >  5 files changed, 192 insertions(+), 3 deletions(-)
> >
> > diff --git a/examples/ipsec-secgw/ep0.cfg 
> > b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..c9f80e81b 100644
> > --- a/examples/ipsec-secgw/ep0.cfg
> > +++ b/examples/ipsec-secgw/ep0.cfg
> > @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst
> > 192.168.186.0/24 sport
> > 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst
> > 192.168.210.0/24 sport
> > 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst
> > 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect
> > 115 pri 1 dst
> > 192.168.210.0/24 sport 0:65535 dport 0:65535
> > +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
> > +dport 0:65535
> >  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 
> > dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 
> > sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst
> > 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp 
> > ipv6 in esp protect 125 pri 1 dst
> > ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
> >  sport 0:65535 dport 0:65535
> >  sp ipv6 in esp protect 126 pri 1 dst
> > ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport
> > 0:65535
> > +sp ipv6 in esp protect 127 pri 1 dst
> > +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> > +0:65535
> >
> >  #SA rules
> >  sa out 5 cipher_algo aes-128-cbc cipher_key
> > 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> >
> >  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src
> > 172.16.2.6 dst
> > 172.16.1.6
> >
> > +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> > +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2 port_id 0 type 
> > +lookaside-protocol-offload
> > +
> >  sa in 125 cipher_algo aes-128-cbc cipher_key 
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key 
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ 
> > sa in
> > 126 cipher_algo aes-128-cbc cipher_key 
> > 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
> >  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> > 1111:1111:1111:1111:1111:1111:1111:6666
> >
> > +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> > +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> > +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3 
> > +port_id
> > +0 type lookaside-protocol-offload
> > +
> >  #Routing rules
> >  rt ipv4 dst 172.16.2.5/32 port 0
> >  rt ipv4 dst 172.16.2.6/32 port 1
> > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> > secgw/ipsec-secgw.c index 4799bc90c..132484422 100644
> > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
> >  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
> >  	{NULL, 0, 0, 0}
> >  };
> > -
> >  /* mask of enabled ports */
> >  static uint32_t enabled_port_mask;
> >  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6
> > +258,30 @@ static struct rte_eth_conf port_conf = {
> >  	.txmode = {
> >  		.mq_mode = ETH_MQ_TX_NONE,
> >  	},
> > +	.fdir_conf = {
> > +	.mode = RTE_FDIR_MODE_NONE,
> > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > +	.status = RTE_FDIR_REPORT_STATUS,
> > +	.mask = {
> > +		.vlan_tci_mask = 0xFFEF,
> > +		.ipv4_mask     = {
> > +			.src_ip = 0xFFFFFFFF,
> > +			.dst_ip = 0xFFFFFFFF,
> > +		},
> > +		.ipv6_mask     = {
> > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +		},
> > +		.src_port_mask = 0xFFFF,
> > +		.dst_port_mask = 0xFFFF,
> > +		.mac_addr_byte_mask = 0xFF,
> > +		.tunnel_type_mask = 1,
> > +		.tunnel_id_mask = 0xFFFFFFFF,
> > +	},
> > +	.drop_queue = 127,
> > +	}
> >  };
> >
> >  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6 
> > @@
> > main_loop(__attribute__((unused)) void *dummy)
> >
> >  			if (nb_rx > 0)
> >  				process_pkts(qconf, pkts, nb_rx, portid);
> > -
> >  			/* dequeue and process completed crypto-ops */
> >  			if (UNPROTECTED_PORT(portid))
> >  				drain_inbound_crypto_queues(qconf,
> > @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
> >  	}
> >  }
> >
> > +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > +	uint16_t i;
> > +	uint16_t portid;
> > +	uint8_t queueid;
> > +
> > +	for (i = 0; i < nb_lcore_params; ++i) {
> > +		portid = lcore_params_array[i].port_id;
> > +		if (portid == fdir_portid) {
> > +			queueid = lcore_params_array[i].queue_id;
> > +			if (queueid == fdir_qid)
> > +				break;
> > +		}
> > +
> > +		if (i == nb_lcore_params - 1)
> > +			return -1;
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> >  static int32_t
> >  check_params(void)
> >  {
> > @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
> >  			continue;
> >
> >  		sa_check_offloads(portid, &req_rx_offloads,
> &req_tx_offloads);
> > +		/* check if FDIR is configured on the port */
> > +		if (check_fdir_configured(portid)) {
> > +			/* Enable FDIR */
> > +			port_conf.fdir_conf.mode =
> > RTE_FDIR_MODE_PERFECT;
> > +			/* Disable RSS */
> > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > +		}
> >  		port_init(portid, req_rx_offloads, req_tx_offloads);
> >  	}
> >
> > diff --git a/examples/ipsec-secgw/ipsec.c 
> > b/examples/ipsec-secgw/ipsec.c index 6e8120702..363809cfd 100644
> > --- a/examples/ipsec-secgw/ipsec.c
> > +++ b/examples/ipsec-secgw/ipsec.c
> > @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx 
> > *skt_ctx, struct ipsec_sa *sa,
> >  	return 0;
> >  }
> >
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > +	int ret = 0;
> > +	struct rte_flow_error err;
> > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > +		return 0; /* No Flow director rules for Egress traffic */
> > +	if (sa->flags == TRANSPORT) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"No Flow director rule for transport mode:");
> > +			return -1;
> > +	}
> > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > +	sa->action[0].conf =
> > +			&(struct rte_flow_action_queue){
> > +				.index = sa->fdir_qid,
> > +	};
> > +	sa->attr.egress = 0;
> > +	sa->attr.ingress = 1;
> > +	if (IS_IP6(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	} else if (IS_IP4(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	}
> > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > +
> > +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> > +				sa->pattern, sa->action,
> > +				&err);
> > +	if (ret < 0) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Validation failed\n");
> > +		return ret;
> > +	}
> > +	sa->flow = rte_flow_create(sa->fdir_portid,
> > +				&sa->attr, sa->pattern, sa->action,
> > +				&err);
> > +	if (!sa->flow) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Creation failed\n");
> > +		return -1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * queue crypto-ops into PMD queue.
> >   */
> > diff --git a/examples/ipsec-secgw/ipsec.h 
> > b/examples/ipsec-secgw/ipsec.h index 4f2fd6184..00147895a 100644
> > --- a/examples/ipsec-secgw/ipsec.h
> > +++ b/examples/ipsec-secgw/ipsec.h
> > @@ -46,6 +46,8 @@
> >
> >  #define IP6_VERSION (6)
> >
> > +#define IPV6_ADDR_LEN   16
> > +
> >  struct rte_crypto_xform;
> >  struct ipsec_xform;
> >  struct rte_mbuf;
> > @@ -138,6 +140,9 @@ struct ipsec_sa {
> >  	};
> >  	enum rte_security_ipsec_sa_direction direction;
> >  	uint16_t portid;
> > +	uint16_t fdir_portid;
> > +	uint8_t fdir_qid;
> > +	uint8_t fdir_flag;
> >
> >  #define MAX_RTE_FLOW_PATTERN (4)
> >  #define MAX_RTE_FLOW_ACTIONS (3)
> > @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx 
> > *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct 
> > socket_ctx *skt_ctx, struct ipsec_sa *sa,
> >  		struct rte_ipsec_session *ips);
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > +
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> >
> > +int check_fdir_configured(uint16_t portid);
> >  #endif /* __IPSEC_H__ */
> > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> > index 4822d6bda..9955dfcbe 100644
> > --- a/examples/ipsec-secgw/sa.c
> > +++ b/examples/ipsec-secgw/sa.c
> > @@ -20,6 +20,9 @@
> >  #include <rte_random.h>
> >  #include <rte_ethdev.h>
> >  #include <rte_malloc.h>
> > +#include <rte_common.h>
> > +#include <rte_string_fns.h>
> > +#include <rte_ethdev_driver.h>
> >
> >  #include "ipsec.h"
> >  #include "esp.h"
> > @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	uint32_t type_p = 0;
> >  	uint32_t portid_p = 0;
> >  	uint32_t fallback_p = 0;
> > +	int16_t status_p = 0;
> >
> >  	if (strcmp(tokens[0], "in") == 0) {
> >  		ri = &nb_sa_in;
> > @@ -681,6 +685,25 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			fallback_p = 1;
> >  			continue;
> >  		}
> > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > +			rule->fdir_flag = 1;
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_portid = atoi(tokens[ti]);
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_qid = atoi(tokens[ti]);
> > +			/* validating portid and queueid */
> > +			status_p = check_flow_params(rule->fdir_portid,
> > +					rule->fdir_qid);
> > +			if (status_p < 0) {
> > +				printf("port id %u / queue id %u is not valid\n",
> > +					rule->fdir_portid, rule->fdir_qid);
> > +			}
> > +			continue;
> > +		}
> >
> >  		/* unrecognizeable input */
> >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> > +846,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
> >  			break;
> >  		}
> >  	}
> > +	if (sa->fdir_flag == 1)
> > +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> > +
> >  	printf("\n");
> >  }
> >
> > @@ -1153,7 +1179,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const 
> > struct ipsec_sa entries[],
> >  				return -EINVAL;
> >  			}
> >  		}
> > -
> > +		if (sa->fdir_flag &&
> > +			ips->type ==
> > +			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
> > &&
> > +			inbound) {
> > +			rc = create_ipsec_esp_flow(sa);
> > +			if (rc != 0)
> > +				RTE_LOG(ERR, IPSEC_ESP,
> > +					"create_ipsec_esp flow failed\n");
> > +			}
> >  		print_one_sa_rule(sa, inbound);
> >  	}
> >
> > @@ -1256,6 +1290,20 @@ fill_ipsec_session(struct rte_ipsec_session 
> > *ss, struct rte_ipsec_sa *sa)
> >  	return rc;
> >  }
> >
> > +int
> > +check_fdir_configured(uint16_t portid) {
> > +	struct ipsec_sa *sa = NULL;
> > +	uint32_t idx_sa = 0;
> > +
> > +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> > +		sa = &sa_in[idx_sa];
> > +		if (sa->fdir_portid == portid)
> > +			return sa->fdir_flag;
> > +	}
> > +	return 0;
> > +}
> > +
> >  /*
> >   * Initialise related rte_ipsec_sa object.
> >   */
> > --
> > 2.17.1


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

* [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow director feature
  2020-03-11 14:55 [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature Praveen Shetty
  2020-03-12 11:00 ` Anoob Joseph
@ 2020-03-19 16:21 ` Praveen Shetty
  2020-03-20  8:15   ` Anoob Joseph
  2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
  1 sibling, 2 replies; 26+ messages in thread
From: Praveen Shetty @ 2020-03-19 16:21 UTC (permalink / raw)
  To: dev, declan.doherty, bernard.iremonger, konstantin.ananyev

Support load distribution in security gateway application using
NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow
to a specified queue.This is achieved by extending the SA rule syntax
to support specification by adding new action_type of <flow-direction>
to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v2 changes:
added more details in commit message.
added a check to throw an error if the security session type is other than LOOKASIDE_NONE

 examples/ipsec-secgw/ep0.cfg       | 11 +++++
 examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h       | 11 +++++
 examples/ipsec-secgw/sa.c          | 60 +++++++++++++++++++++++++-
 5 files changed, 202 insertions(+), 3 deletions(-)

diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4799bc90c..132484422 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -166,7 +166,6 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
 	{NULL, 0, 0, 0}
 };
-
 /* mask of enabled ports */
 static uint32_t enabled_port_mask;
 static uint64_t enabled_cryptodev_mask = UINT64_MAX;
@@ -259,6 +258,30 @@ static struct rte_eth_conf port_conf = {
 	.txmode = {
 		.mq_mode = ETH_MQ_TX_NONE,
 	},
+	.fdir_conf = {
+	.mode = RTE_FDIR_MODE_NONE,
+	.pballoc = RTE_FDIR_PBALLOC_64K,
+	.status = RTE_FDIR_REPORT_STATUS,
+	.mask = {
+		.vlan_tci_mask = 0xFFEF,
+		.ipv4_mask     = {
+			.src_ip = 0xFFFFFFFF,
+			.dst_ip = 0xFFFFFFFF,
+		},
+		.ipv6_mask     = {
+			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+		},
+		.src_port_mask = 0xFFFF,
+		.dst_port_mask = 0xFFFF,
+		.mac_addr_byte_mask = 0xFF,
+		.tunnel_type_mask = 1,
+		.tunnel_id_mask = 0xFFFFFFFF,
+	},
+	.drop_queue = 127,
+	}
 };
 
 static struct socket_ctx socket_ctx[NB_SOCKETS];
@@ -1184,7 +1207,6 @@ main_loop(__attribute__((unused)) void *dummy)
 
 			if (nb_rx > 0)
 				process_pkts(qconf, pkts, nb_rx, portid);
-
 			/* dequeue and process completed crypto-ops */
 			if (UNPROTECTED_PORT(portid))
 				drain_inbound_crypto_queues(qconf,
@@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
 	}
 }
 
+int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_params(void)
 {
@@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
 			continue;
 
 		sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
+		/* check if FDIR is configured on the port */
+		if (check_fdir_configured(portid)) {
+			/* Enable FDIR */
+			port_conf.fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+			/* Disable RSS */
+			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
+			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+		}
 		port_init(portid, req_rx_offloads, req_tx_offloads);
 	}
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6e8120702..363809cfd 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		return 0; /* No Flow director rules for Egress traffic */
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode:");
+			return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
+				sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Validation failed\n");
+		return ret;
+	}
+	sa->flow = rte_flow_create(sa->fdir_portid,
+				&sa->attr, sa->pattern, sa->action,
+				&err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Creation failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 4f2fd6184..00147895a 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -46,6 +46,8 @@
 
 #define IP6_VERSION (6)
 
+#define IPV6_ADDR_LEN   16
+
 struct rte_crypto_xform;
 struct ipsec_xform;
 struct rte_mbuf;
@@ -138,6 +140,9 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint16_t fdir_portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
+int check_fdir_configured(uint16_t portid);
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 4822d6bda..204a685fb 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -20,6 +20,9 @@
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_ethdev_driver.h>
 
 #include "ipsec.h"
 #include "esp.h"
@@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -681,6 +685,38 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+				APP_CHECK(0, status, "Flow Director not "
+					"supported for security session "
+					"type:%d", ips->type);
+					return;
+			}
+			rule->fdir_flag = 1;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_portid = atoi(tokens[ti]);
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_qid = atoi(tokens[ti]);
+			/* validating portid and queueid */
+			status_p = check_flow_params(rule->fdir_portid,
+					rule->fdir_qid);
+			if (status_p < 0) {
+				printf("port id %u / queue id %u is not valid\n",
+					rule->fdir_portid, rule->fdir_qid);
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -823,6 +859,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1153,7 +1192,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 		}
-
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp flow failed\n");
+			}
 		print_one_sa_rule(sa, inbound);
 	}
 
@@ -1256,6 +1300,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa)
 	return rc;
 }
 
+int
+check_fdir_configured(uint16_t portid)
+{
+	struct ipsec_sa *sa = NULL;
+	uint32_t idx_sa = 0;
+
+	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
+		sa = &sa_in[idx_sa];
+		if (sa->fdir_portid == portid)
+			return sa->fdir_flag;
+	}
+	return 0;
+}
+
 /*
  * Initialise related rte_ipsec_sa object.
  */
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow director feature
  2020-03-19 16:21 ` [dpdk-dev] [PATCH v2] " Praveen Shetty
@ 2020-03-20  8:15   ` Anoob Joseph
  2020-03-23 11:24     ` Shetty, Praveen
  2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
  1 sibling, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-03-20  8:15 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty, bernard.iremonger,
	konstantin.ananyev
  Cc: Narayana Prasad Raju Athreya

Hi Praveen,

You need to rebase to the latest dpdk-next-crypto code base. This patch is not applying cleanly.

There were few patches from Intel removing the existing FDIR and adding some new implementation. Hope this patch takes that also into account. Also, why do we need to call the feature flow director. I would assume rte_flow per SA is what is being attempted here.

Few comments. See inline.

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> Sent: Thursday, March 19, 2020 9:52 PM
> To: dev@dpdk.org; declan.doherty@intel.com; bernard.iremonger@intel.co;
> konstantin.ananyev@intel.com
> Subject: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow director
> feature
> 
> Support load distribution in security gateway application using NIC load
> distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow to a specified
> queue.This is achieved by extending the SA rule syntax to support specification
> by adding new action_type of <flow-direction> to a specified <port_id>
> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
> v2 changes:
> added more details in commit message.
> added a check to throw an error if the security session type is other than
> LOOKASIDE_NONE
> 
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
>  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       | 11 +++++
>  examples/ipsec-secgw/sa.c          | 60 +++++++++++++++++++++++++-
>  5 files changed, 202 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
> index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24
> sport 0:65535 dport 0:65535  sp ipv4 in esp protect 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
> @@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
> @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa in
> 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 4799bc90c..132484422 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
>  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
>  	{NULL, 0, 0, 0}
>  };
> -

[Anoob] I would assume the above change is not intentional.
 
>  /* mask of enabled ports */
>  static uint32_t enabled_port_mask;
>  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6 +258,30
> @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6 @@
> main_loop(__attribute__((unused)) void *dummy)
> 
>  			if (nb_rx > 0)
>  				process_pkts(qconf, pkts, nb_rx, portid);
> -

[Anoob] I would assume the above change is not intentional.
 
>  			/* dequeue and process completed crypto-ops */
>  			if (UNPROTECTED_PORT(portid))
>  				drain_inbound_crypto_queues(qconf,
> @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
>  	}
>  }
> 
> +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_params(void)
>  {
> @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
>  			continue;
> 
>  		sa_check_offloads(portid, &req_rx_offloads,
> &req_tx_offloads);
> +		/* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}

[Anoob] This would mean, once FDIR is enabled for one SA, then the port init is changed. RSS is disabled and FDIR gets enabled. Can you confirm if I understood the code correctly?
 
>  		port_init(portid, req_rx_offloads, req_tx_offloads);
>  	}
> 
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index
> 6e8120702..363809cfd 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {

[Anoob] Why just ESP? Can't the same rte_flow rules be used for doing BYPASS/TRANSPORT?
 
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->fdir_portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 4f2fd6184..00147895a 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -46,6 +46,8 @@
> 
>  #define IP6_VERSION (6)
> 
> +#define IPV6_ADDR_LEN   16

[Anoob] Can't we do a sizeof of some structure to get the same? Having an application specific macro may not be the right approach.
 
> +
>  struct rte_crypto_xform;
>  struct ipsec_xform;
>  struct rte_mbuf;
> @@ -138,6 +140,9 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint16_t fdir_portid;

[Anoob] The existing member 'portid' above 'fdir_portid' is used for a similar rte_flow creation for inline IPsec. Can't we use the same here also?
 
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx,
> struct ipsec_sa *sa,  int  create_inline_session(struct socket_ctx *skt_ctx, struct
> ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int check_fdir_configured(uint16_t portid);

[Anoob] Better to stick to the convention followed.
 
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index
> 4822d6bda..204a685fb 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -20,6 +20,9 @@
>  #include <rte_random.h>
>  #include <rte_ethdev.h>
>  #include <rte_malloc.h>
> +#include <rte_common.h>
> +#include <rte_string_fns.h>
> +#include <rte_ethdev_driver.h>
> 
>  #include "ipsec.h"
>  #include "esp.h"
> @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -681,6 +685,38 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> +				ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO
> ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				APP_CHECK(0, status, "Flow Director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +					return;
> +			}
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_portid = atoi(tokens[ti]);
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->fdir_portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->fdir_portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> +859,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1153,7 +1192,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  				return -EINVAL;
>  			}
>  		}
> -
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");
> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1256,6 +1300,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct
> rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid)
> +{
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->fdir_portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* Re: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow director feature
  2020-03-20  8:15   ` Anoob Joseph
@ 2020-03-23 11:24     ` Shetty, Praveen
  0 siblings, 0 replies; 26+ messages in thread
From: Shetty, Praveen @ 2020-03-23 11:24 UTC (permalink / raw)
  To: Anoob Joseph, dev, Doherty, Declan, Iremonger, Bernard, Ananyev,
	Konstantin
  Cc: Narayana Prasad Raju Athreya

Hi Anoob,

Thank you.

Please see my response inline.

Regards,
Praveen

-----Original Message-----
From: Anoob Joseph <anoobj@marvell.com> 
Sent: Friday, March 20, 2020 1:45 PM
To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; bernard.iremonger@intel.co; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Cc: Narayana Prasad Raju Athreya <pathreya@marvell.com>
Subject: RE: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow director feature

Hi Praveen,

You need to rebase to the latest dpdk-next-crypto code base. This patch is not applying cleanly.

[Praveen] Will fix this in V3.

There were few patches from Intel removing the existing FDIR and adding some new implementation. Hope this patch takes that also into account. Also, why do we need to call the feature flow director. I would assume rte_flow per SA is what is being attempted here.

[Praveen] In regards the action name, it wasn't trying to be flow director specific, but the name was trying to capture the action which was flow direction to a specific queue. We're open to change this to whatever is deemed appropriate ...

perhaps just
"flow-queue-action <port_id> <queue-id>" or
"distrubte <port_id> <queue-id>?


Few comments. See inline.

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
> Sent: Thursday, March 19, 2020 9:52 PM
> To: dev@dpdk.org; declan.doherty@intel.com; 
> bernard.iremonger@intel.co; konstantin.ananyev@intel.com
> Subject: [dpdk-dev] [PATCH v2] examples/ipsec-secgw: support flow 
> director feature
> 
> Support load distribution in security gateway application using NIC 
> load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow to 
> a specified queue.This is achieved by extending the SA rule syntax to 
> support specification by adding new action_type of <flow-direction> to 
> a specified <port_id> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
> v2 changes:
> added more details in commit message.
> added a check to throw an error if the security session type is other 
> than LOOKASIDE_NONE
> 
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 56 ++++++++++++++++++++++++-
>  examples/ipsec-secgw/ipsec.c       | 67 ++++++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       | 11 +++++
>  examples/ipsec-secgw/sa.c          | 60 +++++++++++++++++++++++++-
>  5 files changed, 202 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg 
> b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 
> 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 
> 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 
> 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 
> 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 
> dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 
> sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst 
> 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6 
> in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 
> 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 
> 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 
> 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa 
> in
> 126 cipher_algo aes-128-cbc cipher_key 
> 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> secgw/ipsec-secgw.c index 4799bc90c..132484422 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -166,7 +166,6 @@ static const struct option lgopts[] = {
>  	{CMD_LINE_OPT_FRAG_TTL, 1, 0, CMD_LINE_OPT_FRAG_TTL_NUM},
>  	{NULL, 0, 0, 0}
>  };
> -

[Anoob] I would assume the above change is not intentional.

[Praveen] it was not intentional. Will fix this in V3.
 
>  /* mask of enabled ports */
>  static uint32_t enabled_port_mask;
>  static uint64_t enabled_cryptodev_mask = UINT64_MAX; @@ -259,6 
> +258,30 @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  static struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1184,7 +1207,6 
> @@
> main_loop(__attribute__((unused)) void *dummy)
> 
>  			if (nb_rx > 0)
>  				process_pkts(qconf, pkts, nb_rx, portid);
> -

[Anoob] I would assume the above change is not intentional.

[Praveen ] it was not intentional. Will fix this in V3.
 
>  			/* dequeue and process completed crypto-ops */
>  			if (UNPROTECTED_PORT(portid))
>  				drain_inbound_crypto_queues(qconf,
> @@ -1196,6 +1218,27 @@ main_loop(__attribute__((unused)) void *dummy)
>  	}
>  }
> 
> +int check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_params(void)
>  {
> @@ -2503,6 +2546,15 @@ main(int32_t argc, char **argv)
>  			continue;
> 
>  		sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
> +		/* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}

[Anoob] This would mean, once FDIR is enabled for one SA, then the port init is changed. RSS is disabled and FDIR gets enabled. Can you confirm if I understood the code correctly?

[Praveen]  Currently this is correct but in the future the idea would be only to disable the queue which the SA is associated with.
 
>  		port_init(portid, req_rx_offloads, req_tx_offloads);
>  	}
> 
> diff --git a/examples/ipsec-secgw/ipsec.c 
> b/examples/ipsec-secgw/ipsec.c index 6e8120702..363809cfd 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -415,6 +415,73 @@ create_inline_session(struct socket_ctx *skt_ctx, 
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {

[Anoob] Why just ESP? Can't the same rte_flow rules be used for doing BYPASS/TRANSPORT?

[Praveen]  So yes but this is all we have validated at the moment, transport is trickier as it requires a reverse lookup of the SPD to get the SIP/DIP, which we may do in the future. In terms of BYPASS is not SA specified so we haven't looked at offloading the SPD yet. Finally AH isn't supported in the GW so we haven't looked at it.
 
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +				sa->dst.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +				sa->src.ip.ip6.ip6_b, IPV6_ADDR_LEN);
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->fdir_portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->fdir_portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h 
> b/examples/ipsec-secgw/ipsec.h index 4f2fd6184..00147895a 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -46,6 +46,8 @@
> 
>  #define IP6_VERSION (6)
> 
> +#define IPV6_ADDR_LEN   16

[Anoob] Can't we do a sizeof of some structure to get the same? Having an application specific macro may not be the right approach.

[Praveen] okay. Wil fix this in V3.
 
> +
>  struct rte_crypto_xform;
>  struct ipsec_xform;
>  struct rte_mbuf;
> @@ -138,6 +140,9 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint16_t fdir_portid;

[Anoob] The existing member 'portid' above 'fdir_portid' is used for a similar rte_flow creation for inline IPsec. Can't we use the same here also?

[Praveen] Will check if we can use the existing member.

> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -383,5 +388,11 @@ create_lookaside_session(struct ipsec_ctx 
> *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct 
> socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int check_fdir_configured(uint16_t portid);

[Anoob] Better to stick to the convention followed.

[Praveen] Will fix this in V3.

 
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> index 4822d6bda..204a685fb 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -20,6 +20,9 @@
>  #include <rte_random.h>
>  #include <rte_ethdev.h>
>  #include <rte_malloc.h>
> +#include <rte_common.h>
> +#include <rte_string_fns.h>
> +#include <rte_ethdev_driver.h>
> 
>  #include "ipsec.h"
>  #include "esp.h"
> @@ -271,6 +274,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -681,6 +685,38 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> +				ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO
> ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				APP_CHECK(0, status, "Flow Director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +					return;
> +			}
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_portid = atoi(tokens[ti]);
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->fdir_portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->fdir_portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -823,6
> +859,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->fdir_portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1153,7 +1192,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const 
> struct ipsec_sa entries[],
>  				return -EINVAL;
>  			}
>  		}
> -
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");
> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1256,6 +1300,20 @@ fill_ipsec_session(struct rte_ipsec_session 
> *ss, struct rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid) {
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->fdir_portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-03-19 16:21 ` [dpdk-dev] [PATCH v2] " Praveen Shetty
  2020-03-20  8:15   ` Anoob Joseph
@ 2020-03-31 13:02   ` Praveen Shetty
  2020-04-01 13:19     ` Akhil Goyal
                       ` (2 more replies)
  1 sibling, 3 replies; 26+ messages in thread
From: Praveen Shetty @ 2020-03-31 13:02 UTC (permalink / raw)
  To: dev, declan.doherty, anoobj; +Cc: bernard.iremonger, konstantin.ananyev

Support load distribution in security gateway application using
NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow
to a specified queue.This is achieved by extending the SA rule syntax
to support specification by adding new action_type of <flow-direction>
to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v3 changes:
Incorporated Anoob review comments on v2.

 examples/ipsec-secgw/ep0.cfg       | 11 +++++
 examples/ipsec-secgw/ipsec-secgw.c | 55 +++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.c       | 67 +++++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h       |  9 ++++
 examples/ipsec-secgw/sa.c          | 72 ++++++++++++++++++++++++++++--
 5 files changed, 211 insertions(+), 3 deletions(-)

diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index ce36e6d9c..4400b075c 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
 	.txmode = {
 		.mq_mode = ETH_MQ_TX_NONE,
 	},
+	.fdir_conf = {
+	.mode = RTE_FDIR_MODE_NONE,
+	.pballoc = RTE_FDIR_PBALLOC_64K,
+	.status = RTE_FDIR_REPORT_STATUS,
+	.mask = {
+		.vlan_tci_mask = 0xFFEF,
+		.ipv4_mask     = {
+			.src_ip = 0xFFFFFFFF,
+			.dst_ip = 0xFFFFFFFF,
+		},
+		.ipv6_mask     = {
+			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+						0xFFFFFFFF},
+		},
+		.src_port_mask = 0xFFFF,
+		.dst_port_mask = 0xFFFF,
+		.mac_addr_byte_mask = 0xFF,
+		.tunnel_type_mask = 1,
+		.tunnel_id_mask = 0xFFFFFFFF,
+	},
+	.drop_queue = 127,
+	}
 };
 
 struct socket_ctx socket_ctx[NB_SOCKETS];
@@ -1183,6 +1207,28 @@ ipsec_poll_mode_worker(void)
 	}
 }
 
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_poll_mode_params(struct eh_conf *eh_conf)
 {
@@ -2813,6 +2859,15 @@ main(int32_t argc, char **argv)
 
 		sa_check_offloads(portid, &req_rx_offloads[portid],
 				&req_tx_offloads[portid]);
+		 /* check if FDIR is configured on the port */
+		if (check_fdir_configured(portid)) {
+			/* Enable FDIR */
+			port_conf.fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+			/* Disable RSS */
+			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
+			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+		}
 		port_init(portid, req_rx_offloads[portid],
 				req_tx_offloads[portid]);
 	}
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index d40657102..76ee9dbcf 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		return 0; /* No Flow director rules for Egress traffic */
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode:");
+			return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->portid, &sa->attr,
+				sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Validation failed\n");
+		return ret;
+	}
+	sa->flow = rte_flow_create(sa->portid,
+				&sa->attr, sa->pattern, sa->action,
+				&err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC,
+			"Flow Creation failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index f8f29f9b1..b0e9f45cb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -144,6 +144,8 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
+int
+check_fdir_configured(uint16_t portid);
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 0eb52d141..ddd275142 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
 	rule->spi = atoi(tokens[1]);
+	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
 
 	for (ti = 2; ti < n_tokens; ti++) {
@@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-			rule->portid = atoi(tokens[ti]);
-			if (status->status < 0)
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s "
+				"not matching with already assigned portid %u",
+				tokens[ti], rule->portid);
 				return;
+			}
 			portid_p = 1;
 			continue;
 		}
@@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+				APP_CHECK(0, status, "Flow Director not "
+					"supported for security session "
+					"type:%d", ips->type);
+					return;
+			}
+			rule->fdir_flag = 1;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s "
+				"not matching with already assigned portid %u",
+				tokens[ti], rule->portid);
+				return;
+			}
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_qid = atoi(tokens[ti]);
+			/* validating portid and queueid */
+			status_p = check_flow_params(rule->portid,
+					rule->fdir_qid);
+			if (status_p < 0) {
+				printf("port id %u / queue id %u is not valid\n",
+					rule->portid, rule->fdir_qid);
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -719,7 +763,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (!type_p || (!portid_p && ips->type !=
 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
-		rule->portid = -1;
 	}
 
 	*ri = *ri + 1;
@@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1141,6 +1187,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			}
 		}
 
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp flow failed\n");
+			}
 		print_one_sa_rule(sa, inbound);
 	}
 
@@ -1243,6 +1295,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa)
 	return rc;
 }
 
+int
+check_fdir_configured(uint16_t portid)
+{
+	struct ipsec_sa *sa = NULL;
+	uint32_t idx_sa = 0;
+
+	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
+		sa = &sa_in[idx_sa];
+		if (sa->portid == portid)
+			return sa->fdir_flag;
+	}
+	return 0;
+}
+
 /*
  * Initialise related rte_ipsec_sa object.
  */
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
@ 2020-04-01 13:19     ` Akhil Goyal
  2020-04-01 13:26       ` Anoob Joseph
  2020-04-02 13:39     ` [dpdk-dev] [EXT] " Anoob Joseph
  2020-04-08 14:13     ` [dpdk-dev] [PATCH v4] " Praveen Shetty
  2 siblings, 1 reply; 26+ messages in thread
From: Akhil Goyal @ 2020-04-01 13:19 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

Hi Praveen,

Sorry for being late to reply on this, Please delegate the patches properly from next time in patchworks.
This patch was neither delegated to me, nor I was in to/cc. So it got missed.

> 
> Support load distribution in security gateway application using
> NIC load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow
> to a specified queue.This is achieved by extending the SA rule syntax
> to support specification by adding new action_type of <flow-direction>
> to a specified <port_id> <queue_id>.
> 

Please add documentation (doc/guides/sample_app_ug/ipsec_secgw.rst) changes
to explain the new parameter.

> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
> v3 changes:
> Incorporated Anoob review comments on v2.
> 



> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index ce36e6d9c..4400b075c 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {

Fdir_conf is a deprecated parameter. It is not good to introduce 
Something new in the application with a deprecated parameter.
Please use the recommended way to configure flows.

> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  struct socket_ctx socket_ctx[NB_SOCKETS];
> @@ -1183,6 +1207,28 @@ ipsec_poll_mode_worker(void)
>  	}
>  }
> 
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
> +{
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_poll_mode_params(struct eh_conf *eh_conf)
>  {
> @@ -2813,6 +2859,15 @@ main(int32_t argc, char **argv)
> 
>  		sa_check_offloads(portid, &req_rx_offloads[portid],
>  				&req_tx_offloads[portid]);
> +		 /* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}
>  		port_init(portid, req_rx_offloads[portid],
>  				req_tx_offloads[portid]);
>  	}
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index d40657102..76ee9dbcf 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa)
> +{
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index f8f29f9b1..b0e9f45cb 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -144,6 +144,8 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx,
> struct ipsec_sa *sa,
>  int
>  create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int
> +check_fdir_configured(uint16_t portid);
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index 0eb52d141..ddd275142 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (atoi(tokens[1]) == INVALID_SPI)
>  		return;
>  	rule->spi = atoi(tokens[1]);
> +	rule->portid = UINT16_MAX;
>  	ips = ipsec_get_primary_session(rule);
> 
>  	for (ti = 2; ti < n_tokens; ti++) {
> @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -			rule->portid = atoi(tokens[ti]);
> -			if (status->status < 0)
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid %u",
> +				tokens[ti], rule->portid);
>  				return;
> +			}
>  			portid_p = 1;
>  			continue;
>  		}
> @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				APP_CHECK(0, status, "Flow Director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +					return;
> +			}
It means it is supported in cpu crypto as well? Better to have a check for the supported
Action types, as in the future there may be some other action types.

> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid %u",
> +				tokens[ti], rule->portid);
> +				return;
> +			}
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"",
> @@ -719,7 +763,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (!type_p || (!portid_p && ips->type !=
>  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
>  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> -		rule->portid = -1;
>  	}
> 
>  	*ri = *ri + 1;
> @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);

Better to print like below.
printf("flow-direction port %d queue %d ", sa->portid, sa->fdir_qid)

> +
>  	printf("\n");
>  }
> 

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

* Re: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-01 13:19     ` Akhil Goyal
@ 2020-04-01 13:26       ` Anoob Joseph
  2020-04-01 13:53         ` Akhil Goyal
  0 siblings, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-04-01 13:26 UTC (permalink / raw)
  To: Akhil Goyal, Praveen Shetty, dev, declan.doherty
  Cc: bernard.iremonger, konstantin.ananyev

Hi Akhil, Praveen,

Can't rte_flow and RSS co-exist? In rte_flow there is an ACTION type RSS in addition to QUEUE. With this patch, if rte_flow is enabled on any SA, then RSS would be disabled for the entire port. Is that the right behavior? And if we have to address this later, what would be the course of action?

Also, is flow director the right name we should use? Internally it is rte_flow, right? 

Thanks,
Anoob

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Wednesday, April 1, 2020 6:50 PM
> To: Praveen Shetty <praveen.shetty@intel.com>; dev@dpdk.org;
> declan.doherty@intel.com; Anoob Joseph <anoobj@marvell.com>
> Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: [EXT] RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow
> director feature
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Praveen,
> 
> Sorry for being late to reply on this, Please delegate the patches properly from
> next time in patchworks.
> This patch was neither delegated to me, nor I was in to/cc. So it got missed.
> 
> >
> > Support load distribution in security gateway application using NIC
> > load distribution feature(Flow Director).
> > Flow Director is used to redirect the specified inbound ipsec flow to
> > a specified queue.This is achieved by extending the SA rule syntax to
> > support specification by adding new action_type of <flow-direction> to
> > a specified <port_id> <queue_id>.
> >
> 
> Please add documentation (doc/guides/sample_app_ug/ipsec_secgw.rst)
> changes to explain the new parameter.
> 
> > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > ---
> > v3 changes:
> > Incorporated Anoob review comments on v2.
> >
> 
> 
> 
> > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> > secgw/ipsec-secgw.c index ce36e6d9c..4400b075c 100644
> > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
> >  	.txmode = {
> >  		.mq_mode = ETH_MQ_TX_NONE,
> >  	},
> > +	.fdir_conf = {
> 
> Fdir_conf is a deprecated parameter. It is not good to introduce Something new
> in the application with a deprecated parameter.
> Please use the recommended way to configure flows.
> 
> > +	.mode = RTE_FDIR_MODE_NONE,
> > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > +	.status = RTE_FDIR_REPORT_STATUS,
> > +	.mask = {
> > +		.vlan_tci_mask = 0xFFEF,
> > +		.ipv4_mask     = {
> > +			.src_ip = 0xFFFFFFFF,
> > +			.dst_ip = 0xFFFFFFFF,
> > +		},
> > +		.ipv6_mask     = {
> > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +		},
> > +		.src_port_mask = 0xFFFF,
> > +		.dst_port_mask = 0xFFFF,
> > +		.mac_addr_byte_mask = 0xFF,
> > +		.tunnel_type_mask = 1,
> > +		.tunnel_id_mask = 0xFFFFFFFF,
> > +	},
> > +	.drop_queue = 127,
> > +	}
> >  };
> >
> >  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> > ipsec_poll_mode_worker(void)
> >  	}
> >  }
> >
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > +	uint16_t i;
> > +	uint16_t portid;
> > +	uint8_t queueid;
> > +
> > +	for (i = 0; i < nb_lcore_params; ++i) {
> > +		portid = lcore_params_array[i].port_id;
> > +		if (portid == fdir_portid) {
> > +			queueid = lcore_params_array[i].queue_id;
> > +			if (queueid == fdir_qid)
> > +				break;
> > +		}
> > +
> > +		if (i == nb_lcore_params - 1)
> > +			return -1;
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> >  static int32_t
> >  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6
> > +2859,15 @@ main(int32_t argc, char **argv)
> >
> >  		sa_check_offloads(portid, &req_rx_offloads[portid],
> >  				&req_tx_offloads[portid]);
> > +		 /* check if FDIR is configured on the port */
> > +		if (check_fdir_configured(portid)) {
> > +			/* Enable FDIR */
> > +			port_conf.fdir_conf.mode =
> > RTE_FDIR_MODE_PERFECT;
> > +			/* Disable RSS */
> > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > +		}
> >  		port_init(portid, req_rx_offloads[portid],
> >  				req_tx_offloads[portid]);
> >  	}
> > diff --git a/examples/ipsec-secgw/ipsec.c
> > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > --- a/examples/ipsec-secgw/ipsec.c
> > +++ b/examples/ipsec-secgw/ipsec.c
> > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> > struct ipsec_sa *sa,
> >  	return 0;
> >  }
> >
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > +	int ret = 0;
> > +	struct rte_flow_error err;
> > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > +		return 0; /* No Flow director rules for Egress traffic */
> > +	if (sa->flags == TRANSPORT) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"No Flow director rule for transport mode:");
> > +			return -1;
> > +	}
> > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > +	sa->action[0].conf =
> > +			&(struct rte_flow_action_queue){
> > +				.index = sa->fdir_qid,
> > +	};
> > +	sa->attr.egress = 0;
> > +	sa->attr.ingress = 1;
> > +	if (IS_IP6(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	} else if (IS_IP4(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	}
> > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > +
> > +	ret = rte_flow_validate(sa->portid, &sa->attr,
> > +				sa->pattern, sa->action,
> > +				&err);
> > +	if (ret < 0) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Validation failed\n");
> > +		return ret;
> > +	}
> > +	sa->flow = rte_flow_create(sa->portid,
> > +				&sa->attr, sa->pattern, sa->action,
> > +				&err);
> > +	if (!sa->flow) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Creation failed\n");
> > +		return -1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * queue crypto-ops into PMD queue.
> >   */
> > diff --git a/examples/ipsec-secgw/ipsec.h
> > b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..b0e9f45cb 100644
> > --- a/examples/ipsec-secgw/ipsec.h
> > +++ b/examples/ipsec-secgw/ipsec.h
> > @@ -144,6 +144,8 @@ struct ipsec_sa {
> >  	};
> >  	enum rte_security_ipsec_sa_direction direction;
> >  	uint16_t portid;
> > +	uint8_t fdir_qid;
> > +	uint8_t fdir_flag;
> >
> >  #define MAX_RTE_FLOW_PATTERN (4)
> >  #define MAX_RTE_FLOW_ACTIONS (3)
> > @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx
> > *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct
> > socket_ctx *skt_ctx, struct ipsec_sa *sa,
> >  		struct rte_ipsec_session *ips);
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > +
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> >
> > +int
> > +check_fdir_configured(uint16_t portid);
> >  #endif /* __IPSEC_H__ */
> > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> > index 0eb52d141..ddd275142 100644
> > --- a/examples/ipsec-secgw/sa.c
> > +++ b/examples/ipsec-secgw/sa.c
> > @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	uint32_t type_p = 0;
> >  	uint32_t portid_p = 0;
> >  	uint32_t fallback_p = 0;
> > +	int16_t status_p = 0;
> >
> >  	if (strcmp(tokens[0], "in") == 0) {
> >  		ri = &nb_sa_in;
> > @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	if (atoi(tokens[1]) == INVALID_SPI)
> >  		return;
> >  	rule->spi = atoi(tokens[1]);
> > +	rule->portid = UINT16_MAX;
> >  	ips = ipsec_get_primary_session(rule);
> >
> >  	for (ti = 2; ti < n_tokens; ti++) {
> > @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> >  			if (status->status < 0)
> >  				return;
> > -			rule->portid = atoi(tokens[ti]);
> > -			if (status->status < 0)
> > +			if (rule->portid == UINT16_MAX)
> > +				rule->portid = atoi(tokens[ti]);
> > +			else if (rule->portid != atoi(tokens[ti])) {
> > +				APP_CHECK(0, status, "portid %s "
> > +				"not matching with already assigned portid
> %u",
> > +				tokens[ti], rule->portid);
> >  				return;
> > +			}
> >  			portid_p = 1;
> >  			continue;
> >  		}
> > @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			fallback_p = 1;
> >  			continue;
> >  		}
> > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > +			if (ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> > +				ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> > +				ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> > +				APP_CHECK(0, status, "Flow Director not "
> > +					"supported for security session "
> > +					"type:%d", ips->type);
> > +					return;
> > +			}
> It means it is supported in cpu crypto as well? Better to have a check for the
> supported Action types, as in the future there may be some other action types.
> 
> > +			rule->fdir_flag = 1;
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			if (rule->portid == UINT16_MAX)
> > +				rule->portid = atoi(tokens[ti]);
> > +			else if (rule->portid != atoi(tokens[ti])) {
> > +				APP_CHECK(0, status, "portid %s "
> > +				"not matching with already assigned portid
> %u",
> > +				tokens[ti], rule->portid);
> > +				return;
> > +			}
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_qid = atoi(tokens[ti]);
> > +			/* validating portid and queueid */
> > +			status_p = check_flow_params(rule->portid,
> > +					rule->fdir_qid);
> > +			if (status_p < 0) {
> > +				printf("port id %u / queue id %u is not valid\n",
> > +					rule->portid, rule->fdir_qid);
> > +			}
> > +			continue;
> > +		}
> >
> >  		/* unrecognizeable input */
> >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> +763,6
> > @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	if (!type_p || (!portid_p && ips->type !=
> >  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
> >  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> > -		rule->portid = -1;
> >  	}
> >
> >  	*ri = *ri + 1;
> > @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> inbound)
> >  			break;
> >  		}
> >  	}
> > +	if (sa->fdir_flag == 1)
> > +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> 
> Better to print like below.
> printf("flow-direction port %d queue %d ", sa->portid, sa->fdir_qid)
> 
> > +
> >  	printf("\n");
> >  }
> >

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

* Re: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-01 13:26       ` Anoob Joseph
@ 2020-04-01 13:53         ` Akhil Goyal
  2020-04-02 11:15           ` Shetty, Praveen
  0 siblings, 1 reply; 26+ messages in thread
From: Akhil Goyal @ 2020-04-01 13:53 UTC (permalink / raw)
  To: Anoob Joseph, Praveen Shetty, dev, declan.doherty
  Cc: bernard.iremonger, konstantin.ananyev



> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Wednesday, April 1, 2020 6:57 PM
> To: Akhil Goyal <akhil.goyal@nxp.com>; Praveen Shetty
> <praveen.shetty@intel.com>; dev@dpdk.org; declan.doherty@intel.com
> Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director
> feature
> 
> Hi Akhil, Praveen,
> 
> Can't rte_flow and RSS co-exist? In rte_flow there is an ACTION type RSS in
> addition to QUEUE. With this patch, if rte_flow is enabled on any SA, then RSS
> would be disabled for the entire port. Is that the right behavior? And if we have
> to address this later, what would be the course of action?
> 
Yes they can co-exist I believe. What this patch is doing is assigning a fixed queue to
A flow which user can control for an SA. RSS is based on hash and user doesnot have
Control on it.
Removing RSS on entire port is not desirable and it should not be done. Probably there
Should be a mechanism to disable RSS on that particular flow.

> Also, is flow director the right name we should use? Internally it is rte_flow, right?
Name can be anything, I don't feel issue in either flow director or rte_flow.

> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: Akhil Goyal <akhil.goyal@nxp.com>
> > Sent: Wednesday, April 1, 2020 6:50 PM
> > To: Praveen Shetty <praveen.shetty@intel.com>; dev@dpdk.org;
> > declan.doherty@intel.com; Anoob Joseph <anoobj@marvell.com>
> > Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> > Subject: [EXT] RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow
> > director feature
> >
> > External Email
> >
> > ----------------------------------------------------------------------
> > Hi Praveen,
> >
> > Sorry for being late to reply on this, Please delegate the patches properly from
> > next time in patchworks.
> > This patch was neither delegated to me, nor I was in to/cc. So it got missed.
> >
> > >
> > > Support load distribution in security gateway application using NIC
> > > load distribution feature(Flow Director).
> > > Flow Director is used to redirect the specified inbound ipsec flow to
> > > a specified queue.This is achieved by extending the SA rule syntax to
> > > support specification by adding new action_type of <flow-direction> to
> > > a specified <port_id> <queue_id>.
> > >
> >
> > Please add documentation (doc/guides/sample_app_ug/ipsec_secgw.rst)
> > changes to explain the new parameter.
> >
> > > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > > ---
> > > v3 changes:
> > > Incorporated Anoob review comments on v2.
> > >
> >
> >
> >
> > > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> > > secgw/ipsec-secgw.c index ce36e6d9c..4400b075c 100644
> > > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > > @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
> > >  	.txmode = {
> > >  		.mq_mode = ETH_MQ_TX_NONE,
> > >  	},
> > > +	.fdir_conf = {
> >
> > Fdir_conf is a deprecated parameter. It is not good to introduce Something
> new
> > in the application with a deprecated parameter.
> > Please use the recommended way to configure flows.
> >
> > > +	.mode = RTE_FDIR_MODE_NONE,
> > > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > > +	.status = RTE_FDIR_REPORT_STATUS,
> > > +	.mask = {
> > > +		.vlan_tci_mask = 0xFFEF,
> > > +		.ipv4_mask     = {
> > > +			.src_ip = 0xFFFFFFFF,
> > > +			.dst_ip = 0xFFFFFFFF,
> > > +		},
> > > +		.ipv6_mask     = {
> > > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > > +						0xFFFFFFFF},
> > > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > > +						0xFFFFFFFF},
> > > +		},
> > > +		.src_port_mask = 0xFFFF,
> > > +		.dst_port_mask = 0xFFFF,
> > > +		.mac_addr_byte_mask = 0xFF,
> > > +		.tunnel_type_mask = 1,
> > > +		.tunnel_id_mask = 0xFFFFFFFF,
> > > +	},
> > > +	.drop_queue = 127,
> > > +	}
> > >  };
> > >
> > >  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> > > ipsec_poll_mode_worker(void)
> > >  	}
> > >  }
> > >
> > > +int
> > > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > > +	uint16_t i;
> > > +	uint16_t portid;
> > > +	uint8_t queueid;
> > > +
> > > +	for (i = 0; i < nb_lcore_params; ++i) {
> > > +		portid = lcore_params_array[i].port_id;
> > > +		if (portid == fdir_portid) {
> > > +			queueid = lcore_params_array[i].queue_id;
> > > +			if (queueid == fdir_qid)
> > > +				break;
> > > +		}
> > > +
> > > +		if (i == nb_lcore_params - 1)
> > > +			return -1;
> > > +	}
> > > +
> > > +	return 1;
> > > +}
> > > +
> > >  static int32_t
> > >  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6
> > > +2859,15 @@ main(int32_t argc, char **argv)
> > >
> > >  		sa_check_offloads(portid, &req_rx_offloads[portid],
> > >  				&req_tx_offloads[portid]);
> > > +		 /* check if FDIR is configured on the port */
> > > +		if (check_fdir_configured(portid)) {
> > > +			/* Enable FDIR */
> > > +			port_conf.fdir_conf.mode =
> > > RTE_FDIR_MODE_PERFECT;
> > > +			/* Disable RSS */
> > > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > > +		}
> > >  		port_init(portid, req_rx_offloads[portid],
> > >  				req_tx_offloads[portid]);
> > >  	}
> > > diff --git a/examples/ipsec-secgw/ipsec.c
> > > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > > --- a/examples/ipsec-secgw/ipsec.c
> > > +++ b/examples/ipsec-secgw/ipsec.c
> > > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> > > struct ipsec_sa *sa,
> > >  	return 0;
> > >  }
> > >
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > > +	int ret = 0;
> > > +	struct rte_flow_error err;
> > > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > > +		return 0; /* No Flow director rules for Egress traffic */
> > > +	if (sa->flags == TRANSPORT) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"No Flow director rule for transport mode:");
> > > +			return -1;
> > > +	}
> > > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > > +	sa->action[0].conf =
> > > +			&(struct rte_flow_action_queue){
> > > +				.index = sa->fdir_qid,
> > > +	};
> > > +	sa->attr.egress = 0;
> > > +	sa->attr.ingress = 1;
> > > +	if (IS_IP6(sa->flags)) {
> > > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > > +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> > > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > > +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> > > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > > +		sa->pattern[2].spec = &sa->esp_spec;
> > > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > > +	} else if (IS_IP4(sa->flags)) {
> > > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > > +		sa->pattern[2].spec = &sa->esp_spec;
> > > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > > +	}
> > > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > > +
> > > +	ret = rte_flow_validate(sa->portid, &sa->attr,
> > > +				sa->pattern, sa->action,
> > > +				&err);
> > > +	if (ret < 0) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"Flow Validation failed\n");
> > > +		return ret;
> > > +	}
> > > +	sa->flow = rte_flow_create(sa->portid,
> > > +				&sa->attr, sa->pattern, sa->action,
> > > +				&err);
> > > +	if (!sa->flow) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"Flow Creation failed\n");
> > > +		return -1;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  /*
> > >   * queue crypto-ops into PMD queue.
> > >   */
> > > diff --git a/examples/ipsec-secgw/ipsec.h
> > > b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..b0e9f45cb 100644
> > > --- a/examples/ipsec-secgw/ipsec.h
> > > +++ b/examples/ipsec-secgw/ipsec.h
> > > @@ -144,6 +144,8 @@ struct ipsec_sa {
> > >  	};
> > >  	enum rte_security_ipsec_sa_direction direction;
> > >  	uint16_t portid;
> > > +	uint8_t fdir_qid;
> > > +	uint8_t fdir_flag;
> > >
> > >  #define MAX_RTE_FLOW_PATTERN (4)
> > >  #define MAX_RTE_FLOW_ACTIONS (3)
> > > @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx
> > > *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct
> > > socket_ctx *skt_ctx, struct ipsec_sa *sa,
> > >  		struct rte_ipsec_session *ips);
> > > +int
> > > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > > +
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> > >
> > > +int
> > > +check_fdir_configured(uint16_t portid);
> > >  #endif /* __IPSEC_H__ */
> > > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> > > index 0eb52d141..ddd275142 100644
> > > --- a/examples/ipsec-secgw/sa.c
> > > +++ b/examples/ipsec-secgw/sa.c
> > > @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	uint32_t type_p = 0;
> > >  	uint32_t portid_p = 0;
> > >  	uint32_t fallback_p = 0;
> > > +	int16_t status_p = 0;
> > >
> > >  	if (strcmp(tokens[0], "in") == 0) {
> > >  		ri = &nb_sa_in;
> > > @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	if (atoi(tokens[1]) == INVALID_SPI)
> > >  		return;
> > >  	rule->spi = atoi(tokens[1]);
> > > +	rule->portid = UINT16_MAX;
> > >  	ips = ipsec_get_primary_session(rule);
> > >
> > >  	for (ti = 2; ti < n_tokens; ti++) {
> > > @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > >  			if (status->status < 0)
> > >  				return;
> > > -			rule->portid = atoi(tokens[ti]);
> > > -			if (status->status < 0)
> > > +			if (rule->portid == UINT16_MAX)
> > > +				rule->portid = atoi(tokens[ti]);
> > > +			else if (rule->portid != atoi(tokens[ti])) {
> > > +				APP_CHECK(0, status, "portid %s "
> > > +				"not matching with already assigned portid
> > %u",
> > > +				tokens[ti], rule->portid);
> > >  				return;
> > > +			}
> > >  			portid_p = 1;
> > >  			continue;
> > >  		}
> > > @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  			fallback_p = 1;
> > >  			continue;
> > >  		}
> > > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > > +			if (ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> > > +				ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> > > +				ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> > > +				APP_CHECK(0, status, "Flow Director not "
> > > +					"supported for security session "
> > > +					"type:%d", ips->type);
> > > +					return;
> > > +			}
> > It means it is supported in cpu crypto as well? Better to have a check for the
> > supported Action types, as in the future there may be some other action types.
> >
> > > +			rule->fdir_flag = 1;
> > > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > > +			if (status->status < 0)
> > > +				return;
> > > +			if (rule->portid == UINT16_MAX)
> > > +				rule->portid = atoi(tokens[ti]);
> > > +			else if (rule->portid != atoi(tokens[ti])) {
> > > +				APP_CHECK(0, status, "portid %s "
> > > +				"not matching with already assigned portid
> > %u",
> > > +				tokens[ti], rule->portid);
> > > +				return;
> > > +			}
> > > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > > +			if (status->status < 0)
> > > +				return;
> > > +			rule->fdir_qid = atoi(tokens[ti]);
> > > +			/* validating portid and queueid */
> > > +			status_p = check_flow_params(rule->portid,
> > > +					rule->fdir_qid);
> > > +			if (status_p < 0) {
> > > +				printf("port id %u / queue id %u is not valid\n",
> > > +					rule->portid, rule->fdir_qid);
> > > +			}
> > > +			continue;
> > > +		}
> > >
> > >  		/* unrecognizeable input */
> > >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> > +763,6
> > > @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	if (!type_p || (!portid_p && ips->type !=
> > >  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
> > >  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> > > -		rule->portid = -1;
> > >  	}
> > >
> > >  	*ri = *ri + 1;
> > > @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> > inbound)
> > >  			break;
> > >  		}
> > >  	}
> > > +	if (sa->fdir_flag == 1)
> > > +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> >
> > Better to print like below.
> > printf("flow-direction port %d queue %d ", sa->portid, sa->fdir_qid)
> >
> > > +
> > >  	printf("\n");
> > >  }
> > >

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

* Re: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-01 13:53         ` Akhil Goyal
@ 2020-04-02 11:15           ` Shetty, Praveen
  0 siblings, 0 replies; 26+ messages in thread
From: Shetty, Praveen @ 2020-04-02 11:15 UTC (permalink / raw)
  To: Akhil Goyal, Anoob Joseph, dev, Doherty, Declan
  Cc: Iremonger, Bernard, Ananyev, Konstantin



-----Original Message-----
From: Akhil Goyal <akhil.goyal@nxp.com> 
Sent: Wednesday, April 1, 2020 7:24 PM
To: Anoob Joseph <anoobj@marvell.com>; Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow director feature



> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Wednesday, April 1, 2020 6:57 PM
> To: Akhil Goyal <akhil.goyal@nxp.com>; Praveen Shetty 
> <praveen.shetty@intel.com>; dev@dpdk.org; declan.doherty@intel.com
> Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: support flow 
> director feature
> 
> Hi Akhil, Praveen,
> 
> Can't rte_flow and RSS co-exist? In rte_flow there is an ACTION type 
> RSS in addition to QUEUE. With this patch, if rte_flow is enabled on 
> any SA, then RSS would be disabled for the entire port. Is that the 
> right behavior? And if we have to address this later, what would be the course of action?
> 
Yes they can co-exist I believe. What this patch is doing is assigning a fixed queue to A flow which user can control for an SA. RSS is based on hash and user doesnot have Control on it.
Removing RSS on entire port is not desirable and it should not be done. Probably there Should be a mechanism to disable RSS on that particular flow.

[Praveen]  We will remove the code which disables RSS on entire port in V4. 
meanwhile we will also explore a way to disable the RSS on the queue which the SA is associated with. 

future the idea would be only to disable the queue which the SA is associated with
> Also, is flow director the right name we should use? Internally it is rte_flow, right?
Name can be anything, I don't feel issue in either flow director or rte_flow.

> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: Akhil Goyal <akhil.goyal@nxp.com>
> > Sent: Wednesday, April 1, 2020 6:50 PM
> > To: Praveen Shetty <praveen.shetty@intel.com>; dev@dpdk.org; 
> > declan.doherty@intel.com; Anoob Joseph <anoobj@marvell.com>
> > Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> > Subject: [EXT] RE: [dpdk-dev] [PATCH v3] examples/ipsec-secgw: 
> > support flow director feature
> >
> > External Email
> >
> > --------------------------------------------------------------------
> > --
> > Hi Praveen,
> >
> > Sorry for being late to reply on this, Please delegate the patches 
> > properly from next time in patchworks.
> > This patch was neither delegated to me, nor I was in to/cc. So it got missed.

[Praveen] sorry , I forgot to include you. Will do it from next time.
> >
> > >
> > > Support load distribution in security gateway application using 
> > > NIC load distribution feature(Flow Director).
> > > Flow Director is used to redirect the specified inbound ipsec flow 
> > > to a specified queue.This is achieved by extending the SA rule 
> > > syntax to support specification by adding new action_type of 
> > > <flow-direction> to a specified <port_id> <queue_id>.
> > >
> >
> > Please add documentation (doc/guides/sample_app_ug/ipsec_secgw.rst)
> > changes to explain the new parameter.

[Praveen] Will do it in v4.

> >
> > > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > > ---
> > > v3 changes:
> > > Incorporated Anoob review comments on v2.
> > >
> >
> >
> >
> > > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> > > secgw/ipsec-secgw.c index ce36e6d9c..4400b075c 100644
> > > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > > @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
> > >  	.txmode = {
> > >  		.mq_mode = ETH_MQ_TX_NONE,
> > >  	},
> > > +	.fdir_conf = {
> >
> > Fdir_conf is a deprecated parameter. It is not good to introduce 
> > Something
> new
> > in the application with a deprecated parameter.
> > Please use the recommended way to configure flows.

[Praveen] We will check and do it in v4.

> >
> > > +	.mode = RTE_FDIR_MODE_NONE,
> > > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > > +	.status = RTE_FDIR_REPORT_STATUS,
> > > +	.mask = {
> > > +		.vlan_tci_mask = 0xFFEF,
> > > +		.ipv4_mask     = {
> > > +			.src_ip = 0xFFFFFFFF,
> > > +			.dst_ip = 0xFFFFFFFF,
> > > +		},
> > > +		.ipv6_mask     = {
> > > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > > +						0xFFFFFFFF},
> > > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > > +						0xFFFFFFFF},
> > > +		},
> > > +		.src_port_mask = 0xFFFF,
> > > +		.dst_port_mask = 0xFFFF,
> > > +		.mac_addr_byte_mask = 0xFF,
> > > +		.tunnel_type_mask = 1,
> > > +		.tunnel_id_mask = 0xFFFFFFFF,
> > > +	},
> > > +	.drop_queue = 127,
> > > +	}
> > >  };
> > >
> > >  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> > > ipsec_poll_mode_worker(void)
> > >  	}
> > >  }
> > >
> > > +int
> > > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > > +	uint16_t i;
> > > +	uint16_t portid;
> > > +	uint8_t queueid;
> > > +
> > > +	for (i = 0; i < nb_lcore_params; ++i) {
> > > +		portid = lcore_params_array[i].port_id;
> > > +		if (portid == fdir_portid) {
> > > +			queueid = lcore_params_array[i].queue_id;
> > > +			if (queueid == fdir_qid)
> > > +				break;
> > > +		}
> > > +
> > > +		if (i == nb_lcore_params - 1)
> > > +			return -1;
> > > +	}
> > > +
> > > +	return 1;
> > > +}
> > > +
> > >  static int32_t
> > >  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6
> > > +2859,15 @@ main(int32_t argc, char **argv)
> > >
> > >  		sa_check_offloads(portid, &req_rx_offloads[portid],
> > >  				&req_tx_offloads[portid]);
> > > +		 /* check if FDIR is configured on the port */
> > > +		if (check_fdir_configured(portid)) {
> > > +			/* Enable FDIR */
> > > +			port_conf.fdir_conf.mode =
> > > RTE_FDIR_MODE_PERFECT;
> > > +			/* Disable RSS */
> > > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > > +		}
> > >  		port_init(portid, req_rx_offloads[portid],
> > >  				req_tx_offloads[portid]);
> > >  	}
> > > diff --git a/examples/ipsec-secgw/ipsec.c 
> > > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > > --- a/examples/ipsec-secgw/ipsec.c
> > > +++ b/examples/ipsec-secgw/ipsec.c
> > > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx 
> > > *skt_ctx, struct ipsec_sa *sa,
> > >  	return 0;
> > >  }
> > >
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > > +	int ret = 0;
> > > +	struct rte_flow_error err;
> > > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > > +		return 0; /* No Flow director rules for Egress traffic */
> > > +	if (sa->flags == TRANSPORT) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"No Flow director rule for transport mode:");
> > > +			return -1;
> > > +	}
> > > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > > +	sa->action[0].conf =
> > > +			&(struct rte_flow_action_queue){
> > > +				.index = sa->fdir_qid,
> > > +	};
> > > +	sa->attr.egress = 0;
> > > +	sa->attr.ingress = 1;
> > > +	if (IS_IP6(sa->flags)) {
> > > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > > +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> > > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > > +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> > > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > > +		sa->pattern[2].spec = &sa->esp_spec;
> > > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > > +	} else if (IS_IP4(sa->flags)) {
> > > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > > +		sa->pattern[2].spec = &sa->esp_spec;
> > > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > > +	}
> > > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > > +
> > > +	ret = rte_flow_validate(sa->portid, &sa->attr,
> > > +				sa->pattern, sa->action,
> > > +				&err);
> > > +	if (ret < 0) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"Flow Validation failed\n");
> > > +		return ret;
> > > +	}
> > > +	sa->flow = rte_flow_create(sa->portid,
> > > +				&sa->attr, sa->pattern, sa->action,
> > > +				&err);
> > > +	if (!sa->flow) {
> > > +		RTE_LOG(ERR, IPSEC,
> > > +			"Flow Creation failed\n");
> > > +		return -1;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  /*
> > >   * queue crypto-ops into PMD queue.
> > >   */
> > > diff --git a/examples/ipsec-secgw/ipsec.h 
> > > b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..b0e9f45cb 100644
> > > --- a/examples/ipsec-secgw/ipsec.h
> > > +++ b/examples/ipsec-secgw/ipsec.h
> > > @@ -144,6 +144,8 @@ struct ipsec_sa {
> > >  	};
> > >  	enum rte_security_ipsec_sa_direction direction;
> > >  	uint16_t portid;
> > > +	uint8_t fdir_qid;
> > > +	uint8_t fdir_flag;
> > >
> > >  #define MAX_RTE_FLOW_PATTERN (4)
> > >  #define MAX_RTE_FLOW_ACTIONS (3)
> > > @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx 
> > > *ipsec_ctx, struct ipsec_sa *sa,  int  
> > > create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
> > >  		struct rte_ipsec_session *ips);
> > > +int
> > > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > > +
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> > >
> > > +int
> > > +check_fdir_configured(uint16_t portid);
> > >  #endif /* __IPSEC_H__ */
> > > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> > > index 0eb52d141..ddd275142 100644
> > > --- a/examples/ipsec-secgw/sa.c
> > > +++ b/examples/ipsec-secgw/sa.c
> > > @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	uint32_t type_p = 0;
> > >  	uint32_t portid_p = 0;
> > >  	uint32_t fallback_p = 0;
> > > +	int16_t status_p = 0;
> > >
> > >  	if (strcmp(tokens[0], "in") == 0) {
> > >  		ri = &nb_sa_in;
> > > @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	if (atoi(tokens[1]) == INVALID_SPI)
> > >  		return;
> > >  	rule->spi = atoi(tokens[1]);
> > > +	rule->portid = UINT16_MAX;
> > >  	ips = ipsec_get_primary_session(rule);
> > >
> > >  	for (ti = 2; ti < n_tokens; ti++) { @@ -636,9 +638,14 @@ 
> > > parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > >  			if (status->status < 0)
> > >  				return;
> > > -			rule->portid = atoi(tokens[ti]);
> > > -			if (status->status < 0)
> > > +			if (rule->portid == UINT16_MAX)
> > > +				rule->portid = atoi(tokens[ti]);
> > > +			else if (rule->portid != atoi(tokens[ti])) {
> > > +				APP_CHECK(0, status, "portid %s "
> > > +				"not matching with already assigned portid
> > %u",
> > > +				tokens[ti], rule->portid);
> > >  				return;
> > > +			}
> > >  			portid_p = 1;
> > >  			continue;
> > >  		}
> > > @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  			fallback_p = 1;
> > >  			continue;
> > >  		}
> > > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > > +			if (ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> > > +				ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> > > +				ips->type ==
> > > +
> > > 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> > > +				APP_CHECK(0, status, "Flow Director not "
> > > +					"supported for security session "
> > > +					"type:%d", ips->type);
> > > +					return;
> > > +			}
> > It means it is supported in cpu crypto as well? 
[Praveen] As of now we have validated only on "RTE_SECURITY_ACTION_TYPE_NONE" and CPU crypto is independent of the IO device similar to action type NONE.
And also it should be supported in other crypto devices as well but we have not included them here because we have not validated.

> >Better to have a check for the supported Action types, as in the future there may be some other action types.
[Praveen] We will fix this in V4.

> >
> > > +			rule->fdir_flag = 1;
> > > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > > +			if (status->status < 0)
> > > +				return;
> > > +			if (rule->portid == UINT16_MAX)
> > > +				rule->portid = atoi(tokens[ti]);
> > > +			else if (rule->portid != atoi(tokens[ti])) {
> > > +				APP_CHECK(0, status, "portid %s "
> > > +				"not matching with already assigned portid
> > %u",
> > > +				tokens[ti], rule->portid);
> > > +				return;
> > > +			}
> > > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > > +			if (status->status < 0)
> > > +				return;
> > > +			rule->fdir_qid = atoi(tokens[ti]);
> > > +			/* validating portid and queueid */
> > > +			status_p = check_flow_params(rule->portid,
> > > +					rule->fdir_qid);
> > > +			if (status_p < 0) {
> > > +				printf("port id %u / queue id %u is not valid\n",
> > > +					rule->portid, rule->fdir_qid);
> > > +			}
> > > +			continue;
> > > +		}
> > >
> > >  		/* unrecognizeable input */
> > >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> > +763,6
> > > @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> > >  	if (!type_p || (!portid_p && ips->type !=
> > >  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
> > >  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> > > -		rule->portid = -1;
> > >  	}
> > >
> > >  	*ri = *ri + 1;
> > > @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, 
> > > int
> > inbound)
> > >  			break;
> > >  		}
> > >  	}
> > > +	if (sa->fdir_flag == 1)
> > > +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> >
> > Better to print like below.
> > printf("flow-direction port %d queue %d ", sa->portid, sa->fdir_qid)

[Praveen] Will do it in V4.

> >
> > > +
> > >  	printf("\n");
> > >  }
> > >

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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
  2020-04-01 13:19     ` Akhil Goyal
@ 2020-04-02 13:39     ` Anoob Joseph
  2020-04-02 17:56       ` Shetty, Praveen
  2020-04-08 14:13     ` [dpdk-dev] [PATCH v4] " Praveen Shetty
  2 siblings, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-04-02 13:39 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty; +Cc: bernard.iremonger, konstantin.ananyev

Hi Praveen,

I've few minor comments. Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Praveen Shetty <praveen.shetty@intel.com>
> Sent: Tuesday, March 31, 2020 6:32 PM
> To: dev@dpdk.org; declan.doherty@intel.com; Anoob Joseph
> <anoobj@marvell.com>
> Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
> 
> External Email
> 
> ----------------------------------------------------------------------
> Support load distribution in security gateway application using NIC load
> distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow to a specified
> queue.This is achieved by extending the SA rule syntax to support specification
> by adding new action_type of <flow-direction> to a specified <port_id>
> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
> v3 changes:
> Incorporated Anoob review comments on v2.
> 
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 55 +++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.c       | 67 +++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       |  9 ++++
>  examples/ipsec-secgw/sa.c          | 72 ++++++++++++++++++++++++++++--
>  5 files changed, 211 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
> index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24
> sport 0:65535 dport 0:65535  sp ipv4 in esp protect 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
> sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
> @@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
> @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa in
> 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index ce36e6d9c..4400b075c 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> ipsec_poll_mode_worker(void)
>  	}
>  }
> 
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6 +2859,15
> @@ main(int32_t argc, char **argv)
> 
>  		sa_check_offloads(portid, &req_rx_offloads[portid],
>  				&req_tx_offloads[portid]);
> +		 /* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}
>  		port_init(portid, req_rx_offloads[portid],
>  				req_tx_offloads[portid]);
>  	}
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index
> d40657102..76ee9dbcf 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */

[Anoob] Any reason why this is not relevant for Egress. 

As for the code I would suggest something like,
	/* No flow director rules for Egress traffic */
	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
		return 0;

	...
 
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");

[Anoob] Is the ending : required in the line above? And do might need a \n?

Also, why is one case returning 0 (EGRESS) and another (TRANSPORT) is returning -1? One is treated as error and other is not?
 
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");

[Anoob] The above should fit into one line. Also V should be small.
 
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);

[Anoob] Start breaking into multiple lines when you exceed 80 char limits. In the earlier line, &sa->attr should fit into the line above.

Also, having a blank line above rte_flow_create() line would be good.
 
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");

[Anoob] Above should fit into one line. Also C should be small.

> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index f8f29f9b1..b0e9f45cb 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -144,6 +144,8 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx,
> struct ipsec_sa *sa,  int  create_inline_session(struct socket_ctx *skt_ctx, struct
> ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int
> +check_fdir_configured(uint16_t portid);
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index
> 0eb52d141..ddd275142 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (atoi(tokens[1]) == INVALID_SPI)
>  		return;
>  	rule->spi = atoi(tokens[1]);
> +	rule->portid = UINT16_MAX;
>  	ips = ipsec_get_primary_session(rule);
> 
>  	for (ti = 2; ti < n_tokens; ti++) {
> @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -			rule->portid = atoi(tokens[ti]);
> -			if (status->status < 0)
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid
> %u",
> +				tokens[ti], rule->portid);
>  				return;

[Anoob] Alignment for APP_CHECK's broken up parts are not following the convention.

> +			}
>  			portid_p = 1;
>  			continue;
>  		}
> @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				APP_CHECK(0, status, "Flow Director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +					return;
> +			}
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid
> %u",
> +				tokens[ti], rule->portid);
> +				return;
> +			}
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> +763,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (!type_p || (!portid_p && ips->type !=
>  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
>  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> -		rule->portid = -1;
>  	}
> 
>  	*ri = *ri + 1;
> @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1141,6 +1187,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			}
>  		}
> 
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");

[Anoob] Instead of function name, can you give the description of what actually failed?

> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1243,6 +1295,20 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct
> rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid)
> +{
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-02 13:39     ` [dpdk-dev] [EXT] " Anoob Joseph
@ 2020-04-02 17:56       ` Shetty, Praveen
  2020-04-03  5:14         ` Anoob Joseph
  0 siblings, 1 reply; 26+ messages in thread
From: Shetty, Praveen @ 2020-04-02 17:56 UTC (permalink / raw)
  To: Anoob Joseph, dev, Doherty, Declan, Akhil Goyal
  Cc: Iremonger, Bernard, Ananyev, Konstantin


Hi Anoob,

See my response inline.

Regards,
Praveen

-----Original Message-----
From: Anoob Joseph <anoobj@marvell.com> 
Sent: Thursday, April 2, 2020 7:09 PM
To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature

Hi Praveen,

I've few minor comments. Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Praveen Shetty <praveen.shetty@intel.com>
> Sent: Tuesday, March 31, 2020 6:32 PM
> To: dev@dpdk.org; declan.doherty@intel.com; Anoob Joseph 
> <anoobj@marvell.com>
> Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> Subject: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director 
> feature
> 
> External Email
> 
> ----------------------------------------------------------------------
> Support load distribution in security gateway application using NIC 
> load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow to 
> a specified queue.This is achieved by extending the SA rule syntax to 
> support specification by adding new action_type of <flow-direction> to 
> a specified <port_id> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> ---
> v3 changes:
> Incorporated Anoob review comments on v2.
> 
>  examples/ipsec-secgw/ep0.cfg       | 11 +++++
>  examples/ipsec-secgw/ipsec-secgw.c | 55 +++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.c       | 67 +++++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h       |  9 ++++
>  examples/ipsec-secgw/sa.c          | 72 ++++++++++++++++++++++++++++--
>  5 files changed, 211 insertions(+), 3 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg 
> b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 
> 192.168.186.0/24 sport
> 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 
> 192.168.210.0/24 sport
> 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 
> 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 
> 115 pri 1 dst
> 192.168.210.0/24 sport 0:65535 dport 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
> +dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 
> dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 
> sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst 
> 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6 
> in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 
> 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> +0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 
> 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 
> 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa 
> in
> 126 cipher_algo aes-128-cbc cipher_key 
> 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> secgw/ipsec-secgw.c index ce36e6d9c..4400b075c 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
>  	.txmode = {
>  		.mq_mode = ETH_MQ_TX_NONE,
>  	},
> +	.fdir_conf = {
> +	.mode = RTE_FDIR_MODE_NONE,
> +	.pballoc = RTE_FDIR_PBALLOC_64K,
> +	.status = RTE_FDIR_REPORT_STATUS,
> +	.mask = {
> +		.vlan_tci_mask = 0xFFEF,
> +		.ipv4_mask     = {
> +			.src_ip = 0xFFFFFFFF,
> +			.dst_ip = 0xFFFFFFFF,
> +		},
> +		.ipv6_mask     = {
> +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> +						0xFFFFFFFF},
> +		},
> +		.src_port_mask = 0xFFFF,
> +		.dst_port_mask = 0xFFFF,
> +		.mac_addr_byte_mask = 0xFF,
> +		.tunnel_type_mask = 1,
> +		.tunnel_id_mask = 0xFFFFFFFF,
> +	},
> +	.drop_queue = 127,
> +	}
>  };
> 
>  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> ipsec_poll_mode_worker(void)
>  	}
>  }
> 
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6 
> +2859,15 @@ main(int32_t argc, char **argv)
> 
>  		sa_check_offloads(portid, &req_rx_offloads[portid],
>  				&req_tx_offloads[portid]);
> +		 /* check if FDIR is configured on the port */
> +		if (check_fdir_configured(portid)) {
> +			/* Enable FDIR */
> +			port_conf.fdir_conf.mode =
> RTE_FDIR_MODE_PERFECT;
> +			/* Disable RSS */
> +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> +		}
>  		port_init(portid, req_rx_offloads[portid],
>  				req_tx_offloads[portid]);
>  	}
> diff --git a/examples/ipsec-secgw/ipsec.c 
> b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, 
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> +		return 0; /* No Flow director rules for Egress traffic */

[Anoob] Any reason why this is not relevant for Egress. 

[Praveen] we don't see an use case for load distribution across ingress queues for outbound IPsec traffic therefore we have limited this configuration to inbound IPsec processing, as this is the only use case we can verify.

As for the code I would suggest something like,
	/* No flow director rules for Egress traffic */
	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
		return 0;

	...
 
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode:");

[Anoob] Is the ending : required in the line above? And do might need a \n?

[Praveen] Will fix this in v4.

Also, why is one case returning 0 (EGRESS) and another (TRANSPORT) is returning -1? One is treated as error and other is not?

[Praveen] It should be -1(error) for both the cases , will fix this in v4.

 
> +			return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};
> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->portid, &sa->attr,
> +				sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Validation failed\n");

[Anoob] The above should fit into one line. Also V should be small.

[Praveen] Okay. Will fix this in v4.
 
> +		return ret;
> +	}
> +	sa->flow = rte_flow_create(sa->portid,
> +				&sa->attr, sa->pattern, sa->action,
> +				&err);

[Anoob] Start breaking into multiple lines when you exceed 80 char limits. In the earlier line, &sa->attr should fit into the line above.

Also, having a blank line above rte_flow_create() line would be good.

[Praveen] Okay. Will fix it in v4
 
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC,
> +			"Flow Creation failed\n");

[Anoob] Above should fit into one line. Also C should be small.

[Praveen] okay. Will fix this in v4.

> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h 
> b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..b0e9f45cb 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -144,6 +144,8 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx 
> *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct 
> socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
> +int
> +check_fdir_configured(uint16_t portid);
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> index
> 0eb52d141..ddd275142 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (atoi(tokens[1]) == INVALID_SPI)
>  		return;
>  	rule->spi = atoi(tokens[1]);
> +	rule->portid = UINT16_MAX;
>  	ips = ipsec_get_primary_session(rule);
> 
>  	for (ti = 2; ti < n_tokens; ti++) {
> @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -			rule->portid = atoi(tokens[ti]);
> -			if (status->status < 0)
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid
> %u",
> +				tokens[ti], rule->portid);
>  				return;

[Anoob] Alignment for APP_CHECK's broken up parts are not following the convention.

[Praveen] Will fix this in v4.

> +			}
>  			portid_p = 1;
>  			continue;
>  		}
> @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> +				ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				APP_CHECK(0, status, "Flow Director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +					return;
> +			}
> +			rule->fdir_flag = 1;
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s "
> +				"not matching with already assigned portid
> %u",
> +				tokens[ti], rule->portid);
> +				return;
> +			}
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->fdir_qid = atoi(tokens[ti]);
> +			/* validating portid and queueid */
> +			status_p = check_flow_params(rule->portid,
> +					rule->fdir_qid);
> +			if (status_p < 0) {
> +				printf("port id %u / queue id %u is not valid\n",
> +					rule->portid, rule->fdir_qid);
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> +763,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (!type_p || (!portid_p && ips->type !=
>  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
>  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> -		rule->portid = -1;
>  	}
> 
>  	*ri = *ri + 1;
> @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1141,6 +1187,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const 
> struct ipsec_sa entries[],
>  			}
>  		}
> 
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp flow failed\n");

[Anoob] Instead of function name, can you give the description of what actually failed?

[Praveen] Can be done , will do it in v4.

> +			}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> @@ -1243,6 +1295,20 @@ fill_ipsec_session(struct rte_ipsec_session 
> *ss, struct rte_ipsec_sa *sa)
>  	return rc;
>  }
> 
> +int
> +check_fdir_configured(uint16_t portid) {
> +	struct ipsec_sa *sa = NULL;
> +	uint32_t idx_sa = 0;
> +
> +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> +		sa = &sa_in[idx_sa];
> +		if (sa->portid == portid)
> +			return sa->fdir_flag;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * Initialise related rte_ipsec_sa object.
>   */
> --
> 2.17.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-02 17:56       ` Shetty, Praveen
@ 2020-04-03  5:14         ` Anoob Joseph
  2020-04-03  5:52           ` Akhil Goyal
  0 siblings, 1 reply; 26+ messages in thread
From: Anoob Joseph @ 2020-04-03  5:14 UTC (permalink / raw)
  To: Shetty, Praveen, dev, Doherty, Declan, Akhil Goyal
  Cc: Iremonger, Bernard, Ananyev, Konstantin

Hi Praveen,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Shetty, Praveen <praveen.shetty@intel.com>
> Sent: Thursday, April 2, 2020 11:27 PM
> To: Anoob Joseph <anoobj@marvell.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>; Akhil Goyal <akhil.goyal@nxp.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director
> feature
> 
> 
> Hi Anoob,
> 
> See my response inline.
> 
> Regards,
> Praveen
> 
> -----Original Message-----
> From: Anoob Joseph <anoobj@marvell.com>
> Sent: Thursday, April 2, 2020 7:09 PM
> To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty,
> Declan <declan.doherty@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director
> feature
> 
> Hi Praveen,
> 
> I've few minor comments. Please see inline.
> 
> Thanks,
> Anoob
> 
> > -----Original Message-----
> > From: Praveen Shetty <praveen.shetty@intel.com>
> > Sent: Tuesday, March 31, 2020 6:32 PM
> > To: dev@dpdk.org; declan.doherty@intel.com; Anoob Joseph
> > <anoobj@marvell.com>
> > Cc: bernard.iremonger@intel.com; konstantin.ananyev@intel.com
> > Subject: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director
> > feature
> >
> > External Email
> >
> > ----------------------------------------------------------------------
> > Support load distribution in security gateway application using NIC
> > load distribution feature(Flow Director).
> > Flow Director is used to redirect the specified inbound ipsec flow to
> > a specified queue.This is achieved by extending the SA rule syntax to
> > support specification by adding new action_type of <flow-direction> to
> > a specified <port_id> <queue_id>.
> >
> > Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> > ---
> > v3 changes:
> > Incorporated Anoob review comments on v2.
> >
> >  examples/ipsec-secgw/ep0.cfg       | 11 +++++
> >  examples/ipsec-secgw/ipsec-secgw.c | 55 +++++++++++++++++++++++
> >  examples/ipsec-secgw/ipsec.c       | 67 +++++++++++++++++++++++++++
> >  examples/ipsec-secgw/ipsec.h       |  9 ++++
> >  examples/ipsec-secgw/sa.c          | 72 ++++++++++++++++++++++++++++--
> >  5 files changed, 211 insertions(+), 3 deletions(-)
> >
> > diff --git a/examples/ipsec-secgw/ep0.cfg
> > b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..6f8d5aa53 100644
> > --- a/examples/ipsec-secgw/ep0.cfg
> > +++ b/examples/ipsec-secgw/ep0.cfg
> > @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst
> > 192.168.186.0/24 sport
> > 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst
> > 192.168.210.0/24 sport
> > 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst
> > 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect
> > 115 pri 1 dst
> > 192.168.210.0/24 sport 0:65535 dport 0:65535
> > +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535
> > +dport 0:65535
> >  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535
> > dport 0:65535 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24
> > sport 0:65535 dport 0:65535 sp ipv4 in esp protect 126 pri 1 dst
> > 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6
> > in esp protect 125 pri 1 dst
> > ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
> >  sport 0:65535 dport 0:65535
> >  sp ipv6 in esp protect 126 pri 1 dst
> > ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport
> > 0:65535
> > +sp ipv6 in esp protect 127 pri 1 dst
> > +ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport
> > +0:65535
> >
> >  #SA rules
> >  sa out 5 cipher_algo aes-128-cbc cipher_key
> > 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> >
> >  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src
> > 172.16.2.6 dst
> > 172.16.1.6
> >
> > +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src
> > +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> > +
> >  sa in 125 cipher_algo aes-128-cbc cipher_key
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> > c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
> >  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa
> > in
> > 126 cipher_algo aes-128-cbc cipher_key
> > 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
> >  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst
> > 1111:1111:1111:1111:1111:1111:1111:6666
> >
> > +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src
> > +2222:2222:2222:2222:2222:2222:2222:7777 \ dst
> > +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> > +
> >  #Routing rules
> >  rt ipv4 dst 172.16.2.5/32 port 0
> >  rt ipv4 dst 172.16.2.6/32 port 1
> > diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> > secgw/ipsec-secgw.c index ce36e6d9c..4400b075c 100644
> > --- a/examples/ipsec-secgw/ipsec-secgw.c
> > +++ b/examples/ipsec-secgw/ipsec-secgw.c
> > @@ -246,6 +246,30 @@ static struct rte_eth_conf port_conf = {
> >  	.txmode = {
> >  		.mq_mode = ETH_MQ_TX_NONE,
> >  	},
> > +	.fdir_conf = {
> > +	.mode = RTE_FDIR_MODE_NONE,
> > +	.pballoc = RTE_FDIR_PBALLOC_64K,
> > +	.status = RTE_FDIR_REPORT_STATUS,
> > +	.mask = {
> > +		.vlan_tci_mask = 0xFFEF,
> > +		.ipv4_mask     = {
> > +			.src_ip = 0xFFFFFFFF,
> > +			.dst_ip = 0xFFFFFFFF,
> > +		},
> > +		.ipv6_mask     = {
> > +			.src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +			.dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
> > +						0xFFFFFFFF},
> > +		},
> > +		.src_port_mask = 0xFFFF,
> > +		.dst_port_mask = 0xFFFF,
> > +		.mac_addr_byte_mask = 0xFF,
> > +		.tunnel_type_mask = 1,
> > +		.tunnel_id_mask = 0xFFFFFFFF,
> > +	},
> > +	.drop_queue = 127,
> > +	}
> >  };
> >
> >  struct socket_ctx socket_ctx[NB_SOCKETS]; @@ -1183,6 +1207,28 @@
> > ipsec_poll_mode_worker(void)
> >  	}
> >  }
> >
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> > +	uint16_t i;
> > +	uint16_t portid;
> > +	uint8_t queueid;
> > +
> > +	for (i = 0; i < nb_lcore_params; ++i) {
> > +		portid = lcore_params_array[i].port_id;
> > +		if (portid == fdir_portid) {
> > +			queueid = lcore_params_array[i].queue_id;
> > +			if (queueid == fdir_qid)
> > +				break;
> > +		}
> > +
> > +		if (i == nb_lcore_params - 1)
> > +			return -1;
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> >  static int32_t
> >  check_poll_mode_params(struct eh_conf *eh_conf)  { @@ -2813,6
> > +2859,15 @@ main(int32_t argc, char **argv)
> >
> >  		sa_check_offloads(portid, &req_rx_offloads[portid],
> >  				&req_tx_offloads[portid]);
> > +		 /* check if FDIR is configured on the port */
> > +		if (check_fdir_configured(portid)) {
> > +			/* Enable FDIR */
> > +			port_conf.fdir_conf.mode =
> > RTE_FDIR_MODE_PERFECT;
> > +			/* Disable RSS */
> > +			port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
> > +			port_conf.rx_adv_conf.rss_conf.rss_hf = 0;
> > +			port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
> > +		}
> >  		port_init(portid, req_rx_offloads[portid],
> >  				req_tx_offloads[portid]);
> >  	}
> > diff --git a/examples/ipsec-secgw/ipsec.c
> > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > --- a/examples/ipsec-secgw/ipsec.c
> > +++ b/examples/ipsec-secgw/ipsec.c
> > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> > struct ipsec_sa *sa,
> >  	return 0;
> >  }
> >
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > +	int ret = 0;
> > +	struct rte_flow_error err;
> > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > +		return 0; /* No Flow director rules for Egress traffic */
> 
> [Anoob] Any reason why this is not relevant for Egress.
> 
> [Praveen] we don't see an use case for load distribution across ingress queues
> for outbound IPsec traffic therefore we have limited this configuration to
> inbound IPsec processing, as this is the only use case we can verify.

[Anoob] Why do you say load distribution for ingress queues is not required but is required for egress? I would say the use case is the same in either direction.

Said that, adding just egress should be fine. I leave this to Akhil's judgement.

> 
> As for the code I would suggest something like,
> 	/* No flow director rules for Egress traffic */
> 	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> 		return 0;
> 
> 	...
> 
> > +	if (sa->flags == TRANSPORT) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"No Flow director rule for transport mode:");
> 
> [Anoob] Is the ending : required in the line above? And do might need a \n?
> 
> [Praveen] Will fix this in v4.
> 
> Also, why is one case returning 0 (EGRESS) and another (TRANSPORT) is
> returning -1? One is treated as error and other is not?
> 
> [Praveen] It should be -1(error) for both the cases , will fix this in v4.
> 
> 
> > +			return -1;
> > +	}
> > +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> > +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> > +	sa->action[0].conf =
> > +			&(struct rte_flow_action_queue){
> > +				.index = sa->fdir_qid,
> > +	};
> > +	sa->attr.egress = 0;
> > +	sa->attr.ingress = 1;
> > +	if (IS_IP6(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> > +		sa->pattern[1].spec = &sa->ipv6_spec;
> > +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> > +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> > +		memcpy(sa->ipv6_spec.hdr.src_addr,
> > +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	} else if (IS_IP4(sa->flags)) {
> > +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> > +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> > +		sa->pattern[1].spec = &sa->ipv4_spec;
> > +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> > +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> > +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> > +		sa->pattern[2].spec = &sa->esp_spec;
> > +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> > +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> > +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> > +	}
> > +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> > +
> > +	ret = rte_flow_validate(sa->portid, &sa->attr,
> > +				sa->pattern, sa->action,
> > +				&err);
> > +	if (ret < 0) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Validation failed\n");
> 
> [Anoob] The above should fit into one line. Also V should be small.
> 
> [Praveen] Okay. Will fix this in v4.
> 
> > +		return ret;
> > +	}
> > +	sa->flow = rte_flow_create(sa->portid,
> > +				&sa->attr, sa->pattern, sa->action,
> > +				&err);
> 
> [Anoob] Start breaking into multiple lines when you exceed 80 char limits. In the
> earlier line, &sa->attr should fit into the line above.
> 
> Also, having a blank line above rte_flow_create() line would be good.
> 
> [Praveen] Okay. Will fix it in v4
> 
> > +	if (!sa->flow) {
> > +		RTE_LOG(ERR, IPSEC,
> > +			"Flow Creation failed\n");
> 
> [Anoob] Above should fit into one line. Also C should be small.
> 
> [Praveen] okay. Will fix this in v4.
> 
> > +		return -1;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * queue crypto-ops into PMD queue.
> >   */
> > diff --git a/examples/ipsec-secgw/ipsec.h
> > b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..b0e9f45cb 100644
> > --- a/examples/ipsec-secgw/ipsec.h
> > +++ b/examples/ipsec-secgw/ipsec.h
> > @@ -144,6 +144,8 @@ struct ipsec_sa {
> >  	};
> >  	enum rte_security_ipsec_sa_direction direction;
> >  	uint16_t portid;
> > +	uint8_t fdir_qid;
> > +	uint8_t fdir_flag;
> >
> >  #define MAX_RTE_FLOW_PATTERN (4)
> >  #define MAX_RTE_FLOW_ACTIONS (3)
> > @@ -408,5 +410,12 @@ create_lookaside_session(struct ipsec_ctx
> > *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct
> > socket_ctx *skt_ctx, struct ipsec_sa *sa,
> >  		struct rte_ipsec_session *ips);
> > +int
> > +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> > +
> > +int
> > +create_ipsec_esp_flow(struct ipsec_sa *sa);
> >
> > +int
> > +check_fdir_configured(uint16_t portid);
> >  #endif /* __IPSEC_H__ */
> > diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> > index
> > 0eb52d141..ddd275142 100644
> > --- a/examples/ipsec-secgw/sa.c
> > +++ b/examples/ipsec-secgw/sa.c
> > @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	uint32_t type_p = 0;
> >  	uint32_t portid_p = 0;
> >  	uint32_t fallback_p = 0;
> > +	int16_t status_p = 0;
> >
> >  	if (strcmp(tokens[0], "in") == 0) {
> >  		ri = &nb_sa_in;
> > @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	if (atoi(tokens[1]) == INVALID_SPI)
> >  		return;
> >  	rule->spi = atoi(tokens[1]);
> > +	rule->portid = UINT16_MAX;
> >  	ips = ipsec_get_primary_session(rule);
> >
> >  	for (ti = 2; ti < n_tokens; ti++) {
> > @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> >  			if (status->status < 0)
> >  				return;
> > -			rule->portid = atoi(tokens[ti]);
> > -			if (status->status < 0)
> > +			if (rule->portid == UINT16_MAX)
> > +				rule->portid = atoi(tokens[ti]);
> > +			else if (rule->portid != atoi(tokens[ti])) {
> > +				APP_CHECK(0, status, "portid %s "
> > +				"not matching with already assigned portid
> > %u",
> > +				tokens[ti], rule->portid);
> >  				return;
> 
> [Anoob] Alignment for APP_CHECK's broken up parts are not following the
> convention.
> 
> [Praveen] Will fix this in v4.
> 
> > +			}
> >  			portid_p = 1;
> >  			continue;
> >  		}
> > @@ -681,6 +688,43 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  			fallback_p = 1;
> >  			continue;
> >  		}
> > +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> > +			if (ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
> > +				ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
> > +				ips->type ==
> > +
> > 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> > +				APP_CHECK(0, status, "Flow Director not "
> > +					"supported for security session "
> > +					"type:%d", ips->type);
> > +					return;
> > +			}
> > +			rule->fdir_flag = 1;
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			if (rule->portid == UINT16_MAX)
> > +				rule->portid = atoi(tokens[ti]);
> > +			else if (rule->portid != atoi(tokens[ti])) {
> > +				APP_CHECK(0, status, "portid %s "
> > +				"not matching with already assigned portid
> > %u",
> > +				tokens[ti], rule->portid);
> > +				return;
> > +			}
> > +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> > +			if (status->status < 0)
> > +				return;
> > +			rule->fdir_qid = atoi(tokens[ti]);
> > +			/* validating portid and queueid */
> > +			status_p = check_flow_params(rule->portid,
> > +					rule->fdir_qid);
> > +			if (status_p < 0) {
> > +				printf("port id %u / queue id %u is not valid\n",
> > +					rule->portid, rule->fdir_qid);
> > +			}
> > +			continue;
> > +		}
> >
> >  		/* unrecognizeable input */
> >  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -719,7
> > +763,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
> >  	if (!type_p || (!portid_p && ips->type !=
> >  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
> >  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> > -		rule->portid = -1;
> >  	}
> >
> >  	*ri = *ri + 1;
> > @@ -823,6 +866,9 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> > inbound)
> >  			break;
> >  		}
> >  	}
> > +	if (sa->fdir_flag == 1)
> > +		printf("flow-direction %d %d", sa->portid, sa->fdir_qid);
> > +
> >  	printf("\n");
> >  }
> >
> > @@ -1141,6 +1187,12 @@ sa_add_rules(struct sa_ctx *sa_ctx, const
> > struct ipsec_sa entries[],
> >  			}
> >  		}
> >
> > +		if (sa->fdir_flag && inbound) {
> > +			rc = create_ipsec_esp_flow(sa);
> > +			if (rc != 0)
> > +				RTE_LOG(ERR, IPSEC_ESP,
> > +					"create_ipsec_esp flow failed\n");
> 
> [Anoob] Instead of function name, can you give the description of what actually
> failed?
> 
> [Praveen] Can be done , will do it in v4.
> 
> > +			}
> >  		print_one_sa_rule(sa, inbound);
> >  	}
> >
> > @@ -1243,6 +1295,20 @@ fill_ipsec_session(struct rte_ipsec_session
> > *ss, struct rte_ipsec_sa *sa)
> >  	return rc;
> >  }
> >
> > +int
> > +check_fdir_configured(uint16_t portid) {
> > +	struct ipsec_sa *sa = NULL;
> > +	uint32_t idx_sa = 0;
> > +
> > +	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
> > +		sa = &sa_in[idx_sa];
> > +		if (sa->portid == portid)
> > +			return sa->fdir_flag;
> > +	}
> > +	return 0;
> > +}
> > +
> >  /*
> >   * Initialise related rte_ipsec_sa object.
> >   */
> > --
> > 2.17.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-03  5:14         ` Anoob Joseph
@ 2020-04-03  5:52           ` Akhil Goyal
  2020-04-03 10:21             ` Shetty, Praveen
  0 siblings, 1 reply; 26+ messages in thread
From: Akhil Goyal @ 2020-04-03  5:52 UTC (permalink / raw)
  To: Anoob Joseph, Shetty, Praveen, dev, Doherty, Declan
  Cc: Iremonger, Bernard, Ananyev, Konstantin

> > > diff --git a/examples/ipsec-secgw/ipsec.c
> > > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > > --- a/examples/ipsec-secgw/ipsec.c
> > > +++ b/examples/ipsec-secgw/ipsec.c
> > > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> > > struct ipsec_sa *sa,
> > >  	return 0;
> > >  }
> > >
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > > +	int ret = 0;
> > > +	struct rte_flow_error err;
> > > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > > +		return 0; /* No Flow director rules for Egress traffic */
> >
> > [Anoob] Any reason why this is not relevant for Egress.
> >
> > [Praveen] we don't see an use case for load distribution across ingress queues
> > for outbound IPsec traffic therefore we have limited this configuration to
> > inbound IPsec processing, as this is the only use case we can verify.
> 
> [Anoob] Why do you say load distribution for ingress queues is not required but
> is required for egress? I would say the use case is the same in either direction.
> 
> Said that, adding just egress should be fine. I leave this to Akhil's judgement.
> 

I believe it does not matter for EGRESS in most hardwares,
INGRESS flows should have distribution. I think your comments are just reverse but
The code is inline with my understanding.


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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-03  5:52           ` Akhil Goyal
@ 2020-04-03 10:21             ` Shetty, Praveen
  2020-04-03 10:28               ` Anoob Joseph
  0 siblings, 1 reply; 26+ messages in thread
From: Shetty, Praveen @ 2020-04-03 10:21 UTC (permalink / raw)
  To: Akhil Goyal, Anoob Joseph, dev, Doherty, Declan
  Cc: Iremonger, Bernard, Ananyev, Konstantin



-----Original Message-----
From: Akhil Goyal <akhil.goyal@nxp.com> 
Sent: Friday, April 3, 2020 11:22 AM
To: Anoob Joseph <anoobj@marvell.com>; Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature

> > > diff --git a/examples/ipsec-secgw/ipsec.c 
> > > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > > --- a/examples/ipsec-secgw/ipsec.c
> > > +++ b/examples/ipsec-secgw/ipsec.c
> > > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx 
> > > *skt_ctx, struct ipsec_sa *sa,
> > >  	return 0;
> > >  }
> > >
> > > +int
> > > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > > +	int ret = 0;
> > > +	struct rte_flow_error err;
> > > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > > +		return 0; /* No Flow director rules for Egress traffic */
> >
> > [Anoob] Any reason why this is not relevant for Egress.
> >
> > [Praveen] we don't see an use case for load distribution across 
> > ingress queues for outbound IPsec traffic therefore we have limited 
> > this configuration to inbound IPsec processing, as this is the only use case we can verify.
> 
> [Anoob] Why do you say load distribution for ingress queues is not 
> required but is required for egress? I would say the use case is the same in either direction.
> 
> Said that, adding just egress should be fine. I leave this to Akhil's judgement.
> 

I believe it does not matter for EGRESS in most hardwares, INGRESS flows should have distribution. I think your comments are just reverse but The code is inline with my understanding.

[Praveen] 
Current implementation is only for ingress traffic load distribution therefore it is applicable only for inbound IPsec traffic.



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

* Re: [dpdk-dev] [EXT] [PATCH v3] examples/ipsec-secgw: support flow director feature
  2020-04-03 10:21             ` Shetty, Praveen
@ 2020-04-03 10:28               ` Anoob Joseph
  0 siblings, 0 replies; 26+ messages in thread
From: Anoob Joseph @ 2020-04-03 10:28 UTC (permalink / raw)
  To: Shetty, Praveen, Akhil Goyal, dev, Doherty, Declan
  Cc: Iremonger, Bernard, Ananyev, Konstantin

Hi Akhil, Praveen,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Shetty, Praveen <praveen.shetty@intel.com>
> Sent: Friday, April 3, 2020 3:51 PM
> To: Akhil Goyal <akhil.goyal@nxp.com>; Anoob Joseph <anoobj@marvell.com>;
> dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director
> feature
> 
> 
> 
> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Friday, April 3, 2020 11:22 AM
> To: Anoob Joseph <anoobj@marvell.com>; Shetty, Praveen
> <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>
> Subject: RE: [EXT] [PATCH v3] examples/ipsec-secgw: support flow director
> feature
> 
> > > > diff --git a/examples/ipsec-secgw/ipsec.c
> > > > b/examples/ipsec-secgw/ipsec.c index d40657102..76ee9dbcf 100644
> > > > --- a/examples/ipsec-secgw/ipsec.c
> > > > +++ b/examples/ipsec-secgw/ipsec.c
> > > > @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx
> > > > *skt_ctx, struct ipsec_sa *sa,
> > > >  	return 0;
> > > >  }
> > > >
> > > > +int
> > > > +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> > > > +	int ret = 0;
> > > > +	struct rte_flow_error err;
> > > > +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
> > > > +		return 0; /* No Flow director rules for Egress traffic */
> > >
> > > [Anoob] Any reason why this is not relevant for Egress.
> > >
> > > [Praveen] we don't see an use case for load distribution across
> > > ingress queues for outbound IPsec traffic therefore we have limited
> > > this configuration to inbound IPsec processing, as this is the only use case we
> can verify.
> >
> > [Anoob] Why do you say load distribution for ingress queues is not
> > required but is required for egress? I would say the use case is the same in
> either direction.
> >
> > Said that, adding just egress should be fine. I leave this to Akhil's judgement.
> >
> 
> I believe it does not matter for EGRESS in most hardwares, INGRESS flows
> should have distribution. I think your comments are just reverse but The code is
> inline with my understanding.
> 
> [Praveen]
> Current implementation is only for ingress traffic load distribution therefore it is
> applicable only for inbound IPsec traffic.
> 

[Anoob] Yes. I got it reverse. Meant egress instead of ingress and the other way round as well.

I was asking for the rationale behind limiting the scope. Anyway, that can be taken up separately.

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

* [dpdk-dev] [PATCH v4] examples/ipsec-secgw: support flow director feature
  2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
  2020-04-01 13:19     ` Akhil Goyal
  2020-04-02 13:39     ` [dpdk-dev] [EXT] " Anoob Joseph
@ 2020-04-08 14:13     ` Praveen Shetty
  2020-04-09 10:09       ` [dpdk-dev] [PATCH v5] " Praveen Shetty
  2 siblings, 1 reply; 26+ messages in thread
From: Praveen Shetty @ 2020-04-08 14:13 UTC (permalink / raw)
  To: dev, declan.doherty, akhil.goyal, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

Support load distribution in security gateway application using
NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow
to a specified queue.This is achieved by extending the SA rule syntax
to support specification by adding new action_type of <flow-direction>
to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v4 changes:
1. Removed flow direction configuration changes as it is not required anymore.
2. Addressed all the review comments from Akhil and Anoob.
3. Included Release doc and Release notes.

 doc/guides/rel_notes/release_20_05.rst   |  4 ++
 doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
 examples/ipsec-secgw/ep0.cfg             | 11 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
 examples/ipsec-secgw/ipsec.c             | 67 ++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h             |  7 +++
 examples/ipsec-secgw/sa.c                | 61 +++++++++++++++++++--
 7 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 6b1a7c58c..a9ec163cf 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -81,6 +81,10 @@ New Features
   by making use of the event device capabilities. The event mode currently supports
   only inline IPsec protocol offload.
 
+* **Updated ipsec-secgw application.**
+
+  Added IPsec inbound load-distribution support for ipsec-secgw application using NIC
+  load distribution feature(Flow Director).
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 038f593f4..12f921d76 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
 
     sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
     <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
+    <flow-direction> <port_id> <queue_id>
 
 where each options means:
 
@@ -698,6 +699,18 @@ where each options means:
 
    * *fallback lookaside-none*
 
+``<flow-direction>``
+
+ * Action type is for redirecting the specific inbound ipsec-flow to
+   a specified queue.
+
+ * Optional: Yes.
+
+ * Available options:
+
+   * *port_id*: Port ID of the NIC for which the SA is configured.
+   * *queue_id*: Queue ID to which traffic should be redirected.
+
 Example SA rules:
 
 .. code-block:: console
@@ -727,6 +740,9 @@ Example SA rules:
     mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
     type inline-crypto-offload port_id 0
 
+    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+    dst 172.16.1.7 flow-direction 0 2
+
 Routing rule syntax
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 5fde4f728..6d02341de 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
 	}
 }
 
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_poll_mode_params(struct eh_conf *eh_conf)
 {
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index d40657102..461fae461 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for Egress traffic\n");
+		return -1;
+	}
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode\n");
+		return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		return ret;
+	}
+
+	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
+					sa->action, &err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index f8f29f9b1..1790a93ca 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -144,6 +144,8 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index a6bf5e8b1..7ed68fb93 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
 	rule->spi = atoi(tokens[1]);
+	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
 
 	for (ti = 2; ti < n_tokens; ti++) {
@@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-			rule->portid = atoi(tokens[ti]);
-			if (status->status < 0)
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s not matching "
+					"with already assigned portid %u",
+					tokens[ti], rule->portid);
 				return;
+			}
 			portid_p = 1;
 			continue;
 		}
@@ -683,6 +690,44 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_NONE ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+				printf("flow director supported for security "
+					"session type:%d\n", ips->type);
+			} else {
+				APP_CHECK(0, status, "flow director not "
+					"supported for security session "
+					"type:%d", ips->type);
+				return;
+			}
+			rule->fdir_flag = 1;
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s "
+					"not matching with already assigned "
+					"portid %u", tokens[ti], rule->portid);
+				return;
+			}
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->fdir_qid = atoi(tokens[ti]);
+			/* validating portid and queueid */
+			status_p = check_flow_params(rule->portid,
+					rule->fdir_qid);
+			if (status_p < 0) {
+				printf("port id %u / queue id %u is not valid\n",
+					rule->portid, rule->fdir_qid);
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -721,7 +766,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (!type_p || (!portid_p && ips->type !=
 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
-		rule->portid = -1;
 	}
 
 	*ri = *ri + 1;
@@ -825,6 +869,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction port %d queue %d", sa->portid,
+				sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1143,6 +1191,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			}
 		}
 
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp_flow() failed %s\n",
+					strerror(rc));
+		}
 		print_one_sa_rule(sa, inbound);
 	}
 
-- 
2.17.1


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

* [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support flow director feature
  2020-04-08 14:13     ` [dpdk-dev] [PATCH v4] " Praveen Shetty
@ 2020-04-09 10:09       ` Praveen Shetty
  2020-04-14  7:33         ` Shetty, Praveen
                           ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Praveen Shetty @ 2020-04-09 10:09 UTC (permalink / raw)
  To: dev, declan.doherty, akhil.goyal, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

Support load distribution in security gateway application using
NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow
to a specified queue.This is achieved by extending the SA rule syntax
to support specification by adding new action_type of <flow-direction>
to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v5 changes:
Small change in condtional handling in sa.c file.

v4 changes:
1. Removed flow director configuration changes as they are not 
   required anymore.
2. Addressed all the review comments from Akhil and Anoob.
3. Included update to the ipsec-secgw user guide and update to release notes.

 doc/guides/rel_notes/release_20_05.rst   |  4 ++
 doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
 examples/ipsec-secgw/ep0.cfg             | 11 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
 examples/ipsec-secgw/ipsec.c             | 67 ++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h             |  7 +++
 examples/ipsec-secgw/sa.c                | 63 ++++++++++++++++++++--
 7 files changed, 186 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 6b1a7c58c..a9ec163cf 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -81,6 +81,10 @@ New Features
   by making use of the event device capabilities. The event mode currently supports
   only inline IPsec protocol offload.
 
+* **Updated ipsec-secgw application.**
+
+  Added IPsec inbound load-distribution support for ipsec-secgw application using NIC
+  load distribution feature(Flow Director).
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 038f593f4..12f921d76 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
 
     sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
     <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
+    <flow-direction> <port_id> <queue_id>
 
 where each options means:
 
@@ -698,6 +699,18 @@ where each options means:
 
    * *fallback lookaside-none*
 
+``<flow-direction>``
+
+ * Action type is for redirecting the specific inbound ipsec-flow to
+   a specified queue.
+
+ * Optional: Yes.
+
+ * Available options:
+
+   * *port_id*: Port ID of the NIC for which the SA is configured.
+   * *queue_id*: Queue ID to which traffic should be redirected.
+
 Example SA rules:
 
 .. code-block:: console
@@ -727,6 +740,9 @@ Example SA rules:
     mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
     type inline-crypto-offload port_id 0
 
+    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+    dst 172.16.1.7 flow-direction 0 2
+
 Routing rule syntax
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 5fde4f728..6d02341de 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
 	}
 }
 
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_poll_mode_params(struct eh_conf *eh_conf)
 {
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index d40657102..461fae461 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for Egress traffic\n");
+		return -1;
+	}
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode\n");
+		return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		return ret;
+	}
+
+	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
+					sa->action, &err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index f8f29f9b1..1790a93ca 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -144,6 +144,8 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index a6bf5e8b1..06bb25b3e 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
 	rule->spi = atoi(tokens[1]);
+	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
 
 	for (ti = 2; ti < n_tokens; ti++) {
@@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-			rule->portid = atoi(tokens[ti]);
-			if (status->status < 0)
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s not matching "
+					"with already assigned portid %u",
+					tokens[ti], rule->portid);
 				return;
+			}
 			portid_p = 1;
 			continue;
 		}
@@ -683,6 +690,44 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_NONE ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+				rule->fdir_flag = 1;
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (rule->portid == UINT16_MAX)
+					rule->portid = atoi(tokens[ti]);
+				else if (rule->portid != atoi(tokens[ti])) {
+					APP_CHECK(0, status, "portid %s "
+						"not matching with already "
+						"assigned portid %u",
+						tokens[ti], rule->portid);
+					return;
+				}
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				rule->fdir_qid = atoi(tokens[ti]);
+				/* validating portid and queueid */
+				status_p = check_flow_params(rule->portid,
+						rule->fdir_qid);
+				if (status_p < 0) {
+					printf("port id %u / queue id %u is "
+						"not valid\n", rule->portid,
+						 rule->fdir_qid);
+				}
+			} else {
+				APP_CHECK(0, status, "flow director not "
+					"supported for security session "
+					"type:%d", ips->type);
+				return;
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -721,7 +766,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (!type_p || (!portid_p && ips->type !=
 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
-		rule->portid = -1;
 	}
 
 	*ri = *ri + 1;
@@ -806,7 +850,7 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 		printf("lookaside-protocol-offload ");
 		break;
 	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
-		printf("cpu-crypto-accelerated");
+		printf("cpu-crypto-accelerated ");
 		break;
 	}
 
@@ -825,6 +869,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction port %d queue %d", sa->portid,
+				sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1143,6 +1191,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			}
 		}
 
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp_flow() failed %s\n",
+					strerror(rc));
+		}
 		print_one_sa_rule(sa, inbound);
 	}
 
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support flow director feature
  2020-04-09 10:09       ` [dpdk-dev] [PATCH v5] " Praveen Shetty
@ 2020-04-14  7:33         ` Shetty, Praveen
  2020-04-15 18:59         ` Akhil Goyal
  2020-04-16 16:47         ` [dpdk-dev] [PATCH v6] " Praveen Shetty
  2 siblings, 0 replies; 26+ messages in thread
From: Shetty, Praveen @ 2020-04-14  7:33 UTC (permalink / raw)
  To: dev, Doherty, Declan, akhil.goyal, anoobj
  Cc: Iremonger, Bernard, Ananyev, Konstantin

Hi Akhil/Anoob

Do you have any further review comments ?

Regards,
Praveen

-----Original Message-----
From: dev <dev-bounces@dpdk.org> On Behalf Of Praveen Shetty
Sent: Thursday, April 9, 2020 3:40 PM
To: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; akhil.goyal@nxp.com; anoobj@marvell.com
Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support flow director feature

Support load distribution in security gateway application using NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow to a specified queue.This is achieved by extending the SA rule syntax to support specification by adding new action_type of <flow-direction> to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
---
v5 changes:
Small change in condtional handling in sa.c file.

v4 changes:
1. Removed flow director configuration changes as they are not 
   required anymore.
2. Addressed all the review comments from Akhil and Anoob.
3. Included update to the ipsec-secgw user guide and update to release notes.

 doc/guides/rel_notes/release_20_05.rst   |  4 ++
 doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
 examples/ipsec-secgw/ep0.cfg             | 11 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
 examples/ipsec-secgw/ipsec.c             | 67 ++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h             |  7 +++
 examples/ipsec-secgw/sa.c                | 63 ++++++++++++++++++++--
 7 files changed, 186 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 6b1a7c58c..a9ec163cf 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -81,6 +81,10 @@ New Features
   by making use of the event device capabilities. The event mode currently supports
   only inline IPsec protocol offload.
 
+* **Updated ipsec-secgw application.**
+
+  Added IPsec inbound load-distribution support for ipsec-secgw 
+ application using NIC  load distribution feature(Flow Director).
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 038f593f4..12f921d76 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
 
     sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
     <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
+    <flow-direction> <port_id> <queue_id>
 
 where each options means:
 
@@ -698,6 +699,18 @@ where each options means:
 
    * *fallback lookaside-none*
 
+``<flow-direction>``
+
+ * Action type is for redirecting the specific inbound ipsec-flow to
+   a specified queue.
+
+ * Optional: Yes.
+
+ * Available options:
+
+   * *port_id*: Port ID of the NIC for which the SA is configured.
+   * *queue_id*: Queue ID to which traffic should be redirected.
+
 Example SA rules:
 
 .. code-block:: console
@@ -727,6 +740,9 @@ Example SA rules:
     mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
     type inline-crypto-offload port_id 0
 
+    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+    dst 172.16.1.7 flow-direction 0 2
+
 Routing rule syntax
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
+dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535  sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst 
+ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \ sport 0:65535 dport 
+0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 
+172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src 
+2222:2222:2222:2222:2222:2222:2222:7777 \ dst 
+1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 5fde4f728..6d02341de 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
 	}
 }
 
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_poll_mode_params(struct eh_conf *eh_conf)  { diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index d40657102..461fae461 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa) {
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for Egress traffic\n");
+		return -1;
+	}
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode\n");
+		return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf =
+			&(struct rte_flow_action_queue){
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		return ret;
+	}
+
+	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
+					sa->action, &err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..1790a93ca 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -144,6 +144,8 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index a6bf5e8b1..06bb25b3e 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
 	rule->spi = atoi(tokens[1]);
+	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
 
 	for (ti = 2; ti < n_tokens; ti++) {
@@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-			rule->portid = atoi(tokens[ti]);
-			if (status->status < 0)
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status, "portid %s not matching "
+					"with already assigned portid %u",
+					tokens[ti], rule->portid);
 				return;
+			}
 			portid_p = 1;
 			continue;
 		}
@@ -683,6 +690,44 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_NONE ||
+				ips->type ==
+				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+				rule->fdir_flag = 1;
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (rule->portid == UINT16_MAX)
+					rule->portid = atoi(tokens[ti]);
+				else if (rule->portid != atoi(tokens[ti])) {
+					APP_CHECK(0, status, "portid %s "
+						"not matching with already "
+						"assigned portid %u",
+						tokens[ti], rule->portid);
+					return;
+				}
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				rule->fdir_qid = atoi(tokens[ti]);
+				/* validating portid and queueid */
+				status_p = check_flow_params(rule->portid,
+						rule->fdir_qid);
+				if (status_p < 0) {
+					printf("port id %u / queue id %u is "
+						"not valid\n", rule->portid,
+						 rule->fdir_qid);
+				}
+			} else {
+				APP_CHECK(0, status, "flow director not "
+					"supported for security session "
+					"type:%d", ips->type);
+				return;
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -721,7 +766,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (!type_p || (!portid_p && ips->type !=
 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
-		rule->portid = -1;
 	}
 
 	*ri = *ri + 1;
@@ -806,7 +850,7 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 		printf("lookaside-protocol-offload ");
 		break;
 	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
-		printf("cpu-crypto-accelerated");
+		printf("cpu-crypto-accelerated ");
 		break;
 	}
 
@@ -825,6 +869,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction port %d queue %d", sa->portid,
+				sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1143,6 +1191,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			}
 		}
 
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp_flow() failed %s\n",
+					strerror(rc));
+		}
 		print_one_sa_rule(sa, inbound);
 	}
 
--
2.17.1


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

* Re: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support flow director feature
  2020-04-09 10:09       ` [dpdk-dev] [PATCH v5] " Praveen Shetty
  2020-04-14  7:33         ` Shetty, Praveen
@ 2020-04-15 18:59         ` Akhil Goyal
  2020-04-16 11:49           ` Shetty, Praveen
  2020-04-16 16:47         ` [dpdk-dev] [PATCH v6] " Praveen Shetty
  2 siblings, 1 reply; 26+ messages in thread
From: Akhil Goyal @ 2020-04-15 18:59 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

Hi Praveen,

> 
> Support load distribution in security gateway application using
> NIC load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow
> to a specified queue.This is achieved by extending the SA rule syntax
> to support specification by adding new action_type of <flow-direction>
> to a specified <port_id> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>

Please fix a few minor comments below.

Apart from that,
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

> ---
> v5 changes:
> Small change in condtional handling in sa.c file.
> 
> v4 changes:
> 1. Removed flow director configuration changes as they are not
>    required anymore.
> 2. Addressed all the review comments from Akhil and Anoob.
> 3. Included update to the ipsec-secgw user guide and update to release notes.
> 
>  doc/guides/rel_notes/release_20_05.rst   |  4 ++
>  doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
>  examples/ipsec-secgw/ep0.cfg             | 11 ++++
>  examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
>  examples/ipsec-secgw/ipsec.c             | 67 ++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h             |  7 +++
>  examples/ipsec-secgw/sa.c                | 63 ++++++++++++++++++++--
>  7 files changed, 186 insertions(+), 4 deletions(-)
> 
> diff --git a/doc/guides/rel_notes/release_20_05.rst
> b/doc/guides/rel_notes/release_20_05.rst
> index 6b1a7c58c..a9ec163cf 100644
> --- a/doc/guides/rel_notes/release_20_05.rst
> +++ b/doc/guides/rel_notes/release_20_05.rst
> @@ -81,6 +81,10 @@ New Features
>    by making use of the event device capabilities. The event mode currently
> supports
>    only inline IPsec protocol offload.
> 
> +* **Updated ipsec-secgw application.**
> +
> +  Added IPsec inbound load-distribution support for ipsec-secgw application
> using NIC
> +  load distribution feature(Flow Director).

There is one more item in release notes for ipsec-secgw for event mode.
You should add a bullet in that for this feature.

> 
>  Removed Items
>  -------------
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 038f593f4..12f921d76 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
> 
>      sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
>      <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
> +    <flow-direction> <port_id> <queue_id>
> 
>  where each options means:
> 
> @@ -698,6 +699,18 @@ where each options means:
> 
>     * *fallback lookaside-none*
> 
> +``<flow-direction>``
> +
> + * Action type is for redirecting the specific inbound ipsec-flow to
> +   a specified queue.

Flow direction is not an action type. You can re-phrase it as
Option for redirecting a specific inbound ipsec flow of a port to a specific queue of that port. 

> +
> + * Optional: Yes.
> +
> + * Available options:
> +
> +   * *port_id*: Port ID of the NIC for which the SA is configured.
> +   * *queue_id*: Queue ID to which traffic should be redirected.
> +
>  Example SA rules:
> 
>  .. code-block:: console
> @@ -727,6 +740,9 @@ Example SA rules:
>      mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
>      type inline-crypto-offload port_id 0
> 
> +    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
> +    dst 172.16.1.7 flow-direction 0 2
> +
>  Routing rule syntax
>  ^^^^^^^^^^^^^^^^^^^
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
> index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport
> 0:65535 dport 0:6553
>  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport
> 0:65535
>  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport
> 0:65535
>  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport
> 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport
> 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
>  sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
> @@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
>  sport 0:65535 dport 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
> +sport 0:65535 dport 0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
> @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
> +dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
> @@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key
> 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \
>  dst 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
> +src 2222:2222:2222:2222:2222:2222:2222:7777 \
> +dst 1111:1111:1111:1111:1111:1111:1111:7777 \
> +flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 5fde4f728..6d02341de 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
>  	}
>  }
> 
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
> +{
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_poll_mode_params(struct eh_conf *eh_conf)
>  {
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index d40657102..461fae461 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa)
> +{
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for Egress traffic\n");
> +		return -1;
> +	}
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode\n");
> +		return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};

Unnecessary line break, spacing before '{'


> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n",
> err.message);
> +		return ret;
> +	}
> +
> +	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
> +					sa->action, &err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index f8f29f9b1..1790a93ca 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -144,6 +144,8 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx,
> struct ipsec_sa *sa,
>  int
>  create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index a6bf5e8b1..06bb25b3e 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (atoi(tokens[1]) == INVALID_SPI)
>  		return;
>  	rule->spi = atoi(tokens[1]);
> +	rule->portid = UINT16_MAX;
>  	ips = ipsec_get_primary_session(rule);
> 
>  	for (ti = 2; ti < n_tokens; ti++) {
> @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -			rule->portid = atoi(tokens[ti]);
> -			if (status->status < 0)
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s not matching
> "
> +					"with already assigned portid %u",
> +					tokens[ti], rule->portid);

Please do not split strings which are printed as the output on console.
It will make it difficult to grep while debugging.

>  				return;
> +			}
>  			portid_p = 1;
>  			continue;
>  		}
> @@ -683,6 +690,44 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_NONE ||
> +				ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
The code is not readable here.
Either a switch case or a separate function if the indentation it going beyond.

> +				rule->fdir_flag = 1;
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (rule->portid == UINT16_MAX)
> +					rule->portid = atoi(tokens[ti]);
> +				else if (rule->portid != atoi(tokens[ti])) {
> +					APP_CHECK(0, status, "portid %s "
> +						"not matching with already "
> +						"assigned portid %u",
> +						tokens[ti], rule->portid);

Same here, do not split strings which are printed.
You should have the complete string on a separate line. Checkpatch will not trouble for more than 80.

> +					return;
> +				}
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				rule->fdir_qid = atoi(tokens[ti]);
> +				/* validating portid and queueid */
> +				status_p = check_flow_params(rule->portid,
> +						rule->fdir_qid);
> +				if (status_p < 0) {
> +					printf("port id %u / queue id %u is "
> +						"not valid\n", rule->portid,
> +						 rule->fdir_qid);
> +				}
> +			} else {
> +				APP_CHECK(0, status, "flow director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +				return;
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"",
> @@ -721,7 +766,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (!type_p || (!portid_p && ips->type !=
>  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
>  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> -		rule->portid = -1;
>  	}
> 
>  	*ri = *ri + 1;
> @@ -806,7 +850,7 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  		printf("lookaside-protocol-offload ");
>  		break;
>  	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
> -		printf("cpu-crypto-accelerated");
> +		printf("cpu-crypto-accelerated ");
>  		break;
>  	}
> 
> @@ -825,6 +869,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction port %d queue %d", sa->portid,
> +				sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1143,6 +1191,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			}
>  		}
> 
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp_flow() failed %s\n",
> +					strerror(rc));
> +		}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> --
> 2.17.1


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

* Re: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support flow director feature
  2020-04-15 18:59         ` Akhil Goyal
@ 2020-04-16 11:49           ` Shetty, Praveen
  0 siblings, 0 replies; 26+ messages in thread
From: Shetty, Praveen @ 2020-04-16 11:49 UTC (permalink / raw)
  To: Akhil Goyal, dev, Doherty, Declan, anoobj
  Cc: Iremonger, Bernard, Ananyev, Konstantin

Hi Akhil,

Thank you.

Please see my response inline.


-----Original Message-----
From: Akhil Goyal <akhil.goyal@nxp.com> 
Sent: Thursday, April 16, 2020 12:30 AM
To: Shetty, Praveen <praveen.shetty@intel.com>; dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; anoobj@marvell.com
Cc: Iremonger, Bernard <bernard.iremonger@intel.com>; Ananyev, Konstantin <konstantin.ananyev@intel.com>
Subject: RE: [PATCH v5] examples/ipsec-secgw: support flow director feature

Hi Praveen,

> 
> Support load distribution in security gateway application using NIC 
> load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow to 
> a specified queue.This is achieved by extending the SA rule syntax to 
> support specification by adding new action_type of <flow-direction> to 
> a specified <port_id> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>

Please fix a few minor comments below.

Apart from that,
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

> ---
> v5 changes:
> Small change in condtional handling in sa.c file.
> 
> v4 changes:
> 1. Removed flow director configuration changes as they are not
>    required anymore.
> 2. Addressed all the review comments from Akhil and Anoob.
> 3. Included update to the ipsec-secgw user guide and update to release notes.
> 
>  doc/guides/rel_notes/release_20_05.rst   |  4 ++
>  doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
>  examples/ipsec-secgw/ep0.cfg             | 11 ++++
>  examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
>  examples/ipsec-secgw/ipsec.c             | 67 ++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h             |  7 +++
>  examples/ipsec-secgw/sa.c                | 63 ++++++++++++++++++++--
>  7 files changed, 186 insertions(+), 4 deletions(-)
> 
> diff --git a/doc/guides/rel_notes/release_20_05.rst
> b/doc/guides/rel_notes/release_20_05.rst
> index 6b1a7c58c..a9ec163cf 100644
> --- a/doc/guides/rel_notes/release_20_05.rst
> +++ b/doc/guides/rel_notes/release_20_05.rst
> @@ -81,6 +81,10 @@ New Features
>    by making use of the event device capabilities. The event mode 
> currently supports
>    only inline IPsec protocol offload.
> 
> +* **Updated ipsec-secgw application.**
> +
> +  Added IPsec inbound load-distribution support for ipsec-secgw 
> + application
> using NIC
> +  load distribution feature(Flow Director).

There is one more item in release notes for ipsec-secgw for event mode.
You should add a bullet in that for this feature.

[Praveen] okay. Will do it in v6.

> 
>  Removed Items
>  -------------
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 038f593f4..12f921d76 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
> 
>      sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
>      <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
> +    <flow-direction> <port_id> <queue_id>
> 
>  where each options means:
> 
> @@ -698,6 +699,18 @@ where each options means:
> 
>     * *fallback lookaside-none*
> 
> +``<flow-direction>``
> +
> + * Action type is for redirecting the specific inbound ipsec-flow to
> +   a specified queue.

Flow direction is not an action type. You can re-phrase it as Option for redirecting a specific inbound ipsec flow of a port to a specific queue of that port. 

[Praveen] okay. Will update this in v6.
> +
> + * Optional: Yes.
> +
> + * Available options:
> +
> +   * *port_id*: Port ID of the NIC for which the SA is configured.
> +   * *queue_id*: Queue ID to which traffic should be redirected.
> +
>  Example SA rules:
> 
>  .. code-block:: console
> @@ -727,6 +740,9 @@ Example SA rules:
>      mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
>      type inline-crypto-offload port_id 0
> 
> +    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
> +    dst 172.16.1.7 flow-direction 0 2
> +
>  Routing rule syntax
>  ^^^^^^^^^^^^^^^^^^^
> 
> diff --git a/examples/ipsec-secgw/ep0.cfg 
> b/examples/ipsec-secgw/ep0.cfg index dfd4aca7d..6f8d5aa53 100644
> --- a/examples/ipsec-secgw/ep0.cfg
> +++ b/examples/ipsec-secgw/ep0.cfg
> @@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 
> 192.168.186.0/24 sport
> 0:65535 dport 0:6553
>  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 
> dport
> 0:65535
>  sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 
> dport
> 0:65535
>  sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 
> dport
> 0:65535
> +sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 
> +dport
> 0:65535
>  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 
> dport 0:65535  sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 
> sport 0:65535 dport 0:65535  sp ipv4 in esp protect 126 pri 1 dst 
> 192.168.66.0/24 sport 0:65535 dport 0:65535 @@ -61,6 +62,8 @@ sp ipv6 
> in esp protect 125 pri 1 dst
> ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
>  sport 0:65535 dport 0:65535
>  sp ipv6 in esp protect 126 pri 1 dst
> ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \  sport 0:65535 dport 
> 0:65535
> +sp ipv6 in esp protect 127 pri 1 dst
> ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
> +sport 0:65535 dport 0:65535
> 
>  #SA rules
>  sa out 5 cipher_algo aes-128-cbc cipher_key 
> 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \ @@ -118,6 +121,9 @@ dst 172.16.1.5
> 
>  sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 
> 172.16.2.6 dst
> 172.16.1.6
> 
> +sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 
> +172.16.2.7 \ dst 172.16.1.7 flow-direction 0 2
> +
>  sa in 125 cipher_algo aes-128-cbc cipher_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key 
> c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
>  c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \ @@ -130,6 +136,11 @@ sa 
> in 126 cipher_algo aes-128-cbc cipher_key 
> 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
>  src 2222:2222:2222:2222:2222:2222:2222:6666 \  dst 
> 1111:1111:1111:1111:1111:1111:1111:6666
> 
> +sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \ src 
> +2222:2222:2222:2222:2222:2222:2222:7777 \ dst 
> +1111:1111:1111:1111:1111:1111:1111:7777 \ flow-direction 0 3
> +
>  #Routing rules
>  rt ipv4 dst 172.16.2.5/32 port 0
>  rt ipv4 dst 172.16.2.6/32 port 1
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec- 
> secgw/ipsec-secgw.c index 5fde4f728..6d02341de 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
>  	}
>  }
> 
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid) {
> +	uint16_t i;
> +	uint16_t portid;
> +	uint8_t queueid;
> +
> +	for (i = 0; i < nb_lcore_params; ++i) {
> +		portid = lcore_params_array[i].port_id;
> +		if (portid == fdir_portid) {
> +			queueid = lcore_params_array[i].queue_id;
> +			if (queueid == fdir_qid)
> +				break;
> +		}
> +
> +		if (i == nb_lcore_params - 1)
> +			return -1;
> +	}
> +
> +	return 1;
> +}
> +
>  static int32_t
>  check_poll_mode_params(struct eh_conf *eh_conf)  { diff --git 
> a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c index 
> d40657102..461fae461 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -418,6 +418,73 @@ create_inline_session(struct socket_ctx *skt_ctx, 
> struct ipsec_sa *sa,
>  	return 0;
>  }
> 
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa) {
> +	int ret = 0;
> +	struct rte_flow_error err;
> +	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for Egress traffic\n");
> +		return -1;
> +	}
> +	if (sa->flags == TRANSPORT) {
> +		RTE_LOG(ERR, IPSEC,
> +			"No Flow director rule for transport mode\n");
> +		return -1;
> +	}
> +	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> +	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> +	sa->action[0].conf =
> +			&(struct rte_flow_action_queue){
> +				.index = sa->fdir_qid,
> +	};

Unnecessary line break, spacing before '{'

[Praveen] will fix this in v6.


> +	sa->attr.egress = 0;
> +	sa->attr.ingress = 1;
> +	if (IS_IP6(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
> +		sa->pattern[1].spec = &sa->ipv6_spec;
> +		memcpy(sa->ipv6_spec.hdr.dst_addr,
> +			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
> +		memcpy(sa->ipv6_spec.hdr.src_addr,
> +			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	} else if (IS_IP4(sa->flags)) {
> +		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
> +		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> +		sa->pattern[1].spec = &sa->ipv4_spec;
> +		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
> +		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
> +		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
> +		sa->pattern[2].spec = &sa->esp_spec;
> +		sa->pattern[2].mask = &rte_flow_item_esp_mask;
> +		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
> +		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> +	}
> +	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
> +
> +	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
> +				&err);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n",
> err.message);
> +		return ret;
> +	}
> +
> +	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
> +					sa->action, &err);
> +	if (!sa->flow) {
> +		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * queue crypto-ops into PMD queue.
>   */
> diff --git a/examples/ipsec-secgw/ipsec.h 
> b/examples/ipsec-secgw/ipsec.h index f8f29f9b1..1790a93ca 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -144,6 +144,8 @@ struct ipsec_sa {
>  	};
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint16_t portid;
> +	uint8_t fdir_qid;
> +	uint8_t fdir_flag;
> 
>  #define MAX_RTE_FLOW_PATTERN (4)
>  #define MAX_RTE_FLOW_ACTIONS (3)
> @@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx 
> *ipsec_ctx, struct ipsec_sa *sa,  int  create_inline_session(struct 
> socket_ctx *skt_ctx, struct ipsec_sa *sa,
>  		struct rte_ipsec_session *ips);
> +int
> +check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
> +
> +int
> +create_ipsec_esp_flow(struct ipsec_sa *sa);
> 
>  #endif /* __IPSEC_H__ */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c 
> index a6bf5e8b1..06bb25b3e 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	uint32_t type_p = 0;
>  	uint32_t portid_p = 0;
>  	uint32_t fallback_p = 0;
> +	int16_t status_p = 0;
> 
>  	if (strcmp(tokens[0], "in") == 0) {
>  		ri = &nb_sa_in;
> @@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (atoi(tokens[1]) == INVALID_SPI)
>  		return;
>  	rule->spi = atoi(tokens[1]);
> +	rule->portid = UINT16_MAX;
>  	ips = ipsec_get_primary_session(rule);
> 
>  	for (ti = 2; ti < n_tokens; ti++) {
> @@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
>  			if (status->status < 0)
>  				return;
> -			rule->portid = atoi(tokens[ti]);
> -			if (status->status < 0)
> +			if (rule->portid == UINT16_MAX)
> +				rule->portid = atoi(tokens[ti]);
> +			else if (rule->portid != atoi(tokens[ti])) {
> +				APP_CHECK(0, status, "portid %s not matching
> "
> +					"with already assigned portid %u",
> +					tokens[ti], rule->portid);

Please do not split strings which are printed as the output on console.
It will make it difficult to grep while debugging.

[Praveen] okay. Will fix this in v6.

>  				return;
> +			}
>  			portid_p = 1;
>  			continue;
>  		}
> @@ -683,6 +690,44 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			fallback_p = 1;
>  			continue;
>  		}
> +		if (strcmp(tokens[ti], "flow-direction") == 0) {
> +			if (ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_NONE ||
> +				ips->type ==
> +				RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
The code is not readable here.
Either a switch case or a separate function if the indentation it going beyond.

[Praveen] okay. Will do this in v6.

> +				rule->fdir_flag = 1;
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				if (rule->portid == UINT16_MAX)
> +					rule->portid = atoi(tokens[ti]);
> +				else if (rule->portid != atoi(tokens[ti])) {
> +					APP_CHECK(0, status, "portid %s "
> +						"not matching with already "
> +						"assigned portid %u",
> +						tokens[ti], rule->portid);

Same here, do not split strings which are printed.
You should have the complete string on a separate line. Checkpatch will not trouble for more than 80.

[Praveen] Okay. Will do this in v6.

> +					return;
> +				}
> +				INCREMENT_TOKEN_INDEX(ti, n_tokens,
> status);
> +				if (status->status < 0)
> +					return;
> +				rule->fdir_qid = atoi(tokens[ti]);
> +				/* validating portid and queueid */
> +				status_p = check_flow_params(rule->portid,
> +						rule->fdir_qid);
> +				if (status_p < 0) {
> +					printf("port id %u / queue id %u is "
> +						"not valid\n", rule->portid,
> +						 rule->fdir_qid);
> +				}
> +			} else {
> +				APP_CHECK(0, status, "flow director not "
> +					"supported for security session "
> +					"type:%d", ips->type);
> +				return;
> +			}
> +			continue;
> +		}
> 
>  		/* unrecognizeable input */
>  		APP_CHECK(0, status, "unrecognized input \"%s\"", @@ -721,7 +766,6 
> @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  	if (!type_p || (!portid_p && ips->type !=
>  			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
>  		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
> -		rule->portid = -1;
>  	}
> 
>  	*ri = *ri + 1;
> @@ -806,7 +850,7 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
>  		printf("lookaside-protocol-offload ");
>  		break;
>  	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
> -		printf("cpu-crypto-accelerated");
> +		printf("cpu-crypto-accelerated ");
>  		break;
>  	}
> 
> @@ -825,6 +869,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int
> inbound)
>  			break;
>  		}
>  	}
> +	if (sa->fdir_flag == 1)
> +		printf("flow-direction port %d queue %d", sa->portid,
> +				sa->fdir_qid);
> +
>  	printf("\n");
>  }
> 
> @@ -1143,6 +1191,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const 
> struct ipsec_sa entries[],
>  			}
>  		}
> 
> +		if (sa->fdir_flag && inbound) {
> +			rc = create_ipsec_esp_flow(sa);
> +			if (rc != 0)
> +				RTE_LOG(ERR, IPSEC_ESP,
> +					"create_ipsec_esp_flow() failed %s\n",
> +					strerror(rc));
> +		}
>  		print_one_sa_rule(sa, inbound);
>  	}
> 
> --
> 2.17.1

Regards,
Praveen

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

* [dpdk-dev] [PATCH v6] examples/ipsec-secgw: support flow director feature
  2020-04-09 10:09       ` [dpdk-dev] [PATCH v5] " Praveen Shetty
  2020-04-14  7:33         ` Shetty, Praveen
  2020-04-15 18:59         ` Akhil Goyal
@ 2020-04-16 16:47         ` Praveen Shetty
  2020-04-17 20:58           ` Akhil Goyal
  2 siblings, 1 reply; 26+ messages in thread
From: Praveen Shetty @ 2020-04-16 16:47 UTC (permalink / raw)
  To: dev, declan.doherty, akhil.goyal, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

Support load distribution in security gateway application using
NIC load distribution feature(Flow Director).
Flow Director is used to redirect the specified inbound ipsec flow
to a specified queue.This is achieved by extending the SA rule syntax
to support specification by adding new action_type of <flow-direction>
to a specified <port_id> <queue_id>.

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
v6 changes:
Incorporated all the review comments from Akhil on v5.

 doc/guides/rel_notes/release_20_05.rst   |  4 +-
 doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
 examples/ipsec-secgw/ep0.cfg             | 11 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
 examples/ipsec-secgw/ipsec.c             | 66 ++++++++++++++++++++++++
 examples/ipsec-secgw/ipsec.h             |  7 +++
 examples/ipsec-secgw/sa.c                | 65 +++++++++++++++++++++--
 7 files changed, 186 insertions(+), 5 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 184967844..bcb11a45b 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -73,7 +73,7 @@ New Features
 
   Supported large size code blocks which does not fit in one mbuf segment.
 
-* **Added event mode to ipsec-secgw application.**
+* **Updated ipsec-secgw application.**
 
   Updated ipsec-secgw application to add event based packet processing. The worker
   thread(s) would receive events and submit them back to the event device after
@@ -81,6 +81,8 @@ New Features
   by making use of the event device capabilities. The event mode currently supports
   only inline IPsec protocol offload.
 
+  Added IPsec inbound load-distribution support for ipsec-secgw application using NIC
+  load distribution feature(Flow Director).
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 038f593f4..5cc29c414 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -506,6 +506,7 @@ The SA rule syntax is shown as follows:
 
     sa <dir> <spi> <cipher_algo> <cipher_key> <auth_algo> <auth_key>
     <mode> <src_ip> <dst_ip> <action_type> <port_id> <fallback>
+    <flow-direction> <port_id> <queue_id>
 
 where each options means:
 
@@ -698,6 +699,18 @@ where each options means:
 
    * *fallback lookaside-none*
 
+``<flow-direction>``
+
+ * Option for redirecting a specific inbound ipsec flow of a port to a specific
+   queue of that port.
+
+ * Optional: Yes.
+
+ * Available options:
+
+   * *port_id*: Port ID of the NIC for which the SA is configured.
+   * *queue_id*: Queue ID to which traffic should be redirected.
+
 Example SA rules:
 
 .. code-block:: console
@@ -727,6 +740,9 @@ Example SA rules:
     mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5 \
     type inline-crypto-offload port_id 0
 
+    sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+    dst 172.16.1.7 flow-direction 0 2
+
 Routing rule syntax
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index dfd4aca7d..6f8d5aa53 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -29,6 +29,7 @@ sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp protect 117 pri 1 dst 192.168.212.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
@@ -61,6 +62,8 @@ sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:cccc:dddd:0000:0000/96 \
+sport 0:65535 dport 0:65535
 
 #SA rules
 sa out 5 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
@@ -118,6 +121,9 @@ dst 172.16.1.5
 
 sa in 116 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 117 cipher_algo null auth_algo null mode ipv4-tunnel src 172.16.2.7 \
+dst 172.16.1.7 flow-direction 0 2
+
 sa in 125 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
 c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
@@ -130,6 +136,11 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo null auth_algo null mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:7777 \
+dst 1111:1111:1111:1111:1111:1111:1111:7777 \
+flow-direction 0 3
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 5fde4f728..6d02341de 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -1183,6 +1183,28 @@ ipsec_poll_mode_worker(void)
 	}
 }
 
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid)
+{
+	uint16_t i;
+	uint16_t portid;
+	uint8_t queueid;
+
+	for (i = 0; i < nb_lcore_params; ++i) {
+		portid = lcore_params_array[i].port_id;
+		if (portid == fdir_portid) {
+			queueid = lcore_params_array[i].queue_id;
+			if (queueid == fdir_qid)
+				break;
+		}
+
+		if (i == nb_lcore_params - 1)
+			return -1;
+	}
+
+	return 1;
+}
+
 static int32_t
 check_poll_mode_params(struct eh_conf *eh_conf)
 {
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index d40657102..bf88d80d6 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -418,6 +418,72 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa)
+{
+	int ret = 0;
+	struct rte_flow_error err;
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for Egress traffic\n");
+		return -1;
+	}
+	if (sa->flags == TRANSPORT) {
+		RTE_LOG(ERR, IPSEC,
+			"No Flow director rule for transport mode\n");
+		return -1;
+	}
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->action[0].conf = &(struct rte_flow_action_queue) {
+				.index = sa->fdir_qid,
+	};
+	sa->attr.egress = 0;
+	sa->attr.ingress = 1;
+	if (IS_IP6(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
+		sa->pattern[1].spec = &sa->ipv6_spec;
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	} else if (IS_IP4(sa->flags)) {
+		sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
+		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
+		sa->pattern[1].spec = &sa->ipv4_spec;
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[2].spec = &sa->esp_spec;
+		sa->pattern[2].mask = &rte_flow_item_esp_mask;
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+	}
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+	ret = rte_flow_validate(sa->portid, &sa->attr, sa->pattern, sa->action,
+				&err);
+	if (ret < 0) {
+		RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message);
+		return ret;
+	}
+
+	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
+					sa->action, &err);
+	if (!sa->flow) {
+		RTE_LOG(ERR, IPSEC, "Flow creation failed %s\n", err.message);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * queue crypto-ops into PMD queue.
  */
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index f8f29f9b1..1790a93ca 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -144,6 +144,8 @@ struct ipsec_sa {
 	};
 	enum rte_security_ipsec_sa_direction direction;
 	uint16_t portid;
+	uint8_t fdir_qid;
+	uint8_t fdir_flag;
 
 #define MAX_RTE_FLOW_PATTERN (4)
 #define MAX_RTE_FLOW_ACTIONS (3)
@@ -408,5 +410,10 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
+int
+check_flow_params(uint16_t fdir_portid, uint8_t fdir_qid);
+
+int
+create_ipsec_esp_flow(struct ipsec_sa *sa);
 
 #endif /* __IPSEC_H__ */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index a6bf5e8b1..4783bdccd 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -271,6 +271,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t type_p = 0;
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
+	int16_t status_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
@@ -295,6 +296,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
 	rule->spi = atoi(tokens[1]);
+	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
 
 	for (ti = 2; ti < n_tokens; ti++) {
@@ -636,9 +638,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 			if (status->status < 0)
 				return;
-			rule->portid = atoi(tokens[ti]);
-			if (status->status < 0)
+			if (rule->portid == UINT16_MAX)
+				rule->portid = atoi(tokens[ti]);
+			else if (rule->portid != atoi(tokens[ti])) {
+				APP_CHECK(0, status,
+					"portid %s not matching with already assigned portid %u",
+					tokens[ti], rule->portid);
 				return;
+			}
 			portid_p = 1;
 			continue;
 		}
@@ -683,6 +690,46 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			fallback_p = 1;
 			continue;
 		}
+		if (strcmp(tokens[ti], "flow-direction") == 0) {
+			switch (ips->type) {
+			case RTE_SECURITY_ACTION_TYPE_NONE:
+			case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
+				rule->fdir_flag = 1;
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				if (rule->portid == UINT16_MAX)
+					rule->portid = atoi(tokens[ti]);
+				else if (rule->portid != atoi(tokens[ti])) {
+					APP_CHECK(0, status,
+						"portid %s not matching with already assigned portid %u",
+						tokens[ti], rule->portid);
+					return;
+				}
+				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+				if (status->status < 0)
+					return;
+				rule->fdir_qid = atoi(tokens[ti]);
+				/* validating portid and queueid */
+				status_p = check_flow_params(rule->portid,
+						rule->fdir_qid);
+				if (status_p < 0) {
+					printf("port id %u / queue id %u is "
+						"not valid\n", rule->portid,
+						 rule->fdir_qid);
+				}
+				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+			case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
+			case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
+			default:
+				APP_CHECK(0, status,
+					"flow director not supported for security session type %d",
+					ips->type);
+				return;
+			}
+			continue;
+		}
 
 		/* unrecognizeable input */
 		APP_CHECK(0, status, "unrecognized input \"%s\"",
@@ -721,7 +768,6 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	if (!type_p || (!portid_p && ips->type !=
 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
-		rule->portid = -1;
 	}
 
 	*ri = *ri + 1;
@@ -806,7 +852,7 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 		printf("lookaside-protocol-offload ");
 		break;
 	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
-		printf("cpu-crypto-accelerated");
+		printf("cpu-crypto-accelerated ");
 		break;
 	}
 
@@ -825,6 +871,10 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			break;
 		}
 	}
+	if (sa->fdir_flag == 1)
+		printf("flow-direction port %d queue %d", sa->portid,
+				sa->fdir_qid);
+
 	printf("\n");
 }
 
@@ -1143,6 +1193,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			}
 		}
 
+		if (sa->fdir_flag && inbound) {
+			rc = create_ipsec_esp_flow(sa);
+			if (rc != 0)
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_ipsec_esp_flow() failed %s\n",
+					strerror(rc));
+		}
 		print_one_sa_rule(sa, inbound);
 	}
 
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v6] examples/ipsec-secgw: support flow director feature
  2020-04-16 16:47         ` [dpdk-dev] [PATCH v6] " Praveen Shetty
@ 2020-04-17 20:58           ` Akhil Goyal
  0 siblings, 0 replies; 26+ messages in thread
From: Akhil Goyal @ 2020-04-17 20:58 UTC (permalink / raw)
  To: Praveen Shetty, dev, declan.doherty, anoobj
  Cc: bernard.iremonger, konstantin.ananyev

> 
> Support load distribution in security gateway application using
> NIC load distribution feature(Flow Director).
> Flow Director is used to redirect the specified inbound ipsec flow
> to a specified queue.This is achieved by extending the SA rule syntax
> to support specification by adding new action_type of <flow-direction>
> to a specified <port_id> <queue_id>.
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
> ---
> v6 changes:
> Incorporated all the review comments from Akhil on v5.
> 
>  doc/guides/rel_notes/release_20_05.rst   |  4 +-
>  doc/guides/sample_app_ug/ipsec_secgw.rst | 16 ++++++
>  examples/ipsec-secgw/ep0.cfg             | 11 ++++
>  examples/ipsec-secgw/ipsec-secgw.c       | 22 ++++++++
>  examples/ipsec-secgw/ipsec.c             | 66 ++++++++++++++++++++++++
>  examples/ipsec-secgw/ipsec.h             |  7 +++
>  examples/ipsec-secgw/sa.c                | 65 +++++++++++++++++++++--
>  7 files changed, 186 insertions(+), 5 deletions(-)
> 
Applied to dpdk-next-crypto

Thanks.

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

end of thread, other threads:[~2020-04-17 20:58 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 14:55 [dpdk-dev] [PATCH v1] examples/ipsec-secgw: support flow director feature Praveen Shetty
2020-03-12 11:00 ` Anoob Joseph
     [not found]   ` <BN7PR11MB25310A9A6B9C3BE91A411AA29DFD0@BN7PR11MB2531.namprd11.prod.outlook.com>
     [not found]     ` <BN7PR11MB2531E92F9B078563A947615F9DFD0@BN7PR11MB2531.namprd11.prod.outlook.com>
     [not found]       ` <BN7PR11MB2531ABDDAE26D1FD3B216E259DFD0@BN7PR11MB2531.namprd11.prod.outlook.com>
2020-03-13  7:05         ` Shetty, Praveen
2020-03-13 10:51           ` Anoob Joseph
2020-03-13 12:21             ` Shetty, Praveen
2020-03-19 16:21 ` [dpdk-dev] [PATCH v2] " Praveen Shetty
2020-03-20  8:15   ` Anoob Joseph
2020-03-23 11:24     ` Shetty, Praveen
2020-03-31 13:02   ` [dpdk-dev] [PATCH v3] " Praveen Shetty
2020-04-01 13:19     ` Akhil Goyal
2020-04-01 13:26       ` Anoob Joseph
2020-04-01 13:53         ` Akhil Goyal
2020-04-02 11:15           ` Shetty, Praveen
2020-04-02 13:39     ` [dpdk-dev] [EXT] " Anoob Joseph
2020-04-02 17:56       ` Shetty, Praveen
2020-04-03  5:14         ` Anoob Joseph
2020-04-03  5:52           ` Akhil Goyal
2020-04-03 10:21             ` Shetty, Praveen
2020-04-03 10:28               ` Anoob Joseph
2020-04-08 14:13     ` [dpdk-dev] [PATCH v4] " Praveen Shetty
2020-04-09 10:09       ` [dpdk-dev] [PATCH v5] " Praveen Shetty
2020-04-14  7:33         ` Shetty, Praveen
2020-04-15 18:59         ` Akhil Goyal
2020-04-16 11:49           ` Shetty, Praveen
2020-04-16 16:47         ` [dpdk-dev] [PATCH v6] " Praveen Shetty
2020-04-17 20:58           ` Akhil Goyal

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ http://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git