DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features
@ 2021-09-03 11:22 Radu Nicolau
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support Radu Nicolau
                   ` (11 more replies)
  0 siblings, 12 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, Radu Nicolau

Update the IPsec sample app with new features and updates:
- NAT-T and TSO support
- telemetry support
- ol_flags support
- reset callback, enable stats by default, initial SQN

Depends on series 18279 ('new features for ipsec and security libraries')

Radu Nicolau (7):
  examples/ipsec-secgw: add ol_flags support
  examples/ipsec-secgw: add support for NAT-T
  examples/ipsec-secgw: add support for TSO
  examples/ipsec-secgw: enable stats by default
  examples/ipsec-secgw: add support for telemetry
  examples/ipsec-secgw: add support for defining initial sequence number
    value
  examples/ipsec-secgw: add ethdev reset callback

 examples/ipsec-secgw/esp.c         |   7 +-
 examples/ipsec-secgw/ipsec-secgw.c | 404 +++++++++++++++++++++++++---
 examples/ipsec-secgw/ipsec-secgw.h |  33 ++-
 examples/ipsec-secgw/ipsec.c       | 380 ++++++++++++---------------
 examples/ipsec-secgw/ipsec.h       |  26 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 407 ++++++++++++++++++++++++-----
 examples/ipsec-secgw/sad.c         |  10 +-
 examples/ipsec-secgw/sad.h         |  20 +-
 9 files changed, 941 insertions(+), 348 deletions(-)

-- 
2.25.1


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

* [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 12:48   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T Radu Nicolau
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add support for ol_flags to the IPsec GW sample app.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index f252d34985..6d516e2221 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -515,7 +515,7 @@ prepare_traffic(struct rte_mbuf **pkts, struct ipsec_traffic *t,
 
 static inline void
 prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port,
-		const struct lcore_conf *qconf)
+		const struct lcore_conf *qconf __rte_unused)
 {
 	struct ip *ip;
 	struct rte_ether_hdr *ethhdr;
@@ -526,20 +526,17 @@ prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port,
 		rte_pktmbuf_prepend(pkt, RTE_ETHER_HDR_LEN);
 
 	if (ip->ip_v == IPVERSION) {
-		pkt->ol_flags |= qconf->outbound.ipv4_offloads;
-		pkt->l3_len = sizeof(struct ip);
 		pkt->l2_len = RTE_ETHER_HDR_LEN;
 
-		ip->ip_sum = 0;
-
 		/* calculate IPv4 cksum in SW */
-		if ((pkt->ol_flags & PKT_TX_IP_CKSUM) == 0)
+		if ((pkt->ol_flags &
+				(PKT_TX_IP_CKSUM | PKT_TX_OUTER_IP_CKSUM)) == 0)
 			ip->ip_sum = rte_ipv4_cksum((struct rte_ipv4_hdr *)ip);
+		else
+			ip->ip_sum = 0;
 
 		ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
 	} else {
-		pkt->ol_flags |= qconf->outbound.ipv6_offloads;
-		pkt->l3_len = sizeof(struct ip6_hdr);
 		pkt->l2_len = RTE_ETHER_HDR_LEN;
 
 		ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
-- 
2.25.1


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

* [dpdk-dev] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 10:36   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 3/7] examples/ipsec-secgw: add support for TSO Radu Nicolau
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add support to the sample application to support IPsec NAT-T for both
transport and tunnel modes, for both IPv4 and IPv6.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/esp.c         |   7 +-
 examples/ipsec-secgw/ipsec-secgw.c |   3 -
 examples/ipsec-secgw/ipsec.c       | 375 ++++++++++++-----------------
 examples/ipsec-secgw/ipsec.h       |  19 +-
 examples/ipsec-secgw/sa.c          | 240 +++++++++++++-----
 examples/ipsec-secgw/sad.c         |  10 +-
 examples/ipsec-secgw/sad.h         |  20 +-
 7 files changed, 365 insertions(+), 309 deletions(-)

diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c
index bfa7ff7217..3762d61597 100644
--- a/examples/ipsec-secgw/esp.c
+++ b/examples/ipsec-secgw/esp.c
@@ -265,9 +265,9 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
 
 	RTE_ASSERT(IS_TUNNEL(sa->flags) || IS_TRANSPORT(sa->flags));
 
-	if (likely(IS_IP4_TUNNEL(sa->flags)))
+	if (likely((IS_TUNNEL(sa->flags) && IS_IP4(sa->flags))))
 		ip_hdr_len = sizeof(struct ip);
-	else if (IS_IP6_TUNNEL(sa->flags))
+	else if ((IS_TUNNEL(sa->flags) && IS_IP6(sa->flags)))
 		ip_hdr_len = sizeof(struct ip6_hdr);
 	else if (!IS_TRANSPORT(sa->flags)) {
 		RTE_LOG(ERR, IPSEC_ESP, "Unsupported SA flags: 0x%x\n",
@@ -308,7 +308,8 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa,
 				&sa->src, &sa->dst);
 		esp = (struct rte_esp_hdr *)(ip6 + 1);
 		break;
-	case TRANSPORT:
+	case IP4_TRANSPORT:
+	case IP6_TRANSPORT:
 		new_ip = (uint8_t *)rte_pktmbuf_prepend(m,
 				sizeof(struct rte_esp_hdr) + sa->iv_len);
 		memmove(new_ip, ip4, ip_hdr_len);
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 6d516e2221..46fb49d91e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2299,9 +2299,6 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads)
 		/* Pre-populate pkt offloads based on capabilities */
 		qconf->outbound.ipv4_offloads = PKT_TX_IPV4;
 		qconf->outbound.ipv6_offloads = PKT_TX_IPV6;
-		if (local_port_conf.txmode.offloads & DEV_TX_OFFLOAD_IPV4_CKSUM)
-			qconf->outbound.ipv4_offloads |= PKT_TX_IP_CKSUM;
-
 		tx_queueid++;
 
 		/* init RX queues */
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 5b032fecfb..aa68e4f827 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -24,7 +24,7 @@ set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec)
 	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
 		struct rte_security_ipsec_tunnel_param *tunnel =
 				&ipsec->tunnel;
-		if (IS_IP4_TUNNEL(sa->flags)) {
+		if (IS_TUNNEL(sa->flags) && IS_IP4(sa->flags)) {
 			tunnel->type =
 				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 			tunnel->ipv4.ttl = IPDEFTTL;
@@ -34,7 +34,7 @@ set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform *ipsec)
 
 			memcpy((uint8_t *)&tunnel->ipv4.dst_ip,
 				(uint8_t *)&sa->dst.ip.ip4, 4);
-		} else if (IS_IP6_TUNNEL(sa->flags)) {
+		} else if (IS_TUNNEL(sa->flags) && IS_IP6(sa->flags)) {
 			tunnel->type =
 				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 			tunnel->ipv6.hlimit = IPDEFTTL;
@@ -163,262 +163,196 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 {
 	int32_t ret = 0;
 	struct rte_security_ctx *sec_ctx;
+	const struct rte_security_capability *sec_cap;
 	struct rte_security_session_conf sess_conf = {
 		.action_type = ips->type,
 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
 		{.ipsec = {
-			.spi = sa->spi,
+			.spi = htonl(sa->spi),
 			.salt = sa->salt,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
-	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
-		sa->spi, sa->portid);
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		/**
+		 * TODO: address this in rte_security API
+		 * Use tunnel parameters to pass both transport IP addresses
+		 */
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 
-	if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
-		struct rte_flow_error err;
-		const struct rte_security_capability *sec_cap;
-		int ret = 0;
-
-		sec_ctx = (struct rte_security_ctx *)
-					rte_eth_dev_get_sec_ctx(
-					sa->portid);
-		if (sec_ctx == NULL) {
-			RTE_LOG(ERR, IPSEC,
-				" rte_eth_dev_get_sec_ctx failed\n");
-			return -1;
-		}
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 
-		ips->security.ses = rte_security_session_create(sec_ctx,
-				&sess_conf, skt_ctx->session_pool,
-				skt_ctx->session_priv_pool);
-		if (ips->security.ses == NULL) {
-			RTE_LOG(ERR, IPSEC,
-				"SEC Session init failed: err: %d\n", ret);
-			return -1;
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
 		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
 
-		sec_cap = rte_security_capabilities_get(sec_ctx);
-
-		/* iterate until ESP tunnel*/
-		while (sec_cap->action != RTE_SECURITY_ACTION_TYPE_NONE) {
-			if (sec_cap->action == ips->type &&
-			    sec_cap->protocol ==
-				RTE_SECURITY_PROTOCOL_IPSEC &&
-			    sec_cap->ipsec.mode ==
-				RTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&
-			    sec_cap->ipsec.direction == sa->direction)
-				break;
-			sec_cap++;
-		}
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 
-		if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {
-			RTE_LOG(ERR, IPSEC,
-				"No suitable security capability found\n");
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
 			return -1;
 		}
+	}
 
-		ips->security.ol_flags = sec_cap->ol_flags;
-		ips->security.ctx = sec_ctx;
-		sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	if (IS_NATT_UDP_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.options.udp_encap = 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;
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
 
-			memcpy(sa->ipv6_spec.hdr.dst_addr,
-				sa->dst.ip.ip6.ip6_b, 16);
-			memcpy(sa->ipv6_spec.hdr.src_addr,
-			       sa->src.ip.ip6.ip6_b, 16);
-		} 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;
-		}
+	struct rte_flow_action_security action_security;
+	struct rte_flow_error err;
+
+	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
+		sa->spi, sa->portid);
+
+	sec_ctx = (struct rte_security_ctx *)
+				rte_eth_dev_get_sec_ctx(sa->portid);
+	if (sec_ctx == NULL) {
+		RTE_LOG(ERR, IPSEC,
+			" rte_eth_dev_get_sec_ctx failed\n");
+		return -1;
+	}
+
+	ips->security.ses = rte_security_session_create(sec_ctx,
+			&sess_conf, skt_ctx->session_pool,
+			skt_ctx->session_priv_pool);
+	if (ips->security.ses == NULL) {
+		RTE_LOG(ERR, IPSEC,
+			"SEC Session init failed: err: %d\n", ret);
+		return -1;
+	}
+
+	ips->security.ctx = sec_ctx;
+
+	sec_cap = rte_security_capabilities_get(sec_ctx);
+
+	ips->security.ol_flags = sec_cap->ol_flags;
+
+	if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		return 0;
+
+	sa->pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+	sa->pattern[0].spec = NULL;
+
+	if (IS_IP6(sa->flags)) {
+		memcpy(sa->ipv6_spec.hdr.dst_addr,
+			sa->dst.ip.ip6.ip6_b, 16);
+		memcpy(sa->ipv6_spec.hdr.src_addr,
+			sa->src.ip.ip6.ip6_b, 16);
+
+		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;
+
+	} else if (IS_IP4(sa->flags)) {
+		sa->ipv4_spec.hdr.dst_addr = sa->dst.ip.ip4;
+		sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
+
+		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;
+	}
+
+	if (IS_NATT_UDP_TUNNEL(sa->flags)) {
+
+		sa->udp_spec.hdr.dst_port = rte_cpu_to_be_16(sa->udp.dport);
+		sa->udp_spec.hdr.src_port = rte_cpu_to_be_16(sa->udp.sport);
+
+		sa->pattern[2].mask = &rte_flow_item_udp_mask;
+		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+		sa->pattern[2].spec = &sa->udp_spec;
+
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
+
+		sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+		sa->pattern[3].spec = &sa->esp_spec;
+		sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+		sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+	} else {
+		sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
 
 		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[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
-		sa->action[0].conf = ips->security.ses;
-
-		sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
-
-		sa->attr.egress = (sa->direction ==
-				RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
-		sa->attr.ingress = (sa->direction ==
-				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
-		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
-			struct rte_eth_rss_conf rss_conf = {
-				.rss_key = rss_key,
-				.rss_key_len = 40,
-			};
-			struct rte_eth_dev_info dev_info;
-			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-			struct rte_flow_action_rss action_rss;
-			unsigned int i;
-			unsigned int j;
-
-			/* Don't create flow if default flow is created */
-			if (flow_info_tbl[sa->portid].rx_def_flow)
-				return 0;
-
-			ret = rte_eth_dev_info_get(sa->portid, &dev_info);
-			if (ret != 0) {
-				RTE_LOG(ERR, IPSEC,
-					"Error during getting device (port %u) info: %s\n",
-					sa->portid, strerror(-ret));
-				return ret;
-			}
-
-			sa->action[2].type = RTE_FLOW_ACTION_TYPE_END;
-			/* Try RSS. */
-			sa->action[1].type = RTE_FLOW_ACTION_TYPE_RSS;
-			sa->action[1].conf = &action_rss;
-			ret = rte_eth_dev_rss_hash_conf_get(sa->portid,
-					&rss_conf);
-			if (ret != 0) {
-				RTE_LOG(ERR, IPSEC,
-					"rte_eth_dev_rss_hash_conf_get:ret=%d\n",
-					ret);
-				return -1;
-			}
-			for (i = 0, j = 0; i < dev_info.nb_rx_queues; ++i)
-				queue[j++] = i;
-
-			action_rss = (struct rte_flow_action_rss){
-					.types = rss_conf.rss_hf,
-					.key_len = rss_conf.rss_key_len,
-					.queue_num = j,
-					.key = rss_key,
-					.queue = queue,
-			};
-			ret = rte_flow_validate(sa->portid, &sa->attr,
-						sa->pattern, sa->action,
-						&err);
-			if (!ret)
-				goto flow_create;
-			/* Try Queue. */
-			sa->action[1].type = RTE_FLOW_ACTION_TYPE_QUEUE;
-			sa->action[1].conf =
-				&(struct rte_flow_action_queue){
-				.index = 0,
-			};
-			ret = rte_flow_validate(sa->portid, &sa->attr,
-						sa->pattern, sa->action,
-						&err);
-			/* Try End. */
-			sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
-			sa->action[1].conf = NULL;
-			ret = rte_flow_validate(sa->portid, &sa->attr,
-						sa->pattern, sa->action,
-						&err);
-			if (ret)
-				goto flow_create_failure;
-		} else if (sa->attr.egress &&
-				(ips->security.ol_flags &
-					RTE_SECURITY_TX_HW_TRAILER_OFFLOAD)) {
-			sa->action[1].type =
-					RTE_FLOW_ACTION_TYPE_PASSTHRU;
-			sa->action[2].type =
-					RTE_FLOW_ACTION_TYPE_END;
-		}
-flow_create:
-		sa->flow = rte_flow_create(sa->portid,
-				&sa->attr, sa->pattern, sa->action, &err);
-		if (sa->flow == NULL) {
-flow_create_failure:
-			RTE_LOG(ERR, IPSEC,
-				"Failed to create ipsec flow msg: %s\n",
-				err.message);
-			return -1;
-		}
-	} else if (ips->type ==	RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) {
-		const struct rte_security_capability *sec_cap;
+	action_security.security_session = ips->security.ses;
 
-		sec_ctx = (struct rte_security_ctx *)
-				rte_eth_dev_get_sec_ctx(sa->portid);
+	sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
+	sa->action[0].conf = &action_security;
 
-		if (sec_ctx == NULL) {
-			RTE_LOG(ERR, IPSEC,
-				"Ethernet device doesn't have security features registered\n");
-			return -1;
-		}
 
-		/* Set IPsec parameters in conf */
-		set_ipsec_conf(sa, &(sess_conf.ipsec));
-
-		/* Save SA as userdata for the security session. When
-		 * the packet is received, this userdata will be
-		 * retrieved using the metadata from the packet.
-		 *
-		 * The PMD is expected to set similar metadata for other
-		 * operations, like rte_eth_event, which are tied to
-		 * security session. In such cases, the userdata could
-		 * be obtained to uniquely identify the security
-		 * parameters denoted.
-		 */
+	sa->action[1].type = RTE_FLOW_ACTION_TYPE_END;
+	sa->action[1].conf = NULL;
 
-		sess_conf.userdata = (void *) sa;
+	sa->attr.egress = (sa->direction ==
+			RTE_SECURITY_IPSEC_SA_DIR_EGRESS);
 
-		ips->security.ses = rte_security_session_create(sec_ctx,
-					&sess_conf, skt_ctx->session_pool,
-					skt_ctx->session_priv_pool);
-		if (ips->security.ses == NULL) {
-			RTE_LOG(ERR, IPSEC,
-				"SEC Session init failed: err: %d\n", ret);
-			return -1;
-		}
+	if (sa->attr.egress)
+		return 0;
 
-		sec_cap = rte_security_capabilities_get(sec_ctx);
-		if (sec_cap == NULL) {
-			RTE_LOG(ERR, IPSEC,
-				"No capabilities registered\n");
-			return -1;
-		}
+	sa->attr.ingress = (sa->direction ==
+			RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 
-		/* iterate until ESP tunnel*/
-		while (sec_cap->action !=
-				RTE_SECURITY_ACTION_TYPE_NONE) {
-			if (sec_cap->action == ips->type &&
-			    sec_cap->protocol ==
-				RTE_SECURITY_PROTOCOL_IPSEC &&
-			    sec_cap->ipsec.mode ==
-				sess_conf.ipsec.mode &&
-			    sec_cap->ipsec.direction == sa->direction)
-				break;
-			sec_cap++;
-		}
 
-		if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) {
-			RTE_LOG(ERR, IPSEC,
-				"No suitable security capability found\n");
-			return -1;
-		}
+	ret = rte_flow_validate(sa->portid,
+				&sa->attr,
+				sa->pattern,
+				sa->action,
+				&err);
+	if (ret)
+		goto flow_create_failure;
 
-		ips->security.ol_flags = sec_cap->ol_flags;
-		ips->security.ctx = sec_ctx;
+	sa->flow = rte_flow_create(sa->portid, &sa->attr, sa->pattern,
+					sa->action, &err);
+	if (sa->flow == NULL) {
+flow_create_failure:
+		RTE_LOG(ERR, IPSEC,
+			"Failed to create ipsec flow msg: %s\n",
+			err.message);
+		return -1;
 	}
 
+	sa->cdev_id_qp = 0;
+
 	return 0;
 }
 
@@ -427,23 +361,28 @@ 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) {
+
+	if (IS_TRANSPORT(sa->flags)) {
 		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;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index ae5058de27..b496b4a936 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -122,11 +122,15 @@ struct ipsec_sa {
 	uint16_t flags;
 #define IP4_TUNNEL (1 << 0)
 #define IP6_TUNNEL (1 << 1)
-#define TRANSPORT  (1 << 2)
+#define NATT_UDP_TUNNEL  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -142,7 +146,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -151,6 +155,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
@@ -181,18 +186,16 @@ struct ipsec_mbuf_metadata {
 	uint8_t buf[32];
 } __rte_cache_aligned;
 
-#define IS_TRANSPORT(flags) ((flags) & TRANSPORT)
+#define IS_TRANSPORT(flags) ((flags) & (IP4_TRANSPORT | IP6_TRANSPORT))
 
 #define IS_TUNNEL(flags) ((flags) & (IP4_TUNNEL | IP6_TUNNEL))
 
+#define IS_NATT_UDP_TUNNEL(flags) ((flags) & NATT_UDP_TUNNEL)
+
 #define IS_IP4(flags) ((flags) & (IP4_TUNNEL | IP4_TRANSPORT))
 
 #define IS_IP6(flags) ((flags) & (IP6_TUNNEL | IP6_TRANSPORT))
 
-#define IS_IP4_TUNNEL(flags) ((flags) & IP4_TUNNEL)
-
-#define IS_IP6_TUNNEL(flags) ((flags) & IP6_TUNNEL)
-
 /*
  * Macro for getting ipsec_sa flags statuses without version of protocol
  * used for transport (IP4_TRANSPORT and IP6_TRANSPORT flags).
@@ -200,7 +203,7 @@ struct ipsec_mbuf_metadata {
 #define WITHOUT_TRANSPORT_VERSION(flags) \
 		((flags) & (IP4_TUNNEL | \
 			IP6_TUNNEL | \
-			TRANSPORT))
+			(IP4_TRANSPORT | IP6_TRANSPORT)))
 
 struct cdev_qp {
 	uint16_t id;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 17a28556c9..d5943f8cdc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -339,13 +340,28 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
 				rule->flags = IP4_TUNNEL;
+			} else if (strcmp(tokens[ti], "ipv4-udp-tunnel") == 0) {
+				sa_cnt->nb_v4++;
+				rule->flags = IP4_TUNNEL | NATT_UDP_TUNNEL;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
 				rule->flags = IP6_TUNNEL;
+			} else if (strcmp(tokens[ti], "ipv6-udp-tunnel") == 0) {
+				sa_cnt->nb_v6++;
+				rule->flags = IP6_TUNNEL | NATT_UDP_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags = IP4_TRANSPORT | IP6_TRANSPORT;
+			} else if (strcmp(tokens[ti], "udp-transport") == 0) {
+				sa_cnt->nb_v4++;
+				sa_cnt->nb_v6++;
+				rule->flags = IP4_TRANSPORT | IP6_TRANSPORT |
+						NATT_UDP_TUNNEL;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -548,7 +564,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
-			if (IS_IP4_TUNNEL(rule->flags)) {
+			if (IS_IP4(rule->flags) && IS_TUNNEL(rule->flags)) {
 				struct in_addr ip;
 
 				APP_CHECK(parse_ipv4_addr(tokens[ti],
@@ -560,7 +576,8 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 					return;
 				rule->src.ip.ip4 = rte_bswap32(
 					(uint32_t)ip.s_addr);
-			} else if (IS_IP6_TUNNEL(rule->flags)) {
+			} else if (IS_IP6(rule->flags) &&
+					IS_TUNNEL(rule->flags)) {
 				struct in6_addr ip;
 
 				APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
@@ -591,7 +608,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
-			if (IS_IP4_TUNNEL(rule->flags)) {
+			if (IS_IP4(rule->flags) && IS_TUNNEL(rule->flags)) {
 				struct in_addr ip;
 
 				APP_CHECK(parse_ipv4_addr(tokens[ti],
@@ -603,7 +620,8 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 					return;
 				rule->dst.ip.ip4 = rte_bswap32(
 					(uint32_t)ip.s_addr);
-			} else if (IS_IP6_TUNNEL(rule->flags)) {
+			} else if (IS_IP6(rule->flags) &&
+					IS_TUNNEL(rule->flags)) {
 				struct in6_addr ip;
 
 				APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
@@ -832,19 +850,19 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	const struct rte_ipsec_session *ips;
 	const struct rte_ipsec_session *fallback_ips;
 
-	printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi);
+	printf("\tspi_%s (%3u):", inbound?"in":"out", sa->spi);
 
 	for (i = 0; i < RTE_DIM(cipher_algos); i++) {
 		if (cipher_algos[i].algo == sa->cipher_algo &&
 				cipher_algos[i].key_len == sa->cipher_key_len) {
-			printf("%s ", cipher_algos[i].keyword);
+			printf(" %s", cipher_algos[i].keyword);
 			break;
 		}
 	}
 
 	for (i = 0; i < RTE_DIM(auth_algos); i++) {
 		if (auth_algos[i].algo == sa->auth_algo) {
-			printf("%s ", auth_algos[i].keyword);
+			printf(" %s", auth_algos[i].keyword);
 			break;
 		}
 	}
@@ -852,23 +870,29 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	for (i = 0; i < RTE_DIM(aead_algos); i++) {
 		if (aead_algos[i].algo == sa->aead_algo &&
 				aead_algos[i].key_len-4 == sa->cipher_key_len) {
-			printf("%s ", aead_algos[i].keyword);
+			printf(" %s ", aead_algos[i].keyword);
 			break;
 		}
 	}
 
-	printf("mode:");
+	printf(", mode:");
+
+	if (IS_IP4(sa->flags) && IS_TUNNEL(sa->flags)) {
 
-	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
-	case IP4_TUNNEL:
-		printf("IP4Tunnel ");
+		if (IS_NATT_UDP_TUNNEL(sa->flags))
+			printf("IP4Tunnel NAT-T (");
+		else
+			printf("IP4Tunnel (");
 		uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d);
 		printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a);
 		uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d);
 		printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a);
-		break;
-	case IP6_TUNNEL:
-		printf("IP6Tunnel ");
+	} else if (IS_IP6(sa->flags) && IS_TUNNEL(sa->flags)) {
+
+		if (IS_NATT_UDP_TUNNEL(sa->flags))
+			printf("IP6Tunnel NAT-T (");
+		else
+			printf("IP6Tunnel (");
 		for (i = 0; i < 16; i++) {
 			if (i % 2 && i != 15)
 				printf("%.2x:", sa->src.ip.ip6.ip6_b[i]);
@@ -882,14 +906,15 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 			else
 				printf("%.2x", sa->dst.ip.ip6.ip6_b[i]);
 		}
-		break;
-	case TRANSPORT:
-		printf("Transport ");
-		break;
+	} else if (IS_TRANSPORT(sa->flags)) {
+		if (IS_NATT_UDP_TUNNEL(sa->flags))
+			printf("Transport NAT-T (");
+		else
+			printf("Transport (");
 	}
 
 	ips = &sa->sessions[IPSEC_SESSION_PRIMARY];
-	printf(" type:");
+	printf("), type: ");
 	switch (ips->type) {
 	case RTE_SECURITY_ACTION_TYPE_NONE:
 		printf("no-offload ");
@@ -1053,7 +1078,11 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 	protocol = get_spi_proto(sa->spi, sa->direction, ip_addr, mask);
 	if (protocol < 0)
 		return protocol;
-	else if (protocol == IPPROTO_IPIP) {
+
+	/* Clear transport bits before selecting IP4/IP6 */
+	sa->flags &= ~(IP4_TRANSPORT | IP6_TRANSPORT);
+
+	if (protocol == IPPROTO_IPIP) {
 		sa->flags |= IP4_TRANSPORT;
 		if (mask[0] == IP4_FULL_MASK &&
 				mask[1] == IP4_FULL_MASK &&
@@ -1131,12 +1160,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 		}
 
-		switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
-		case IP4_TUNNEL:
-			sa->src.ip.ip4 = rte_cpu_to_be_32(sa->src.ip.ip4);
-			sa->dst.ip.ip4 = rte_cpu_to_be_32(sa->dst.ip.ip4);
-			break;
-		case TRANSPORT:
+		if (IS_TRANSPORT(sa->flags)) {
 			if (ips->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
 				inline_status =
@@ -1144,11 +1168,25 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				if (inline_status < 0)
 					return inline_status;
 			}
-			break;
+		} else if (IS_TUNNEL(sa->flags)) {
+			if (IS_IP4(sa->flags)) {
+				sa->src.ip.ip4 =
+					rte_cpu_to_be_32(sa->src.ip.ip4);
+				sa->dst.ip.ip4 =
+					rte_cpu_to_be_32(sa->dst.ip.ip4);
+			}
+
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)
+				iv_length = 8;
+			else
+				iv_length = 12;
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1285,9 +1323,21 @@ fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
 	prm->ipsec_xform.replay_win_sz = app_prm->window_size;
 }
 
+struct udp_ipv4_tunnel {
+	struct rte_ipv4_hdr v4;
+	struct rte_udp_hdr udp;
+} __rte_packed;
+
+struct udp_ipv6_tunnel {
+	struct rte_ipv6_hdr v6;
+	struct rte_udp_hdr udp;
+} __rte_packed;
+
 static int
 fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
-	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
+	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6,
+	const struct udp_ipv4_tunnel *udp_ipv4,
+	const struct udp_ipv6_tunnel *udp_ipv6)
 {
 	int32_t rc;
 
@@ -1311,22 +1361,49 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap =
+			(IS_NATT_UDP_TUNNEL(ss->flags)) ? 1 : 0;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
-	if (IS_IP4_TUNNEL(ss->flags)) {
-		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
-		prm->tun.hdr_len = sizeof(*v4);
-		prm->tun.next_proto = rc;
-		prm->tun.hdr = v4;
-	} else if (IS_IP6_TUNNEL(ss->flags)) {
-		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
-		prm->tun.hdr_len = sizeof(*v6);
-		prm->tun.next_proto = rc;
-		prm->tun.hdr = v6;
-	} else {
+	if (IS_TRANSPORT(ss->flags)) {
 		/* transport mode */
 		prm->trs.proto = rc;
+	} else if (IS_TUNNEL(ss->flags)) {
+		prm->tun.hdr_l3_off = 0;
+
+		/* tunnel mode */
+		if (IS_IP4(ss->flags)) {
+			prm->ipsec_xform.tunnel.type =
+					RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+			prm->tun.next_proto = rc;
+			prm->tun.hdr_l3_len = sizeof(*v4);
+
+			if (IS_NATT_UDP_TUNNEL(ss->flags)) {
+				prm->tun.hdr_len = sizeof(*udp_ipv4);
+				prm->tun.hdr = udp_ipv4;
+
+			} else {
+				prm->tun.hdr_len = sizeof(*v4);
+				prm->tun.hdr = v4;
+			}
+
+		} else if (IS_IP6(ss->flags)) {
+			prm->ipsec_xform.tunnel.type =
+					RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+			prm->tun.next_proto = rc;
+			prm->tun.hdr_l3_len = sizeof(*v6);
+
+			if (IS_NATT_UDP_TUNNEL(ss->flags)) {
+
+				prm->tun.hdr_len = sizeof(*udp_ipv6);
+				prm->tun.hdr = udp_ipv6;
+
+			} else {
+				prm->tun.hdr_len = sizeof(*v6);
+				prm->tun.hdr = v6;
+			}
+		}
 	}
 
 	/* setup crypto section */
@@ -1362,25 +1439,66 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	int rc;
 	struct rte_ipsec_sa_prm prm;
 	struct rte_ipsec_session *ips;
-	struct rte_ipv4_hdr v4  = {
-		.version_ihl = IPVERSION << 4 |
-			sizeof(v4) / RTE_IPV4_IHL_MULTIPLIER,
-		.time_to_live = IPDEFTTL,
-		.next_proto_id = IPPROTO_ESP,
-		.src_addr = lsa->src.ip.ip4,
-		.dst_addr = lsa->dst.ip.ip4,
-	};
-	struct rte_ipv6_hdr v6 = {
-		.vtc_flow = htonl(IP6_VERSION << 28),
-		.proto = IPPROTO_ESP,
-	};
-
-	if (IS_IP6_TUNNEL(lsa->flags)) {
-		memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b, sizeof(v6.src_addr));
-		memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
+	struct rte_ipv4_hdr v4;
+	struct rte_ipv6_hdr v6;
+	struct udp_ipv4_tunnel udp_ipv4;
+	struct udp_ipv6_tunnel udp_ipv6;
+
+
+	if (IS_TUNNEL(lsa->flags) && IS_NATT_UDP_TUNNEL(lsa->flags)) {
+		if (IS_IP4(lsa->flags)) {
+
+			udp_ipv4.v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+					RTE_IPV4_IHL_MULTIPLIER;
+			udp_ipv4.v4.time_to_live = IPDEFTTL;
+			udp_ipv4.v4.next_proto_id = IPPROTO_UDP;
+			udp_ipv4.v4.src_addr = lsa->src.ip.ip4;
+			udp_ipv4.v4.dst_addr = lsa->dst.ip.ip4;
+
+			udp_ipv4.udp.src_port =
+					rte_cpu_to_be_16(lsa->udp.sport);
+			udp_ipv4.udp.dst_port =
+					rte_cpu_to_be_16(lsa->udp.dport);
+
+		} else if (IS_IP6(lsa->flags)) {
+
+			udp_ipv6.v6.vtc_flow = htonl(IP6_VERSION << 28),
+			udp_ipv6.v6.proto = IPPROTO_UDP,
+			memcpy(udp_ipv6.v6.src_addr, lsa->src.ip.ip6.ip6_b,
+					sizeof(udp_ipv6.v6.src_addr));
+			memcpy(udp_ipv6.v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+					sizeof(udp_ipv6.v6.dst_addr));
+
+			udp_ipv6.udp.src_port =
+					rte_cpu_to_be_16(lsa->udp.sport);
+			udp_ipv6.udp.dst_port =
+					rte_cpu_to_be_16(lsa->udp.dport);
+		}
+
+	} else if (IS_TUNNEL(lsa->flags)) {
+
+		if (IS_IP4(lsa->flags)) {
+			v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+					RTE_IPV4_IHL_MULTIPLIER;
+			v4.time_to_live = IPDEFTTL;
+			v4.next_proto_id = IPPROTO_ESP;
+			v4.src_addr = lsa->src.ip.ip4;
+			v4.dst_addr = lsa->dst.ip.ip4;
+
+		} else if (IS_IP6(lsa->flags)) {
+
+			v6.vtc_flow = htonl(IP6_VERSION << 28),
+			v6.proto = IPPROTO_ESP,
+			memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b,
+					sizeof(v6.src_addr));
+			memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+					sizeof(v6.dst_addr));
+
+		}
+
 	}
 
-	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
+	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6, &udp_ipv4, &udp_ipv6);
 	if (rc == 0)
 		rc = rte_ipsec_sa_init(sa, &prm, sa_size);
 	if (rc < 0)
@@ -1415,7 +1533,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
 
 	/* determine SA size */
 	idx = 0;
-	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
+	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL, NULL, NULL);
 	sz = rte_ipsec_sa_size(&prm);
 	if (sz < 0) {
 		RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
index 5b2c0e6792..191fc79faf 100644
--- a/examples/ipsec-secgw/sad.c
+++ b/examples/ipsec-secgw/sad.c
@@ -25,8 +25,8 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 	/* spi field is common for ipv4 and ipv6 key types */
 	key.v4.spi = rte_cpu_to_be_32(sa->spi);
 	lookup_key[0] = &key;
-	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
-	case IP4_TUNNEL:
+
+	if (IS_IP4(sa->flags) && IS_TUNNEL(sa->flags)) {
 		rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
 		if (tmp != NULL)
 			return -EEXIST;
@@ -35,8 +35,7 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 			RTE_IPSEC_SAD_SPI_ONLY, sa);
 		if (ret != 0)
 			return ret;
-		break;
-	case IP6_TUNNEL:
+	} else if (IS_IP6(sa->flags) && IS_TUNNEL(sa->flags)) {
 		rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
 		if (tmp != NULL)
 			return -EEXIST;
@@ -45,8 +44,7 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 			RTE_IPSEC_SAD_SPI_ONLY, sa);
 		if (ret != 0)
 			return ret;
-		break;
-	case TRANSPORT:
+	} else if (IS_TRANSPORT(sa->flags)) {
 		if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
 			rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
 			if (tmp != NULL)
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index 3224b6252c..6813a47942 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -29,16 +29,16 @@ static inline int
 cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,
 	struct rte_ipv6_hdr *ipv6)
 {
-	int sa_type = WITHOUT_TRANSPORT_VERSION(sa->flags);
-	if ((sa_type == TRANSPORT) ||
-			/* IPv4 check */
-			(is_v4 && (sa_type == IP4_TUNNEL) &&
-			(sa->src.ip.ip4 == ipv4->src_addr) &&
-			(sa->dst.ip.ip4 == ipv4->dst_addr)) ||
-			/* IPv6 check */
-			(!is_v4 && (sa_type == IP6_TUNNEL) &&
-			(!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&
-			(!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))
+
+	if (IS_TRANSPORT(sa->flags) ||
+		/* IPv4 check */
+		(is_v4 && IS_IP4(sa->flags) &&
+		(sa->src.ip.ip4 == ipv4->src_addr) &&
+		(sa->dst.ip.ip4 == ipv4->dst_addr)) ||
+		/* IPv6 check */
+		(!is_v4 && IS_IP6(sa->flags) &&
+		(!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&
+		(!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))
 		return 1;
 
 	return 0;
-- 
2.25.1


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

* [dpdk-dev] [PATCH 3/7] examples/ipsec-secgw: add support for TSO
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support Radu Nicolau
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 12:54   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default Radu Nicolau
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add support to allow user to specific MSS for TSO offload on a per SA
basis. MSS configuration in the context of IPsec is only supported for
outbound SA's in the context of an inline IPsec Crypto offload.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.h |  1 +
 examples/ipsec-secgw/sa.c    | 15 +++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index b496b4a936..7ba29406bf 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -143,6 +143,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint16_t mss;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index d5943f8cdc..bc83e4bccc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -695,6 +695,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "mss") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->mss = atoi(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
@@ -1366,6 +1376,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
+	if (ss->mss > 0) {
+		prm->ipsec_xform.options.tso = 1;
+		prm->ipsec_xform.mss = ss->mss;
+	}
+
 	if (IS_TRANSPORT(ss->flags)) {
 		/* transport mode */
 		prm->trs.proto = rc;
-- 
2.25.1


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

* [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (2 preceding siblings ...)
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 3/7] examples/ipsec-secgw: add support for TSO Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-03 12:50   ` Zhang, Roy Fan
  2021-09-08 13:08   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry Radu Nicolau
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Enable stats screen by default

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..ede610bcde 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -7,7 +7,7 @@
 #include <stdbool.h>
 
 #ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
+#define STATS_INTERVAL 10ULL
 #endif
 
 #define NB_SOCKETS 4
-- 
2.25.1


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

* [dpdk-dev] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (3 preceding siblings ...)
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 14:09   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add telemetry support to the IPsec GW sample app

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 370 +++++++++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h |  31 +++
 examples/ipsec-secgw/ipsec.h       |   2 +
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          |  21 +-
 5 files changed, 401 insertions(+), 25 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 46fb49d91e..e725d84e7c 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -48,6 +48,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -668,7 +669,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -685,25 +686,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -747,6 +753,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -762,16 +769,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -779,20 +790,27 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	if (ip->num == 0 || sp == NULL)
 		return;
 
-	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
-			ip->num, DEFAULT_MAX_CATEGORIES);
+	rte_acl_classify((struct rte_acl_ctx *)sp,
+			ip->data, ip->res, ip->num,
+			DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -804,15 +822,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -966,6 +989,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1001,6 +1025,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1017,6 +1042,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1053,6 +1079,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1126,6 +1153,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1143,13 +1171,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2826,6 +2856,308 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dopped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.outbound.spd4.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.outbound.spd6.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+static void
+telemetry_init(void)
+{
+	rte_ipsec_telemetry_init();
+
+	ipsec_secgw_telemetry_init();
+
+}
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2863,6 +3195,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index ede610bcde..faa2b2c262 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -83,6 +83,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 #if (STATS_INTERVAL > 0)
 struct ipsec_core_statistics {
 	uint64_t tx;
@@ -91,6 +102,26 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 7ba29406bf..4f12c57dc3 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,8 @@ struct ipsec_sa {
 #define NATT_UDP_TUNNEL  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	struct {
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index bc83e4bccc..37039e70fc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -323,6 +323,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -339,26 +340,26 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv4-udp-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL | NATT_UDP_TUNNEL;
+				rule->flags |= IP4_TUNNEL | NATT_UDP_TUNNEL;
 				rule->udp.sport = 0;
 				rule->udp.dport = 4500;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-udp-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL | NATT_UDP_TUNNEL;
+				rule->flags |= IP6_TUNNEL | NATT_UDP_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = IP4_TRANSPORT | IP6_TRANSPORT;
+				rule->flags |= IP4_TRANSPORT | IP6_TRANSPORT;
 			} else if (strcmp(tokens[ti], "udp-transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = IP4_TRANSPORT | IP6_TRANSPORT |
+				rule->flags |= IP4_TRANSPORT | IP6_TRANSPORT |
 						NATT_UDP_TUNNEL;
 				rule->udp.sport = 0;
 				rule->udp.dport = 4500;
@@ -372,6 +373,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1519,6 +1525,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (4 preceding siblings ...)
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 14:11   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add esn field to SA definition block to allow initial ESN value

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.c |  5 +++++
 examples/ipsec-secgw/ipsec.h |  2 ++
 examples/ipsec-secgw/sa.c    | 15 +++++++++++++++
 3 files changed, 22 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index aa68e4f827..28772da345 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -234,6 +234,11 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
 	struct rte_flow_action_security action_security;
 	struct rte_flow_error err;
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 4f12c57dc3..db7988604a 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -146,6 +146,8 @@ struct ipsec_sa {
 	uint8_t udp_encap;
 	uint16_t portid;
 	uint16_t mss;
+	uint16_t esn;
+
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 37039e70fc..3ee5ed7dcf 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -711,6 +711,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
@@ -1387,6 +1397,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 		prm->ipsec_xform.mss = ss->mss;
 	}
 
+	if (ss->esn > 0) {
+		prm->ipsec_xform.options.esn = 1;
+		prm->ipsec_xform.esn.value = ss->esn;
+	}
+
 	if (IS_TRANSPORT(ss->flags)) {
 		/* transport mode */
 		prm->trs.proto = rc;
-- 
2.25.1


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

* [dpdk-dev] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (5 preceding siblings ...)
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
@ 2021-09-03 11:22 ` Radu Nicolau
  2021-09-08 14:24   ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-09-03 11:22 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty

Add event handler for ethdev reset callback

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c |  18 +++-
 examples/ipsec-secgw/ipsec.h       |   4 +-
 examples/ipsec-secgw/sa.c          | 130 +++++++++++++++++++++++++++--
 3 files changed, 139 insertions(+), 13 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index e725d84e7c..9ba9568978 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2254,7 +2254,7 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads)
 			local_port_conf.rxmode.offloads)
 		rte_exit(EXIT_FAILURE,
 			"Error: port %u required RX offloads: 0x%" PRIx64
-			", avaialbe RX offloads: 0x%" PRIx64 "\n",
+			", available RX offloads: 0x%" PRIx64 "\n",
 			portid, local_port_conf.rxmode.offloads,
 			dev_info.rx_offload_capa);
 
@@ -2262,7 +2262,7 @@ port_init(uint16_t portid, uint64_t req_rx_offloads, uint64_t req_tx_offloads)
 			local_port_conf.txmode.offloads)
 		rte_exit(EXIT_FAILURE,
 			"Error: port %u required TX offloads: 0x%" PRIx64
-			", avaialbe TX offloads: 0x%" PRIx64 "\n",
+			", available TX offloads: 0x%" PRIx64 "\n",
 			portid, local_port_conf.txmode.offloads,
 			dev_info.tx_offload_capa);
 
@@ -2543,6 +2543,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type __rte_unused,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d\n", port_id);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3317,6 +3328,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index db7988604a..e8752e0bde 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -65,7 +65,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
+#define MAX_KEY_SIZE	132
 
 /*
  * application wide SA parameters
@@ -146,7 +146,7 @@ struct ipsec_sa {
 	uint8_t udp_encap;
 	uint16_t portid;
 	uint16_t mss;
-	uint16_t esn;
+	uint32_t esn;
 
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 3ee5ed7dcf..0be8bdef7a 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -46,6 +46,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -352,6 +428,8 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			} else if (strcmp(tokens[ti], "ipv6-udp-tunnel") == 0) {
 				sa_cnt->nb_v6++;
 				rule->flags |= IP6_TUNNEL | NATT_UDP_TUNNEL;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
@@ -499,6 +577,15 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1209,10 +1296,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
 			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
 
-			if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
 				iv_length = 8;
-			else
-				iv_length = 12;
+			} else {
+				if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+					iv_length = 11;
+				else
+					iv_length = 12;
+			}
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1236,10 +1328,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1248,6 +1338,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				if (ips->type ==
+				    RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+					iv_length = 8;
+				} else {
+					iv_length = 12;
+				}
+			}
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1269,6 +1368,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1290,11 +1392,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* Re: [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default Radu Nicolau
@ 2021-09-03 12:50   ` Zhang, Roy Fan
  2021-09-08 13:08   ` [dpdk-dev] [EXT] " Akhil Goyal
  1 sibling, 0 replies; 82+ messages in thread
From: Zhang, Roy Fan @ 2021-09-03 12:50 UTC (permalink / raw)
  To: Nicolau, Radu, Nicolau, Radu, Akhil Goyal; +Cc: dev, Doherty, Declan



> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Radu Nicolau
> Sent: Friday, September 3, 2021 12:23 PM
> To: Nicolau, Radu <radu.nicolau@intel.com>; Akhil Goyal
> <gakhil@marvell.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
> Subject: [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by
> default
> 
> Enable stats screen by default
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec-secgw.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-
> secgw/ipsec-secgw.h
> index 96e22de45e..ede610bcde 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.h
> +++ b/examples/ipsec-secgw/ipsec-secgw.h
> @@ -7,7 +7,7 @@
>  #include <stdbool.h>
> 
>  #ifndef STATS_INTERVAL
> -#define STATS_INTERVAL 0
> +#define STATS_INTERVAL 10ULL
>  #endif
> 
>  #define NB_SOCKETS 4
> --
> 2.25.1
Acked-by: Fan Zhang <roy.fan.zhang@intel.com>

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

* Re: [dpdk-dev] [EXT] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T Radu Nicolau
@ 2021-09-08 10:36   ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 10:36 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty

Hi Radu,

> Add support to the sample application to support IPsec NAT-T for both
> transport and tunnel modes, for both IPv4 and IPv6.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---

Udp-encapsulation is already supported in the app with the option
--udp-encap in sa configuration and it is enabled for INLINE PROTO and
LOOKASIDE PROTO for IPv4/IPv6. I believe the same can be used for inline crypto case
As well.
Did you try using it? Is there some specific reason for not using it? I believe
We can enhance that option if something is missing in that.

Regards,
Akhil

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

* Re: [dpdk-dev] [EXT] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support Radu Nicolau
@ 2021-09-08 12:48   ` Akhil Goyal
  2021-09-09  8:57     ` Nicolau, Radu
  0 siblings, 1 reply; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 12:48 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty

> Add support for ol_flags to the IPsec GW sample app.

Description is not appropriate.
ol_flags are supported to do what?
How the existing code was not good and
what benefit do we get from this patch?

> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec-secgw.c | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index f252d34985..6d516e2221 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -515,7 +515,7 @@ prepare_traffic(struct rte_mbuf **pkts, struct
> ipsec_traffic *t,
> 
>  static inline void
>  prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port,
> -		const struct lcore_conf *qconf)
> +		const struct lcore_conf *qconf __rte_unused)
>  {
>  	struct ip *ip;
>  	struct rte_ether_hdr *ethhdr;
> @@ -526,20 +526,17 @@ prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t
> port,
>  		rte_pktmbuf_prepend(pkt, RTE_ETHER_HDR_LEN);
> 
>  	if (ip->ip_v == IPVERSION) {
> -		pkt->ol_flags |= qconf->outbound.ipv4_offloads;
> -		pkt->l3_len = sizeof(struct ip);
>  		pkt->l2_len = RTE_ETHER_HDR_LEN;
> 
> -		ip->ip_sum = 0;
> -
>  		/* calculate IPv4 cksum in SW */
> -		if ((pkt->ol_flags & PKT_TX_IP_CKSUM) == 0)
> +		if ((pkt->ol_flags &
> +				(PKT_TX_IP_CKSUM |
> PKT_TX_OUTER_IP_CKSUM)) == 0)
>  			ip->ip_sum = rte_ipv4_cksum((struct rte_ipv4_hdr
> *)ip);
> +		else
> +			ip->ip_sum = 0;
> 
>  		ethhdr->ether_type =
> rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
>  	} else {
> -		pkt->ol_flags |= qconf->outbound.ipv6_offloads;
> -		pkt->l3_len = sizeof(struct ip6_hdr);
>  		pkt->l2_len = RTE_ETHER_HDR_LEN;
> 
>  		ethhdr->ether_type =
> rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH 3/7] examples/ipsec-secgw: add support for TSO
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 3/7] examples/ipsec-secgw: add support for TSO Radu Nicolau
@ 2021-09-08 12:54   ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 12:54 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty


> Add support to allow user to specific MSS for TSO offload on a per SA

Spell check 'specify'

> basis. MSS configuration in the context of IPsec is only supported for
> outbound SA's in the context of an inline IPsec Crypto offload.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec.h |  1 +
>  examples/ipsec-secgw/sa.c    | 15 +++++++++++++++

No update for the new mss option in the documentation of the app

Please also update description to explain the new option.

>  2 files changed, 16 insertions(+)
> 
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index b496b4a936..7ba29406bf 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -143,6 +143,7 @@ struct ipsec_sa {
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint8_t udp_encap;
>  	uint16_t portid;
> +	uint16_t mss;
>  	uint8_t fdir_qid;
>  	uint8_t fdir_flag;
> 
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index d5943f8cdc..bc83e4bccc 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -695,6 +695,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			continue;
>  		}
> 
> +		if (strcmp(tokens[ti], "mss") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->mss = atoi(tokens[ti]);
> +			if (status->status < 0)
> +				return;
> +			continue;
> +		}
> +
>  		if (strcmp(tokens[ti], "fallback") == 0) {
>  			struct rte_ipsec_session *fb;
> 
> @@ -1366,6 +1376,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm,
> const struct ipsec_sa *ss,
>  	prm->ipsec_xform.options.ecn = 1;
>  	prm->ipsec_xform.options.copy_dscp = 1;
> 
> +	if (ss->mss > 0) {
> +		prm->ipsec_xform.options.tso = 1;
> +		prm->ipsec_xform.mss = ss->mss;
> +	}
> +
>  	if (IS_TRANSPORT(ss->flags)) {
>  		/* transport mode */
>  		prm->trs.proto = rc;
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH 4/7] examples/ipsec-secgw: enable stats by default
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default Radu Nicolau
  2021-09-03 12:50   ` Zhang, Roy Fan
@ 2021-09-08 13:08   ` Akhil Goyal
  2021-09-08 16:05     ` Hemant Agrawal
  1 sibling, 1 reply; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 13:08 UTC (permalink / raw)
  To: Radu Nicolau
  Cc: dev, declan.doherty, Anoob Joseph, Hemant Agrawal,
	konstantin.ananyev, matan


> Enable stats screen by default
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---

I believe timeout should be configurable like we have in l3fwd/l2fwd.
And without recompiling, there should be a way out to disable it.
If we are not doing an effort to do that, then by default it should be
Disabled in my opinion. Others can comment on it.

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

* Re: [dpdk-dev] [EXT] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry Radu Nicolau
@ 2021-09-08 14:09   ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 14:09 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty

> Add telemetry support to the IPsec GW sample app
> 
Add description about how user can use this feature.

> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>


> @@ -779,20 +790,27 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type
> *ip,
>  	if (ip->num == 0 || sp == NULL)
>  		return;
> 
> -	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
> -			ip->num, DEFAULT_MAX_CATEGORIES);
> +	rte_acl_classify((struct rte_acl_ctx *)sp,
> +			ip->data, ip->res, ip->num,
> +			DEFAULT_MAX_CATEGORIES);
Unnecessary change.

> @@ -804,15 +822,20 @@ process_pkts_outbound(struct ipsec_ctx
> *ipsec_ctx,
>  {
>  	struct rte_mbuf *m;
>  	uint16_t idx, nb_pkts_out, i;
> +	unsigned int lcoreid = rte_lcore_id();
> 
>  	/* Drop any IPsec traffic from protected ports */
>  	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
> 
>  	traffic->ipsec.num = 0;
> 
> -	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
> +	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
> +		&traffic->ip4, &traffic->ipsec,
> +		&core_statistics[lcoreid].outbound.spd4);
> 
> -	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
> +	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
> +		&traffic->ip6, &traffic->ipsec,
> +		&core_statistics[lcoreid].outbound.spd4);

It should be core_statistics[lcoreid].outbound.spd6



> +	rte_tel_data_add_dict_u64(data, "packets dopped",
> +				total_pkts_dropped);
> +
> +
Extra line

> +	return 0;
> +}
> +

> +		if (strcmp(tokens[ti], "telemetry") == 0) {
> +			rule->flags |= SA_TELEMETRY_ENABLE;
> +			continue;
> +		}

Documentation update missing for this new option

Please do not add new features without documentation.



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

* Re: [dpdk-dev] [EXT] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
@ 2021-09-08 14:11   ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 14:11 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty

> Add esn field to SA definition block to allow initial ESN value
> 
Add description about the new option added and how to use it.


> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec.c |  5 +++++
>  examples/ipsec-secgw/ipsec.h |  2 ++
>  examples/ipsec-secgw/sa.c    | 15 +++++++++++++++

Documentation missing again.

>  3 files changed, 22 insertions(+)
> 
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index aa68e4f827..28772da345 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -234,6 +234,11 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
>  	}
> 
> +	if (sa->esn > 0) {
> +		sess_conf.ipsec.options.esn = 1;
> +		sess_conf.ipsec.esn.value = sa->esn;
> +	}
> +
>  	struct rte_flow_action_security action_security;
>  	struct rte_flow_error err;
> 
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 4f12c57dc3..db7988604a 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -146,6 +146,8 @@ struct ipsec_sa {
>  	uint8_t udp_encap;
>  	uint16_t portid;
>  	uint16_t mss;
> +	uint16_t esn;
> +
>  	uint8_t fdir_qid;
>  	uint8_t fdir_flag;
> 
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index 37039e70fc..3ee5ed7dcf 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -711,6 +711,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			continue;
>  		}
> 
> +		if (strcmp(tokens[ti], "esn") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->esn = atoll(tokens[ti]);
> +			if (status->status < 0)
> +				return;
> +			continue;
> +		}
> +
>  		if (strcmp(tokens[ti], "fallback") == 0) {
>  			struct rte_ipsec_session *fb;
> 
> @@ -1387,6 +1397,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm,
> const struct ipsec_sa *ss,
>  		prm->ipsec_xform.mss = ss->mss;
>  	}
> 
> +	if (ss->esn > 0) {
> +		prm->ipsec_xform.options.esn = 1;
> +		prm->ipsec_xform.esn.value = ss->esn;
> +	}
> +
>  	if (IS_TRANSPORT(ss->flags)) {
>  		/* transport mode */
>  		prm->trs.proto = rc;
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-09-08 14:24   ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-09-08 14:24 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty

> Add event handler for ethdev reset callback

I believe the below patch need to be split in 4-5 patches.
It has a lot of irrelevant stuff.

> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec-secgw.c |  18 +++-
>  examples/ipsec-secgw/ipsec.h       |   4 +-
>  examples/ipsec-secgw/sa.c          | 130 +++++++++++++++++++++++++++--
>  3 files changed, 139 insertions(+), 13 deletions(-)
> 
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index e725d84e7c..9ba9568978 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -2254,7 +2254,7 @@ port_init(uint16_t portid, uint64_t
> req_rx_offloads, uint64_t req_tx_offloads)
>  			local_port_conf.rxmode.offloads)
>  		rte_exit(EXIT_FAILURE,
>  			"Error: port %u required RX offloads: 0x%" PRIx64
> -			", avaialbe RX offloads: 0x%" PRIx64 "\n",
> +			", available RX offloads: 0x%" PRIx64 "\n",
>  			portid, local_port_conf.rxmode.offloads,
>  			dev_info.rx_offload_capa);
> 
> @@ -2262,7 +2262,7 @@ port_init(uint16_t portid, uint64_t
> req_rx_offloads, uint64_t req_tx_offloads)
>  			local_port_conf.txmode.offloads)
>  		rte_exit(EXIT_FAILURE,
>  			"Error: port %u required TX offloads: 0x%" PRIx64
> -			", avaialbe TX offloads: 0x%" PRIx64 "\n",
> +			", available TX offloads: 0x%" PRIx64 "\n",
>  			portid, local_port_conf.txmode.offloads,
>  			dev_info.tx_offload_capa);

Submit a separate patch for above so that it can be back ported.

> 
> @@ -2543,6 +2543,17 @@ inline_ipsec_event_callback(uint16_t port_id,
> enum rte_eth_event_type type,
>  	return -1;
>  }
> 
> +static int
> +ethdev_reset_event_callback(uint16_t port_id,
> +		enum rte_eth_event_type type __rte_unused,
> +		 void *param __rte_unused, void *ret_param __rte_unused)
> +{
> +	printf("Reset Event on port id %d\n", port_id);
> +	printf("Force quit application");
> +	force_quit = true;
> +	return 0;
> +}
> +
>  static uint16_t
>  rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
>  	struct rte_mbuf *pkt[], uint16_t nb_pkts,
> @@ -3317,6 +3328,9 @@ main(int32_t argc, char **argv)
>  					rte_strerror(-ret), portid);
>  		}
> 
> +		rte_eth_dev_callback_register(portid,
> RTE_ETH_EVENT_INTR_RESET,
> +			ethdev_reset_event_callback, NULL);
> +
>  		rte_eth_dev_callback_register(portid,
>  			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback,
> NULL);
>  	}
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index db7988604a..e8752e0bde 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -65,7 +65,7 @@ struct ip_addr {
>  	} ip;
>  };
> 
> -#define MAX_KEY_SIZE		36
> +#define MAX_KEY_SIZE	132

Reason?? This change do not match with the patch description.

> 
>  /*
>   * application wide SA parameters
> @@ -146,7 +146,7 @@ struct ipsec_sa {
>  	uint8_t udp_encap;
>  	uint16_t portid;
>  	uint16_t mss;
> -	uint16_t esn;
> +	uint32_t esn;
> 
>  	uint8_t fdir_qid;
>  	uint8_t fdir_flag;
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index 3ee5ed7dcf..0be8bdef7a 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -46,6 +46,7 @@ struct supported_cipher_algo {
>  struct supported_auth_algo {
>  	const char *keyword;
>  	enum rte_crypto_auth_algorithm algo;
> +	uint16_t iv_len;
>  	uint16_t digest_len;
>  	uint16_t key_len;
>  	uint8_t key_not_req;
> @@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
>  		.block_size = 4,
>  		.key_len = 20
>  	},
> +	{
> +		.keyword = "aes-192-ctr",
> +		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
> +		.iv_len = 16,
> +		.block_size = 16,
> +		.key_len = 28
> +	},
> +	{
> +		.keyword = "aes-256-ctr",
> +		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
> +		.iv_len = 16,
> +		.block_size = 16,
> +		.key_len = 36
> +	},

I think the above change need a separate patch to add support for new algos.

>  	{
>  		.keyword = "3des-cbc",
>  		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
> @@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
>  		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
>  		.digest_len = 16,
>  		.key_len = 32
> +	},
> +	{
> +		.keyword = "sha384-hmac",
> +		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
> +		.digest_len = 24,
> +		.key_len = 48
> +	},
> +	{
> +		.keyword = "sha512-hmac",
> +		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
> +		.digest_len = 32,
> +		.key_len = 64
> +	},
> +	{
> +		.keyword = "aes-gmac",
> +		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
> +		.iv_len = 8,
> +		.digest_len = 16,
> +		.key_len = 20
> +	},
> +	{
> +		.keyword = "aes-xcbc-mac-96",
> +		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
> +		.digest_len = 12,
> +		.key_len = 16
>  	}
>  };
> 
> @@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
>  		.key_len = 36,
>  		.digest_len = 16,
>  		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-128-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 20,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-192-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 28,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-256-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 36,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "chacha20-poly1305",
> +		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
> +		.iv_len = 12,
> +		.block_size = 64,
> +		.key_len = 36,
> +		.digest_len = 16,
> +		.aad_len = 8,

Above changes are also not relevant to this patch.
And MAX_KEY_SIZE is updated as 132, but max size that I see here is 64.
 
>  	}
>  };
> 
> @@ -352,6 +428,8 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			} else if (strcmp(tokens[ti], "ipv6-udp-tunnel") == 0) {
>  				sa_cnt->nb_v6++;
>  				rule->flags |= IP6_TUNNEL |
> NATT_UDP_TUNNEL;
> +				rule->udp.sport = 0;
> +				rule->udp.dport = 4500;

Again irrelevant change as per the description.

>  			} else if (strcmp(tokens[ti], "transport") == 0) {
>  				sa_cnt->nb_v4++;
>  				sa_cnt->nb_v6++;
> @@ -499,6 +577,15 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			if (status->status < 0)
>  				return;
> 
> +			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
> +				key_len -= 4;
> +				rule->auth_key_len = key_len;
> +				rule->iv_len = algo->iv_len;
> +				memcpy(&rule->salt,
> +					&rule->auth_key[key_len], 4);
> +			}
> +
> +
Extra line and irrelevant change.

>  			auth_algo_p = 1;
>  			continue;
>  		}
> @@ -1209,10 +1296,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
>  			sa->aead_algo ==
> RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
> 
> -			if (ips->type ==
> RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
>  				iv_length = 8;
> -			else
> -				iv_length = 12;
> +			} else {
> +				if (sa->aead_algo ==
> RTE_CRYPTO_AEAD_AES_CCM)
> +					iv_length = 11;
> +				else
> +					iv_length = 12;
> +			}
> 
>  			sa_ctx->xf[idx].a.type =
> RTE_CRYPTO_SYM_XFORM_AEAD;
>  			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
> @@ -1236,10 +1328,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			case RTE_CRYPTO_CIPHER_NULL:
>  			case RTE_CRYPTO_CIPHER_3DES_CBC:
>  			case RTE_CRYPTO_CIPHER_AES_CBC:
> -				iv_length = sa->iv_len;
> -				break;
>  			case RTE_CRYPTO_CIPHER_AES_CTR:
> -				iv_length = 16;
> +				iv_length = sa->iv_len;
>  				break;
>  			default:
>  				RTE_LOG(ERR, IPSEC_ESP,
> @@ -1248,6 +1338,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  				return -EINVAL;
>  			}
> 
> +			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
> {
> +				if (ips->type ==
> +
> RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +					iv_length = 8;
> +				} else {
> +					iv_length = 12;
> +				}
> +			}
> +
>  			if (inbound) {
>  				sa_ctx->xf[idx].b.type =
> RTE_CRYPTO_SYM_XFORM_CIPHER;
>  				sa_ctx->xf[idx].b.cipher.algo = sa-
> >cipher_algo;
> @@ -1269,6 +1368,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  					sa->digest_len;
>  				sa_ctx->xf[idx].a.auth.op =
>  					RTE_CRYPTO_AUTH_OP_VERIFY;
> +				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
> +				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
> +
>  			} else { /* outbound */
>  				sa_ctx->xf[idx].a.type =
> RTE_CRYPTO_SYM_XFORM_CIPHER;
>  				sa_ctx->xf[idx].a.cipher.algo = sa-
> >cipher_algo;
> @@ -1290,11 +1392,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  					sa->digest_len;
>  				sa_ctx->xf[idx].b.auth.op =
>  					RTE_CRYPTO_AUTH_OP_GENERATE;
> +				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
> +				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
> +
>  			}
> 
> -			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
> -			sa_ctx->xf[idx].b.next = NULL;
> -			sa->xforms = &sa_ctx->xf[idx].a;
> +			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
> {
> +				sa->xforms = inbound ?
> +					&sa_ctx->xf[idx].a : &sa_ctx-
> >xf[idx].b;
> +				sa->xforms->next = NULL;
> +
> +			} else {
> +				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
> +				sa_ctx->xf[idx].b.next = NULL;
> +				sa->xforms = &sa_ctx->xf[idx].a;
> +			}
>  		}
> 
>  		if (ips->type ==
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH 4/7] examples/ipsec-secgw: enable stats by default
  2021-09-08 13:08   ` [dpdk-dev] [EXT] " Akhil Goyal
@ 2021-09-08 16:05     ` Hemant Agrawal
  0 siblings, 0 replies; 82+ messages in thread
From: Hemant Agrawal @ 2021-09-08 16:05 UTC (permalink / raw)
  To: Akhil Goyal, Radu Nicolau
  Cc: dev, declan.doherty, Anoob Joseph, Hemant Agrawal,
	konstantin.ananyev, matan


On 9/8/2021 6:38 PM, Akhil Goyal wrote:
>> Enable stats screen by default
>>
>> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
>> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
>> ---
> I believe timeout should be configurable like we have in l3fwd/l2fwd.
> And without recompiling, there should be a way out to disable it.
> If we are not doing an effort to do that, then by default it should be
> Disabled in my opinion. Others can comment on it.


+1 we shall make it optional and disabled by default.


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

* Re: [dpdk-dev] [EXT] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support
  2021-09-08 12:48   ` [dpdk-dev] [EXT] " Akhil Goyal
@ 2021-09-09  8:57     ` Nicolau, Radu
  0 siblings, 0 replies; 82+ messages in thread
From: Nicolau, Radu @ 2021-09-09  8:57 UTC (permalink / raw)
  To: Akhil Goyal; +Cc: dev, declan.doherty

Hi Akhil,

On 9/8/2021 1:48 PM, Akhil Goyal wrote:
>> Add support for ol_flags to the IPsec GW sample app.
> Description is not appropriate.
> ol_flags are supported to do what?
> How the existing code was not good and
> what benefit do we get from this patch?
>
Thanks for reviewing the series! I will address your feedback for all 
the patches in the v2.



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

* [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (6 preceding siblings ...)
  2021-09-03 11:22 ` [dpdk-dev] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-09-15 13:45 ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 1/9] examples/ipsec-secgw: update create inline session Radu Nicolau
                     ` (8 more replies)
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                   ` (3 subsequent siblings)
  11 siblings, 9 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, hemant.agrawal, Radu Nicolau

Update the IPsec sample app with new features and updates:
- egress TSO support
- telemetry support
- add reset callback
- stats screen configurable as a command line parameter
- UDP encapsulation support for inline crypto
- ESN with configurable start value

Depends on series 18837 ('new features for ipsec and security libraries')

Radu Nicolau (9):
  examples/ipsec-secgw: update create inline session
  examples/ipsec-secgw: update SA parameters with L3 options
  examples/ipsec-secgw: add support for telemetry
  examples/ipsec-secgw: add stats interval argument
  examples/ipsec-secgw: add support for TSO
  examples/ipsec-secgw: add support for defining initial sequence number
    value
  examples/ipsec-secgw: add ethdev reset callback
  examples/ipsec-secgw: add support for additional algorithms
  examples/ipsec-secgw: add support for inline crypto UDP encapsulation

 doc/guides/sample_app_ug/ipsec_secgw.rst |  36 ++
 examples/ipsec-secgw/ipsec-secgw.c       | 408 +++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
 examples/ipsec-secgw/ipsec.c             |  95 +++++-
 examples/ipsec-secgw/ipsec.h             |  14 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                | 305 +++++++++++++++--
 7 files changed, 816 insertions(+), 92 deletions(-)

-- 
v2: reworked the patchset to improve quality and address feedback

2.25.1


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

* [dpdk-dev] [PATCH v2 1/9] examples/ipsec-secgw: update create inline session
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 2/9] examples/ipsec-secgw: update SA parameters with L3 options Radu Nicolau
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Rework create inline session function as to update the session
configuration parameters before create session is called.
Also updated the rss key array size to prevent buffers overflows
with PMDs that copy more than 40 bytes.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.c | 56 ++++++++++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 8 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 5b032fecfb..0af49f3f4b 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -167,21 +167,61 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		.action_type = ips->type,
 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
 		{.ipsec = {
-			.spi = sa->spi,
+			.spi = rte_cpu_to_be_32(sa->spi),
 			.salt = sa->salt,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
+			return -1;
+		}
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -267,10 +307,10 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sa->attr.ingress = (sa->direction ==
 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
+			uint8_t rss_key[64];
 			struct rte_eth_rss_conf rss_conf = {
 				.rss_key = rss_key,
-				.rss_key_len = 40,
+				.rss_key_len = sizeof(rss_key),
 			};
 			struct rte_eth_dev_info dev_info;
 			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 2/9] examples/ipsec-secgw: update SA parameters with L3 options
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 1/9] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 3/9] examples/ipsec-secgw: add support for telemetry Radu Nicolau
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Set the L3 offset and L3 length in the SA parameters

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/sa.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 17a28556c9..7fb8fef264 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -1316,11 +1316,15 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+		prm->tun.hdr_l3_len = sizeof(*v4);
+		prm->tun.hdr_l3_off = 0;
 		prm->tun.hdr_len = sizeof(*v4);
 		prm->tun.next_proto = rc;
 		prm->tun.hdr = v4;
 	} else if (IS_IP6_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+		prm->tun.hdr_l3_len = sizeof(*v6);
+		prm->tun.hdr_l3_off = 0;
 		prm->tun.hdr_len = sizeof(*v6);
 		prm->tun.next_proto = rc;
 		prm->tun.hdr = v6;
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 3/9] examples/ipsec-secgw: add support for telemetry
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 1/9] examples/ipsec-secgw: update create inline session Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 2/9] examples/ipsec-secgw: update SA parameters with L3 options Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument Radu Nicolau
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add telemetry support to the IPsec GW sample app

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
 examples/ipsec-secgw/ipsec-secgw.c       | 365 ++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec-secgw.h       |  33 +-
 examples/ipsec-secgw/ipsec.h             |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                |  15 +-
 6 files changed, 406 insertions(+), 22 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 78171b25f9..20bc1e6bc4 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -720,6 +720,17 @@ where each options means:
 
    * *udp-encap*
 
+ ``<telemetry>``
+
+ * Option to enable per SA telemetry.
+   Currently only supported with IPsec library path.
+
+ * Optional: Yes, it is disabled by default
+
+ * Syntax:
+
+   * *telemetry*
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index f252d34985..265fff4bef 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -48,6 +48,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -671,7 +672,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -688,25 +689,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -750,6 +756,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -765,16 +772,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -785,17 +796,23 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
 			ip->num, DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -807,15 +824,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd6);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -969,6 +991,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1004,6 +1027,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1020,6 +1044,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1056,6 +1081,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1129,6 +1155,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1146,13 +1173,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2832,6 +2861,308 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dopped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.outbound.spd4.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.outbound.spd6.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+static void
+telemetry_init(void)
+{
+	rte_ipsec_telemetry_init();
+
+	ipsec_secgw_telemetry_init();
+
+}
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2869,6 +3200,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..f3082a1037 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -83,7 +83,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
-#if (STATS_INTERVAL > 0)
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -91,10 +101,29 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
-#endif /* STATS_INTERVAL */
 
 extern struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS];
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index ae5058de27..a3de8952b6 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,8 @@ struct ipsec_sa {
 #define TRANSPORT  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	uint8_t cipher_key[MAX_KEY_SIZE];
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 7fb8fef264..db5fd46e67 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -322,6 +322,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -338,14 +339,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags |= TRANSPORT;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -356,6 +357,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1390,6 +1396,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (2 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 3/9] examples/ipsec-secgw: add support for telemetry Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-16  9:13     ` Hemant Agrawal
  2021-09-16  9:30     ` [dpdk-dev] [EXT] " Anoob Joseph
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 5/9] examples/ipsec-secgw: add support for TSO Radu Nicolau
                     ` (4 subsequent siblings)
  8 siblings, 2 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add -t for stats screen update interval, disabled by default.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
 examples/ipsec-secgw/ipsec-secgw.h       | 15 ------------
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 20bc1e6bc4..0d55e74022 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -127,6 +127,7 @@ The application has a number of command line options::
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINDOW_SIZE -e -a
                         -c SAD_CACHE_SIZE
+                        -t STATISTICS_INTERVAL
                         -s NUMBER_OF_MBUFS_IN_PACKET_POOL
                         -f CONFIG_FILE_PATH
                         --config (port,queue,lcore)[,(port,queue,lcore)]
@@ -176,6 +177,10 @@ Where:
     Zero value disables cache.
     Default value: 128.
 
+*   ``-t``: specifies the statistics screen update interval. If set to zero or
+    omitted statistics screen is disabled.
+    Default value: 0.
+
 *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
     will be calculated based on number of cores, eth ports and crypto queues.
 
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 265fff4bef..60b25be872 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -181,6 +181,7 @@ static uint32_t frag_tbl_sz;
 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
 static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
+static uint32_t stats_interval;
 
 /* application wide librte_ipsec/SA parameters */
 struct app_sa_prm app_sa_prm = {
@@ -292,7 +293,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
 	}
 }
 
-#if (STATS_INTERVAL > 0)
 
 /* Print out statistics on packet distribution */
 static void
@@ -352,9 +352,8 @@ print_stats_cb(__rte_unused void *param)
 		   total_packets_dropped);
 	printf("\n====================================================\n");
 
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
+	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
 }
-#endif /* STATS_INTERVAL */
 
 static inline void
 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
@@ -1435,6 +1434,7 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-t STATS_INTERVAL]"
 		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -1459,6 +1459,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -t specifies statistics screen update interval,\n"
+		"     zero disables statistics screen (default value: 0)\n"
 		"  -s number of mbufs in packet pool, if not specified number\n"
 		"     of mbufs will be calculated based on number of cores,\n"
 		"     ports and crypto queues\n"
@@ -1666,7 +1668,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1747,6 +1749,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 			}
 			app_sa_prm.cache_sz = ret;
 			break;
+		case 't':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid interval value: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			stats_interval = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
@@ -3350,11 +3361,11 @@ main(int32_t argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
-#if (STATS_INTERVAL > 0)
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
-#else
-	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
-#endif /* STATS_INTERVAL */
+	if (stats_interval > 0)
+		rte_eal_alarm_set(stats_interval * US_PER_S,
+				print_stats_cb, NULL);
+	else
+		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
 
 	/* launch per-lcore init on every lcore */
 	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index f3082a1037..de9f382742 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -6,9 +6,6 @@
 
 #include <stdbool.h>
 
-#ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
-#endif
 
 #define NB_SOCKETS 4
 
@@ -144,38 +141,26 @@ is_unprotected_port(uint16_t port_id)
 static inline void
 core_stats_update_rx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].rx += n;
 	core_statistics[lcore_id].rx_call++;
 	if (n == MAX_PKT_BURST)
 		core_statistics[lcore_id].burst_rx += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_tx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].tx += n;
 	core_statistics[lcore_id].tx_call++;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_drop(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].dropped += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 /* helper routine to free bulk of packets */
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 5/9] examples/ipsec-secgw: add support for TSO
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (3 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 6/9] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support to allow user to specific MSS for TSO offload on a per SA
basis. MSS configuration in the context of IPsec is only supported for
outbound SA's in the context of an inline IPsec Crypto offload.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 15 +++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 0d55e74022..7727051394 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -736,6 +736,16 @@ where each options means:
 
    * *telemetry*
 
+ ``<mss>``
+
+ * Maximum segment size for TSO offload, available for egress SAs only.
+
+ * Optional: Yes, TSO offload not set by default
+
+ * Syntax:
+
+   * *mss N* N is the segment size
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index a3de8952b6..c3da5fb243 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -141,6 +141,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint16_t mss;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index db5fd46e67..1a53430ec9 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -683,6 +683,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "mss") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->mss = atoi(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
@@ -1320,6 +1330,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
+	if (ss->mss > 0) {
+		prm->ipsec_xform.options.tso = 1;
+		prm->ipsec_xform.mss = ss->mss;
+	}
+
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_l3_len = sizeof(*v4);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 6/9] examples/ipsec-secgw: add support for defining initial sequence number value
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (4 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 5/9] examples/ipsec-secgw: add support for TSO Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 7/9] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add esn field to SA definition block to allow initial ESN value

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.c             |  5 +++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 15 +++++++++++++++
 4 files changed, 31 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 7727051394..dc3ced244d 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -746,6 +746,16 @@ where each options means:
 
    * *mss N* N is the segment size
 
+ ``<esn>``
+
+ * Enable ESN and set the initial ESN value.
+
+ * Optional: Yes, ESN not enabled by default
+
+ * Syntax:
+
+   * *esn N* N is the initial ESN value
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 0af49f3f4b..868089ad3e 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -222,6 +222,11 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index c3da5fb243..2807b41ebb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -142,6 +142,7 @@ struct ipsec_sa {
 	uint8_t udp_encap;
 	uint16_t portid;
 	uint16_t mss;
+	uint64_t esn;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 1a53430ec9..cfab416c9c 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -693,6 +693,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
@@ -1335,6 +1345,11 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 		prm->ipsec_xform.mss = ss->mss;
 	}
 
+	if (ss->esn > 0) {
+		prm->ipsec_xform.options.esn = 1;
+		prm->ipsec_xform.esn.value = ss->esn;
+	}
+
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_l3_len = sizeof(*v4);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 7/9] examples/ipsec-secgw: add ethdev reset callback
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (5 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 6/9] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 8/9] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 9/9] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add event handler for ethdev reset callback

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 60b25be872..ba8880e363 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2559,6 +2559,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type __rte_unused,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d\n", port_id);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3333,6 +3344,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 8/9] examples/ipsec-secgw: add support for additional algorithms
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (6 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 7/9] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 9/9] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
AES_CCM, CHACHA20_POLY1305

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.h |   3 +-
 examples/ipsec-secgw/sa.c    | 133 ++++++++++++++++++++++++++++++++---
 2 files changed, 126 insertions(+), 10 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 2807b41ebb..3ec3e55170 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -65,8 +65,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
-
+#define MAX_KEY_SIZE		96
 /*
  * application wide SA parameters
  */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index cfab416c9c..bd58edebc9 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -45,6 +45,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -97,6 +98,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -125,6 +140,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -155,6 +195,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -483,6 +559,15 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1173,8 +1258,20 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			break;
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+				iv_length = 8;
+			} else {
+				if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+					iv_length = 11;
+				else
+					iv_length = 12;
+			}
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1198,10 +1295,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1210,6 +1305,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				if (ips->type ==
+				    RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+					iv_length = 8;
+				} else {
+					iv_length = 12;
+				}
+			}
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1231,6 +1335,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1252,11 +1359,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* [dpdk-dev] [PATCH v2 9/9] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
                     ` (7 preceding siblings ...)
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 8/9] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
@ 2021-09-15 13:45   ` Radu Nicolau
  8 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-09-15 13:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.c |  34 ++++++++--
 examples/ipsec-secgw/ipsec.h |   7 +-
 examples/ipsec-secgw/sa.c    | 123 ++++++++++++++++++++++++++++-------
 3 files changed, 136 insertions(+), 28 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 868089ad3e..edc0b21478 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -222,6 +222,13 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->udp_encap) {
+		sess_conf.ipsec.options.udp_encap = 1;
+
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
+
 	if (sa->esn > 0) {
 		sess_conf.ipsec.options.esn = 1;
 		sess_conf.ipsec.esn.value = sa->esn;
@@ -295,12 +302,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			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;
+		if (sa->udp_encap) {
+
+			sa->udp_spec.hdr.dst_port =
+					rte_cpu_to_be_16(sa->udp.dport);
+			sa->udp_spec.hdr.src_port =
+					rte_cpu_to_be_16(sa->udp.sport);
+
+			sa->pattern[2].mask = &rte_flow_item_udp_mask;
+			sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+			sa->pattern[2].spec = &sa->udp_spec;
+
+			sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+			sa->pattern[3].spec = &sa->esp_spec;
+			sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+			sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+		} else {
+			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->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+		}
 
 		sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
 		sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 3ec3e55170..5fa4e62f37 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -128,6 +128,10 @@ struct ipsec_sa {
 
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -145,7 +149,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -154,6 +158,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index bd58edebc9..847ac37b81 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -882,6 +883,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 				app_sa_prm.udp_encap = 1;
 				udp_encap_p = 1;
 				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+				rule->udp_encap = 1;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
+				break;
 			default:
 				APP_CHECK(0, status,
 					"UDP encapsulation not supported for "
@@ -969,6 +975,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	}
 
 	printf("mode:");
+	if (sa->udp_encap)
+		printf("UDP encapsulated ");
 
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
@@ -1428,9 +1436,21 @@ fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
 	prm->ipsec_xform.replay_win_sz = app_prm->window_size;
 }
 
+struct udp_ipv4_tunnel {
+	struct rte_ipv4_hdr v4;
+	struct rte_udp_hdr udp;
+} __rte_packed;
+
+struct udp_ipv6_tunnel {
+	struct rte_ipv6_hdr v6;
+	struct rte_udp_hdr udp;
+} __rte_packed;
+
 static int
 fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
-	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
+	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6,
+	const struct udp_ipv4_tunnel *udp_ipv4,
+	const struct udp_ipv6_tunnel *udp_ipv6)
 {
 	int32_t rc;
 
@@ -1454,6 +1474,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
@@ -1471,16 +1492,31 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_l3_len = sizeof(*v4);
 		prm->tun.hdr_l3_off = 0;
-		prm->tun.hdr_len = sizeof(*v4);
 		prm->tun.next_proto = rc;
-		prm->tun.hdr = v4;
+		if (ss->udp_encap) {
+			prm->tun.hdr_len = sizeof(*udp_ipv4);
+			prm->tun.hdr = udp_ipv4;
+
+		} else {
+			prm->tun.hdr_len = sizeof(*v4);
+			prm->tun.hdr = v4;
+		}
+
 	} else if (IS_IP6_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 		prm->tun.hdr_l3_len = sizeof(*v6);
 		prm->tun.hdr_l3_off = 0;
-		prm->tun.hdr_len = sizeof(*v6);
 		prm->tun.next_proto = rc;
-		prm->tun.hdr = v6;
+		if (ss->udp_encap) {
+
+			prm->tun.hdr_len = sizeof(*udp_ipv6);
+			prm->tun.hdr = udp_ipv6;
+
+		} else {
+			prm->tun.hdr_len = sizeof(*v6);
+			prm->tun.hdr = v6;
+		}
+
 	} else {
 		/* transport mode */
 		prm->trs.proto = rc;
@@ -1519,25 +1555,66 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	int rc;
 	struct rte_ipsec_sa_prm prm;
 	struct rte_ipsec_session *ips;
-	struct rte_ipv4_hdr v4  = {
-		.version_ihl = IPVERSION << 4 |
-			sizeof(v4) / RTE_IPV4_IHL_MULTIPLIER,
-		.time_to_live = IPDEFTTL,
-		.next_proto_id = IPPROTO_ESP,
-		.src_addr = lsa->src.ip.ip4,
-		.dst_addr = lsa->dst.ip.ip4,
-	};
-	struct rte_ipv6_hdr v6 = {
-		.vtc_flow = htonl(IP6_VERSION << 28),
-		.proto = IPPROTO_ESP,
-	};
-
-	if (IS_IP6_TUNNEL(lsa->flags)) {
-		memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b, sizeof(v6.src_addr));
-		memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
+	struct rte_ipv4_hdr v4;
+	struct rte_ipv6_hdr v6;
+	struct udp_ipv4_tunnel udp_ipv4;
+	struct udp_ipv6_tunnel udp_ipv6;
+
+
+	if (IS_TUNNEL(lsa->flags) && (lsa->udp_encap)) {
+		if (IS_IP4(lsa->flags)) {
+
+			udp_ipv4.v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+					RTE_IPV4_IHL_MULTIPLIER;
+			udp_ipv4.v4.time_to_live = IPDEFTTL;
+			udp_ipv4.v4.next_proto_id = IPPROTO_UDP;
+			udp_ipv4.v4.src_addr = lsa->src.ip.ip4;
+			udp_ipv4.v4.dst_addr = lsa->dst.ip.ip4;
+
+			udp_ipv4.udp.src_port =
+					rte_cpu_to_be_16(lsa->udp.sport);
+			udp_ipv4.udp.dst_port =
+					rte_cpu_to_be_16(lsa->udp.dport);
+
+		} else if (IS_IP6(lsa->flags)) {
+
+			udp_ipv6.v6.vtc_flow = htonl(IP6_VERSION << 28),
+			udp_ipv6.v6.proto = IPPROTO_UDP,
+			memcpy(udp_ipv6.v6.src_addr, lsa->src.ip.ip6.ip6_b,
+					sizeof(udp_ipv6.v6.src_addr));
+			memcpy(udp_ipv6.v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+					sizeof(udp_ipv6.v6.dst_addr));
+
+			udp_ipv6.udp.src_port =
+					rte_cpu_to_be_16(lsa->udp.sport);
+			udp_ipv6.udp.dst_port =
+					rte_cpu_to_be_16(lsa->udp.dport);
+		}
+
+	} else if (IS_TUNNEL(lsa->flags)) {
+
+		if (IS_IP4(lsa->flags)) {
+			v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+					RTE_IPV4_IHL_MULTIPLIER;
+			v4.time_to_live = IPDEFTTL;
+			v4.next_proto_id = IPPROTO_ESP;
+			v4.src_addr = lsa->src.ip.ip4;
+			v4.dst_addr = lsa->dst.ip.ip4;
+
+		} else if (IS_IP6(lsa->flags)) {
+
+			v6.vtc_flow = htonl(IP6_VERSION << 28),
+			v6.proto = IPPROTO_ESP,
+			memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b,
+					sizeof(v6.src_addr));
+			memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+					sizeof(v6.dst_addr));
+
+		}
+
 	}
 
-	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
+	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6, &udp_ipv4, &udp_ipv6);
 	if (rc == 0)
 		rc = rte_ipsec_sa_init(sa, &prm, sa_size);
 	if (rc < 0)
@@ -1575,7 +1652,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
 
 	/* determine SA size */
 	idx = 0;
-	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
+	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL, NULL, NULL);
 	sz = rte_ipsec_sa_size(&prm);
 	if (sz < 0) {
 		RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
-- 
2.25.1


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

* Re: [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-09-16  9:13     ` Hemant Agrawal
  2021-09-16  9:30     ` [dpdk-dev] [EXT] " Anoob Joseph
  1 sibling, 0 replies; 82+ messages in thread
From: Hemant Agrawal @ 2021-09-16  9:13 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty


On 9/15/2021 7:15 PM, Radu Nicolau wrote:
> Add -t for stats screen update interval, disabled by default.
>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>   doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
>   examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
>   examples/ipsec-secgw/ipsec-secgw.h       | 15 ------------
>   3 files changed, 25 insertions(+), 24 deletions(-)
>
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 20bc1e6bc4..0d55e74022 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -127,6 +127,7 @@ The application has a number of command line options::
>                           -p PORTMASK -P -u PORTMASK -j FRAMESIZE
>                           -l -w REPLAY_WINDOW_SIZE -e -a
>                           -c SAD_CACHE_SIZE
> +                        -t STATISTICS_INTERVAL
>                           -s NUMBER_OF_MBUFS_IN_PACKET_POOL
>                           -f CONFIG_FILE_PATH
>                           --config (port,queue,lcore)[,(port,queue,lcore)]
> @@ -176,6 +177,10 @@ Where:
>       Zero value disables cache.
>       Default value: 128.
>   
> +*   ``-t``: specifies the statistics screen update interval. If set to zero or
> +    omitted statistics screen is disabled.
> +    Default value: 0.
> +
>   *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
>       will be calculated based on number of cores, eth ports and crypto queues.
>   
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
> index 265fff4bef..60b25be872 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -181,6 +181,7 @@ static uint32_t frag_tbl_sz;
>   static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
>   static uint32_t mtu_size = RTE_ETHER_MTU;
>   static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
> +static uint32_t stats_interval;
>   
>   /* application wide librte_ipsec/SA parameters */
>   struct app_sa_prm app_sa_prm = {
> @@ -292,7 +293,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
>   	}
>   }
>   
> -#if (STATS_INTERVAL > 0)
>   
>   /* Print out statistics on packet distribution */
>   static void
> @@ -352,9 +352,8 @@ print_stats_cb(__rte_unused void *param)
>   		   total_packets_dropped);
>   	printf("\n====================================================\n");
>   
> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
> +	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
>   }
> -#endif /* STATS_INTERVAL */
>   
>   static inline void
>   prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
> @@ -1435,6 +1434,7 @@ print_usage(const char *prgname)
>   		" [-e]"
>   		" [-a]"
>   		" [-c]"
> +		" [-t STATS_INTERVAL]"
>   		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
>   		" -f CONFIG_FILE"
>   		" --config (port,queue,lcore)[,(port,queue,lcore)]"
> @@ -1459,6 +1459,8 @@ print_usage(const char *prgname)
>   		"  -a enables SA SQN atomic behaviour\n"
>   		"  -c specifies inbound SAD cache size,\n"
>   		"     zero value disables the cache (default value: 128)\n"
> +		"  -t specifies statistics screen update interval,\n"
> +		"     zero disables statistics screen (default value: 0)\n"
>   		"  -s number of mbufs in packet pool, if not specified number\n"
>   		"     of mbufs will be calculated based on number of cores,\n"
>   		"     ports and crypto queues\n"
> @@ -1666,7 +1668,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
>   
>   	argvopt = argv;
>   
> -	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
> +	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
>   				lgopts, &option_index)) != EOF) {
>   
>   		switch (opt) {
> @@ -1747,6 +1749,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
>   			}
>   			app_sa_prm.cache_sz = ret;
>   			break;
> +		case 't':
> +			ret = parse_decimal(optarg);
> +			if (ret < 0) {
> +				printf("Invalid interval value: %s\n", optarg);
> +				print_usage(prgname);
> +				return -1;
> +			}
> +			stats_interval = ret;
> +			break;
>   		case CMD_LINE_OPT_CONFIG_NUM:
>   			ret = parse_config(optarg);
>   			if (ret) {
> @@ -3350,11 +3361,11 @@ main(int32_t argc, char **argv)
>   
>   	check_all_ports_link_status(enabled_port_mask);
>   
> -#if (STATS_INTERVAL > 0)
> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
> -#else
> -	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
> -#endif /* STATS_INTERVAL */
> +	if (stats_interval > 0)
> +		rte_eal_alarm_set(stats_interval * US_PER_S,
> +				print_stats_cb, NULL);
> +	else
> +		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
>   
>   	/* launch per-lcore init on every lcore */
>   	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
> diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
> index f3082a1037..de9f382742 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.h
> +++ b/examples/ipsec-secgw/ipsec-secgw.h
> @@ -6,9 +6,6 @@
>   
>   #include <stdbool.h>
>   
> -#ifndef STATS_INTERVAL
> -#define STATS_INTERVAL 0
> -#endif
>   
>   #define NB_SOCKETS 4
>   
> @@ -144,38 +141,26 @@ is_unprotected_port(uint16_t port_id)
>   static inline void
>   core_stats_update_rx(int n)
>   {
> -#if (STATS_INTERVAL > 0)
>   	int lcore_id = rte_lcore_id();
>   	core_statistics[lcore_id].rx += n;
>   	core_statistics[lcore_id].rx_call++;
>   	if (n == MAX_PKT_BURST)
>   		core_statistics[lcore_id].burst_rx += n;
> -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>   }
>   
>   static inline void
>   core_stats_update_tx(int n)
>   {
> -#if (STATS_INTERVAL > 0)
>   	int lcore_id = rte_lcore_id();
>   	core_statistics[lcore_id].tx += n;
>   	core_statistics[lcore_id].tx_call++;
> -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>   }
>   
>   static inline void
>   core_stats_update_drop(int n)
>   {
> -#if (STATS_INTERVAL > 0)
>   	int lcore_id = rte_lcore_id();
>   	core_statistics[lcore_id].dropped += n;
> -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>   }
>   
>   /* helper routine to free bulk of packets */
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>

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

* Re: [dpdk-dev] [EXT] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument
  2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument Radu Nicolau
  2021-09-16  9:13     ` Hemant Agrawal
@ 2021-09-16  9:30     ` Anoob Joseph
  2021-09-16 10:24       ` Nicolau, Radu
  1 sibling, 1 reply; 82+ messages in thread
From: Anoob Joseph @ 2021-09-16  9:30 UTC (permalink / raw)
  To: Radu Nicolau
  Cc: dev, declan.doherty, hemant.agrawal, Akhil Goyal, Ananyev, Konstantin

Hi Radu,

Making stats dynamic would have a perf cost. That was the reason it was introduced as a compile time option. Why do we need it changed?

Also, it looks like this patch is only disabling stats printing when timeout is 0. I don't see stats collection being conditional. Stats collection would also have perf impact, right?

Thanks,
Anoob

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Radu Nicolau
> Sent: Wednesday, September 15, 2021 7:15 PM
> To: Radu Nicolau <radu.nicolau@intel.com>; Akhil Goyal
> <gakhil@marvell.com>
> Cc: dev@dpdk.org; declan.doherty@intel.com;
> hemant.agrawal@oss.nxp.com
> Subject: [EXT] [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats
> interval argument
> 
> External Email
> 
> ----------------------------------------------------------------------
> Add -t for stats screen update interval, disabled by default.
> 
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
>  examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
>  examples/ipsec-secgw/ipsec-secgw.h       | 15 ------------
>  3 files changed, 25 insertions(+), 24 deletions(-)
> 
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 20bc1e6bc4..0d55e74022 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -127,6 +127,7 @@ The application has a number of command line
> options::
>                          -p PORTMASK -P -u PORTMASK -j FRAMESIZE
>                          -l -w REPLAY_WINDOW_SIZE -e -a
>                          -c SAD_CACHE_SIZE
> +                        -t STATISTICS_INTERVAL
>                          -s NUMBER_OF_MBUFS_IN_PACKET_POOL
>                          -f CONFIG_FILE_PATH
>                          --config (port,queue,lcore)[,(port,queue,lcore)]
> @@ -176,6 +177,10 @@ Where:
>      Zero value disables cache.
>      Default value: 128.
> 
> +*   ``-t``: specifies the statistics screen update interval. If set to zero or
> +    omitted statistics screen is disabled.
> +    Default value: 0.
> +
>  *   ``-s``: sets number of mbufs in packet pool, if not provided number of
> mbufs
>      will be calculated based on number of cores, eth ports and crypto queues.
> 
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 265fff4bef..60b25be872 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -181,6 +181,7 @@ static uint32_t frag_tbl_sz;  static uint32_t
> frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;  static uint32_t mtu_size
> = RTE_ETHER_MTU;  static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
> +static uint32_t stats_interval;
> 
>  /* application wide librte_ipsec/SA parameters */  struct app_sa_prm
> app_sa_prm = { @@ -292,7 +293,6 @@ adjust_ipv6_pktlen(struct rte_mbuf
> *m, const struct rte_ipv6_hdr *iph,
>  	}
>  }
> 
> -#if (STATS_INTERVAL > 0)
> 
>  /* Print out statistics on packet distribution */  static void @@ -352,9 +352,8
> @@ print_stats_cb(__rte_unused void *param)
>  		   total_packets_dropped);
> 
> 	printf("\n=============================================
> =======\n");
> 
> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb,
> NULL);
> +	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
>  }
> -#endif /* STATS_INTERVAL */
> 
>  static inline void
>  prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t) @@ -
> 1435,6 +1434,7 @@ print_usage(const char *prgname)
>  		" [-e]"
>  		" [-a]"
>  		" [-c]"
> +		" [-t STATS_INTERVAL]"
>  		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
>  		" -f CONFIG_FILE"
>  		" --config (port,queue,lcore)[,(port,queue,lcore)]"
> @@ -1459,6 +1459,8 @@ print_usage(const char *prgname)
>  		"  -a enables SA SQN atomic behaviour\n"
>  		"  -c specifies inbound SAD cache size,\n"
>  		"     zero value disables the cache (default value: 128)\n"
> +		"  -t specifies statistics screen update interval,\n"
> +		"     zero disables statistics screen (default value: 0)\n"
>  		"  -s number of mbufs in packet pool, if not specified
> number\n"
>  		"     of mbufs will be calculated based on number of cores,\n"
>  		"     ports and crypto queues\n"
> @@ -1666,7 +1668,7 @@ parse_args(int32_t argc, char **argv, struct
> eh_conf *eh_conf)
> 
>  	argvopt = argv;
> 
> -	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
> +	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
>  				lgopts, &option_index)) != EOF) {
> 
>  		switch (opt) {
> @@ -1747,6 +1749,15 @@ parse_args(int32_t argc, char **argv, struct
> eh_conf *eh_conf)
>  			}
>  			app_sa_prm.cache_sz = ret;
>  			break;
> +		case 't':
> +			ret = parse_decimal(optarg);
> +			if (ret < 0) {
> +				printf("Invalid interval value: %s\n", optarg);
> +				print_usage(prgname);
> +				return -1;
> +			}
> +			stats_interval = ret;
> +			break;
>  		case CMD_LINE_OPT_CONFIG_NUM:
>  			ret = parse_config(optarg);
>  			if (ret) {
> @@ -3350,11 +3361,11 @@ main(int32_t argc, char **argv)
> 
>  	check_all_ports_link_status(enabled_port_mask);
> 
> -#if (STATS_INTERVAL > 0)
> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb,
> NULL);
> -#else
> -	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
> -#endif /* STATS_INTERVAL */
> +	if (stats_interval > 0)
> +		rte_eal_alarm_set(stats_interval * US_PER_S,
> +				print_stats_cb, NULL);
> +	else
> +		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
> 
>  	/* launch per-lcore init on every lcore */
>  	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf,
> CALL_MAIN); diff --git a/examples/ipsec-secgw/ipsec-secgw.h
> b/examples/ipsec-secgw/ipsec-secgw.h
> index f3082a1037..de9f382742 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.h
> +++ b/examples/ipsec-secgw/ipsec-secgw.h
> @@ -6,9 +6,6 @@
> 
>  #include <stdbool.h>
> 
> -#ifndef STATS_INTERVAL
> -#define STATS_INTERVAL 0
> -#endif
> 
>  #define NB_SOCKETS 4
> 
> @@ -144,38 +141,26 @@ is_unprotected_port(uint16_t port_id)  static inline
> void  core_stats_update_rx(int n)  { -#if (STATS_INTERVAL > 0)
>  	int lcore_id = rte_lcore_id();
>  	core_statistics[lcore_id].rx += n;
>  	core_statistics[lcore_id].rx_call++;
>  	if (n == MAX_PKT_BURST)
>  		core_statistics[lcore_id].burst_rx += n; -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>  }
> 
>  static inline void
>  core_stats_update_tx(int n)
>  {
> -#if (STATS_INTERVAL > 0)
>  	int lcore_id = rte_lcore_id();
>  	core_statistics[lcore_id].tx += n;
>  	core_statistics[lcore_id].tx_call++;
> -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>  }
> 
>  static inline void
>  core_stats_update_drop(int n)
>  {
> -#if (STATS_INTERVAL > 0)
>  	int lcore_id = rte_lcore_id();
>  	core_statistics[lcore_id].dropped += n; -#else
> -	RTE_SET_USED(n);
> -#endif /* STATS_INTERVAL */
>  }
> 
>  /* helper routine to free bulk of packets */
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument
  2021-09-16  9:30     ` [dpdk-dev] [EXT] " Anoob Joseph
@ 2021-09-16 10:24       ` Nicolau, Radu
  2021-09-17 12:51         ` Anoob Joseph
  0 siblings, 1 reply; 82+ messages in thread
From: Nicolau, Radu @ 2021-09-16 10:24 UTC (permalink / raw)
  To: Anoob Joseph
  Cc: dev, declan.doherty, hemant.agrawal, Akhil Goyal, Ananyev, Konstantin

Hi Anoob,

On 9/16/2021 10:30 AM, Anoob Joseph wrote:
> Hi Radu,
>
> Making stats dynamic would have a perf cost. That was the reason it was introduced as a compile time option. Why do we need it changed?
We changed it for two reasons, for a better UX and for the telemetry 
feature that is introduced with patch 3.
>
> Also, it looks like this patch is only disabling stats printing when timeout is 0. I don't see stats collection being conditional. Stats collection would also have perf impact, right?
I don't think there is a measurable performance impact because these are 
per burst calls.

Regards,
Radu
>
> Thanks,
> Anoob
>
>> -----Original Message-----
>> From: dev <dev-bounces@dpdk.org> On Behalf Of Radu Nicolau
>> Sent: Wednesday, September 15, 2021 7:15 PM
>> To: Radu Nicolau <radu.nicolau@intel.com>; Akhil Goyal
>> <gakhil@marvell.com>
>> Cc: dev@dpdk.org; declan.doherty@intel.com;
>> hemant.agrawal@oss.nxp.com
>> Subject: [EXT] [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats
>> interval argument
>>
>> External Email
>>
>> ----------------------------------------------------------------------
>> Add -t for stats screen update interval, disabled by default.
>>
>> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
>> ---
>>   doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
>>   examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
>>   examples/ipsec-secgw/ipsec-secgw.h       | 15 ------------
>>   3 files changed, 25 insertions(+), 24 deletions(-)
>>
>> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
>> b/doc/guides/sample_app_ug/ipsec_secgw.rst
>> index 20bc1e6bc4..0d55e74022 100644
>> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
>> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
>> @@ -127,6 +127,7 @@ The application has a number of command line
>> options::
>>                           -p PORTMASK -P -u PORTMASK -j FRAMESIZE
>>                           -l -w REPLAY_WINDOW_SIZE -e -a
>>                           -c SAD_CACHE_SIZE
>> +                        -t STATISTICS_INTERVAL
>>                           -s NUMBER_OF_MBUFS_IN_PACKET_POOL
>>                           -f CONFIG_FILE_PATH
>>                           --config (port,queue,lcore)[,(port,queue,lcore)]
>> @@ -176,6 +177,10 @@ Where:
>>       Zero value disables cache.
>>       Default value: 128.
>>
>> +*   ``-t``: specifies the statistics screen update interval. If set to zero or
>> +    omitted statistics screen is disabled.
>> +    Default value: 0.
>> +
>>   *   ``-s``: sets number of mbufs in packet pool, if not provided number of
>> mbufs
>>       will be calculated based on number of cores, eth ports and crypto queues.
>>
>> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
>> secgw/ipsec-secgw.c
>> index 265fff4bef..60b25be872 100644
>> --- a/examples/ipsec-secgw/ipsec-secgw.c
>> +++ b/examples/ipsec-secgw/ipsec-secgw.c
>> @@ -181,6 +181,7 @@ static uint32_t frag_tbl_sz;  static uint32_t
>> frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;  static uint32_t mtu_size
>> = RTE_ETHER_MTU;  static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
>> +static uint32_t stats_interval;
>>
>>   /* application wide librte_ipsec/SA parameters */  struct app_sa_prm
>> app_sa_prm = { @@ -292,7 +293,6 @@ adjust_ipv6_pktlen(struct rte_mbuf
>> *m, const struct rte_ipv6_hdr *iph,
>>   	}
>>   }
>>
>> -#if (STATS_INTERVAL > 0)
>>
>>   /* Print out statistics on packet distribution */  static void @@ -352,9 +352,8
>> @@ print_stats_cb(__rte_unused void *param)
>>   		   total_packets_dropped);
>>
>> 	printf("\n=============================================
>> =======\n");
>>
>> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb,
>> NULL);
>> +	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
>>   }
>> -#endif /* STATS_INTERVAL */
>>
>>   static inline void
>>   prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t) @@ -
>> 1435,6 +1434,7 @@ print_usage(const char *prgname)
>>   		" [-e]"
>>   		" [-a]"
>>   		" [-c]"
>> +		" [-t STATS_INTERVAL]"
>>   		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
>>   		" -f CONFIG_FILE"
>>   		" --config (port,queue,lcore)[,(port,queue,lcore)]"
>> @@ -1459,6 +1459,8 @@ print_usage(const char *prgname)
>>   		"  -a enables SA SQN atomic behaviour\n"
>>   		"  -c specifies inbound SAD cache size,\n"
>>   		"     zero value disables the cache (default value: 128)\n"
>> +		"  -t specifies statistics screen update interval,\n"
>> +		"     zero disables statistics screen (default value: 0)\n"
>>   		"  -s number of mbufs in packet pool, if not specified
>> number\n"
>>   		"     of mbufs will be calculated based on number of cores,\n"
>>   		"     ports and crypto queues\n"
>> @@ -1666,7 +1668,7 @@ parse_args(int32_t argc, char **argv, struct
>> eh_conf *eh_conf)
>>
>>   	argvopt = argv;
>>
>> -	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
>> +	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
>>   				lgopts, &option_index)) != EOF) {
>>
>>   		switch (opt) {
>> @@ -1747,6 +1749,15 @@ parse_args(int32_t argc, char **argv, struct
>> eh_conf *eh_conf)
>>   			}
>>   			app_sa_prm.cache_sz = ret;
>>   			break;
>> +		case 't':
>> +			ret = parse_decimal(optarg);
>> +			if (ret < 0) {
>> +				printf("Invalid interval value: %s\n", optarg);
>> +				print_usage(prgname);
>> +				return -1;
>> +			}
>> +			stats_interval = ret;
>> +			break;
>>   		case CMD_LINE_OPT_CONFIG_NUM:
>>   			ret = parse_config(optarg);
>>   			if (ret) {
>> @@ -3350,11 +3361,11 @@ main(int32_t argc, char **argv)
>>
>>   	check_all_ports_link_status(enabled_port_mask);
>>
>> -#if (STATS_INTERVAL > 0)
>> -	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb,
>> NULL);
>> -#else
>> -	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
>> -#endif /* STATS_INTERVAL */
>> +	if (stats_interval > 0)
>> +		rte_eal_alarm_set(stats_interval * US_PER_S,
>> +				print_stats_cb, NULL);
>> +	else
>> +		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
>>
>>   	/* launch per-lcore init on every lcore */
>>   	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf,
>> CALL_MAIN); diff --git a/examples/ipsec-secgw/ipsec-secgw.h
>> b/examples/ipsec-secgw/ipsec-secgw.h
>> index f3082a1037..de9f382742 100644
>> --- a/examples/ipsec-secgw/ipsec-secgw.h
>> +++ b/examples/ipsec-secgw/ipsec-secgw.h
>> @@ -6,9 +6,6 @@
>>
>>   #include <stdbool.h>
>>
>> -#ifndef STATS_INTERVAL
>> -#define STATS_INTERVAL 0
>> -#endif
>>
>>   #define NB_SOCKETS 4
>>
>> @@ -144,38 +141,26 @@ is_unprotected_port(uint16_t port_id)  static inline
>> void  core_stats_update_rx(int n)  { -#if (STATS_INTERVAL > 0)
>>   	int lcore_id = rte_lcore_id();
>>   	core_statistics[lcore_id].rx += n;
>>   	core_statistics[lcore_id].rx_call++;
>>   	if (n == MAX_PKT_BURST)
>>   		core_statistics[lcore_id].burst_rx += n; -#else
>> -	RTE_SET_USED(n);
>> -#endif /* STATS_INTERVAL */
>>   }
>>
>>   static inline void
>>   core_stats_update_tx(int n)
>>   {
>> -#if (STATS_INTERVAL > 0)
>>   	int lcore_id = rte_lcore_id();
>>   	core_statistics[lcore_id].tx += n;
>>   	core_statistics[lcore_id].tx_call++;
>> -#else
>> -	RTE_SET_USED(n);
>> -#endif /* STATS_INTERVAL */
>>   }
>>
>>   static inline void
>>   core_stats_update_drop(int n)
>>   {
>> -#if (STATS_INTERVAL > 0)
>>   	int lcore_id = rte_lcore_id();
>>   	core_statistics[lcore_id].dropped += n; -#else
>> -	RTE_SET_USED(n);
>> -#endif /* STATS_INTERVAL */
>>   }
>>
>>   /* helper routine to free bulk of packets */
>> --
>> 2.25.1

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

* Re: [dpdk-dev] [EXT] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument
  2021-09-16 10:24       ` Nicolau, Radu
@ 2021-09-17 12:51         ` Anoob Joseph
  0 siblings, 0 replies; 82+ messages in thread
From: Anoob Joseph @ 2021-09-17 12:51 UTC (permalink / raw)
  To: Nicolau, Radu
  Cc: dev, declan.doherty, hemant.agrawal, Akhil Goyal, Ananyev, Konstantin

Hi Radu,

Please see inline.

Thanks,
Anoob

> Subject: Re: [EXT] [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add
> stats interval argument
> 
> Hi Anoob,
> 
> On 9/16/2021 10:30 AM, Anoob Joseph wrote:
> > Hi Radu,
> >
> > Making stats dynamic would have a perf cost. That was the reason it was
> introduced as a compile time option. Why do we need it changed?
> We changed it for two reasons, for a better UX and for the telemetry feature
> that is introduced with patch 3.
> >
> > Also, it looks like this patch is only disabling stats printing when timeout is 0.
> I don't see stats collection being conditional. Stats collection would also have
> perf impact, right?
> I don't think there is a measurable performance impact because these are
> per burst calls.

[Anoob] Agreed. If it was done intentionally, then I don’t see any problem.

Acked-by: Anoob Joseph <anoobj@marvell.com>
 
[snip]

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

* [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (7 preceding siblings ...)
  2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
@ 2021-10-01  9:51 ` Radu Nicolau
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument Radu Nicolau
                     ` (7 more replies)
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (2 subsequent siblings)
  11 siblings, 8 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, hemant.agrawal, Radu Nicolau

Update the IPsec sample app with new features and updates:
- egress TSO support
- telemetry support
- add reset callback
- stats screen configurable as a command line parameter
- UDP encapsulation support for inline crypto
- ESN with configurable start value

Depends on series 18837 ('new features for ipsec and security libraries')

Radu Nicolau (8):
  examples/ipsec-secgw: add stats interval argument
  examples/ipsec-secgw: update create inline session
  examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  examples/ipsec-secgw: add support for TSO
  examples/ipsec-secgw: add support for telemetry
  examples/ipsec-secgw: add support for defining initial sequence number
    value
  examples/ipsec-secgw: add ethdev reset callback
  examples/ipsec-secgw: add support for additional algorithms

 doc/guides/sample_app_ug/ipsec_secgw.rst |  36 ++
 examples/ipsec-secgw/ipsec-secgw.c       | 404 +++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
 examples/ipsec-secgw/ipsec.c             |  93 +++++-
 examples/ipsec-secgw/ipsec.h             |  14 +-
 examples/ipsec-secgw/ipsec_process.c     |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                | 179 +++++++++-
 8 files changed, 710 insertions(+), 68 deletions(-)

-- 
v2: reworked the patchset to improve quality and address feedback
v3: reworked the patchset to accomodate changes in the ipsec libray

2.25.1


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

* [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
@ 2021-10-01  9:51   ` Radu Nicolau
  2021-10-08 18:37     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session Radu Nicolau
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

Add -t for stats screen update interval, disabled by default.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
 examples/ipsec-secgw/ipsec-secgw.h       | 17 --------------
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 78171b25f9..846cf2b81a 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -127,6 +127,7 @@ The application has a number of command line options::
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINDOW_SIZE -e -a
                         -c SAD_CACHE_SIZE
+                        -t STATISTICS_INTERVAL
                         -s NUMBER_OF_MBUFS_IN_PACKET_POOL
                         -f CONFIG_FILE_PATH
                         --config (port,queue,lcore)[,(port,queue,lcore)]
@@ -176,6 +177,10 @@ Where:
     Zero value disables cache.
     Default value: 128.
 
+*   ``-t``: specifies the statistics screen update interval. If set to zero or
+    omitted statistics screen is disabled.
+    Default value: 0.
+
 *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
     will be calculated based on number of cores, eth ports and crypto queues.
 
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index f252d34985..1d30f39450 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -180,6 +180,7 @@ static uint32_t frag_tbl_sz;
 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
 static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
+static uint32_t stats_interval;
 
 /* application wide librte_ipsec/SA parameters */
 struct app_sa_prm app_sa_prm = {
@@ -291,7 +292,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
 	}
 }
 
-#if (STATS_INTERVAL > 0)
 
 /* Print out statistics on packet distribution */
 static void
@@ -351,9 +351,8 @@ print_stats_cb(__rte_unused void *param)
 		   total_packets_dropped);
 	printf("\n====================================================\n");
 
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
+	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
 }
-#endif /* STATS_INTERVAL */
 
 static inline void
 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
@@ -1406,6 +1405,7 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-t STATS_INTERVAL]"
 		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -1430,6 +1430,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -t specifies statistics screen update interval,\n"
+		"     zero disables statistics screen (default value: 0)\n"
 		"  -s number of mbufs in packet pool, if not specified number\n"
 		"     of mbufs will be calculated based on number of cores,\n"
 		"     ports and crypto queues\n"
@@ -1637,7 +1639,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1718,6 +1720,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 			}
 			app_sa_prm.cache_sz = ret;
 			break;
+		case 't':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid interval value: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			stats_interval = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
@@ -3017,11 +3028,11 @@ main(int32_t argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
-#if (STATS_INTERVAL > 0)
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
-#else
-	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
-#endif /* STATS_INTERVAL */
+	if (stats_interval > 0)
+		rte_eal_alarm_set(stats_interval * US_PER_S,
+				print_stats_cb, NULL);
+	else
+		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
 
 	/* launch per-lcore init on every lcore */
 	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..04b4644370 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -6,9 +6,6 @@
 
 #include <stdbool.h>
 
-#ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
-#endif
 
 #define NB_SOCKETS 4
 
@@ -83,7 +80,6 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
-#if (STATS_INTERVAL > 0)
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -94,7 +90,6 @@ struct ipsec_core_statistics {
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
-#endif /* STATS_INTERVAL */
 
 extern struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS];
 
@@ -115,38 +110,26 @@ is_unprotected_port(uint16_t port_id)
 static inline void
 core_stats_update_rx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].rx += n;
 	core_statistics[lcore_id].rx_call++;
 	if (n == MAX_PKT_BURST)
 		core_statistics[lcore_id].burst_rx += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_tx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].tx += n;
 	core_statistics[lcore_id].tx_call++;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_drop(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].dropped += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 /* helper routine to free bulk of packets */
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-10-01  9:51   ` Radu Nicolau
  2021-10-08 18:38     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Rework create inline session function as to update the session
configuration parameters before create session is called.
Also updated the rss key array size to prevent buffers overflows
with PMDs that copy more than 40 bytes.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.c | 54 +++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 7 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 5b032fecfb..daaae24d2b 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -172,16 +172,56 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
+			return -1;
+		}
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -267,10 +307,10 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sa->attr.ingress = (sa->direction ==
 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
+			uint8_t rss_key[64];
 			struct rte_eth_rss_conf rss_conf = {
 				.rss_key = rss_key,
-				.rss_key_len = 40,
+				.rss_key_len = sizeof(rss_key),
 			};
 			struct rte_eth_dev_info dev_info;
 			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument Radu Nicolau
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-10-01  9:51   ` Radu Nicolau
  2021-10-08 18:42     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO Radu Nicolau
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.c | 33 +++++++++++++++++++++++++++++----
 examples/ipsec-secgw/ipsec.h |  7 ++++++-
 examples/ipsec-secgw/sa.c    |  9 +++++++++
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index daaae24d2b..3bee2ec2d3 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -222,6 +222,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->udp_encap) {
+		sess_conf.ipsec.options.udp_encap = 1;
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -290,12 +296,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			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;
+		if (sa->udp_encap) {
+
+			sa->udp_spec.hdr.dst_port =
+					rte_cpu_to_be_16(sa->udp.dport);
+			sa->udp_spec.hdr.src_port =
+					rte_cpu_to_be_16(sa->udp.sport);
+
+			sa->pattern[2].mask = &rte_flow_item_udp_mask;
+			sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+			sa->pattern[2].spec = &sa->udp_spec;
+
+			sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+			sa->pattern[3].spec = &sa->esp_spec;
+			sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+			sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+		} else {
+			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->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+		}
 
 		sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
 		sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index ae5058de27..50fb7a8b46 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -127,6 +127,10 @@ struct ipsec_sa {
 #define IP6_TRANSPORT (1 << 4)
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -142,7 +146,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -151,6 +155,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 17a28556c9..b32c168bcc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -771,6 +772,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 				app_sa_prm.udp_encap = 1;
 				udp_encap_p = 1;
 				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+				rule->udp_encap = 1;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
+				break;
 			default:
 				APP_CHECK(0, status,
 					"UDP encapsulation not supported for "
@@ -858,6 +864,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	}
 
 	printf("mode:");
+	if (sa->udp_encap)
+		printf("UDP encapsulated ");
 
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
@@ -1311,6 +1319,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                     ` (2 preceding siblings ...)
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-10-01  9:51   ` Radu Nicolau
  2021-10-08 18:46     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry Radu Nicolau
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support to allow user to specific MSS for TSO offload on a per SA
basis. MSS configuration in the context of IPsec is only supported for
outbound SA's in the context of an inline IPsec Crypto offload.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec-secgw.c       |  4 ++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/ipsec_process.c     |  2 ++
 examples/ipsec-secgw/sa.c                | 12 ++++++++++++
 5 files changed, 29 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 846cf2b81a..cf7a94f58a 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -725,6 +725,16 @@ where each options means:
 
    * *udp-encap*
 
+ ``<mss>``
+
+ * Maximum segment size for TSO offload, available for egress SAs only.
+
+ * Optional: Yes, TSO offload not set by default
+
+ * Syntax:
+
+   * *mss N* N is the segment size
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 1d30f39450..3da520ec6e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -399,6 +399,10 @@ prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
 		pkt->l2_len = 0;
 		pkt->l3_len = sizeof(*iph4);
 		pkt->packet_type |= RTE_PTYPE_L3_IPV4;
+		if  (pkt->packet_type & RTE_PTYPE_L4_TCP)
+			pkt->l4_len = sizeof(struct rte_tcp_hdr);
+		else
+			pkt->l4_len = sizeof(struct rte_udp_hdr);
 	} else if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
 		int next_proto;
 		size_t l3len, ext_len;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 50fb7a8b46..36b1ac9355 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -143,6 +143,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint16_t mss;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/ipsec_process.c b/examples/ipsec-secgw/ipsec_process.c
index 5012e1a6a4..fc2a3cbcd1 100644
--- a/examples/ipsec-secgw/ipsec_process.c
+++ b/examples/ipsec-secgw/ipsec_process.c
@@ -222,6 +222,8 @@ prep_process_group(void *sa, struct rte_mbuf *mb[], uint32_t cnt)
 	for (j = 0; j != cnt; j++) {
 		priv = get_priv(mb[j]);
 		priv->sa = sa;
+		if (priv->sa->mss)
+			mb[j]->tso_segsz = priv->sa->mss;
 	}
 }
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index b32c168bcc..3851a900dc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -678,6 +678,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "mss") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->mss = atoi(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
@@ -1326,11 +1336,13 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_len = sizeof(*v4);
+		prm->tun.hdr_l3_off = 0;
 		prm->tun.next_proto = rc;
 		prm->tun.hdr = v4;
 	} else if (IS_IP6_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 		prm->tun.hdr_len = sizeof(*v6);
+		prm->tun.hdr_l3_off = 0;
 		prm->tun.next_proto = rc;
 		prm->tun.hdr = v6;
 	} else {
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                     ` (3 preceding siblings ...)
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO Radu Nicolau
@ 2021-10-01  9:51   ` Radu Nicolau
  2021-10-08 18:51     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:51 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add telemetry support to the IPsec GW sample app

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
 examples/ipsec-secgw/ipsec-secgw.c       | 357 ++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec-secgw.h       |  31 ++
 examples/ipsec-secgw/ipsec.h             |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                |  15 +-
 6 files changed, 398 insertions(+), 20 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index cf7a94f58a..54c96ddb58 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -735,6 +735,17 @@ where each options means:
 
    * *mss N* N is the segment size
 
+``<telemetry>``
+
+ * Option to enable per SA telemetry.
+   Currently only supported with IPsec library path.
+
+ * Optional: Yes, it is disabled by default
+
+ * Syntax:
+
+   * *telemetry*
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 3da520ec6e..4ee5568aa2 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -48,6 +48,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -674,7 +675,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -691,25 +692,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -753,6 +759,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -768,16 +775,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -788,17 +799,23 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
 			ip->num, DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -810,15 +827,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd6);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -972,6 +994,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1007,6 +1030,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1023,6 +1047,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1059,6 +1084,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1132,6 +1158,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1149,13 +1176,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2847,6 +2876,300 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dopped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.outbound.spd4.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.outbound.spd6.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2884,6 +3207,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	ipsec_secgw_telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 04b4644370..de9f382742 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -80,6 +80,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -87,6 +98,26 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 36b1ac9355..f18c97959e 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,8 @@ struct ipsec_sa {
 #define TRANSPORT  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	struct {
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 3851a900dc..8cd5309517 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -323,6 +323,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -339,14 +340,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags |= TRANSPORT;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -357,6 +358,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1407,6 +1413,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                     ` (4 preceding siblings ...)
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry Radu Nicolau
@ 2021-10-01  9:52   ` Radu Nicolau
  2021-10-08 18:57     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 7/8] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:52 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add esn field to SA definition block to allow initial ESN value

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.c             |  6 ++++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 10 ++++++++++
 4 files changed, 27 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 54c96ddb58..0e08c30248 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -746,6 +746,16 @@ where each options means:
 
    * *telemetry*
 
+ ``<esn>``
+
+ * Enable ESN and set the initial ESN value.
+
+ * Optional: Yes, ESN not enabled by default
+
+ * Syntax:
+
+   * *esn N* N is the initial ESN value
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 3bee2ec2d3..0026b16041 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -228,6 +228,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index f18c97959e..8a76405ad9 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -146,6 +146,7 @@ struct ipsec_sa {
 	uint8_t udp_encap;
 	uint16_t portid;
 	uint16_t mss;
+	uint64_t esn;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 8cd5309517..d52dd94056 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -694,6 +694,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 7/8] examples/ipsec-secgw: add ethdev reset callback
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                     ` (5 preceding siblings ...)
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
@ 2021-10-01  9:52   ` Radu Nicolau
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:52 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add event handler for ethdev reset callback

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4ee5568aa2..6ca7011d72 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2563,6 +2563,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type __rte_unused,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d\n", port_id);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3329,6 +3340,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
-- 
2.25.1


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

* [dpdk-dev] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
                     ` (6 preceding siblings ...)
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 7/8] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-10-01  9:52   ` Radu Nicolau
  2021-10-08 19:07     ` [dpdk-dev] [EXT] " Akhil Goyal
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-01  9:52 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
AES_CCM, CHACHA20_POLY1305

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec.h |   3 +-
 examples/ipsec-secgw/sa.c    | 133 ++++++++++++++++++++++++++++++++---
 2 files changed, 126 insertions(+), 10 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8a76405ad9..5fa4e62f37 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -65,8 +65,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
-
+#define MAX_KEY_SIZE		96
 /*
  * application wide SA parameters
  */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index d52dd94056..08fd1efea8 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -46,6 +46,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -484,6 +560,15 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1181,8 +1266,20 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			break;
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (ips->type ==
+				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+				iv_length = 8;
+			} else {
+				if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+					iv_length = 11;
+				else
+					iv_length = 12;
+			}
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1206,10 +1303,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1218,6 +1313,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				if (ips->type ==
+				    RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+					iv_length = 8;
+				} else {
+					iv_length = 12;
+				}
+			}
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1239,6 +1343,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1260,11 +1367,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-10-08 18:37     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:37 UTC (permalink / raw)
  To: Radu Nicolau
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 78171b25f9..846cf2b81a 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -127,6 +127,7 @@ The application has a number of command line
> options::
>                          -p PORTMASK -P -u PORTMASK -j FRAMESIZE
>                          -l -w REPLAY_WINDOW_SIZE -e -a
>                          -c SAD_CACHE_SIZE
> +                        -t STATISTICS_INTERVAL
>                          -s NUMBER_OF_MBUFS_IN_PACKET_POOL
>                          -f CONFIG_FILE_PATH
>                          --config (port,queue,lcore)[,(port,queue,lcore)]
> @@ -176,6 +177,10 @@ Where:
>      Zero value disables cache.
>      Default value: 128.
> 
> +*   ``-t``: specifies the statistics screen update interval. If set to zero or
> +    omitted statistics screen is disabled.
> +    Default value: 0.

Please also mention the unit of interval.



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

* Re: [dpdk-dev] [EXT] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-10-08 18:38     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:38 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Rework create inline session function as to update the session
> configuration parameters before create session is called.
> Also updated the rss key array size to prevent buffers overflows
> with PMDs that copy more than 40 bytes.
> 
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
Acked-by: Akhil Goyal <gakhil@marvell.com>

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

* Re: [dpdk-dev] [EXT] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-10-08 18:42     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:42 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal


> Enable UDP encapsulation for both transport and tunnel modes for the
> inline crypto offload path.
> 
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec.c | 33 +++++++++++++++++++++++++++++----
>  examples/ipsec-secgw/ipsec.h |  7 ++++++-
>  examples/ipsec-secgw/sa.c    |  9 +++++++++
>  3 files changed, 44 insertions(+), 5 deletions(-)
> 
Please update "doc/guides/sample_app_ug/ipsec_secgw.rst".
It has a limitation added that it is supported only on lookaside proto mode.




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

* Re: [dpdk-dev] [EXT] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO Radu Nicolau
@ 2021-10-08 18:46     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:46 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Add support to allow user to specific MSS for TSO offload on a per SA
> basis. MSS configuration in the context of IPsec is only supported for
> outbound SA's in the context of an inline IPsec Crypto offload.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
>  examples/ipsec-secgw/ipsec-secgw.c       |  4 ++++
>  examples/ipsec-secgw/ipsec.h             |  1 +
>  examples/ipsec-secgw/ipsec_process.c     |  2 ++
>  examples/ipsec-secgw/sa.c                | 12 ++++++++++++
>  5 files changed, 29 insertions(+)

I think it is worth mentioning in release notes for this feature.

> 
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 846cf2b81a..cf7a94f58a 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -725,6 +725,16 @@ where each options means:
> 
>     * *udp-encap*
> 
> + ``<mss>``
> +
> + * Maximum segment size for TSO offload, available for egress SAs only.
> +
> + * Optional: Yes, TSO offload not set by default
> +
> + * Syntax:
> +
> +   * *mss N* N is the segment size

Specify units as well.
N is the segment size in bytes

> +
>  Example SA rules:
> 
>  .. code-block:: console
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 1d30f39450..3da520ec6e 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -399,6 +399,10 @@ prepare_one_packet(struct rte_mbuf *pkt, struct
> ipsec_traffic *t)
>  		pkt->l2_len = 0;
>  		pkt->l3_len = sizeof(*iph4);
>  		pkt->packet_type |= RTE_PTYPE_L3_IPV4;
> +		if  (pkt->packet_type & RTE_PTYPE_L4_TCP)
> +			pkt->l4_len = sizeof(struct rte_tcp_hdr);
> +		else
> +			pkt->l4_len = sizeof(struct rte_udp_hdr);

If the packet is neither TCP nor UDP then?

>  	} else if (eth->ether_type ==
> rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
>  		int next_proto;
>  		size_t l3len, ext_len;
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 50fb7a8b46..36b1ac9355 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -143,6 +143,7 @@ struct ipsec_sa {
>  	enum rte_security_ipsec_sa_direction direction;
>  	uint8_t udp_encap;
>  	uint16_t portid;
> +	uint16_t mss;
>  	uint8_t fdir_qid;
>  	uint8_t fdir_flag;
> 
> diff --git a/examples/ipsec-secgw/ipsec_process.c b/examples/ipsec-
> secgw/ipsec_process.c
> index 5012e1a6a4..fc2a3cbcd1 100644
> --- a/examples/ipsec-secgw/ipsec_process.c
> +++ b/examples/ipsec-secgw/ipsec_process.c
> @@ -222,6 +222,8 @@ prep_process_group(void *sa, struct rte_mbuf
> *mb[], uint32_t cnt)
>  	for (j = 0; j != cnt; j++) {
>  		priv = get_priv(mb[j]);
>  		priv->sa = sa;
> +		if (priv->sa->mss)
> +			mb[j]->tso_segsz = priv->sa->mss;
>  	}
>  }
> 
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index b32c168bcc..3851a900dc 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -678,6 +678,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			continue;
>  		}
> 
> +		if (strcmp(tokens[ti], "mss") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->mss = atoi(tokens[ti]);
> +			if (status->status < 0)
> +				return;
> +			continue;
> +		}
> +
>  		if (strcmp(tokens[ti], "fallback") == 0) {
>  			struct rte_ipsec_session *fb;
> 
> @@ -1326,11 +1336,13 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm
> *prm, const struct ipsec_sa *ss,
>  	if (IS_IP4_TUNNEL(ss->flags)) {
>  		prm->ipsec_xform.tunnel.type =
> RTE_SECURITY_IPSEC_TUNNEL_IPV4;
>  		prm->tun.hdr_len = sizeof(*v4);
> +		prm->tun.hdr_l3_off = 0;
>  		prm->tun.next_proto = rc;
>  		prm->tun.hdr = v4;
>  	} else if (IS_IP6_TUNNEL(ss->flags)) {
>  		prm->ipsec_xform.tunnel.type =
> RTE_SECURITY_IPSEC_TUNNEL_IPV6;
>  		prm->tun.hdr_len = sizeof(*v6);
> +		prm->tun.hdr_l3_off = 0;
>  		prm->tun.next_proto = rc;
>  		prm->tun.hdr = v6;
>  	} else {

Also update print_usage() function with the new options added.
Check in other patches also.


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

* Re: [dpdk-dev] [EXT] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry
  2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry Radu Nicolau
@ 2021-10-08 18:51     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:51 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

Subject can be
Examples/ipsec-secgw: support telemetry

> Add telemetry support to the IPsec GW sample app
> 
Elaborate patch description to show how it can be used.
Probably it is worth mentioning how the output will look like.

> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
>  examples/ipsec-secgw/ipsec-secgw.c       | 357 ++++++++++++++++++++++-
>  examples/ipsec-secgw/ipsec-secgw.h       |  31 ++
>  examples/ipsec-secgw/ipsec.h             |   2 +
>  examples/ipsec-secgw/meson.build         |   2 +-
>  examples/ipsec-secgw/sa.c                |  15 +-
>  6 files changed, 398 insertions(+), 20 deletions(-)
> 

Release notes. 
Add a sub-bullet for each of the new features added.

> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index cf7a94f58a..54c96ddb58 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -735,6 +735,17 @@ where each options means:
> 
>     * *mss N* N is the segment size
> 
> +``<telemetry>``
> +
> + * Option to enable per SA telemetry.
> +   Currently only supported with IPsec library path.
> +
> + * Optional: Yes, it is disabled by default
> +
> + * Syntax:
> +
> +   * *telemetry*
> +
>  Example SA rules:
> 
print_usage() is not updated.


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

* Re: [dpdk-dev] [EXT] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
@ 2021-10-08 18:57     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 18:57 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal


> Subject: [EXT] [PATCH v3 6/8] examples/ipsec-secgw: add support for
> defining initial sequence number value
> 
Subject too long.
examples/ipsec-secgw: define initial ESN value

> Add esn field to SA definition block to allow initial ESN value

The commit description should describe the new option added in the app.
Only a one liner comment is not sufficient. Please check other patches as well.

> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
>  examples/ipsec-secgw/ipsec.c             |  6 ++++++
>  examples/ipsec-secgw/ipsec.h             |  1 +
>  examples/ipsec-secgw/sa.c                | 10 ++++++++++
>  4 files changed, 27 insertions(+)
> 
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 54c96ddb58..0e08c30248 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -746,6 +746,16 @@ where each options means:
> 
>     * *telemetry*
> 
> + ``<esn>``
> +
> + * Enable ESN and set the initial ESN value.
> +
> + * Optional: Yes, ESN not enabled by default
> +
> + * Syntax:
> +
> +   * *esn N* N is the initial ESN value
> +

Print_usage() update missing.

>  Example SA rules:
> 
>  .. code-block:: console
> diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
> index 3bee2ec2d3..0026b16041 100644
> --- a/examples/ipsec-secgw/ipsec.c
> +++ b/examples/ipsec-secgw/ipsec.c
> @@ -228,6 +228,12 @@ create_inline_session(struct socket_ctx *skt_ctx,
> struct ipsec_sa *sa,
>  		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
>  	}
> 
> +	if (sa->esn > 0) {
> +		sess_conf.ipsec.options.esn = 1;
> +		sess_conf.ipsec.esn.value = sa->esn;
> +	}
> +
> +

Extra line

>  	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port
> %u\n",
>  		sa->spi, sa->portid);
> 
> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index f18c97959e..8a76405ad9 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -146,6 +146,7 @@ struct ipsec_sa {
>  	uint8_t udp_encap;
>  	uint16_t portid;
>  	uint16_t mss;
> +	uint64_t esn;
>  	uint8_t fdir_qid;
>  	uint8_t fdir_flag;
> 
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index 8cd5309517..d52dd94056 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -694,6 +694,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			continue;
>  		}
> 
> +		if (strcmp(tokens[ti], "esn") == 0) {
> +			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
> +			if (status->status < 0)
> +				return;
> +			rule->esn = atoll(tokens[ti]);
> +			if (status->status < 0)
> +				return;
> +			continue;
> +		}
> +
>  		if (strcmp(tokens[ti], "fallback") == 0) {
>  			struct rte_ipsec_session *fb;
> 
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms
  2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
@ 2021-10-08 19:07     ` Akhil Goyal
  2021-10-11 15:40       ` Nicolau, Radu
  0 siblings, 1 reply; 82+ messages in thread
From: Akhil Goyal @ 2021-10-08 19:07 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
> AES_CCM, CHACHA20_POLY1305
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec.h |   3 +-
>  examples/ipsec-secgw/sa.c    | 133 ++++++++++++++++++++++++++++++++---
>  2 files changed, 126 insertions(+), 10 deletions(-)
> 

Documentation?
Release notes?


> diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
> index 8a76405ad9..5fa4e62f37 100644
> --- a/examples/ipsec-secgw/ipsec.h
> +++ b/examples/ipsec-secgw/ipsec.h
> @@ -65,8 +65,7 @@ struct ip_addr {
>  	} ip;
>  };
> 
> -#define MAX_KEY_SIZE		36
> -
> +#define MAX_KEY_SIZE		96

Max key length defined below is 64, then why 96?

>  /*
>   * application wide SA parameters
>   */
> diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
> index d52dd94056..08fd1efea8 100644
> --- a/examples/ipsec-secgw/sa.c
> +++ b/examples/ipsec-secgw/sa.c
> @@ -46,6 +46,7 @@ struct supported_cipher_algo {
>  struct supported_auth_algo {
>  	const char *keyword;
>  	enum rte_crypto_auth_algorithm algo;
> +	uint16_t iv_len;
>  	uint16_t digest_len;
>  	uint16_t key_len;
>  	uint8_t key_not_req;
> @@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
>  		.block_size = 4,
>  		.key_len = 20
>  	},
> +	{
> +		.keyword = "aes-192-ctr",
> +		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
> +		.iv_len = 16,
> +		.block_size = 16,
> +		.key_len = 28
> +	},
> +	{
> +		.keyword = "aes-256-ctr",
> +		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
> +		.iv_len = 16,
> +		.block_size = 16,
> +		.key_len = 36
> +	},
>  	{
>  		.keyword = "3des-cbc",
>  		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
> @@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
>  		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
>  		.digest_len = 16,
>  		.key_len = 32
> +	},
> +	{
> +		.keyword = "sha384-hmac",
> +		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
> +		.digest_len = 24,
> +		.key_len = 48
> +	},
> +	{
> +		.keyword = "sha512-hmac",
> +		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
> +		.digest_len = 32,
> +		.key_len = 64
> +	},
> +	{
> +		.keyword = "aes-gmac",
> +		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
> +		.iv_len = 8,
> +		.digest_len = 16,
> +		.key_len = 20
> +	},
> +	{
> +		.keyword = "aes-xcbc-mac-96",
> +		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
> +		.digest_len = 12,
> +		.key_len = 16
>  	}
>  };
> 
> @@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
>  		.key_len = 36,
>  		.digest_len = 16,
>  		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-128-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 20,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-192-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 28,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "aes-256-ccm",
> +		.algo = RTE_CRYPTO_AEAD_AES_CCM,
> +		.iv_len = 8,
> +		.block_size = 4,
> +		.key_len = 36,
> +		.digest_len = 16,
> +		.aad_len = 8,
> +	},
> +	{
> +		.keyword = "chacha20-poly1305",
> +		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
> +		.iv_len = 12,
> +		.block_size = 64,
> +		.key_len = 36,
> +		.digest_len = 16,
> +		.aad_len = 8,
>  	}
>  };
> 
> @@ -484,6 +560,15 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
>  			if (status->status < 0)
>  				return;
> 
> +			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
> +				key_len -= 4;
> +				rule->auth_key_len = key_len;
> +				rule->iv_len = algo->iv_len;
> +				memcpy(&rule->salt,
> +					&rule->auth_key[key_len], 4);
> +			}
> +
> +

Extra line

>  			auth_algo_p = 1;
>  			continue;
>  		}
> @@ -1181,8 +1266,20 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			break;
>  		}
> 
> -		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
> -			iv_length = 12;
> +
> +		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
> +			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
> +			sa->aead_algo ==
> RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
> +
> +			if (ips->type ==
> +
> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +				iv_length = 8;

How is IV length dependent on the action type?
It should be same for all modes for a particular algorithm. Right?

> +			} else {
> +				if (sa->aead_algo ==
> RTE_CRYPTO_AEAD_AES_CCM)
> +					iv_length = 11;
> +				else
> +					iv_length = 12;
> +			}
> 
>  			sa_ctx->xf[idx].a.type =
> RTE_CRYPTO_SYM_XFORM_AEAD;
>  			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
> @@ -1206,10 +1303,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  			case RTE_CRYPTO_CIPHER_NULL:
>  			case RTE_CRYPTO_CIPHER_3DES_CBC:
>  			case RTE_CRYPTO_CIPHER_AES_CBC:
> -				iv_length = sa->iv_len;
> -				break;
>  			case RTE_CRYPTO_CIPHER_AES_CTR:
> -				iv_length = 16;
> +				iv_length = sa->iv_len;
>  				break;
>  			default:
>  				RTE_LOG(ERR, IPSEC_ESP,
> @@ -1218,6 +1313,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  				return -EINVAL;
>  			}
> 
> +			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
> {
> +				if (ips->type ==
> +
> RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
> +					iv_length = 8;

Same comment here.

> +				} else {
> +					iv_length = 12;
> +				}
> +			}
> +
>  			if (inbound) {
>  				sa_ctx->xf[idx].b.type =
> RTE_CRYPTO_SYM_XFORM_CIPHER;
>  				sa_ctx->xf[idx].b.cipher.algo = sa-
> >cipher_algo;
> @@ -1239,6 +1343,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  					sa->digest_len;
>  				sa_ctx->xf[idx].a.auth.op =
>  					RTE_CRYPTO_AUTH_OP_VERIFY;
> +				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
> +				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
> +
>  			} else { /* outbound */
>  				sa_ctx->xf[idx].a.type =
> RTE_CRYPTO_SYM_XFORM_CIPHER;
>  				sa_ctx->xf[idx].a.cipher.algo = sa-
> >cipher_algo;
> @@ -1260,11 +1367,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct
> ipsec_sa entries[],
>  					sa->digest_len;
>  				sa_ctx->xf[idx].b.auth.op =
>  					RTE_CRYPTO_AUTH_OP_GENERATE;
> +				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
> +				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
> +
>  			}
> 
> -			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
> -			sa_ctx->xf[idx].b.next = NULL;
> -			sa->xforms = &sa_ctx->xf[idx].a;
> +			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
> {
> +				sa->xforms = inbound ?
> +					&sa_ctx->xf[idx].a : &sa_ctx-
> >xf[idx].b;
> +				sa->xforms->next = NULL;
> +
> +			} else {
> +				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
> +				sa_ctx->xf[idx].b.next = NULL;
> +				sa->xforms = &sa_ctx->xf[idx].a;
> +			}
>  		}
> 
>  		if (ips->type ==
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms
  2021-10-08 19:07     ` [dpdk-dev] [EXT] " Akhil Goyal
@ 2021-10-11 15:40       ` Nicolau, Radu
  0 siblings, 0 replies; 82+ messages in thread
From: Nicolau, Radu @ 2021-10-11 15:40 UTC (permalink / raw)
  To: Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Hi Akhil, thanks for the feedback, some comments below.

On 10/8/2021 8:07 PM, Akhil Goyal wrote:
>> Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
>> AES_CCM, CHACHA20_POLY1305
>>
>> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
>> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
>> ---
>>   examples/ipsec-secgw/ipsec.h |   3 +-
>>   examples/ipsec-secgw/sa.c    | 133 ++++++++++++++++++++++++++++++++---
>>   2 files changed, 126 insertions(+), 10 deletions(-)
>>
> Documentation?
> Release notes?

I will follow up with an updated patchset.


>> -
>> +#define MAX_KEY_SIZE		96
> Max key length defined below is 64, then why 96?
I guess just to have some room, I will set it back to 64.
>
>>   /*
>>   		}
>>
>> -		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
>> -			iv_length = 12;
>> +
>> +		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
>> +			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
>> +			sa->aead_algo ==
>> RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
>> +
>> +			if (ips->type ==
>> +
>> 	RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
>> +				iv_length = 8;
> How is IV length dependent on the action type?
> It should be same for all modes for a particular algorithm. Right?

The issue here with inline crypto and AEAD algorithms is that we have 
the IV and the salt used for building the nonce but only the IV is 
included in the ESP header. And technically and according to the RFCs 
the value in the inline branch is the correct one, the other is actually 
the nonce buffer length, not the IV length. I'm not sure if this is the 
proper fix, probably it's not, but it's probably a change that will not 
break it for other crypto devices.



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

* [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (8 preceding siblings ...)
  2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
@ 2021-10-18 10:28 ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
                     ` (6 more replies)
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
  11 siblings, 7 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, hemant.agrawal, Radu Nicolau

Update the IPsec sample app with new features and updates:
- telemetry support
- add reset callback
- stats screen configurable as a command line parameter
- UDP encapsulation support for inline crypto
- ESN with configurable start value


Radu Nicolau (7):
  examples/ipsec-secgw: add stats interval argument
  examples/ipsec-secgw: update create inline session
  examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  examples/ipsec-secgw: support telemetry
  examples/ipsec-secgw: define initial ESN value
  examples/ipsec-secgw: add ethdev reset callback
  examples/ipsec-secgw: add support for additional algorithms

 doc/guides/rel_notes/release_21_11.rst   |   6 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  32 +-
 examples/ipsec-secgw/ipsec-secgw.c       | 400 +++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
 examples/ipsec-secgw/ipsec.c             |  93 +++++-
 examples/ipsec-secgw/ipsec.h             |  13 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                | 156 ++++++++-
 8 files changed, 680 insertions(+), 70 deletions(-)

-- 
v2: reworked the patchset to improve quality and address feedback
v3: reworked the patchset to accomodate changes in the ipsec libray
v4: removed TSO patch and reworked the patchset after feedback

2.25.1


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

* [dpdk-dev] [PATCH v4 1/7] examples/ipsec-secgw: add stats interval argument
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

Add -t for stats screen update interval, disabled by default.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
 examples/ipsec-secgw/ipsec-secgw.h       | 17 --------------
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 78171b25f9..5a27708872 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -127,6 +127,7 @@ The application has a number of command line options::
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINDOW_SIZE -e -a
                         -c SAD_CACHE_SIZE
+                        -t STATISTICS_INTERVAL
                         -s NUMBER_OF_MBUFS_IN_PACKET_POOL
                         -f CONFIG_FILE_PATH
                         --config (port,queue,lcore)[,(port,queue,lcore)]
@@ -176,6 +177,10 @@ Where:
     Zero value disables cache.
     Default value: 128.
 
+*   ``-t``: specifies the statistics screen update interval in seconds. If set
+    to zero or omitted statistics screen is disabled.
+    Default value: 0.
+
 *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
     will be calculated based on number of cores, eth ports and crypto queues.
 
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index f458d15a7a..5a29e330d9 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -180,6 +180,7 @@ static uint32_t frag_tbl_sz;
 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
 static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
+static uint32_t stats_interval;
 
 /* application wide librte_ipsec/SA parameters */
 struct app_sa_prm app_sa_prm = {
@@ -291,7 +292,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
 	}
 }
 
-#if (STATS_INTERVAL > 0)
 
 /* Print out statistics on packet distribution */
 static void
@@ -351,9 +351,8 @@ print_stats_cb(__rte_unused void *param)
 		   total_packets_dropped);
 	printf("\n====================================================\n");
 
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
+	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
 }
-#endif /* STATS_INTERVAL */
 
 static inline void
 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
@@ -1396,6 +1395,7 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-t STATS_INTERVAL]"
 		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -1420,6 +1420,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -t specifies statistics screen update interval,\n"
+		"     zero disables statistics screen (default value: 0)\n"
 		"  -s number of mbufs in packet pool, if not specified number\n"
 		"     of mbufs will be calculated based on number of cores,\n"
 		"     ports and crypto queues\n"
@@ -1629,7 +1631,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1710,6 +1712,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 			}
 			app_sa_prm.cache_sz = ret;
 			break;
+		case 't':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid interval value: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			stats_interval = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
@@ -3009,11 +3020,11 @@ main(int32_t argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
-#if (STATS_INTERVAL > 0)
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
-#else
-	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
-#endif /* STATS_INTERVAL */
+	if (stats_interval > 0)
+		rte_eal_alarm_set(stats_interval * US_PER_S,
+				print_stats_cb, NULL);
+	else
+		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
 
 	/* launch per-lcore init on every lcore */
 	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..04b4644370 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -6,9 +6,6 @@
 
 #include <stdbool.h>
 
-#ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
-#endif
 
 #define NB_SOCKETS 4
 
@@ -83,7 +80,6 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
-#if (STATS_INTERVAL > 0)
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -94,7 +90,6 @@ struct ipsec_core_statistics {
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
-#endif /* STATS_INTERVAL */
 
 extern struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS];
 
@@ -115,38 +110,26 @@ is_unprotected_port(uint16_t port_id)
 static inline void
 core_stats_update_rx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].rx += n;
 	core_statistics[lcore_id].rx_call++;
 	if (n == MAX_PKT_BURST)
 		core_statistics[lcore_id].burst_rx += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_tx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].tx += n;
 	core_statistics[lcore_id].tx_call++;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_drop(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].dropped += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 /* helper routine to free bulk of packets */
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 2/7] examples/ipsec-secgw: update create inline session
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Rework create inline session function as to update the session
configuration parameters before create session is called.
Also updated the rss key array size to prevent buffers overflows
with PMDs that copy more than 40 bytes.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 examples/ipsec-secgw/ipsec.c | 54 +++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 7 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6817139663..b6b7bddca8 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -171,16 +171,56 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
+			return -1;
+		}
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -266,10 +306,10 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sa->attr.ingress = (sa->direction ==
 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
+			uint8_t rss_key[64];
 			struct rte_eth_rss_conf rss_conf = {
 				.rss_key = rss_key,
-				.rss_key_len = 40,
+				.rss_key_len = sizeof(rss_key),
 			};
 			struct rte_eth_dev_info dev_info;
 			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  3 ++-
 examples/ipsec-secgw/ipsec.c             | 33 +++++++++++++++++++++---
 examples/ipsec-secgw/ipsec.h             |  7 ++++-
 examples/ipsec-secgw/sa.c                |  9 +++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 5a27708872..9c985873df 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -717,7 +717,8 @@ where each options means:
  ``<udp-encap>``
 
  * Option to enable IPsec UDP encapsulation for NAT Traversal.
-   Only *lookaside-protocol-offload* mode is supported at the moment.
+   Only *lookaside-protocol-offload* and *inline-protocol-offload* modes are
+   supported at the moment.
 
  * Optional: Yes, it is disabled by default
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index b6b7bddca8..90d9e61e5b 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -221,6 +221,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->udp_encap) {
+		sess_conf.ipsec.options.udp_encap = 1;
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -289,12 +295,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			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;
+		if (sa->udp_encap) {
+
+			sa->udp_spec.hdr.dst_port =
+					rte_cpu_to_be_16(sa->udp.dport);
+			sa->udp_spec.hdr.src_port =
+					rte_cpu_to_be_16(sa->udp.sport);
+
+			sa->pattern[2].mask = &rte_flow_item_udp_mask;
+			sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+			sa->pattern[2].spec = &sa->udp_spec;
+
+			sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+			sa->pattern[3].spec = &sa->esp_spec;
+			sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+			sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+		} else {
+			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->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+		}
 
 		sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
 		sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8405c48171..06bb11d5d5 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,10 @@ struct ipsec_sa {
 #define IP6_TRANSPORT (1 << 4)
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -140,7 +144,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -149,6 +153,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 17a28556c9..b32c168bcc 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -771,6 +772,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 				app_sa_prm.udp_encap = 1;
 				udp_encap_p = 1;
 				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+				rule->udp_encap = 1;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
+				break;
 			default:
 				APP_CHECK(0, status,
 					"UDP encapsulation not supported for "
@@ -858,6 +864,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	}
 
 	printf("mode:");
+	if (sa->udp_encap)
+		printf("UDP encapsulated ");
 
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
@@ -1311,6 +1319,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 4/7] examples/ipsec-secgw: support telemetry
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (2 preceding siblings ...)
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add telemetry support to the IPsec GW sample app and add
support for per SA telemetry when using IPsec library.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   4 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
 examples/ipsec-secgw/ipsec-secgw.c       | 357 ++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec-secgw.h       |  31 ++
 examples/ipsec-secgw/ipsec.h             |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                |  15 +-
 7 files changed, 402 insertions(+), 20 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index f819582878..2aca2aae45 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -177,6 +177,10 @@ New Features
   * Added tests to verify tunnel header verification in IPsec inbound.
   * Added tests to verify inner checksum.
 
+* **IPsec Security Gateway sample application new features.**
+
+  * Added support for telemetry
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 9c985873df..d2c2a7c9ca 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -726,6 +726,17 @@ where each options means:
 
    * *udp-encap*
 
+``<telemetry>``
+
+ * Option to enable per SA telemetry.
+   Currently only supported with IPsec library path.
+
+ * Optional: Yes, it is disabled by default
+
+ * Syntax:
+
+   * *telemetry*
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 5a29e330d9..54fe26d8a3 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -48,6 +48,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -670,7 +671,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -687,25 +688,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -749,6 +755,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -764,16 +771,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -784,17 +795,23 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
 			ip->num, DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -806,15 +823,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd6);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -958,6 +980,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -993,6 +1016,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1009,6 +1033,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1045,6 +1070,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1118,6 +1144,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1135,13 +1162,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2835,6 +2864,300 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dopped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.outbound.spd4.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.outbound.spd6.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2872,6 +3195,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	ipsec_secgw_telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 04b4644370..de9f382742 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -80,6 +80,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -87,6 +98,26 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 06bb11d5d5..de4e0606e2 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -123,6 +123,8 @@ struct ipsec_sa {
 #define TRANSPORT  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	struct {
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index b32c168bcc..dcdf886af9 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -323,6 +323,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -339,14 +340,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags |= TRANSPORT;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -357,6 +358,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1395,6 +1401,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 5/7] examples/ipsec-secgw: define initial ESN value
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (3 preceding siblings ...)
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
  2021-10-18 10:29   ` [dpdk-dev] [PATCH v4 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

New option added to the SA configuration arguments that
allows setting an arbitrary start value for ESN.

For example in the SA below ESN will be enabled and first egress
IPsec packet will have the ESN value 10000:

sa out 15 cipher_algo null auth_algo null mode ipv4-tunnel \
src 172.16.1.5 dst 172.16.2.5 \
esn 10000

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.c             |  6 ++++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 10 ++++++++++
 4 files changed, 27 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index d2c2a7c9ca..f5f858380e 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -737,6 +737,16 @@ where each options means:
 
    * *telemetry*
 
+ ``<esn>``
+
+ * Enable ESN and set the initial ESN value.
+
+ * Optional: Yes, ESN not enabled by default
+
+ * Syntax:
+
+   * *esn N* N is the initial ESN value
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 90d9e61e5b..2d4a26c962 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -227,6 +227,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index de4e0606e2..b037d5179f 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -143,6 +143,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint64_t esn;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index dcdf886af9..6acc4a5213 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -684,6 +684,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 6/7] examples/ipsec-secgw: add ethdev reset callback
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (4 preceding siblings ...)
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
@ 2021-10-18 10:28   ` Radu Nicolau
  2021-10-18 10:29   ` [dpdk-dev] [PATCH v4 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:28 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Applications should not quietly ignore an ethdev reset event.
Register an event handler for ethdev reset callback
RTE_ETH_EVENT_INTR_RESET that prints a message and
quits the application.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 54fe26d8a3..33d9650b6a 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2551,6 +2551,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type __rte_unused,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d\n", port_id);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3317,6 +3328,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
-- 
2.25.1


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

* [dpdk-dev] [PATCH v4 7/7] examples/ipsec-secgw: add support for additional algorithms
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (5 preceding siblings ...)
  2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-10-18 10:29   ` Radu Nicolau
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-18 10:29 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
AES_CCM, CHACHA20_POLY1305

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   2 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |   3 +-
 examples/ipsec-secgw/ipsec.h             |   3 +-
 examples/ipsec-secgw/sa.c                | 122 +++++++++++++++++++++--
 4 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 2aca2aae45..3dae5181b1 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -180,6 +180,8 @@ New Features
 * **IPsec Security Gateway sample application new features.**
 
   * Added support for telemetry
+  * Added support for more AEAD algorithms: AES-GMAC, AES_CTR, AES_XCBC_MAC,
+    AES_CCM, CHACHA20_POLY1305
 
 
 Removed Items
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index f5f858380e..6510456e31 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -106,7 +106,8 @@ Constraints
 
 *  No IPv6 options headers.
 *  No AH mode.
-*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1 and NULL.
+*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1,
+   AES-GMAC, AES_CTR, AES_XCBC_MAC, AES_CCM, CHACHA20_POLY1305 and NULL.
 *  Each SA must be handle by a unique lcore (*1 RX queue per port*).
 
 Compiling the Application
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index b037d5179f..0dfb0d6acb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -63,8 +63,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
-
+#define MAX_KEY_SIZE		64
 /*
  * application wide SA parameters
  */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 6acc4a5213..de06f24d01 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -46,6 +46,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -484,6 +560,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1171,8 +1255,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			break;
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+				iv_length = 11;
+			else
+				iv_length = 12;
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1196,10 +1287,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1208,6 +1297,10 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			/* AES_GMAC uses salt like AEAD algorithms */
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
+					iv_length = 12;
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1229,6 +1322,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1250,11 +1346,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (9 preceding siblings ...)
  2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-10-27 11:45 ` Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
                     ` (6 more replies)
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
  11 siblings, 7 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, hemant.agrawal, Radu Nicolau

Update the IPsec sample app with new features and updates:
- telemetry support
- add reset callback
- stats screen configurable as a command line parameter
- UDP encapsulation support for inline crypto
- ESN with configurable start value

Radu Nicolau (7):
  examples/ipsec-secgw: add stats interval argument
  examples/ipsec-secgw: update create inline session
  examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  examples/ipsec-secgw: support telemetry
  examples/ipsec-secgw: define initial ESN value
  examples/ipsec-secgw: add ethdev reset callback
  examples/ipsec-secgw: add support for additional algorithms

 doc/guides/rel_notes/release_21_11.rst   |   6 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  32 +-
 examples/ipsec-secgw/ipsec-secgw.c       | 400 +++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
 examples/ipsec-secgw/ipsec.c             |  93 +++++-
 examples/ipsec-secgw/ipsec.h             |  13 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                | 156 ++++++++-
 8 files changed, 680 insertions(+), 70 deletions(-)

-- 

v2: reworked the patchset to improve quality and address feedback
v3: reworked the patchset to accomodate changes in the ipsec libray
v4: removed TSO patch and reworked the patchset after feedback
v5: rebased to RC1

2.25.1


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

* [dpdk-dev] [PATCH v5 1/7] examples/ipsec-secgw: add stats interval argument
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

Add -t for stats screen update interval, disabled by default.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
 examples/ipsec-secgw/ipsec-secgw.h       | 17 --------------
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 782574dd39..282926924f 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -127,6 +127,7 @@ The application has a number of command line options::
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINDOW_SIZE -e -a
                         -c SAD_CACHE_SIZE
+                        -t STATISTICS_INTERVAL
                         -s NUMBER_OF_MBUFS_IN_PACKET_POOL
                         -f CONFIG_FILE_PATH
                         --config (port,queue,lcore)[,(port,queue,lcore)]
@@ -176,6 +177,10 @@ Where:
     Zero value disables cache.
     Default value: 128.
 
+*   ``-t``: specifies the statistics screen update interval in seconds. If set
+    to zero or omitted statistics screen is disabled.
+    Default value: 0.
+
 *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
     will be calculated based on number of cores, eth ports and crypto queues.
 
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4bdf99b62b..d9a6838459 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -179,6 +179,7 @@ static uint32_t frag_tbl_sz;
 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
 static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
+static uint32_t stats_interval;
 
 /* application wide librte_ipsec/SA parameters */
 struct app_sa_prm app_sa_prm = {
@@ -289,7 +290,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
 	}
 }
 
-#if (STATS_INTERVAL > 0)
 
 /* Print out statistics on packet distribution */
 static void
@@ -349,9 +349,8 @@ print_stats_cb(__rte_unused void *param)
 		   total_packets_dropped);
 	printf("\n====================================================\n");
 
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
+	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
 }
-#endif /* STATS_INTERVAL */
 
 static inline void
 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
@@ -1394,6 +1393,7 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-t STATS_INTERVAL]"
 		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -1418,6 +1418,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -t specifies statistics screen update interval,\n"
+		"     zero disables statistics screen (default value: 0)\n"
 		"  -s number of mbufs in packet pool, if not specified number\n"
 		"     of mbufs will be calculated based on number of cores,\n"
 		"     ports and crypto queues\n"
@@ -1627,7 +1629,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1708,6 +1710,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 			}
 			app_sa_prm.cache_sz = ret;
 			break;
+		case 't':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid interval value: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			stats_interval = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
@@ -3003,11 +3014,11 @@ main(int32_t argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
-#if (STATS_INTERVAL > 0)
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
-#else
-	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
-#endif /* STATS_INTERVAL */
+	if (stats_interval > 0)
+		rte_eal_alarm_set(stats_interval * US_PER_S,
+				print_stats_cb, NULL);
+	else
+		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
 
 	/* launch per-lcore init on every lcore */
 	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..04b4644370 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -6,9 +6,6 @@
 
 #include <stdbool.h>
 
-#ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
-#endif
 
 #define NB_SOCKETS 4
 
@@ -83,7 +80,6 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
-#if (STATS_INTERVAL > 0)
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -94,7 +90,6 @@ struct ipsec_core_statistics {
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
-#endif /* STATS_INTERVAL */
 
 extern struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS];
 
@@ -115,38 +110,26 @@ is_unprotected_port(uint16_t port_id)
 static inline void
 core_stats_update_rx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].rx += n;
 	core_statistics[lcore_id].rx_call++;
 	if (n == MAX_PKT_BURST)
 		core_statistics[lcore_id].burst_rx += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_tx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].tx += n;
 	core_statistics[lcore_id].tx_call++;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_drop(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].dropped += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 /* helper routine to free bulk of packets */
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 2/7] examples/ipsec-secgw: update create inline session
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Rework create inline session function as to update the session
configuration parameters before create session is called.
Also updated the rss key array size to prevent buffers overflows
with PMDs that copy more than 40 bytes.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 examples/ipsec-secgw/ipsec.c | 54 +++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 7 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6817139663..b6b7bddca8 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -171,16 +171,56 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
+			return -1;
+		}
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -266,10 +306,10 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sa->attr.ingress = (sa->direction ==
 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
+			uint8_t rss_key[64];
 			struct rte_eth_rss_conf rss_conf = {
 				.rss_key = rss_key,
-				.rss_key_len = 40,
+				.rss_key_len = sizeof(rss_key),
 			};
 			struct rte_eth_dev_info dev_info;
 			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-31 20:03     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  3 ++-
 examples/ipsec-secgw/ipsec.c             | 33 +++++++++++++++++++++---
 examples/ipsec-secgw/ipsec.h             |  7 ++++-
 examples/ipsec-secgw/sa.c                |  9 +++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 282926924f..2d0f322427 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -717,7 +717,8 @@ where each options means:
  ``<udp-encap>``
 
  * Option to enable IPsec UDP encapsulation for NAT Traversal.
-   Only *lookaside-protocol-offload* mode is supported at the moment.
+   Only *lookaside-protocol-offload* and *inline-protocol-offload* modes are
+   supported at the moment.
 
  * Optional: Yes, it is disabled by default
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index b6b7bddca8..90d9e61e5b 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -221,6 +221,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->udp_encap) {
+		sess_conf.ipsec.options.udp_encap = 1;
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -289,12 +295,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			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;
+		if (sa->udp_encap) {
+
+			sa->udp_spec.hdr.dst_port =
+					rte_cpu_to_be_16(sa->udp.dport);
+			sa->udp_spec.hdr.src_port =
+					rte_cpu_to_be_16(sa->udp.sport);
+
+			sa->pattern[2].mask = &rte_flow_item_udp_mask;
+			sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+			sa->pattern[2].spec = &sa->udp_spec;
+
+			sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+			sa->pattern[3].spec = &sa->esp_spec;
+			sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+			sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+		} else {
+			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->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+		}
 
 		sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
 		sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8405c48171..06bb11d5d5 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,10 @@ struct ipsec_sa {
 #define IP6_TRANSPORT (1 << 4)
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -140,7 +144,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -149,6 +153,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 88dd30464f..daebc1f09b 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -771,6 +772,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 				app_sa_prm.udp_encap = 1;
 				udp_encap_p = 1;
 				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+				rule->udp_encap = 1;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
+				break;
 			default:
 				APP_CHECK(0, status,
 					"UDP encapsulation not supported for "
@@ -858,6 +864,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	}
 
 	printf("mode:");
+	if (sa->udp_encap)
+		printf("UDP encapsulated ");
 
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
@@ -1311,6 +1319,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (2 preceding siblings ...)
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-31 20:22     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add telemetry support to the IPsec GW sample app and add
support for per SA telemetry when using IPsec library.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   4 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
 examples/ipsec-secgw/ipsec-secgw.c       | 357 ++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec-secgw.h       |  31 ++
 examples/ipsec-secgw/ipsec.h             |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                |  15 +-
 7 files changed, 402 insertions(+), 20 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 1ccac87b73..0a0bf05568 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -305,6 +305,10 @@ New Features
     * Pcapng format with timestamps and meta-data.
     * Fixes packet capture with stripped VLAN tags.
 
+* **IPsec Security Gateway sample application new features.**
+
+  * Added support for telemetry
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 2d0f322427..b0256da1d8 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -726,6 +726,17 @@ where each options means:
 
    * *udp-encap*
 
+``<telemetry>``
+
+ * Option to enable per SA telemetry.
+   Currently only supported with IPsec library path.
+
+ * Optional: Yes, it is disabled by default
+
+ * Syntax:
+
+   * *telemetry*
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index d9a6838459..1ef24b7b5c 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -47,6 +47,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -668,7 +669,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -685,25 +686,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -747,6 +753,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -762,16 +769,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -782,17 +793,23 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
 			ip->num, DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -804,15 +821,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd6);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -956,6 +978,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -991,6 +1014,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1007,6 +1031,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1043,6 +1068,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1116,6 +1142,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1133,13 +1160,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2829,6 +2858,300 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dopped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.outbound.spd4.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.outbound.spd6.protect);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2866,6 +3189,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	ipsec_secgw_telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 04b4644370..de9f382742 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -80,6 +80,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -87,6 +98,26 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 06bb11d5d5..de4e0606e2 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -123,6 +123,8 @@ struct ipsec_sa {
 #define TRANSPORT  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	struct {
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index daebc1f09b..65c975993d 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -323,6 +323,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -339,14 +340,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags |= TRANSPORT;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -357,6 +358,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1395,6 +1401,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (3 preceding siblings ...)
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-31 20:23     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  6 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

New option added to the SA configuration arguments that
allows setting an arbitrary start value for ESN.

For example in the SA below ESN will be enabled and first egress
IPsec packet will have the ESN value 10000:

sa out 15 cipher_algo null auth_algo null mode ipv4-tunnel \
src 172.16.1.5 dst 172.16.2.5 \
esn 10000

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.c             |  6 ++++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 10 ++++++++++
 4 files changed, 27 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index b0256da1d8..02846ac160 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -737,6 +737,16 @@ where each options means:
 
    * *telemetry*
 
+ ``<esn>``
+
+ * Enable ESN and set the initial ESN value.
+
+ * Optional: Yes, ESN not enabled by default
+
+ * Syntax:
+
+   * *esn N* N is the initial ESN value
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 90d9e61e5b..2d4a26c962 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -227,6 +227,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index de4e0606e2..b037d5179f 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -143,6 +143,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint64_t esn;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 65c975993d..8725001fc7 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -684,6 +684,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (4 preceding siblings ...)
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-31 20:25     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  6 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Applications should not quietly ignore an ethdev reset event.
Register an event handler for ethdev reset callback
RTE_ETH_EVENT_INTR_RESET that prints a message and
quits the application.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 1ef24b7b5c..bfa2070b8d 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2545,6 +2545,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type __rte_unused,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d\n", port_id);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3311,6 +3322,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
-- 
2.25.1


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

* [dpdk-dev] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (5 preceding siblings ...)
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-10-27 11:45   ` Radu Nicolau
  2021-10-31 20:29     ` [dpdk-dev] [EXT] " Akhil Goyal
  6 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-10-27 11:45 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
AES_CCM, CHACHA20_POLY1305

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   2 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |   3 +-
 examples/ipsec-secgw/ipsec.h             |   3 +-
 examples/ipsec-secgw/sa.c                | 122 +++++++++++++++++++++--
 4 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 0a0bf05568..1d656b8e2b 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -308,6 +308,8 @@ New Features
 * **IPsec Security Gateway sample application new features.**
 
   * Added support for telemetry
+  * Added support for more AEAD algorithms: AES-GMAC, AES_CTR, AES_XCBC_MAC,
+    AES_CCM, CHACHA20_POLY1305
 
 
 Removed Items
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 02846ac160..edd3d439f5 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -106,7 +106,8 @@ Constraints
 
 *  No IPv6 options headers.
 *  No AH mode.
-*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1 and NULL.
+*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1,
+   AES-GMAC, AES_CTR, AES_XCBC_MAC, AES_CCM, CHACHA20_POLY1305 and NULL.
 *  Each SA must be handle by a unique lcore (*1 RX queue per port*).
 
 Compiling the Application
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index b037d5179f..0dfb0d6acb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -63,8 +63,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
-
+#define MAX_KEY_SIZE		64
 /*
  * application wide SA parameters
  */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 8725001fc7..44c18badbb 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -46,6 +46,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -484,6 +560,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1171,8 +1255,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			break;
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+				iv_length = 11;
+			else
+				iv_length = 12;
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1196,10 +1287,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1208,6 +1297,10 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			/* AES_GMAC uses salt like AEAD algorithms */
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
+					iv_length = 12;
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1229,6 +1322,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1250,11 +1346,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-10-31 20:03     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-31 20:03 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Enable UDP encapsulation for both transport and tunnel modes for the
> inline crypto offload path.
> 
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  doc/guides/sample_app_ug/ipsec_secgw.rst |  3 ++-
>  examples/ipsec-secgw/ipsec.c             | 33 +++++++++++++++++++++---
>  examples/ipsec-secgw/ipsec.h             |  7 ++++-
>  examples/ipsec-secgw/sa.c                |  9 +++++++
>  4 files changed, 46 insertions(+), 6 deletions(-)
> 
> diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst
> b/doc/guides/sample_app_ug/ipsec_secgw.rst
> index 282926924f..2d0f322427 100644
> --- a/doc/guides/sample_app_ug/ipsec_secgw.rst
> +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
> @@ -717,7 +717,8 @@ where each options means:
>   ``<udp-encap>``
> 
>   * Option to enable IPsec UDP encapsulation for NAT Traversal.
> -   Only *lookaside-protocol-offload* mode is supported at the moment.
> +   Only *lookaside-protocol-offload* and *inline-protocol-offload* modes
> are
> +   supported at the moment.

Patch says inline crypto is supported but here inline protocol offload is supported.

With this fixed,
Acked-by: Akhil Goyal <gakhil@marvell.com>


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

* Re: [dpdk-dev] [EXT] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
@ 2021-10-31 20:22     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-31 20:22 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> +static int
> +handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
> +		const char *params, struct rte_tel_data *data)
> +{
> +	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
> +	unsigned int coreid;
> +
> +	rte_tel_data_start_dict(data);
> +
> +	if (params) {
> +		coreid = (uint32_t)atoi(params);
> +		if (rte_lcore_is_enabled(coreid) == 0)
> +			return -EINVAL;
> +
> +		total_pkts_dropped = core_statistics[coreid].dropped;
> +		total_pkts_tx = core_statistics[coreid].tx;
> +		total_pkts_rx = core_statistics[coreid].rx;
> +
> +	} else {
> +		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
> +
> +			/* skip disabled cores */
> +			if (rte_lcore_is_enabled(coreid) == 0)
> +				continue;
> +
> +			total_pkts_dropped +=
> core_statistics[coreid].dropped;
> +			total_pkts_tx += core_statistics[coreid].tx;
> +			total_pkts_rx += core_statistics[coreid].rx;
> +		}
> +	}
> +
> +	/* add telemetry key/values pairs */
> +	rte_tel_data_add_dict_u64(data, "packets received",
> +				total_pkts_rx);
> +
> +	rte_tel_data_add_dict_u64(data, "packets transmitted",
> +				total_pkts_tx);
> +
> +	rte_tel_data_add_dict_u64(data, "packets dopped",
> +				total_pkts_dropped);

Fix typo dopped

> +
> +
> +	return 0;
> +}
> +
> +static void
> +update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
> +{
> +	struct ipsec_core_statistics *lcore_stats;
> +
> +	/* skip disabled cores */
> +	if (rte_lcore_is_enabled(coreid) == 0)
> +		return;
> +
> +	lcore_stats = &core_statistics[coreid];
> +
> +	total->rx = lcore_stats->rx;
> +	total->dropped = lcore_stats->dropped;
> +	total->tx = lcore_stats->tx;
> +
> +	/* outbound stats */
> +	total->outbound.spd6.protect += lcore_stats-
> >outbound.spd6.protect;
> +	total->outbound.spd6.bypass += lcore_stats-
> >outbound.spd6.bypass;
> +	total->outbound.spd6.discard += lcore_stats-
> >outbound.spd6.discard;
> +
> +	total->outbound.spd4.protect += lcore_stats-
> >outbound.spd4.protect;
> +	total->outbound.spd4.bypass += lcore_stats-
> >outbound.spd4.bypass;
> +	total->outbound.spd4.discard += lcore_stats-
> >outbound.spd4.discard;
> +
> +	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
> +
> +	/* inbound stats */
> +	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
> +	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
> +	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
> +
> +	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
> +	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
> +	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
> +
> +	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
> +
> +
> +	/* routing stats */
> +	total->lpm4.miss += lcore_stats->lpm4.miss;
> +	total->lpm6.miss += lcore_stats->lpm6.miss;
> +}
> +
> +static void
> +update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
> +{
> +	memset(total, 0, sizeof(*total));
> +
> +	if (coreid != UINT32_MAX) {
> +		update_lcore_statistics(total, coreid);
> +	} else {
> +		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
> +			update_lcore_statistics(total, coreid);
> +	}
> +}
> +
> +static int
> +handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd
> __rte_unused,
> +		const char *params, struct rte_tel_data *data)
> +{
> +	struct ipsec_core_statistics total_stats;
> +
> +	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
> +	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
> +	struct rte_tel_data *sad_data = rte_tel_data_alloc();
> +
> +	unsigned int coreid = UINT32_MAX;
> +
> +	/* verify allocated telemetry data structures */
> +	if (!spd4_data || !spd6_data || !sad_data)
> +		return -ENOMEM;
> +
> +	/* initialize telemetry data structs as dicts */
> +	rte_tel_data_start_dict(data);
> +
> +	rte_tel_data_start_dict(spd4_data);
> +	rte_tel_data_start_dict(spd6_data);
> +	rte_tel_data_start_dict(sad_data);
> +
> +	if (params) {
> +		coreid = (uint32_t)atoi(params);
> +		if (rte_lcore_is_enabled(coreid) == 0)
> +			return -EINVAL;
> +	}
> +
> +	update_statistics(&total_stats, coreid);
> +
> +	/* add spd 4 telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(spd4_data, "protect",
> +		total_stats.outbound.spd4.protect);
> +	rte_tel_data_add_dict_u64(spd4_data, "bypass",
> +		total_stats.outbound.spd4.bypass);
> +	rte_tel_data_add_dict_u64(spd4_data, "discard",
> +		total_stats.outbound.spd4.discard);
> +
> +	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
> +
> +	/* add spd 6 telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(spd6_data, "protect",
> +		total_stats.outbound.spd6.protect);
> +	rte_tel_data_add_dict_u64(spd6_data, "bypass",
> +		total_stats.outbound.spd6.bypass);
> +	rte_tel_data_add_dict_u64(spd6_data, "discard",
> +		total_stats.outbound.spd6.discard);
> +
> +	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
> +
> +	/* add sad telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(sad_data, "miss",
> +		total_stats.outbound.sad.miss);
> +
> +	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
> +
> +	return 0;
> +}
> +
> +static int
> +handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd
> __rte_unused,
> +		const char *params, struct rte_tel_data *data)
> +{
> +	struct ipsec_core_statistics total_stats;
> +
> +	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
> +	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
> +	struct rte_tel_data *sad_data = rte_tel_data_alloc();
> +
> +	unsigned int coreid = UINT32_MAX;
> +
> +	/* verify allocated telemetry data structures */
> +	if (!spd4_data || !spd6_data || !sad_data)
> +		return -ENOMEM;
> +
> +	/* initialize telemetry data structs as dicts */
> +	rte_tel_data_start_dict(data);
> +	rte_tel_data_start_dict(spd4_data);
> +	rte_tel_data_start_dict(spd6_data);
> +	rte_tel_data_start_dict(sad_data);
> +
> +	/* add children dicts to parent dict */
> +
> +	if (params) {
> +		coreid = (uint32_t)atoi(params);
> +		if (rte_lcore_is_enabled(coreid) == 0)
> +			return -EINVAL;
> +	}
> +
> +	update_statistics(&total_stats, coreid);
> +
> +	/* add sad telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(sad_data, "miss",
> +		total_stats.outbound.sad.miss);

This should be inbound I guess.

> +
> +	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
> +
> +	/* add spd 4 telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(spd4_data, "protect",
> +		total_stats.inbound.spd4.protect);
> +	rte_tel_data_add_dict_u64(spd4_data, "bypass",
> +		total_stats.inbound.spd4.bypass);
> +	rte_tel_data_add_dict_u64(spd4_data, "discard",
> +		total_stats.inbound.spd4.discard);
> +
> +	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
> +
> +	/* add spd 6 telemetry key/values pairs */
> +
> +	rte_tel_data_add_dict_u64(spd6_data, "protect",
> +		total_stats.inbound.spd6.protect);
> +	rte_tel_data_add_dict_u64(spd6_data, "bypass",
> +		total_stats.inbound.spd6.bypass);
> +	rte_tel_data_add_dict_u64(spd6_data, "discard",
> +		total_stats.inbound.spd6.discard);
> +
> +	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
> +
> +	return 0;
> +}
> +
> +static int
> +handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd
> __rte_unused,
> +		const char *params, struct rte_tel_data *data)
> +{
> +	struct ipsec_core_statistics total_stats;
> +
> +	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
> +	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
> +
> +	unsigned int coreid = UINT32_MAX;
> +
> +	/* initialize telemetry data structs as dicts */
> +	rte_tel_data_start_dict(data);
> +	rte_tel_data_start_dict(lpm4_data);
> +	rte_tel_data_start_dict(lpm6_data);
> +
> +
> +	if (params) {
> +		coreid = (uint32_t)atoi(params);
> +		if (rte_lcore_is_enabled(coreid) == 0)
> +			return -EINVAL;
> +	}
> +
> +	update_statistics(&total_stats, coreid);
> +
> +	/* add lpm 4 telemetry key/values pairs */
> +	rte_tel_data_add_dict_u64(lpm4_data, "miss",
> +		total_stats.outbound.spd4.protect);

Again typo, total_stats.lpm4.miss

> +
> +	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
> +
> +	/* add lpm 6 telemetry key/values pairs */
> +	rte_tel_data_add_dict_u64(lpm6_data, "miss",
> +		total_stats.outbound.spd6.protect);
Here also
Total_stats.lpm6.miss

> +
> +	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
> +
> +	return 0;
> +}
> +
> +static void
> +ipsec_secgw_telemetry_init(void)
> +{
> +	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
> +		handle_telemetry_cmd_ipsec_secgw_stats,
> +		"Returns outbound global stats. "

Returns global stats

> +		"Optional Parameters: int <logical core id>");
> +
> +	rte_telemetry_register_cmd("/examples/ipsec-
> secgw/stats/outbound",
> +		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
> +		"Returns outbound global stats. "
> +		"Optional Parameters: int <logical core id>");
> +
> +	rte_telemetry_register_cmd("/examples/ipsec-
> secgw/stats/inbound",
> +		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
> +		"Returns outbound global stats. "

This should be inbound.

> +		"Optional Parameters: int <logical core id>");
> +
> +	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
> +		handle_telemetry_cmd_ipsec_secgw_stats_routing,
> +		"Returns outbound global stats. "

Returns routing stats.

Please review the patch for any other Typos before submitting v6.

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

* Re: [dpdk-dev] [EXT] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
@ 2021-10-31 20:23     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-31 20:23 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> New option added to the SA configuration arguments that
> allows setting an arbitrary start value for ESN.
> 
> For example in the SA below ESN will be enabled and first egress
> IPsec packet will have the ESN value 10000:
> 
> sa out 15 cipher_algo null auth_algo null mode ipv4-tunnel \
> src 172.16.1.5 dst 172.16.2.5 \
> esn 10000
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>

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

* Re: [dpdk-dev] [EXT] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-10-31 20:25     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-31 20:25 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Applications should not quietly ignore an ethdev reset event.
> Register an event handler for ethdev reset callback
> RTE_ETH_EVENT_INTR_RESET that prints a message and
> quits the application.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
>  examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-
> secgw/ipsec-secgw.c
> index 1ef24b7b5c..bfa2070b8d 100644
> --- a/examples/ipsec-secgw/ipsec-secgw.c
> +++ b/examples/ipsec-secgw/ipsec-secgw.c
> @@ -2545,6 +2545,17 @@ inline_ipsec_event_callback(uint16_t port_id,
> enum rte_eth_event_type type,
>  	return -1;
>  }
> 
> +static int
> +ethdev_reset_event_callback(uint16_t port_id,
> +		enum rte_eth_event_type type __rte_unused,
> +		 void *param __rte_unused, void *ret_param __rte_unused)
> +{
> +	printf("Reset Event on port id %d\n", port_id);

You can also print the type of eth event that has happened.
With this fixed,
Acked-by: Akhil Goyal <gakhil@marvell.com>

> +	printf("Force quit application");
> +	force_quit = true;
> +	return 0;
> +}
> +
>  static uint16_t
>  rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
>  	struct rte_mbuf *pkt[], uint16_t nb_pkts,
> @@ -3311,6 +3322,9 @@ main(int32_t argc, char **argv)
>  					rte_strerror(-ret), portid);
>  		}
> 
> +		rte_eth_dev_callback_register(portid,
> RTE_ETH_EVENT_INTR_RESET,
> +			ethdev_reset_event_callback, NULL);
> +
>  		rte_eth_dev_callback_register(portid,
>  			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback,
> NULL);
>  	}
> --
> 2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms
  2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
@ 2021-10-31 20:29     ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-10-31 20:29 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
> AES_CCM, CHACHA20_POLY1305
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
> ---
Acked-by: Akhil Goyal <gakhil@marvell.com>

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

* [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features
  2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
                   ` (10 preceding siblings ...)
  2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-11-01 12:58 ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
                     ` (7 more replies)
  11 siblings, 8 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  Cc: dev, gakhil, declan.doherty, hemant.agrawal, Radu Nicolau

Update the IPsec sample app with new features and updates:
- telemetry support
- add reset callback
- stats screen configurable as a command line parameter
- UDP encapsulation support for inline crypto
- ESN with configurable start value

Radu Nicolau (7):
  examples/ipsec-secgw: add stats interval argument
  examples/ipsec-secgw: update create inline session
  examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  examples/ipsec-secgw: support telemetry
  examples/ipsec-secgw: define initial ESN value
  examples/ipsec-secgw: add ethdev reset callback
  examples/ipsec-secgw: add support for additional algorithms

 doc/guides/rel_notes/release_21_11.rst   |   6 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  32 +-
 examples/ipsec-secgw/ipsec-secgw.c       | 400 +++++++++++++++++++++--
 examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
 examples/ipsec-secgw/ipsec.c             |  93 +++++-
 examples/ipsec-secgw/ipsec.h             |  13 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                | 156 ++++++++-
 8 files changed, 680 insertions(+), 70 deletions(-)

-- 
v2: reworked the patchset to improve quality and address feedback
v3: reworked the patchset to accomodate changes in the ipsec libray
v4: removed TSO patch and reworked the patchset after feedback
v5: rebased to RC1
v6: addressed feeedback

2.25.1


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

* [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-03  9:23     ` [dpdk-dev] [EXT] " Akhil Goyal
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

Add -t for stats screen update interval, disabled by default.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  5 ++++
 examples/ipsec-secgw/ipsec-secgw.c       | 29 ++++++++++++++++--------
 examples/ipsec-secgw/ipsec-secgw.h       | 17 --------------
 3 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 782574dd39..282926924f 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -127,6 +127,7 @@ The application has a number of command line options::
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINDOW_SIZE -e -a
                         -c SAD_CACHE_SIZE
+                        -t STATISTICS_INTERVAL
                         -s NUMBER_OF_MBUFS_IN_PACKET_POOL
                         -f CONFIG_FILE_PATH
                         --config (port,queue,lcore)[,(port,queue,lcore)]
@@ -176,6 +177,10 @@ Where:
     Zero value disables cache.
     Default value: 128.
 
+*   ``-t``: specifies the statistics screen update interval in seconds. If set
+    to zero or omitted statistics screen is disabled.
+    Default value: 0.
+
 *   ``-s``: sets number of mbufs in packet pool, if not provided number of mbufs
     will be calculated based on number of cores, eth ports and crypto queues.
 
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4bdf99b62b..d9a6838459 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -179,6 +179,7 @@ static uint32_t frag_tbl_sz;
 static uint32_t frame_buf_size = RTE_MBUF_DEFAULT_BUF_SIZE;
 static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
+static uint32_t stats_interval;
 
 /* application wide librte_ipsec/SA parameters */
 struct app_sa_prm app_sa_prm = {
@@ -289,7 +290,6 @@ adjust_ipv6_pktlen(struct rte_mbuf *m, const struct rte_ipv6_hdr *iph,
 	}
 }
 
-#if (STATS_INTERVAL > 0)
 
 /* Print out statistics on packet distribution */
 static void
@@ -349,9 +349,8 @@ print_stats_cb(__rte_unused void *param)
 		   total_packets_dropped);
 	printf("\n====================================================\n");
 
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
+	rte_eal_alarm_set(stats_interval * US_PER_S, print_stats_cb, NULL);
 }
-#endif /* STATS_INTERVAL */
 
 static inline void
 prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
@@ -1394,6 +1393,7 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-t STATS_INTERVAL]"
 		" [-s NUMBER_OF_MBUFS_IN_PKT_POOL]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
@@ -1418,6 +1418,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -t specifies statistics screen update interval,\n"
+		"     zero disables statistics screen (default value: 0)\n"
 		"  -s number of mbufs in packet pool, if not specified number\n"
 		"     of mbufs will be calculated based on number of cores,\n"
 		"     ports and crypto queues\n"
@@ -1627,7 +1629,7 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:s:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:t:s:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1708,6 +1710,15 @@ parse_args(int32_t argc, char **argv, struct eh_conf *eh_conf)
 			}
 			app_sa_prm.cache_sz = ret;
 			break;
+		case 't':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid interval value: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			stats_interval = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
@@ -3003,11 +3014,11 @@ main(int32_t argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
-#if (STATS_INTERVAL > 0)
-	rte_eal_alarm_set(STATS_INTERVAL * US_PER_S, print_stats_cb, NULL);
-#else
-	RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
-#endif /* STATS_INTERVAL */
+	if (stats_interval > 0)
+		rte_eal_alarm_set(stats_interval * US_PER_S,
+				print_stats_cb, NULL);
+	else
+		RTE_LOG(INFO, IPSEC, "Stats display disabled\n");
 
 	/* launch per-lcore init on every lcore */
 	rte_eal_mp_remote_launch(ipsec_launch_one_lcore, eh_conf, CALL_MAIN);
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 96e22de45e..04b4644370 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -6,9 +6,6 @@
 
 #include <stdbool.h>
 
-#ifndef STATS_INTERVAL
-#define STATS_INTERVAL 0
-#endif
 
 #define NB_SOCKETS 4
 
@@ -83,7 +80,6 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
-#if (STATS_INTERVAL > 0)
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -94,7 +90,6 @@ struct ipsec_core_statistics {
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
-#endif /* STATS_INTERVAL */
 
 extern struct ethaddr_info ethaddr_tbl[RTE_MAX_ETHPORTS];
 
@@ -115,38 +110,26 @@ is_unprotected_port(uint16_t port_id)
 static inline void
 core_stats_update_rx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].rx += n;
 	core_statistics[lcore_id].rx_call++;
 	if (n == MAX_PKT_BURST)
 		core_statistics[lcore_id].burst_rx += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_tx(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].tx += n;
 	core_statistics[lcore_id].tx_call++;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 static inline void
 core_stats_update_drop(int n)
 {
-#if (STATS_INTERVAL > 0)
 	int lcore_id = rte_lcore_id();
 	core_statistics[lcore_id].dropped += n;
-#else
-	RTE_SET_USED(n);
-#endif /* STATS_INTERVAL */
 }
 
 /* helper routine to free bulk of packets */
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 2/7] examples/ipsec-secgw: update create inline session
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Rework create inline session function as to update the session
configuration parameters before create session is called.
Also updated the rss key array size to prevent buffers overflows
with PMDs that copy more than 40 bytes.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 examples/ipsec-secgw/ipsec.c | 54 +++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 7 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6817139663..b6b7bddca8 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -171,16 +171,56 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			.options = { 0 },
 			.replay_win_sz = 0,
 			.direction = sa->direction,
-			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
-			.mode = (sa->flags == IP4_TUNNEL ||
-					sa->flags == IP6_TUNNEL) ?
-					RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
-					RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP
 		} },
 		.crypto_xform = sa->xforms,
 		.userdata = NULL,
 	};
 
+	if (IS_TRANSPORT(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		}
+	} else if (IS_TUNNEL(sa->flags)) {
+		sess_conf.ipsec.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+
+		if (IS_IP4(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+			sess_conf.ipsec.tunnel.ipv4.src_ip.s_addr =
+				sa->src.ip.ip4;
+			sess_conf.ipsec.tunnel.ipv4.dst_ip.s_addr =
+				sa->dst.ip.ip4;
+		} else if (IS_IP6(sa->flags)) {
+			sess_conf.ipsec.tunnel.type =
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6;
+
+			memcpy(sess_conf.ipsec.tunnel.ipv6.src_addr.s6_addr,
+				sa->src.ip.ip6.ip6_b, 16);
+			memcpy(sess_conf.ipsec.tunnel.ipv6.dst_addr.s6_addr,
+				sa->dst.ip.ip6.ip6_b, 16);
+		} else {
+			RTE_LOG(ERR, IPSEC, "invalid tunnel type\n");
+			return -1;
+		}
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -266,10 +306,10 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sa->attr.ingress = (sa->direction ==
 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 		if (sa->attr.ingress) {
-			uint8_t rss_key[40];
+			uint8_t rss_key[64];
 			struct rte_eth_rss_conf rss_conf = {
 				.rss_key = rss_key,
-				.rss_key_len = 40,
+				.rss_key_len = sizeof(rss_key),
 			};
 			struct rte_eth_dev_info dev_info;
 			uint16_t queue[RTE_MAX_QUEUES_PER_PORT];
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst |  3 ++-
 examples/ipsec-secgw/ipsec.c             | 33 +++++++++++++++++++++---
 examples/ipsec-secgw/ipsec.h             |  7 ++++-
 examples/ipsec-secgw/sa.c                |  9 +++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 282926924f..ec0085d8c4 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -717,7 +717,8 @@ where each options means:
  ``<udp-encap>``
 
  * Option to enable IPsec UDP encapsulation for NAT Traversal.
-   Only *lookaside-protocol-offload* mode is supported at the moment.
+   Only *lookaside-protocol-offload* and *inline-crypto-offload* modes are
+   supported at the moment.
 
  * Optional: Yes, it is disabled by default
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index b6b7bddca8..90d9e61e5b 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -221,6 +221,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		}
 	}
 
+	if (sa->udp_encap) {
+		sess_conf.ipsec.options.udp_encap = 1;
+		sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+	}
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
@@ -289,12 +295,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			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;
+		if (sa->udp_encap) {
+
+			sa->udp_spec.hdr.dst_port =
+					rte_cpu_to_be_16(sa->udp.dport);
+			sa->udp_spec.hdr.src_port =
+					rte_cpu_to_be_16(sa->udp.sport);
+
+			sa->pattern[2].mask = &rte_flow_item_udp_mask;
+			sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+			sa->pattern[2].spec = &sa->udp_spec;
+
+			sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+			sa->pattern[3].spec = &sa->esp_spec;
+			sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+			sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+		} else {
+			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->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+		}
 
 		sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
 		sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8405c48171..06bb11d5d5 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -125,6 +125,10 @@ struct ipsec_sa {
 #define IP6_TRANSPORT (1 << 4)
 	struct ip_addr src;
 	struct ip_addr dst;
+	struct {
+		uint16_t sport;
+		uint16_t dport;
+	} udp;
 	uint8_t cipher_key[MAX_KEY_SIZE];
 	uint16_t cipher_key_len;
 	uint8_t auth_key[MAX_KEY_SIZE];
@@ -140,7 +144,7 @@ struct ipsec_sa {
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
 	struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
 	struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -149,6 +153,7 @@ struct ipsec_sa {
 		struct rte_flow_item_ipv4 ipv4_spec;
 		struct rte_flow_item_ipv6 ipv6_spec;
 	};
+	struct rte_flow_item_udp udp_spec;
 	struct rte_flow_item_esp esp_spec;
 	struct rte_flow *flow;
 	struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 88dd30464f..daebc1f09b 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -771,6 +772,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 				app_sa_prm.udp_encap = 1;
 				udp_encap_p = 1;
 				break;
+			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+				rule->udp_encap = 1;
+				rule->udp.sport = 0;
+				rule->udp.dport = 4500;
+				break;
 			default:
 				APP_CHECK(0, status,
 					"UDP encapsulation not supported for "
@@ -858,6 +864,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	}
 
 	printf("mode:");
+	if (sa->udp_encap)
+		printf("UDP encapsulated ");
 
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
@@ -1311,6 +1319,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
 	prm->ipsec_xform.options.ecn = 1;
 	prm->ipsec_xform.options.copy_dscp = 1;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 4/7] examples/ipsec-secgw: support telemetry
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (2 preceding siblings ...)
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add telemetry support to the IPsec GW sample app and add
support for per SA telemetry when using IPsec library.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   4 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |  11 +
 examples/ipsec-secgw/ipsec-secgw.c       | 357 ++++++++++++++++++++++-
 examples/ipsec-secgw/ipsec-secgw.h       |  31 ++
 examples/ipsec-secgw/ipsec.h             |   2 +
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/sa.c                |  15 +-
 7 files changed, 402 insertions(+), 20 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 1e58bbbfde..4f01c406ae 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -310,6 +310,10 @@ New Features
     * Pcapng format with timestamps and meta-data.
     * Fixes packet capture with stripped VLAN tags.
 
+* **IPsec Security Gateway sample application new features.**
+
+  * Added support for telemetry
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index ec0085d8c4..c67e2ba1b0 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -726,6 +726,17 @@ where each options means:
 
    * *udp-encap*
 
+``<telemetry>``
+
+ * Option to enable per SA telemetry.
+   Currently only supported with IPsec library path.
+
+ * Optional: Yes, it is disabled by default
+
+ * Syntax:
+
+   * *telemetry*
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index d9a6838459..4e4a6f9f1b 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -47,6 +47,7 @@
 #include <rte_ip.h>
 #include <rte_ip_frag.h>
 #include <rte_alarm.h>
+#include <rte_telemetry.h>
 
 #include "event_helper.h"
 #include "flow.h"
@@ -668,7 +669,7 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 
 static inline void
 inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+		uint16_t lim, struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, res, sa_idx;
@@ -685,25 +686,30 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 		res = ip->res[i];
 		if (res == BYPASS) {
 			ip->pkts[j++] = m;
+			stats->bypass++;
 			continue;
 		}
 		if (res == DISCARD) {
 			free_pkts(&m, 1);
+			stats->discard++;
 			continue;
 		}
 
 		/* Only check SPI match for processed IPSec packets */
 		if (i < lim && ((m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) == 0)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 
 		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
+			stats->discard++;
 			free_pkts(&m, 1);
 			continue;
 		}
 		ip->pkts[j++] = m;
+		stats->protect++;
 	}
 	ip->num = j;
 }
@@ -747,6 +753,7 @@ static inline void
 process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		struct ipsec_traffic *traffic)
 {
+	unsigned int lcoreid = rte_lcore_id();
 	uint16_t nb_pkts_in, n_ip4, n_ip6;
 
 	n_ip4 = traffic->ip4.num;
@@ -762,16 +769,20 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
-			n_ip4);
+	inbound_sp_sa(ipsec_ctx->sp4_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip4, n_ip4,
+		&core_statistics[lcoreid].inbound.spd4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
-			n_ip6);
+	inbound_sp_sa(ipsec_ctx->sp6_ctx,
+		ipsec_ctx->sa_ctx, &traffic->ip6, n_ip6,
+		&core_statistics[lcoreid].inbound.spd6);
 }
 
 static inline void
-outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
-		struct traffic_type *ipsec)
+outbound_spd_lookup(struct sp_ctx *sp,
+		struct traffic_type *ip,
+		struct traffic_type *ipsec,
+		struct ipsec_spd_stats *stats)
 {
 	struct rte_mbuf *m;
 	uint32_t i, j, sa_idx;
@@ -782,17 +793,23 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
 			ip->num, DEFAULT_MAX_CATEGORIES);
 
-	j = 0;
-	for (i = 0; i < ip->num; i++) {
+	for (i = 0, j = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
 		sa_idx = ip->res[i] - 1;
-		if (ip->res[i] == DISCARD)
+
+		if (unlikely(ip->res[i] == DISCARD)) {
 			free_pkts(&m, 1);
-		else if (ip->res[i] == BYPASS)
+
+			stats->discard++;
+		} else if (unlikely(ip->res[i] == BYPASS)) {
 			ip->pkts[j++] = m;
-		else {
+
+			stats->bypass++;
+		} else {
 			ipsec->res[ipsec->num] = sa_idx;
 			ipsec->pkts[ipsec->num++] = m;
+
+			stats->protect++;
 		}
 	}
 	ip->num = j;
@@ -804,15 +821,20 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 {
 	struct rte_mbuf *m;
 	uint16_t idx, nb_pkts_out, i;
+	unsigned int lcoreid = rte_lcore_id();
 
 	/* Drop any IPsec traffic from protected ports */
 	free_pkts(traffic->ipsec.pkts, traffic->ipsec.num);
 
 	traffic->ipsec.num = 0;
 
-	outbound_sp(ipsec_ctx->sp4_ctx, &traffic->ip4, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp4_ctx,
+		&traffic->ip4, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd4);
 
-	outbound_sp(ipsec_ctx->sp6_ctx, &traffic->ip6, &traffic->ipsec);
+	outbound_spd_lookup(ipsec_ctx->sp6_ctx,
+		&traffic->ip6, &traffic->ipsec,
+		&core_statistics[lcoreid].outbound.spd6);
 
 	if (app_sa_prm.enable == 0) {
 
@@ -956,6 +978,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -991,6 +1014,7 @@ route4_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if ((pkt_hop & RTE_LPM_LOOKUP_SUCCESS) == 0) {
+			core_statistics[lcoreid].lpm4.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1007,6 +1031,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 	int32_t pkt_hop = 0;
 	uint16_t i, offset;
 	uint16_t lpm_pkts = 0;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (nb_pkts == 0)
 		return;
@@ -1043,6 +1068,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint8_t nb_pkts)
 		}
 
 		if (pkt_hop == -1) {
+			core_statistics[lcoreid].lpm6.miss++;
 			free_pkts(&pkts[i], 1);
 			continue;
 		}
@@ -1116,6 +1142,7 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 {
 	uint32_t n;
 	struct ipsec_traffic trf;
+	unsigned int lcoreid = rte_lcore_id();
 
 	if (app_sa_prm.enable == 0) {
 
@@ -1133,13 +1160,15 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0,
+			&core_statistics[lcoreid].inbound.spd4);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0,
+			&core_statistics[lcoreid].inbound.spd6);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -2829,6 +2858,300 @@ calculate_nb_mbufs(uint16_t nb_ports, uint16_t nb_crypto_qp, uint32_t nb_rxq,
 		       8192U);
 }
 
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	uint64_t total_pkts_dropped = 0, total_pkts_tx = 0, total_pkts_rx = 0;
+	unsigned int coreid;
+
+	rte_tel_data_start_dict(data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+
+		total_pkts_dropped = core_statistics[coreid].dropped;
+		total_pkts_tx = core_statistics[coreid].tx;
+		total_pkts_rx = core_statistics[coreid].rx;
+
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++) {
+
+			/* skip disabled cores */
+			if (rte_lcore_is_enabled(coreid) == 0)
+				continue;
+
+			total_pkts_dropped += core_statistics[coreid].dropped;
+			total_pkts_tx += core_statistics[coreid].tx;
+			total_pkts_rx += core_statistics[coreid].rx;
+		}
+	}
+
+	/* add telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(data, "packets received",
+				total_pkts_rx);
+
+	rte_tel_data_add_dict_u64(data, "packets transmitted",
+				total_pkts_tx);
+
+	rte_tel_data_add_dict_u64(data, "packets dropped",
+				total_pkts_dropped);
+
+
+	return 0;
+}
+
+static void
+update_lcore_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	struct ipsec_core_statistics *lcore_stats;
+
+	/* skip disabled cores */
+	if (rte_lcore_is_enabled(coreid) == 0)
+		return;
+
+	lcore_stats = &core_statistics[coreid];
+
+	total->rx = lcore_stats->rx;
+	total->dropped = lcore_stats->dropped;
+	total->tx = lcore_stats->tx;
+
+	/* outbound stats */
+	total->outbound.spd6.protect += lcore_stats->outbound.spd6.protect;
+	total->outbound.spd6.bypass += lcore_stats->outbound.spd6.bypass;
+	total->outbound.spd6.discard += lcore_stats->outbound.spd6.discard;
+
+	total->outbound.spd4.protect += lcore_stats->outbound.spd4.protect;
+	total->outbound.spd4.bypass += lcore_stats->outbound.spd4.bypass;
+	total->outbound.spd4.discard += lcore_stats->outbound.spd4.discard;
+
+	total->outbound.sad.miss += lcore_stats->outbound.sad.miss;
+
+	/* inbound stats */
+	total->inbound.spd6.protect += lcore_stats->inbound.spd6.protect;
+	total->inbound.spd6.bypass += lcore_stats->inbound.spd6.bypass;
+	total->inbound.spd6.discard += lcore_stats->inbound.spd6.discard;
+
+	total->inbound.spd4.protect += lcore_stats->inbound.spd4.protect;
+	total->inbound.spd4.bypass += lcore_stats->inbound.spd4.bypass;
+	total->inbound.spd4.discard += lcore_stats->inbound.spd4.discard;
+
+	total->inbound.sad.miss += lcore_stats->inbound.sad.miss;
+
+
+	/* routing stats */
+	total->lpm4.miss += lcore_stats->lpm4.miss;
+	total->lpm6.miss += lcore_stats->lpm6.miss;
+}
+
+static void
+update_statistics(struct ipsec_core_statistics *total, uint32_t coreid)
+{
+	memset(total, 0, sizeof(*total));
+
+	if (coreid != UINT32_MAX) {
+		update_lcore_statistics(total, coreid);
+	} else {
+		for (coreid = 0; coreid < RTE_MAX_LCORE; coreid++)
+			update_lcore_statistics(total, coreid);
+	}
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_outbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.outbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.outbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.outbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.outbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.outbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.outbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.outbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_inbound(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *spd4_data = rte_tel_data_alloc();
+	struct rte_tel_data *spd6_data = rte_tel_data_alloc();
+	struct rte_tel_data *sad_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* verify allocated telemetry data structures */
+	if (!spd4_data || !spd6_data || !sad_data)
+		return -ENOMEM;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(spd4_data);
+	rte_tel_data_start_dict(spd6_data);
+	rte_tel_data_start_dict(sad_data);
+
+	/* add children dicts to parent dict */
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add sad telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(sad_data, "miss",
+		total_stats.inbound.sad.miss);
+
+	rte_tel_data_add_dict_container(data, "sad", sad_data, 0);
+
+	/* add spd 4 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd4_data, "protect",
+		total_stats.inbound.spd4.protect);
+	rte_tel_data_add_dict_u64(spd4_data, "bypass",
+		total_stats.inbound.spd4.bypass);
+	rte_tel_data_add_dict_u64(spd4_data, "discard",
+		total_stats.inbound.spd4.discard);
+
+	rte_tel_data_add_dict_container(data, "spd4", spd4_data, 0);
+
+	/* add spd 6 telemetry key/values pairs */
+
+	rte_tel_data_add_dict_u64(spd6_data, "protect",
+		total_stats.inbound.spd6.protect);
+	rte_tel_data_add_dict_u64(spd6_data, "bypass",
+		total_stats.inbound.spd6.bypass);
+	rte_tel_data_add_dict_u64(spd6_data, "discard",
+		total_stats.inbound.spd6.discard);
+
+	rte_tel_data_add_dict_container(data, "spd6", spd6_data, 0);
+
+	return 0;
+}
+
+static int
+handle_telemetry_cmd_ipsec_secgw_stats_routing(const char *cmd __rte_unused,
+		const char *params, struct rte_tel_data *data)
+{
+	struct ipsec_core_statistics total_stats;
+
+	struct rte_tel_data *lpm4_data = rte_tel_data_alloc();
+	struct rte_tel_data *lpm6_data = rte_tel_data_alloc();
+
+	unsigned int coreid = UINT32_MAX;
+
+	/* initialize telemetry data structs as dicts */
+	rte_tel_data_start_dict(data);
+	rte_tel_data_start_dict(lpm4_data);
+	rte_tel_data_start_dict(lpm6_data);
+
+
+	if (params) {
+		coreid = (uint32_t)atoi(params);
+		if (rte_lcore_is_enabled(coreid) == 0)
+			return -EINVAL;
+	}
+
+	update_statistics(&total_stats, coreid);
+
+	/* add lpm 4 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm4_data, "miss",
+		total_stats.lpm4.miss);
+
+	rte_tel_data_add_dict_container(data, "IPv4 LPM", lpm4_data, 0);
+
+	/* add lpm 6 telemetry key/values pairs */
+	rte_tel_data_add_dict_u64(lpm6_data, "miss",
+		total_stats.lpm6.miss);
+
+	rte_tel_data_add_dict_container(data, "IPv6 LPM", lpm6_data, 0);
+
+	return 0;
+}
+
+static void
+ipsec_secgw_telemetry_init(void)
+{
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats",
+		handle_telemetry_cmd_ipsec_secgw_stats,
+		"Returns global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/outbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_outbound,
+		"Returns outbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/inbound",
+		handle_telemetry_cmd_ipsec_secgw_stats_inbound,
+		"Returns inbound global stats. "
+		"Optional Parameters: int <logical core id>");
+
+	rte_telemetry_register_cmd("/examples/ipsec-secgw/stats/routing",
+		handle_telemetry_cmd_ipsec_secgw_stats_routing,
+		"Returns routing stats. "
+		"Optional Parameters: int <logical core id>");
+}
+
+
 int32_t
 main(int32_t argc, char **argv)
 {
@@ -2866,6 +3189,8 @@ main(int32_t argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
 
+	ipsec_secgw_telemetry_init();
+
 	/* parse configuration file */
 	if (parse_cfg_file(cfgfile) < 0) {
 		printf("parsing file \"%s\" failed\n",
diff --git a/examples/ipsec-secgw/ipsec-secgw.h b/examples/ipsec-secgw/ipsec-secgw.h
index 04b4644370..de9f382742 100644
--- a/examples/ipsec-secgw/ipsec-secgw.h
+++ b/examples/ipsec-secgw/ipsec-secgw.h
@@ -80,6 +80,17 @@ struct ethaddr_info {
 	uint64_t src, dst;
 };
 
+struct ipsec_spd_stats {
+	uint64_t protect;
+	uint64_t bypass;
+	uint64_t discard;
+};
+
+struct ipsec_sa_stats {
+	uint64_t hit;
+	uint64_t miss;
+};
+
 struct ipsec_core_statistics {
 	uint64_t tx;
 	uint64_t rx;
@@ -87,6 +98,26 @@ struct ipsec_core_statistics {
 	uint64_t tx_call;
 	uint64_t dropped;
 	uint64_t burst_rx;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} outbound;
+
+	struct {
+		struct ipsec_spd_stats spd4;
+		struct ipsec_spd_stats spd6;
+		struct ipsec_sa_stats sad;
+	} inbound;
+
+	struct {
+		uint64_t miss;
+	} lpm4;
+
+	struct {
+		uint64_t miss;
+	} lpm6;
 } __rte_cache_aligned;
 
 struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 06bb11d5d5..de4e0606e2 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -123,6 +123,8 @@ struct ipsec_sa {
 #define TRANSPORT  (1 << 2)
 #define IP4_TRANSPORT (1 << 3)
 #define IP6_TRANSPORT (1 << 4)
+#define SA_TELEMETRY_ENABLE (1 << 5)
+
 	struct ip_addr src;
 	struct ip_addr dst;
 	struct {
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index b4b483a782..ccdaef1c4d 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -6,7 +6,7 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev']
+deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec', 'eventdev', 'telemetry']
 allow_experimental_apis = true
 sources = files(
         'esp.c',
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index daebc1f09b..65c975993d 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -323,6 +323,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		return;
 	if (atoi(tokens[1]) == INVALID_SPI)
 		return;
+	rule->flags = 0;
 	rule->spi = atoi(tokens[1]);
 	rule->portid = UINT16_MAX;
 	ips = ipsec_get_primary_session(rule);
@@ -339,14 +340,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
 				sa_cnt->nb_v4++;
-				rule->flags = IP4_TUNNEL;
+				rule->flags |= IP4_TUNNEL;
 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
 				sa_cnt->nb_v6++;
-				rule->flags = IP6_TUNNEL;
+				rule->flags |= IP6_TUNNEL;
 			} else if (strcmp(tokens[ti], "transport") == 0) {
 				sa_cnt->nb_v4++;
 				sa_cnt->nb_v6++;
-				rule->flags = TRANSPORT;
+				rule->flags |= TRANSPORT;
 			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
@@ -357,6 +358,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "telemetry") == 0) {
+			rule->flags |= SA_TELEMETRY_ENABLE;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
 			const struct supported_cipher_algo *algo;
 			uint32_t key_len;
@@ -1395,6 +1401,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 	if (rc < 0)
 		return rc;
 
+	if (lsa->flags & SA_TELEMETRY_ENABLE)
+		rte_ipsec_telemetry_sa_add(sa);
+
 	/* init primary processing session */
 	ips = ipsec_get_primary_session(lsa);
 	rc = fill_ipsec_session(ips, sa);
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 5/7] examples/ipsec-secgw: define initial ESN value
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (3 preceding siblings ...)
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

New option added to the SA configuration arguments that
allows setting an arbitrary start value for ESN.

For example in the SA below ESN will be enabled and first egress
IPsec packet will have the ESN value 10000:

sa out 15 cipher_algo null auth_algo null mode ipv4-tunnel \
src 172.16.1.5 dst 172.16.2.5 \
esn 10000

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 10 ++++++++++
 examples/ipsec-secgw/ipsec.c             |  6 ++++++
 examples/ipsec-secgw/ipsec.h             |  1 +
 examples/ipsec-secgw/sa.c                | 10 ++++++++++
 4 files changed, 27 insertions(+)

diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index c67e2ba1b0..7252e8b08c 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -737,6 +737,16 @@ where each options means:
 
    * *telemetry*
 
+ ``<esn>``
+
+ * Enable ESN and set the initial ESN value.
+
+ * Optional: Yes, ESN not enabled by default
+
+ * Syntax:
+
+   * *esn N* N is the initial ESN value
+
 Example SA rules:
 
 .. code-block:: console
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 90d9e61e5b..2d4a26c962 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -227,6 +227,12 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
 	}
 
+	if (sa->esn > 0) {
+		sess_conf.ipsec.options.esn = 1;
+		sess_conf.ipsec.esn.value = sa->esn;
+	}
+
+
 	RTE_LOG_DP(DEBUG, IPSEC, "Create session for SA spi %u on port %u\n",
 		sa->spi, sa->portid);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index de4e0606e2..b037d5179f 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -143,6 +143,7 @@ struct ipsec_sa {
 	enum rte_security_ipsec_sa_direction direction;
 	uint8_t udp_encap;
 	uint16_t portid;
+	uint64_t esn;
 	uint8_t fdir_qid;
 	uint8_t fdir_flag;
 
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 65c975993d..8725001fc7 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -684,6 +684,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			continue;
 		}
 
+		if (strcmp(tokens[ti], "esn") == 0) {
+			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+			if (status->status < 0)
+				return;
+			rule->esn = atoll(tokens[ti]);
+			if (status->status < 0)
+				return;
+			continue;
+		}
+
 		if (strcmp(tokens[ti], "fallback") == 0) {
 			struct rte_ipsec_session *fb;
 
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 6/7] examples/ipsec-secgw: add ethdev reset callback
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (4 preceding siblings ...)
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
  2021-11-03 14:13   ` [dpdk-dev] [EXT] [PATCH v6 0/7] IPsec Sec GW new features Akhil Goyal
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Applications should not quietly ignore an ethdev reset event.
Register an event handler for ethdev reset callback
RTE_ETH_EVENT_INTR_RESET that prints a message and
quits the application.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 examples/ipsec-secgw/ipsec-secgw.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4e4a6f9f1b..ca8e5f26d5 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -2545,6 +2545,17 @@ inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 	return -1;
 }
 
+static int
+ethdev_reset_event_callback(uint16_t port_id,
+		enum rte_eth_event_type type,
+		 void *param __rte_unused, void *ret_param __rte_unused)
+{
+	printf("Reset Event on port id %d type %d\n", port_id, type);
+	printf("Force quit application");
+	force_quit = true;
+	return 0;
+}
+
 static uint16_t
 rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
 	struct rte_mbuf *pkt[], uint16_t nb_pkts,
@@ -3311,6 +3322,9 @@ main(int32_t argc, char **argv)
 					rte_strerror(-ret), portid);
 		}
 
+		rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_RESET,
+			ethdev_reset_event_callback, NULL);
+
 		rte_eth_dev_callback_register(portid,
 			RTE_ETH_EVENT_IPSEC, inline_ipsec_event_callback, NULL);
 	}
-- 
2.25.1


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

* [dpdk-dev] [PATCH v6 7/7] examples/ipsec-secgw: add support for additional algorithms
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (5 preceding siblings ...)
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
@ 2021-11-01 12:58   ` Radu Nicolau
  2021-11-03 14:13   ` [dpdk-dev] [EXT] [PATCH v6 0/7] IPsec Sec GW new features Akhil Goyal
  7 siblings, 0 replies; 82+ messages in thread
From: Radu Nicolau @ 2021-11-01 12:58 UTC (permalink / raw)
  To: Radu Nicolau, Akhil Goyal; +Cc: dev, declan.doherty, hemant.agrawal

Add support for AES-GMAC, AES_CTR, AES_XCBC_MAC,
AES_CCM, CHACHA20_POLY1305

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
---
 doc/guides/rel_notes/release_21_11.rst   |   2 +
 doc/guides/sample_app_ug/ipsec_secgw.rst |   3 +-
 examples/ipsec-secgw/ipsec.h             |   3 +-
 examples/ipsec-secgw/sa.c                | 122 +++++++++++++++++++++--
 4 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst
index 4f01c406ae..b65c6eff88 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -313,6 +313,8 @@ New Features
 * **IPsec Security Gateway sample application new features.**
 
   * Added support for telemetry
+  * Added support for more AEAD algorithms: AES-GMAC, AES_CTR, AES_XCBC_MAC,
+    AES_CCM, CHACHA20_POLY1305
 
 
 Removed Items
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index 7252e8b08c..027d9b8fa1 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -106,7 +106,8 @@ Constraints
 
 *  No IPv6 options headers.
 *  No AH mode.
-*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1 and NULL.
+*  Supported algorithms: AES-CBC, AES-CTR, AES-GCM, 3DES-CBC, HMAC-SHA1,
+   AES-GMAC, AES_CTR, AES_XCBC_MAC, AES_CCM, CHACHA20_POLY1305 and NULL.
 *  Each SA must be handle by a unique lcore (*1 RX queue per port*).
 
 Compiling the Application
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index b037d5179f..0dfb0d6acb 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -63,8 +63,7 @@ struct ip_addr {
 	} ip;
 };
 
-#define MAX_KEY_SIZE		36
-
+#define MAX_KEY_SIZE		64
 /*
  * application wide SA parameters
  */
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 8725001fc7..c62221f32c 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -46,6 +46,7 @@ struct supported_cipher_algo {
 struct supported_auth_algo {
 	const char *keyword;
 	enum rte_crypto_auth_algorithm algo;
+	uint16_t iv_len;
 	uint16_t digest_len;
 	uint16_t key_len;
 	uint8_t key_not_req;
@@ -98,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = {
 		.block_size = 4,
 		.key_len = 20
 	},
+	{
+		.keyword = "aes-192-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 28
+	},
+	{
+		.keyword = "aes-256-ctr",
+		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
+		.iv_len = 16,
+		.block_size = 16,
+		.key_len = 36
+	},
 	{
 		.keyword = "3des-cbc",
 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
@@ -126,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = {
 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
 		.digest_len = 16,
 		.key_len = 32
+	},
+	{
+		.keyword = "sha384-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+		.digest_len = 24,
+		.key_len = 48
+	},
+	{
+		.keyword = "sha512-hmac",
+		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+		.digest_len = 32,
+		.key_len = 64
+	},
+	{
+		.keyword = "aes-gmac",
+		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+		.iv_len = 8,
+		.digest_len = 16,
+		.key_len = 20
+	},
+	{
+		.keyword = "aes-xcbc-mac-96",
+		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+		.digest_len = 12,
+		.key_len = 16
 	}
 };
 
@@ -156,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = {
 		.key_len = 36,
 		.digest_len = 16,
 		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-128-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 20,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-192-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 28,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "aes-256-ccm",
+		.algo = RTE_CRYPTO_AEAD_AES_CCM,
+		.iv_len = 8,
+		.block_size = 4,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
+	},
+	{
+		.keyword = "chacha20-poly1305",
+		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
+		.iv_len = 12,
+		.block_size = 64,
+		.key_len = 36,
+		.digest_len = 16,
+		.aad_len = 8,
 	}
 };
 
@@ -484,6 +560,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
+			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				key_len -= 4;
+				rule->auth_key_len = key_len;
+				rule->iv_len = algo->iv_len;
+				memcpy(&rule->salt,
+					&rule->auth_key[key_len], 4);
+			}
+
 			auth_algo_p = 1;
 			continue;
 		}
@@ -1171,8 +1255,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			break;
 		}
 
-		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			iv_length = 12;
+
+		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
+			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+
+			if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
+				iv_length = 11;
+			else
+				iv_length = 12;
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
@@ -1196,10 +1287,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			case RTE_CRYPTO_CIPHER_NULL:
 			case RTE_CRYPTO_CIPHER_3DES_CBC:
 			case RTE_CRYPTO_CIPHER_AES_CBC:
-				iv_length = sa->iv_len;
-				break;
 			case RTE_CRYPTO_CIPHER_AES_CTR:
-				iv_length = 16;
+				iv_length = sa->iv_len;
 				break;
 			default:
 				RTE_LOG(ERR, IPSEC_ESP,
@@ -1208,6 +1297,10 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				return -EINVAL;
 			}
 
+			/* AES_GMAC uses salt like AEAD algorithms */
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
+				iv_length = 12;
+
 			if (inbound) {
 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
@@ -1229,6 +1322,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].a.auth.op =
 					RTE_CRYPTO_AUTH_OP_VERIFY;
+				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].a.auth.iv.length = iv_length;
+
 			} else { /* outbound */
 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
@@ -1250,11 +1346,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 					sa->digest_len;
 				sa_ctx->xf[idx].b.auth.op =
 					RTE_CRYPTO_AUTH_OP_GENERATE;
+				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
+				sa_ctx->xf[idx].b.auth.iv.length = iv_length;
+
 			}
 
-			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
-			sa_ctx->xf[idx].b.next = NULL;
-			sa->xforms = &sa_ctx->xf[idx].a;
+			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				sa->xforms = inbound ?
+					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
+				sa->xforms->next = NULL;
+
+			} else {
+				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
+				sa_ctx->xf[idx].b.next = NULL;
+				sa->xforms = &sa_ctx->xf[idx].a;
+			}
 		}
 
 		if (ips->type ==
-- 
2.25.1


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

* Re: [dpdk-dev] [EXT] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
@ 2021-11-03  9:23     ` Akhil Goyal
  2021-11-03 10:51       ` Nicolau, Radu
  0 siblings, 1 reply; 82+ messages in thread
From: Akhil Goyal @ 2021-11-03  9:23 UTC (permalink / raw)
  To: Radu Nicolau
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

> -#if (STATS_INTERVAL > 0)
>  struct ipsec_core_statistics {
>  	uint64_t tx;
>  	uint64_t rx;
> @@ -94,7 +90,6 @@ struct ipsec_core_statistics {
>  } __rte_cache_aligned;
> 
>  struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
> -#endif /* STATS_INTERVAL */
Did you check compilation with this patchset? Even CI is reporting compilation issues.
core_statistics need to be declared in .c file.


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

* Re: [dpdk-dev] [EXT] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument
  2021-11-03  9:23     ` [dpdk-dev] [EXT] " Akhil Goyal
@ 2021-11-03 10:51       ` Nicolau, Radu
  2021-11-03 13:20         ` Akhil Goyal
  0 siblings, 1 reply; 82+ messages in thread
From: Nicolau, Radu @ 2021-11-03 10:51 UTC (permalink / raw)
  To: Akhil Goyal
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph


On 11/3/2021 9:23 AM, Akhil Goyal wrote:
>> -#if (STATS_INTERVAL > 0)
>>   struct ipsec_core_statistics {
>>   	uint64_t tx;
>>   	uint64_t rx;
>> @@ -94,7 +90,6 @@ struct ipsec_core_statistics {
>>   } __rte_cache_aligned;
>>
>>   struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
>> -#endif /* STATS_INTERVAL */
> Did you check compilation with this patchset? Even CI is reporting compilation issues.
> core_statistics need to be declared in .c file.

Hi Akhil, I did check on my local dev system and it passed, but I can 
see the problem.

But the issue was not introduced by this patchset, it was only made 
apparent by removing the #ifdef. It was introduced by this patch:

commit 1329602b6c8f20949ebaefb7aa55f7dca6d1b4f4
Author: Anoob Joseph <anoobj@marvell.com>
Date:   Wed May 13 23:15:19 2020 +0530

     examples/ipsec-secgw: add per-core packet statistics

I will send a fix shortly.


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

* Re: [dpdk-dev] [EXT] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument
  2021-11-03 10:51       ` Nicolau, Radu
@ 2021-11-03 13:20         ` Akhil Goyal
  0 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-11-03 13:20 UTC (permalink / raw)
  To: Nicolau, Radu
  Cc: dev, declan.doherty, hemant.agrawal, Hemant Agrawal, Anoob Joseph

> On 11/3/2021 9:23 AM, Akhil Goyal wrote:
> >> -#if (STATS_INTERVAL > 0)
> >>   struct ipsec_core_statistics {
> >>   	uint64_t tx;
> >>   	uint64_t rx;
> >> @@ -94,7 +90,6 @@ struct ipsec_core_statistics {
> >>   } __rte_cache_aligned;
> >>
> >>   struct ipsec_core_statistics core_statistics[RTE_MAX_LCORE];
> >> -#endif /* STATS_INTERVAL */
> > Did you check compilation with this patchset? Even CI is reporting
> compilation issues.
> > core_statistics need to be declared in .c file.
> 
> Hi Akhil, I did check on my local dev system and it passed, but I can
> see the problem.
> 
> But the issue was not introduced by this patchset, it was only made
> apparent by removing the #ifdef. It was introduced by this patch:
> 
Yes the issue was not visible as it was compiled off, but since your patch
Removed ifdefs, the compilation will be broken. Not sure how it passed your
Dev environment.


> commit 1329602b6c8f20949ebaefb7aa55f7dca6d1b4f4
> Author: Anoob Joseph <anoobj@marvell.com>
> Date:   Wed May 13 23:15:19 2020 +0530
> 
>      examples/ipsec-secgw: add per-core packet statistics
> 
> I will send a fix shortly.


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

* Re: [dpdk-dev] [EXT] [PATCH v6 0/7] IPsec Sec GW new features
  2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
                     ` (6 preceding siblings ...)
  2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
@ 2021-11-03 14:13   ` Akhil Goyal
  7 siblings, 0 replies; 82+ messages in thread
From: Akhil Goyal @ 2021-11-03 14:13 UTC (permalink / raw)
  To: Radu Nicolau; +Cc: dev, declan.doherty, hemant.agrawal

> Update the IPsec sample app with new features and updates:
> - telemetry support
> - add reset callback
> - stats screen configurable as a command line parameter
> - UDP encapsulation support for inline crypto
> - ESN with configurable start value
> 
> Radu Nicolau (7):
>   examples/ipsec-secgw: add stats interval argument
>   examples/ipsec-secgw: update create inline session
>   examples/ipsec-secgw: add support for inline crypto UDP encapsulation
>   examples/ipsec-secgw: support telemetry
>   examples/ipsec-secgw: define initial ESN value
>   examples/ipsec-secgw: add ethdev reset callback
>   examples/ipsec-secgw: add support for additional algorithms
> 
>  doc/guides/rel_notes/release_21_11.rst   |   6 +
>  doc/guides/sample_app_ug/ipsec_secgw.rst |  32 +-
>  examples/ipsec-secgw/ipsec-secgw.c       | 400 +++++++++++++++++++++--
>  examples/ipsec-secgw/ipsec-secgw.h       |  48 ++-
>  examples/ipsec-secgw/ipsec.c             |  93 +++++-
>  examples/ipsec-secgw/ipsec.h             |  13 +-
>  examples/ipsec-secgw/meson.build         |   2 +-
>  examples/ipsec-secgw/sa.c                | 156 ++++++++-
>  8 files changed, 680 insertions(+), 70 deletions(-)
> 
> --
> v2: reworked the patchset to improve quality and address feedback
> v3: reworked the patchset to accomodate changes in the ipsec libray
> v4: removed TSO patch and reworked the patchset after feedback
> v5: rebased to RC1
> v6: addressed feeedback

This patch had a lot of issues which should have been addressed before
submitting on ML. Please take care in future.
Rebased over TOT.
Applied to dpdk-next-crypto


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

end of thread, other threads:[~2021-11-03 14:13 UTC | newest]

Thread overview: 82+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-03 11:22 [dpdk-dev] [PATCH 0/7] IPsec Sec GW new features Radu Nicolau
2021-09-03 11:22 ` [dpdk-dev] [PATCH 1/7] examples/ipsec-secgw: add ol_flags support Radu Nicolau
2021-09-08 12:48   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-09  8:57     ` Nicolau, Radu
2021-09-03 11:22 ` [dpdk-dev] [PATCH 2/7] examples/ipsec-secgw: add support for NAT-T Radu Nicolau
2021-09-08 10:36   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-03 11:22 ` [dpdk-dev] [PATCH 3/7] examples/ipsec-secgw: add support for TSO Radu Nicolau
2021-09-08 12:54   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-03 11:22 ` [dpdk-dev] [PATCH 4/7] examples/ipsec-secgw: enable stats by default Radu Nicolau
2021-09-03 12:50   ` Zhang, Roy Fan
2021-09-08 13:08   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-08 16:05     ` Hemant Agrawal
2021-09-03 11:22 ` [dpdk-dev] [PATCH 5/7] examples/ipsec-secgw: add support for telemetry Radu Nicolau
2021-09-08 14:09   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-03 11:22 ` [dpdk-dev] [PATCH 6/7] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
2021-09-08 14:11   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-03 11:22 ` [dpdk-dev] [PATCH 7/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-09-08 14:24   ` [dpdk-dev] [EXT] " Akhil Goyal
2021-09-15 13:45 ` [dpdk-dev] [PATCH v2 0/9] IPsec Sec GW new features Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 1/9] examples/ipsec-secgw: update create inline session Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 2/9] examples/ipsec-secgw: update SA parameters with L3 options Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 3/9] examples/ipsec-secgw: add support for telemetry Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 4/9] examples/ipsec-secgw: add stats interval argument Radu Nicolau
2021-09-16  9:13     ` Hemant Agrawal
2021-09-16  9:30     ` [dpdk-dev] [EXT] " Anoob Joseph
2021-09-16 10:24       ` Nicolau, Radu
2021-09-17 12:51         ` Anoob Joseph
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 5/9] examples/ipsec-secgw: add support for TSO Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 6/9] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 7/9] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 8/9] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
2021-09-15 13:45   ` [dpdk-dev] [PATCH v2 9/9] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
2021-10-01  9:51 ` [dpdk-dev] [PATCH v3 0/8] IPsec Sec GW new features Radu Nicolau
2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 1/8] examples/ipsec-secgw: add stats interval argument Radu Nicolau
2021-10-08 18:37     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 2/8] examples/ipsec-secgw: update create inline session Radu Nicolau
2021-10-08 18:38     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 3/8] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
2021-10-08 18:42     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 4/8] examples/ipsec-secgw: add support for TSO Radu Nicolau
2021-10-08 18:46     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:51   ` [dpdk-dev] [PATCH v3 5/8] examples/ipsec-secgw: add support for telemetry Radu Nicolau
2021-10-08 18:51     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 6/8] examples/ipsec-secgw: add support for defining initial sequence number value Radu Nicolau
2021-10-08 18:57     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 7/8] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-10-01  9:52   ` [dpdk-dev] [PATCH v3 8/8] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
2021-10-08 19:07     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-11 15:40       ` Nicolau, Radu
2021-10-18 10:28 ` [dpdk-dev] [PATCH v4 0/7] IPsec Sec GW new features Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
2021-10-18 10:28   ` [dpdk-dev] [PATCH v4 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-10-18 10:29   ` [dpdk-dev] [PATCH v4 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
2021-10-27 11:45 ` [dpdk-dev] [PATCH v5 0/7] IPsec Sec GW new features Radu Nicolau
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
2021-10-31 20:03     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
2021-10-31 20:22     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
2021-10-31 20:23     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-10-31 20:25     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-10-27 11:45   ` [dpdk-dev] [PATCH v5 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
2021-10-31 20:29     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-11-01 12:58 ` [dpdk-dev] [PATCH v6 0/7] IPsec Sec GW new features Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 1/7] examples/ipsec-secgw: add stats interval argument Radu Nicolau
2021-11-03  9:23     ` [dpdk-dev] [EXT] " Akhil Goyal
2021-11-03 10:51       ` Nicolau, Radu
2021-11-03 13:20         ` Akhil Goyal
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 2/7] examples/ipsec-secgw: update create inline session Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 3/7] examples/ipsec-secgw: add support for inline crypto UDP encapsulation Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 4/7] examples/ipsec-secgw: support telemetry Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 5/7] examples/ipsec-secgw: define initial ESN value Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 6/7] examples/ipsec-secgw: add ethdev reset callback Radu Nicolau
2021-11-01 12:58   ` [dpdk-dev] [PATCH v6 7/7] examples/ipsec-secgw: add support for additional algorithms Radu Nicolau
2021-11-03 14:13   ` [dpdk-dev] [EXT] [PATCH v6 0/7] IPsec Sec GW new features Akhil Goyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).