xref: /dpdk/examples/ipsec-secgw/ipsec_worker.c (revision e1a06e391ba74f9c4d46a6ecef6d8ee084f4229e)
14965dda0SLukasz Bartosik /* SPDX-License-Identifier: BSD-3-Clause
24965dda0SLukasz Bartosik  * Copyright(c) 2010-2016 Intel Corporation
34965dda0SLukasz Bartosik  * Copyright (C) 2020 Marvell International Ltd.
44965dda0SLukasz Bartosik  */
59ad50c29SLukasz Bartosik #include <rte_acl.h>
66938fc92SVolodymyr Fialko #include <rte_event_crypto_adapter.h>
74965dda0SLukasz Bartosik #include <rte_event_eth_tx_adapter.h>
89ad50c29SLukasz Bartosik #include <rte_lpm.h>
99ad50c29SLukasz Bartosik #include <rte_lpm6.h>
104965dda0SLukasz Bartosik 
114965dda0SLukasz Bartosik #include "event_helper.h"
124965dda0SLukasz Bartosik #include "ipsec.h"
134965dda0SLukasz Bartosik #include "ipsec-secgw.h"
149ad50c29SLukasz Bartosik #include "ipsec_worker.h"
156938fc92SVolodymyr Fialko #include "sad.h"
169ad50c29SLukasz Bartosik 
176eb3ba03SRahul Bhansali #if defined(__ARM_NEON)
186eb3ba03SRahul Bhansali #include "ipsec_lpm_neon.h"
196eb3ba03SRahul Bhansali #endif
206eb3ba03SRahul Bhansali 
21ea28ab88SNithin Dabilpuram struct port_drv_mode_data {
222973dbf9SAkhil Goyal 	void *sess;
2379bdb787SAkhil Goyal 	void *ctx;
24ea28ab88SNithin Dabilpuram };
25ea28ab88SNithin Dabilpuram 
260d76e22dSNithin Dabilpuram typedef void (*ipsec_worker_fn_t)(void);
270d76e22dSNithin Dabilpuram 
28d8d51d4fSRahul Bhansali int ip_reassembly_dynfield_offset = -1;
29d8d51d4fSRahul Bhansali uint64_t ip_reassembly_dynflag;
30d8d51d4fSRahul Bhansali 
319ad50c29SLukasz Bartosik static inline enum pkt_type
329ad50c29SLukasz Bartosik process_ipsec_get_pkt_type(struct rte_mbuf *pkt, uint8_t **nlp)
339ad50c29SLukasz Bartosik {
349ad50c29SLukasz Bartosik 	struct rte_ether_hdr *eth;
352e7abb8bSNithin Dabilpuram 	uint32_t ptype = pkt->packet_type;
369ad50c29SLukasz Bartosik 
379ad50c29SLukasz Bartosik 	eth = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
382e7abb8bSNithin Dabilpuram 	rte_prefetch0(eth);
392e7abb8bSNithin Dabilpuram 
402e7abb8bSNithin Dabilpuram 	if (RTE_ETH_IS_IPV4_HDR(ptype)) {
419ad50c29SLukasz Bartosik 		*nlp = RTE_PTR_ADD(eth, RTE_ETHER_HDR_LEN +
429ad50c29SLukasz Bartosik 				offsetof(struct ip, ip_p));
432e7abb8bSNithin Dabilpuram 		if ((ptype & RTE_PTYPE_TUNNEL_MASK) == RTE_PTYPE_TUNNEL_ESP)
449ad50c29SLukasz Bartosik 			return PKT_TYPE_IPSEC_IPV4;
459ad50c29SLukasz Bartosik 		else
469ad50c29SLukasz Bartosik 			return PKT_TYPE_PLAIN_IPV4;
472e7abb8bSNithin Dabilpuram 	} else if (RTE_ETH_IS_IPV6_HDR(ptype)) {
489ad50c29SLukasz Bartosik 		*nlp = RTE_PTR_ADD(eth, RTE_ETHER_HDR_LEN +
499ad50c29SLukasz Bartosik 				offsetof(struct ip6_hdr, ip6_nxt));
502e7abb8bSNithin Dabilpuram 		if ((ptype & RTE_PTYPE_TUNNEL_MASK) == RTE_PTYPE_TUNNEL_ESP)
519ad50c29SLukasz Bartosik 			return PKT_TYPE_IPSEC_IPV6;
529ad50c29SLukasz Bartosik 		else
539ad50c29SLukasz Bartosik 			return PKT_TYPE_PLAIN_IPV6;
549ad50c29SLukasz Bartosik 	}
559ad50c29SLukasz Bartosik 
569ad50c29SLukasz Bartosik 	/* Unknown/Unsupported type */
579ad50c29SLukasz Bartosik 	return PKT_TYPE_INVALID;
589ad50c29SLukasz Bartosik }
599ad50c29SLukasz Bartosik 
609ad50c29SLukasz Bartosik static inline void
6158e2cf4cSNithin Dabilpuram update_mac_addrs(struct rte_ether_hdr *ethhdr, uint16_t portid)
629ad50c29SLukasz Bartosik {
6304d43857SDmitry Kozlyuk 	memcpy(&ethhdr->src_addr, &ethaddr_tbl[portid].src, RTE_ETHER_ADDR_LEN);
6404d43857SDmitry Kozlyuk 	memcpy(&ethhdr->dst_addr, &ethaddr_tbl[portid].dst, RTE_ETHER_ADDR_LEN);
659ad50c29SLukasz Bartosik }
664965dda0SLukasz Bartosik 
674965dda0SLukasz Bartosik static inline void
684965dda0SLukasz Bartosik ipsec_event_pre_forward(struct rte_mbuf *m, unsigned int port_id)
694965dda0SLukasz Bartosik {
704965dda0SLukasz Bartosik 	/* Save the destination port in the mbuf */
714965dda0SLukasz Bartosik 	m->port = port_id;
724965dda0SLukasz Bartosik 
734965dda0SLukasz Bartosik 	/* Save eth queue for Tx */
744965dda0SLukasz Bartosik 	rte_event_eth_tx_adapter_txq_set(m, 0);
754965dda0SLukasz Bartosik }
764965dda0SLukasz Bartosik 
774965dda0SLukasz Bartosik static inline void
7886738ebeSSrujana Challa ev_vector_attr_init(struct rte_event_vector *vec)
7986738ebeSSrujana Challa {
8086738ebeSSrujana Challa 	vec->attr_valid = 1;
8186738ebeSSrujana Challa 	vec->port = 0xFFFF;
8286738ebeSSrujana Challa 	vec->queue = 0;
8386738ebeSSrujana Challa }
8486738ebeSSrujana Challa 
8586738ebeSSrujana Challa static inline void
8686738ebeSSrujana Challa ev_vector_attr_update(struct rte_event_vector *vec, struct rte_mbuf *pkt)
8786738ebeSSrujana Challa {
8886738ebeSSrujana Challa 	if (vec->port == 0xFFFF) {
8986738ebeSSrujana Challa 		vec->port = pkt->port;
9086738ebeSSrujana Challa 		return;
9186738ebeSSrujana Challa 	}
9286738ebeSSrujana Challa 	if (vec->attr_valid && (vec->port != pkt->port))
9386738ebeSSrujana Challa 		vec->attr_valid = 0;
9486738ebeSSrujana Challa }
9586738ebeSSrujana Challa 
9686738ebeSSrujana Challa static inline void
974965dda0SLukasz Bartosik prepare_out_sessions_tbl(struct sa_ctx *sa_out,
98ea28ab88SNithin Dabilpuram 			 struct port_drv_mode_data *data,
99ea28ab88SNithin Dabilpuram 			 uint16_t size)
1004965dda0SLukasz Bartosik {
1014965dda0SLukasz Bartosik 	struct rte_ipsec_session *pri_sess;
1024965dda0SLukasz Bartosik 	struct ipsec_sa *sa;
1034965dda0SLukasz Bartosik 	uint32_t i;
1044965dda0SLukasz Bartosik 
1054965dda0SLukasz Bartosik 	if (!sa_out)
1064965dda0SLukasz Bartosik 		return;
1074965dda0SLukasz Bartosik 
1084965dda0SLukasz Bartosik 	for (i = 0; i < sa_out->nb_sa; i++) {
1094965dda0SLukasz Bartosik 
1104965dda0SLukasz Bartosik 		sa = &sa_out->sa[i];
1114965dda0SLukasz Bartosik 		if (!sa)
1124965dda0SLukasz Bartosik 			continue;
1134965dda0SLukasz Bartosik 
1144965dda0SLukasz Bartosik 		pri_sess = ipsec_get_primary_session(sa);
1154965dda0SLukasz Bartosik 		if (!pri_sess)
1164965dda0SLukasz Bartosik 			continue;
1174965dda0SLukasz Bartosik 
1184965dda0SLukasz Bartosik 		if (pri_sess->type !=
1194965dda0SLukasz Bartosik 			RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) {
1204965dda0SLukasz Bartosik 
1214965dda0SLukasz Bartosik 			RTE_LOG(ERR, IPSEC, "Invalid session type %d\n",
1224965dda0SLukasz Bartosik 				pri_sess->type);
1234965dda0SLukasz Bartosik 			continue;
1244965dda0SLukasz Bartosik 		}
1254965dda0SLukasz Bartosik 
1264965dda0SLukasz Bartosik 		if (sa->portid >= size) {
1274965dda0SLukasz Bartosik 			RTE_LOG(ERR, IPSEC,
1284965dda0SLukasz Bartosik 				"Port id >= than table size %d, %d\n",
1294965dda0SLukasz Bartosik 				sa->portid, size);
1304965dda0SLukasz Bartosik 			continue;
1314965dda0SLukasz Bartosik 		}
1324965dda0SLukasz Bartosik 
1334965dda0SLukasz Bartosik 		/* Use only first inline session found for a given port */
134ea28ab88SNithin Dabilpuram 		if (data[sa->portid].sess)
1354965dda0SLukasz Bartosik 			continue;
136ea28ab88SNithin Dabilpuram 		data[sa->portid].sess = pri_sess->security.ses;
137ea28ab88SNithin Dabilpuram 		data[sa->portid].ctx = pri_sess->security.ctx;
1384965dda0SLukasz Bartosik 	}
1394965dda0SLukasz Bartosik }
1404965dda0SLukasz Bartosik 
1419ad50c29SLukasz Bartosik static inline int
1429ad50c29SLukasz Bartosik check_sp(struct sp_ctx *sp, const uint8_t *nlp, uint32_t *sa_idx)
1439ad50c29SLukasz Bartosik {
1449ad50c29SLukasz Bartosik 	uint32_t res;
1459ad50c29SLukasz Bartosik 
1469ad50c29SLukasz Bartosik 	if (unlikely(sp == NULL))
1479ad50c29SLukasz Bartosik 		return 0;
1489ad50c29SLukasz Bartosik 
1499ad50c29SLukasz Bartosik 	rte_acl_classify((struct rte_acl_ctx *)sp, &nlp, &res, 1,
1509ad50c29SLukasz Bartosik 			DEFAULT_MAX_CATEGORIES);
1519ad50c29SLukasz Bartosik 
152ab722af6SAnkur Dwivedi 	if (unlikely(res == DISCARD))
1539ad50c29SLukasz Bartosik 		return 0;
1549ad50c29SLukasz Bartosik 	else if (res == BYPASS) {
1559ad50c29SLukasz Bartosik 		*sa_idx = -1;
1569ad50c29SLukasz Bartosik 		return 1;
1579ad50c29SLukasz Bartosik 	}
1589ad50c29SLukasz Bartosik 
1599ad50c29SLukasz Bartosik 	*sa_idx = res - 1;
1609ad50c29SLukasz Bartosik 	return 1;
1619ad50c29SLukasz Bartosik }
1629ad50c29SLukasz Bartosik 
16386738ebeSSrujana Challa static inline void
16486738ebeSSrujana Challa check_sp_bulk(struct sp_ctx *sp, struct traffic_type *ip,
16586738ebeSSrujana Challa 	      struct traffic_type *ipsec)
16686738ebeSSrujana Challa {
16786738ebeSSrujana Challa 	uint32_t i, j, res;
16886738ebeSSrujana Challa 	struct rte_mbuf *m;
16986738ebeSSrujana Challa 
17086738ebeSSrujana Challa 	if (unlikely(sp == NULL || ip->num == 0))
17186738ebeSSrujana Challa 		return;
17286738ebeSSrujana Challa 
17386738ebeSSrujana Challa 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, ip->num,
17486738ebeSSrujana Challa 			 DEFAULT_MAX_CATEGORIES);
17586738ebeSSrujana Challa 
17686738ebeSSrujana Challa 	j = 0;
17786738ebeSSrujana Challa 	for (i = 0; i < ip->num; i++) {
17886738ebeSSrujana Challa 		m = ip->pkts[i];
17986738ebeSSrujana Challa 		res = ip->res[i];
18086738ebeSSrujana Challa 		if (unlikely(res == DISCARD))
18186738ebeSSrujana Challa 			free_pkts(&m, 1);
18286738ebeSSrujana Challa 		else if (res == BYPASS)
18386738ebeSSrujana Challa 			ip->pkts[j++] = m;
18486738ebeSSrujana Challa 		else {
18586738ebeSSrujana Challa 			ipsec->res[ipsec->num] = res - 1;
18686738ebeSSrujana Challa 			ipsec->pkts[ipsec->num++] = m;
18786738ebeSSrujana Challa 		}
18886738ebeSSrujana Challa 	}
18986738ebeSSrujana Challa 	ip->num = j;
19086738ebeSSrujana Challa }
19186738ebeSSrujana Challa 
19286738ebeSSrujana Challa static inline void
19386738ebeSSrujana Challa check_sp_sa_bulk(struct sp_ctx *sp, struct sa_ctx *sa_ctx,
19486738ebeSSrujana Challa 		 struct traffic_type *ip)
19586738ebeSSrujana Challa {
19686738ebeSSrujana Challa 	struct ipsec_sa *sa;
19786738ebeSSrujana Challa 	uint32_t i, j, res;
19886738ebeSSrujana Challa 	struct rte_mbuf *m;
19986738ebeSSrujana Challa 
20086738ebeSSrujana Challa 	if (unlikely(sp == NULL || ip->num == 0))
20186738ebeSSrujana Challa 		return;
20286738ebeSSrujana Challa 
20386738ebeSSrujana Challa 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res, ip->num,
20486738ebeSSrujana Challa 			 DEFAULT_MAX_CATEGORIES);
20586738ebeSSrujana Challa 
20686738ebeSSrujana Challa 	j = 0;
20786738ebeSSrujana Challa 	for (i = 0; i < ip->num; i++) {
20886738ebeSSrujana Challa 		m = ip->pkts[i];
20986738ebeSSrujana Challa 		res = ip->res[i];
21086738ebeSSrujana Challa 		if (unlikely(res == DISCARD))
21186738ebeSSrujana Challa 			free_pkts(&m, 1);
21286738ebeSSrujana Challa 		else if (res == BYPASS)
21386738ebeSSrujana Challa 			ip->pkts[j++] = m;
21486738ebeSSrujana Challa 		else {
21586738ebeSSrujana Challa 			sa = *(struct ipsec_sa **)rte_security_dynfield(m);
2165fb245baSNithin Dabilpuram 			if (sa == NULL) {
21786738ebeSSrujana Challa 				free_pkts(&m, 1);
2185fb245baSNithin Dabilpuram 				continue;
2195fb245baSNithin Dabilpuram 			}
22086738ebeSSrujana Challa 
22186738ebeSSrujana Challa 			/* SPI on the packet should match with the one in SA */
2225fb245baSNithin Dabilpuram 			if (unlikely(sa->spi != sa_ctx->sa[res - 1].spi)) {
22386738ebeSSrujana Challa 				free_pkts(&m, 1);
2245fb245baSNithin Dabilpuram 				continue;
2255fb245baSNithin Dabilpuram 			}
22686738ebeSSrujana Challa 
22786738ebeSSrujana Challa 			ip->pkts[j++] = m;
22886738ebeSSrujana Challa 		}
22986738ebeSSrujana Challa 	}
23086738ebeSSrujana Challa 	ip->num = j;
23186738ebeSSrujana Challa }
23286738ebeSSrujana Challa 
2336938fc92SVolodymyr Fialko static inline void
2346938fc92SVolodymyr Fialko ipv4_pkt_l3_len_set(struct rte_mbuf *pkt)
2356938fc92SVolodymyr Fialko {
2366938fc92SVolodymyr Fialko 	struct rte_ipv4_hdr *ipv4;
2376938fc92SVolodymyr Fialko 
2386938fc92SVolodymyr Fialko 	ipv4 = rte_pktmbuf_mtod(pkt, struct rte_ipv4_hdr *);
2396938fc92SVolodymyr Fialko 	pkt->l3_len = ipv4->ihl * 4;
2406938fc92SVolodymyr Fialko }
2416938fc92SVolodymyr Fialko 
2426938fc92SVolodymyr Fialko static inline int
2436938fc92SVolodymyr Fialko ipv6_pkt_l3_len_set(struct rte_mbuf *pkt)
2446938fc92SVolodymyr Fialko {
2456938fc92SVolodymyr Fialko 	struct rte_ipv6_hdr *ipv6;
2466938fc92SVolodymyr Fialko 	size_t l3_len, ext_len;
2476938fc92SVolodymyr Fialko 	uint32_t l3_type;
2486938fc92SVolodymyr Fialko 	int next_proto;
2496938fc92SVolodymyr Fialko 	uint8_t *p;
2506938fc92SVolodymyr Fialko 
2516938fc92SVolodymyr Fialko 	ipv6 = rte_pktmbuf_mtod(pkt, struct rte_ipv6_hdr *);
2526938fc92SVolodymyr Fialko 	l3_len = sizeof(struct rte_ipv6_hdr);
2536938fc92SVolodymyr Fialko 	l3_type = pkt->packet_type & RTE_PTYPE_L3_MASK;
2546938fc92SVolodymyr Fialko 
2556938fc92SVolodymyr Fialko 	if (l3_type == RTE_PTYPE_L3_IPV6_EXT ||
2566938fc92SVolodymyr Fialko 		l3_type == RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) {
2576938fc92SVolodymyr Fialko 		p = rte_pktmbuf_mtod(pkt, uint8_t *);
2586938fc92SVolodymyr Fialko 		next_proto = ipv6->proto;
2596938fc92SVolodymyr Fialko 		while (next_proto != IPPROTO_ESP &&
2606938fc92SVolodymyr Fialko 			l3_len < pkt->data_len &&
2616938fc92SVolodymyr Fialko 			(next_proto = rte_ipv6_get_next_ext(p + l3_len,
2626938fc92SVolodymyr Fialko 					next_proto, &ext_len)) >= 0)
2636938fc92SVolodymyr Fialko 			l3_len += ext_len;
2646938fc92SVolodymyr Fialko 
2656938fc92SVolodymyr Fialko 		/* Drop pkt when IPv6 header exceeds first seg size */
2666938fc92SVolodymyr Fialko 		if (unlikely(l3_len > pkt->data_len))
2676938fc92SVolodymyr Fialko 			return -EINVAL;
2686938fc92SVolodymyr Fialko 	}
2696938fc92SVolodymyr Fialko 	pkt->l3_len = l3_len;
2706938fc92SVolodymyr Fialko 
2716938fc92SVolodymyr Fialko 	return 0;
2726938fc92SVolodymyr Fialko }
2736938fc92SVolodymyr Fialko 
2749ad50c29SLukasz Bartosik static inline uint16_t
2759ad50c29SLukasz Bartosik route4_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx)
2769ad50c29SLukasz Bartosik {
2779ad50c29SLukasz Bartosik 	uint32_t dst_ip;
2789ad50c29SLukasz Bartosik 	uint16_t offset;
2799ad50c29SLukasz Bartosik 	uint32_t hop;
2809ad50c29SLukasz Bartosik 	int ret;
2819ad50c29SLukasz Bartosik 
2829ad50c29SLukasz Bartosik 	offset = RTE_ETHER_HDR_LEN + offsetof(struct ip, ip_dst);
2839ad50c29SLukasz Bartosik 	dst_ip = *rte_pktmbuf_mtod_offset(pkt, uint32_t *, offset);
2849ad50c29SLukasz Bartosik 	dst_ip = rte_be_to_cpu_32(dst_ip);
2859ad50c29SLukasz Bartosik 
2869ad50c29SLukasz Bartosik 	ret = rte_lpm_lookup((struct rte_lpm *)rt_ctx, dst_ip, &hop);
2879ad50c29SLukasz Bartosik 
2889ad50c29SLukasz Bartosik 	if (ret == 0) {
2899ad50c29SLukasz Bartosik 		/* We have a hit */
2909ad50c29SLukasz Bartosik 		return hop;
2919ad50c29SLukasz Bartosik 	}
2929ad50c29SLukasz Bartosik 
2939ad50c29SLukasz Bartosik 	/* else */
2949ad50c29SLukasz Bartosik 	return RTE_MAX_ETHPORTS;
2959ad50c29SLukasz Bartosik }
2969ad50c29SLukasz Bartosik 
2979ad50c29SLukasz Bartosik /* TODO: To be tested */
2989ad50c29SLukasz Bartosik static inline uint16_t
2999ad50c29SLukasz Bartosik route6_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx)
3009ad50c29SLukasz Bartosik {
301*e1a06e39SRobin Jarry 	struct rte_ipv6_hdr *ip;
3029ad50c29SLukasz Bartosik 	uint32_t hop;
3039ad50c29SLukasz Bartosik 	int ret;
3049ad50c29SLukasz Bartosik 
305*e1a06e39SRobin Jarry 	ip = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *, RTE_ETHER_HDR_LEN);
306*e1a06e39SRobin Jarry 	ret = rte_lpm6_lookup((struct rte_lpm6 *)rt_ctx, &ip->dst_addr, &hop);
3079ad50c29SLukasz Bartosik 
3089ad50c29SLukasz Bartosik 	if (ret == 0) {
3099ad50c29SLukasz Bartosik 		/* We have a hit */
3109ad50c29SLukasz Bartosik 		return hop;
3119ad50c29SLukasz Bartosik 	}
3129ad50c29SLukasz Bartosik 
3139ad50c29SLukasz Bartosik 	/* else */
3149ad50c29SLukasz Bartosik 	return RTE_MAX_ETHPORTS;
3159ad50c29SLukasz Bartosik }
3169ad50c29SLukasz Bartosik 
3179ad50c29SLukasz Bartosik static inline uint16_t
3189ad50c29SLukasz Bartosik get_route(struct rte_mbuf *pkt, struct route_table *rt, enum pkt_type type)
3199ad50c29SLukasz Bartosik {
3209ad50c29SLukasz Bartosik 	if (type == PKT_TYPE_PLAIN_IPV4 || type == PKT_TYPE_IPSEC_IPV4)
3219ad50c29SLukasz Bartosik 		return route4_pkt(pkt, rt->rt4_ctx);
3229ad50c29SLukasz Bartosik 	else if (type == PKT_TYPE_PLAIN_IPV6 || type == PKT_TYPE_IPSEC_IPV6)
3239ad50c29SLukasz Bartosik 		return route6_pkt(pkt, rt->rt6_ctx);
3249ad50c29SLukasz Bartosik 
3259ad50c29SLukasz Bartosik 	return RTE_MAX_ETHPORTS;
3269ad50c29SLukasz Bartosik }
3279ad50c29SLukasz Bartosik 
3286938fc92SVolodymyr Fialko static inline void
3296938fc92SVolodymyr Fialko crypto_op_reset(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
3306938fc92SVolodymyr Fialko 		struct rte_crypto_op *cop[], uint16_t num)
3316938fc92SVolodymyr Fialko {
3326938fc92SVolodymyr Fialko 	struct rte_crypto_sym_op *sop;
3336938fc92SVolodymyr Fialko 	uint32_t i;
3346938fc92SVolodymyr Fialko 
3356938fc92SVolodymyr Fialko 	const struct rte_crypto_op unproc_cop = {
3366938fc92SVolodymyr Fialko 		.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
3376938fc92SVolodymyr Fialko 		.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
3386938fc92SVolodymyr Fialko 		.sess_type = RTE_CRYPTO_OP_SECURITY_SESSION,
3396938fc92SVolodymyr Fialko 	};
3406938fc92SVolodymyr Fialko 
3416938fc92SVolodymyr Fialko 	for (i = 0; i != num; i++) {
3426938fc92SVolodymyr Fialko 		cop[i]->raw = unproc_cop.raw;
3436938fc92SVolodymyr Fialko 		sop = cop[i]->sym;
3446938fc92SVolodymyr Fialko 		sop->m_src = mb[i];
3456938fc92SVolodymyr Fialko 		sop->m_dst = NULL;
3466938fc92SVolodymyr Fialko 		__rte_security_attach_session(sop, ss->security.ses);
3476938fc92SVolodymyr Fialko 	}
3486938fc92SVolodymyr Fialko }
3496938fc92SVolodymyr Fialko 
3501d5078c6SVolodymyr Fialko static inline void
3511d5078c6SVolodymyr Fialko crypto_prepare_event(struct rte_mbuf *pkt, struct rte_ipsec_session *sess, struct rte_event *ev)
3526938fc92SVolodymyr Fialko {
3536938fc92SVolodymyr Fialko 	struct ipsec_mbuf_metadata *priv;
3546938fc92SVolodymyr Fialko 	struct rte_crypto_op *cop;
3556938fc92SVolodymyr Fialko 
3566938fc92SVolodymyr Fialko 	/* Get pkt private data */
3576938fc92SVolodymyr Fialko 	priv = get_priv(pkt);
3586938fc92SVolodymyr Fialko 	cop = &priv->cop;
3596938fc92SVolodymyr Fialko 
3606938fc92SVolodymyr Fialko 	/* Reset crypto operation data */
3616938fc92SVolodymyr Fialko 	crypto_op_reset(sess, &pkt, &cop, 1);
3626938fc92SVolodymyr Fialko 
3636938fc92SVolodymyr Fialko 	/* Update event_ptr with rte_crypto_op */
3641d5078c6SVolodymyr Fialko 	ev->event = 0;
3651d5078c6SVolodymyr Fialko 	ev->event_ptr = cop;
3661d5078c6SVolodymyr Fialko }
3671d5078c6SVolodymyr Fialko 
3681d5078c6SVolodymyr Fialko static inline void
3691d5078c6SVolodymyr Fialko free_pkts_from_events(struct rte_event events[], uint16_t count)
3701d5078c6SVolodymyr Fialko {
3711d5078c6SVolodymyr Fialko 	struct rte_crypto_op *cop;
3721d5078c6SVolodymyr Fialko 	int i;
3731d5078c6SVolodymyr Fialko 
3741d5078c6SVolodymyr Fialko 	for (i = 0; i < count; i++) {
3751d5078c6SVolodymyr Fialko 		cop = events[i].event_ptr;
3761d5078c6SVolodymyr Fialko 		free_pkts(&cop->sym->m_src, 1);
3771d5078c6SVolodymyr Fialko 	}
3781d5078c6SVolodymyr Fialko }
3791d5078c6SVolodymyr Fialko 
3801d5078c6SVolodymyr Fialko static inline int
3811d5078c6SVolodymyr Fialko event_crypto_enqueue(struct rte_mbuf *pkt,
3821d5078c6SVolodymyr Fialko 		struct ipsec_sa *sa, const struct eh_event_link_info *ev_link)
3831d5078c6SVolodymyr Fialko {
3841d5078c6SVolodymyr Fialko 	struct rte_ipsec_session *sess;
3851d5078c6SVolodymyr Fialko 	struct rte_event ev;
3861d5078c6SVolodymyr Fialko 	int ret;
3871d5078c6SVolodymyr Fialko 
3881d5078c6SVolodymyr Fialko 	/* Get IPsec session */
3891d5078c6SVolodymyr Fialko 	sess = ipsec_get_primary_session(sa);
3901d5078c6SVolodymyr Fialko 
3911d5078c6SVolodymyr Fialko 	crypto_prepare_event(pkt, sess, &ev);
3926938fc92SVolodymyr Fialko 
3936938fc92SVolodymyr Fialko 	/* Enqueue event to crypto adapter */
3946938fc92SVolodymyr Fialko 	ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id,
3951d5078c6SVolodymyr Fialko 			ev_link->event_port_id, &ev, 1);
3961d5078c6SVolodymyr Fialko 	if (unlikely(ret != 1)) {
3976938fc92SVolodymyr Fialko 		/* pkt will be freed by the caller */
3986938fc92SVolodymyr Fialko 		RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue event: %i (errno: %i)\n", ret, rte_errno);
3996938fc92SVolodymyr Fialko 		return rte_errno;
4006938fc92SVolodymyr Fialko 	}
4016938fc92SVolodymyr Fialko 
4026938fc92SVolodymyr Fialko 	return 0;
4036938fc92SVolodymyr Fialko }
4046938fc92SVolodymyr Fialko 
4059ad50c29SLukasz Bartosik static inline int
4069ad50c29SLukasz Bartosik process_ipsec_ev_inbound(struct ipsec_ctx *ctx, struct route_table *rt,
4076938fc92SVolodymyr Fialko 	const struct eh_event_link_info *ev_link, struct rte_event *ev)
4089ad50c29SLukasz Bartosik {
4099ad50c29SLukasz Bartosik 	struct ipsec_sa *sa = NULL;
4109ad50c29SLukasz Bartosik 	struct rte_mbuf *pkt;
4119ad50c29SLukasz Bartosik 	uint16_t port_id = 0;
4129ad50c29SLukasz Bartosik 	enum pkt_type type;
4139ad50c29SLukasz Bartosik 	uint32_t sa_idx;
4149ad50c29SLukasz Bartosik 	uint8_t *nlp;
4159ad50c29SLukasz Bartosik 
4169ad50c29SLukasz Bartosik 	/* Get pkt from event */
4179ad50c29SLukasz Bartosik 	pkt = ev->mbuf;
418d8d51d4fSRahul Bhansali 	if (is_ip_reassembly_incomplete(pkt) > 0) {
419d8d51d4fSRahul Bhansali 		free_reassembly_fail_pkt(pkt);
420d8d51d4fSRahul Bhansali 		return PKT_DROPPED;
421d8d51d4fSRahul Bhansali 	}
4229ad50c29SLukasz Bartosik 
4239ad50c29SLukasz Bartosik 	/* Check the packet type */
4249ad50c29SLukasz Bartosik 	type = process_ipsec_get_pkt_type(pkt, &nlp);
4259ad50c29SLukasz Bartosik 
4269ad50c29SLukasz Bartosik 	switch (type) {
4279ad50c29SLukasz Bartosik 	case PKT_TYPE_PLAIN_IPV4:
428daa02b5cSOlivier Matz 		if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) {
4299ad50c29SLukasz Bartosik 			if (unlikely(pkt->ol_flags &
430daa02b5cSOlivier Matz 				     RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
4319ad50c29SLukasz Bartosik 				RTE_LOG(ERR, IPSEC,
4329ad50c29SLukasz Bartosik 					"Inbound security offload failed\n");
4339ad50c29SLukasz Bartosik 				goto drop_pkt_and_exit;
4349ad50c29SLukasz Bartosik 			}
435614af754SThomas Monjalon 			sa = *(struct ipsec_sa **)rte_security_dynfield(pkt);
4369ad50c29SLukasz Bartosik 		}
4379ad50c29SLukasz Bartosik 
4389ad50c29SLukasz Bartosik 		/* Check if we have a match */
4399ad50c29SLukasz Bartosik 		if (check_sp(ctx->sp4_ctx, nlp, &sa_idx) == 0) {
4409ad50c29SLukasz Bartosik 			/* No valid match */
4419ad50c29SLukasz Bartosik 			goto drop_pkt_and_exit;
4429ad50c29SLukasz Bartosik 		}
4439ad50c29SLukasz Bartosik 		break;
4449ad50c29SLukasz Bartosik 
4459ad50c29SLukasz Bartosik 	case PKT_TYPE_PLAIN_IPV6:
446daa02b5cSOlivier Matz 		if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) {
4479ad50c29SLukasz Bartosik 			if (unlikely(pkt->ol_flags &
448daa02b5cSOlivier Matz 				     RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
4499ad50c29SLukasz Bartosik 				RTE_LOG(ERR, IPSEC,
4509ad50c29SLukasz Bartosik 					"Inbound security offload failed\n");
4519ad50c29SLukasz Bartosik 				goto drop_pkt_and_exit;
4529ad50c29SLukasz Bartosik 			}
453614af754SThomas Monjalon 			sa = *(struct ipsec_sa **)rte_security_dynfield(pkt);
4549ad50c29SLukasz Bartosik 		}
4559ad50c29SLukasz Bartosik 
4569ad50c29SLukasz Bartosik 		/* Check if we have a match */
4579ad50c29SLukasz Bartosik 		if (check_sp(ctx->sp6_ctx, nlp, &sa_idx) == 0) {
4589ad50c29SLukasz Bartosik 			/* No valid match */
4599ad50c29SLukasz Bartosik 			goto drop_pkt_and_exit;
4609ad50c29SLukasz Bartosik 		}
4619ad50c29SLukasz Bartosik 		break;
4626938fc92SVolodymyr Fialko 	case PKT_TYPE_IPSEC_IPV4:
4636938fc92SVolodymyr Fialko 		rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
4646938fc92SVolodymyr Fialko 		ipv4_pkt_l3_len_set(pkt);
4656938fc92SVolodymyr Fialko 		sad_lookup(&ctx->sa_ctx->sad, &pkt, (void **)&sa, 1);
4666938fc92SVolodymyr Fialko 		sa = ipsec_mask_saptr(sa);
4676938fc92SVolodymyr Fialko 		if (unlikely(sa == NULL)) {
4686938fc92SVolodymyr Fialko 			RTE_LOG_DP(DEBUG, IPSEC, "Cannot find sa\n");
4696938fc92SVolodymyr Fialko 			goto drop_pkt_and_exit;
4706938fc92SVolodymyr Fialko 		}
4719ad50c29SLukasz Bartosik 
4721d5078c6SVolodymyr Fialko 		if (unlikely(event_crypto_enqueue(pkt, sa, ev_link)))
4736938fc92SVolodymyr Fialko 			goto drop_pkt_and_exit;
4746938fc92SVolodymyr Fialko 
4756938fc92SVolodymyr Fialko 		return PKT_POSTED;
4766938fc92SVolodymyr Fialko 	case PKT_TYPE_IPSEC_IPV6:
4776938fc92SVolodymyr Fialko 		rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
4786938fc92SVolodymyr Fialko 		if (unlikely(ipv6_pkt_l3_len_set(pkt) != 0))
4796938fc92SVolodymyr Fialko 			goto drop_pkt_and_exit;
4806938fc92SVolodymyr Fialko 		sad_lookup(&ctx->sa_ctx->sad, &pkt, (void **)&sa, 1);
4816938fc92SVolodymyr Fialko 		sa = ipsec_mask_saptr(sa);
4826938fc92SVolodymyr Fialko 		if (unlikely(sa == NULL)) {
4836938fc92SVolodymyr Fialko 			RTE_LOG_DP(DEBUG, IPSEC, "Cannot find sa\n");
4846938fc92SVolodymyr Fialko 			goto drop_pkt_and_exit;
4856938fc92SVolodymyr Fialko 		}
4866938fc92SVolodymyr Fialko 
4871d5078c6SVolodymyr Fialko 		if (unlikely(event_crypto_enqueue(pkt, sa, ev_link)))
4886938fc92SVolodymyr Fialko 			goto drop_pkt_and_exit;
4896938fc92SVolodymyr Fialko 
4906938fc92SVolodymyr Fialko 		return PKT_POSTED;
4919ad50c29SLukasz Bartosik 	default:
4925315b774SNithin Dabilpuram 		RTE_LOG_DP(DEBUG, IPSEC_ESP, "Unsupported packet type = %d\n",
4935315b774SNithin Dabilpuram 			   type);
4949ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
4959ad50c29SLukasz Bartosik 	}
4969ad50c29SLukasz Bartosik 
4979ad50c29SLukasz Bartosik 	/* Check if the packet has to be bypassed */
4989ad50c29SLukasz Bartosik 	if (sa_idx == BYPASS)
4999ad50c29SLukasz Bartosik 		goto route_and_send_pkt;
5009ad50c29SLukasz Bartosik 
5019ad50c29SLukasz Bartosik 	/* Validate sa_idx */
5029ad50c29SLukasz Bartosik 	if (sa_idx >= ctx->sa_ctx->nb_sa)
5039ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5049ad50c29SLukasz Bartosik 
5059ad50c29SLukasz Bartosik 	/* Else the packet has to be protected with SA */
5069ad50c29SLukasz Bartosik 
5079ad50c29SLukasz Bartosik 	/* If the packet was IPsec processed, then SA pointer should be set */
5089ad50c29SLukasz Bartosik 	if (sa == NULL)
5099ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5109ad50c29SLukasz Bartosik 
5119ad50c29SLukasz Bartosik 	/* SPI on the packet should match with the one in SA */
5129ad50c29SLukasz Bartosik 	if (unlikely(sa->spi != ctx->sa_ctx->sa[sa_idx].spi))
5139ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5149ad50c29SLukasz Bartosik 
5159ad50c29SLukasz Bartosik route_and_send_pkt:
5169ad50c29SLukasz Bartosik 	port_id = get_route(pkt, rt, type);
5179ad50c29SLukasz Bartosik 	if (unlikely(port_id == RTE_MAX_ETHPORTS)) {
5189ad50c29SLukasz Bartosik 		/* no match */
5199ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5209ad50c29SLukasz Bartosik 	}
5219ad50c29SLukasz Bartosik 	/* else, we have a matching route */
5229ad50c29SLukasz Bartosik 
5239ad50c29SLukasz Bartosik 	/* Update mac addresses */
52458e2cf4cSNithin Dabilpuram 	update_mac_addrs(rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *), port_id);
5259ad50c29SLukasz Bartosik 
5269ad50c29SLukasz Bartosik 	/* Update the event with the dest port */
5279ad50c29SLukasz Bartosik 	ipsec_event_pre_forward(pkt, port_id);
5289ad50c29SLukasz Bartosik 	return PKT_FORWARDED;
5299ad50c29SLukasz Bartosik 
5309ad50c29SLukasz Bartosik drop_pkt_and_exit:
531f44481efSVolodymyr Fialko 	free_pkts(&pkt, 1);
5329ad50c29SLukasz Bartosik 	ev->mbuf = NULL;
5339ad50c29SLukasz Bartosik 	return PKT_DROPPED;
5349ad50c29SLukasz Bartosik }
5359ad50c29SLukasz Bartosik 
5369ad50c29SLukasz Bartosik static inline int
5379ad50c29SLukasz Bartosik process_ipsec_ev_outbound(struct ipsec_ctx *ctx, struct route_table *rt,
5386938fc92SVolodymyr Fialko 		const struct eh_event_link_info *ev_link, struct rte_event *ev)
5399ad50c29SLukasz Bartosik {
5409ad50c29SLukasz Bartosik 	struct rte_ipsec_session *sess;
54158e2cf4cSNithin Dabilpuram 	struct rte_ether_hdr *ethhdr;
5429ad50c29SLukasz Bartosik 	struct sa_ctx *sa_ctx;
5439ad50c29SLukasz Bartosik 	struct rte_mbuf *pkt;
5449ad50c29SLukasz Bartosik 	uint16_t port_id = 0;
5459ad50c29SLukasz Bartosik 	struct ipsec_sa *sa;
5469ad50c29SLukasz Bartosik 	enum pkt_type type;
5479ad50c29SLukasz Bartosik 	uint32_t sa_idx;
5489ad50c29SLukasz Bartosik 	uint8_t *nlp;
5499ad50c29SLukasz Bartosik 
5509ad50c29SLukasz Bartosik 	/* Get pkt from event */
5519ad50c29SLukasz Bartosik 	pkt = ev->mbuf;
5529ad50c29SLukasz Bartosik 
5539ad50c29SLukasz Bartosik 	/* Check the packet type */
5549ad50c29SLukasz Bartosik 	type = process_ipsec_get_pkt_type(pkt, &nlp);
5559ad50c29SLukasz Bartosik 
5569ad50c29SLukasz Bartosik 	switch (type) {
5579ad50c29SLukasz Bartosik 	case PKT_TYPE_PLAIN_IPV4:
5589ad50c29SLukasz Bartosik 		/* Check if we have a match */
5599ad50c29SLukasz Bartosik 		if (check_sp(ctx->sp4_ctx, nlp, &sa_idx) == 0) {
5609ad50c29SLukasz Bartosik 			/* No valid match */
5619ad50c29SLukasz Bartosik 			goto drop_pkt_and_exit;
5629ad50c29SLukasz Bartosik 		}
5639ad50c29SLukasz Bartosik 		break;
5649ad50c29SLukasz Bartosik 	case PKT_TYPE_PLAIN_IPV6:
5659ad50c29SLukasz Bartosik 		/* Check if we have a match */
5669ad50c29SLukasz Bartosik 		if (check_sp(ctx->sp6_ctx, nlp, &sa_idx) == 0) {
5679ad50c29SLukasz Bartosik 			/* No valid match */
5689ad50c29SLukasz Bartosik 			goto drop_pkt_and_exit;
5699ad50c29SLukasz Bartosik 		}
5709ad50c29SLukasz Bartosik 		break;
5719ad50c29SLukasz Bartosik 	default:
5729ad50c29SLukasz Bartosik 		/*
5739ad50c29SLukasz Bartosik 		 * Only plain IPv4 & IPv6 packets are allowed
5749ad50c29SLukasz Bartosik 		 * on protected port. Drop the rest.
5759ad50c29SLukasz Bartosik 		 */
576aabf7ec4SNithin Dabilpuram 		RTE_LOG_DP(DEBUG, IPSEC, "Unsupported packet type = %d\n", type);
5779ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5789ad50c29SLukasz Bartosik 	}
5799ad50c29SLukasz Bartosik 
58058e2cf4cSNithin Dabilpuram 	ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
5819ad50c29SLukasz Bartosik 	/* Check if the packet has to be bypassed */
5829ad50c29SLukasz Bartosik 	if (sa_idx == BYPASS) {
5839ad50c29SLukasz Bartosik 		port_id = get_route(pkt, rt, type);
5849ad50c29SLukasz Bartosik 		if (unlikely(port_id == RTE_MAX_ETHPORTS)) {
5859ad50c29SLukasz Bartosik 			/* no match */
5869ad50c29SLukasz Bartosik 			goto drop_pkt_and_exit;
5879ad50c29SLukasz Bartosik 		}
5889ad50c29SLukasz Bartosik 		/* else, we have a matching route */
5899ad50c29SLukasz Bartosik 		goto send_pkt;
5909ad50c29SLukasz Bartosik 	}
5919ad50c29SLukasz Bartosik 
5929ad50c29SLukasz Bartosik 	/* Validate sa_idx */
5932e7abb8bSNithin Dabilpuram 	if (unlikely(sa_idx >= ctx->sa_ctx->nb_sa))
5949ad50c29SLukasz Bartosik 		goto drop_pkt_and_exit;
5959ad50c29SLukasz Bartosik 
5969ad50c29SLukasz Bartosik 	/* Else the packet has to be protected */
5979ad50c29SLukasz Bartosik 
5989ad50c29SLukasz Bartosik 	/* Get SA ctx*/
5999ad50c29SLukasz Bartosik 	sa_ctx = ctx->sa_ctx;
6009ad50c29SLukasz Bartosik 
6019ad50c29SLukasz Bartosik 	/* Get SA */
6029ad50c29SLukasz Bartosik 	sa = &(sa_ctx->sa[sa_idx]);
6039ad50c29SLukasz Bartosik 
6049ad50c29SLukasz Bartosik 	/* Get IPsec session */
6059ad50c29SLukasz Bartosik 	sess = ipsec_get_primary_session(sa);
6069ad50c29SLukasz Bartosik 
6076938fc92SVolodymyr Fialko 	/* Determine protocol type */
6086938fc92SVolodymyr Fialko 	if (sess->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
6096938fc92SVolodymyr Fialko 		goto lookaside;
6109ad50c29SLukasz Bartosik 
611ea28ab88SNithin Dabilpuram 	rte_security_set_pkt_metadata(sess->security.ctx,
612ea28ab88SNithin Dabilpuram 				      sess->security.ses, pkt, NULL);
6139ad50c29SLukasz Bartosik 
6149ad50c29SLukasz Bartosik 	/* Mark the packet for Tx security offload */
615daa02b5cSOlivier Matz 	pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD;
61658e2cf4cSNithin Dabilpuram 	/* Update ether type */
61758e2cf4cSNithin Dabilpuram 	ethhdr->ether_type = (IS_IP4(sa->flags) ? rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) :
61858e2cf4cSNithin Dabilpuram 			      rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6));
6199ad50c29SLukasz Bartosik 
6209ad50c29SLukasz Bartosik 	/* Get the port to which this pkt need to be submitted */
6219ad50c29SLukasz Bartosik 	port_id = sa->portid;
6229ad50c29SLukasz Bartosik 
6239ad50c29SLukasz Bartosik send_pkt:
624ea28ab88SNithin Dabilpuram 	/* Provide L2 len for Outbound processing */
625ea28ab88SNithin Dabilpuram 	pkt->l2_len = RTE_ETHER_HDR_LEN;
626ea28ab88SNithin Dabilpuram 
6279ad50c29SLukasz Bartosik 	/* Update mac addresses */
62858e2cf4cSNithin Dabilpuram 	update_mac_addrs(ethhdr, port_id);
6299ad50c29SLukasz Bartosik 
6309ad50c29SLukasz Bartosik 	/* Update the event with the dest port */
6319ad50c29SLukasz Bartosik 	ipsec_event_pre_forward(pkt, port_id);
6329ad50c29SLukasz Bartosik 	return PKT_FORWARDED;
6339ad50c29SLukasz Bartosik 
6346938fc92SVolodymyr Fialko lookaside:
6356938fc92SVolodymyr Fialko 	/* prepare pkt - advance start to L3 */
6366938fc92SVolodymyr Fialko 	rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
6376938fc92SVolodymyr Fialko 
6381d5078c6SVolodymyr Fialko 	if (likely(event_crypto_enqueue(pkt, sa, ev_link) == 0))
6396938fc92SVolodymyr Fialko 		return PKT_POSTED;
6406938fc92SVolodymyr Fialko 
6419ad50c29SLukasz Bartosik drop_pkt_and_exit:
6429ad50c29SLukasz Bartosik 	RTE_LOG(ERR, IPSEC, "Outbound packet dropped\n");
643f44481efSVolodymyr Fialko 	free_pkts(&pkt, 1);
6449ad50c29SLukasz Bartosik 	ev->mbuf = NULL;
6459ad50c29SLukasz Bartosik 	return PKT_DROPPED;
6469ad50c29SLukasz Bartosik }
6479ad50c29SLukasz Bartosik 
64886738ebeSSrujana Challa static inline int
6491d5078c6SVolodymyr Fialko ipsec_ev_route_ip_pkts(struct rte_event_vector *vec, struct route_table *rt,
6501d5078c6SVolodymyr Fialko 		    struct ipsec_traffic *t)
65186738ebeSSrujana Challa {
65258e2cf4cSNithin Dabilpuram 	struct rte_ether_hdr *ethhdr;
65386738ebeSSrujana Challa 	struct rte_mbuf *pkt;
6541d5078c6SVolodymyr Fialko 	uint16_t port_id = 0;
6551d5078c6SVolodymyr Fialko 	uint32_t i, j = 0;
65686738ebeSSrujana Challa 
65786738ebeSSrujana Challa 	/* Route IPv4 packets */
65886738ebeSSrujana Challa 	for (i = 0; i < t->ip4.num; i++) {
65986738ebeSSrujana Challa 		pkt = t->ip4.pkts[i];
66086738ebeSSrujana Challa 		port_id = route4_pkt(pkt, rt->rt4_ctx);
66186738ebeSSrujana Challa 		if (port_id != RTE_MAX_ETHPORTS) {
66286738ebeSSrujana Challa 			/* Update mac addresses */
66358e2cf4cSNithin Dabilpuram 			ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
66458e2cf4cSNithin Dabilpuram 			update_mac_addrs(ethhdr, port_id);
66586738ebeSSrujana Challa 			/* Update the event with the dest port */
66686738ebeSSrujana Challa 			ipsec_event_pre_forward(pkt, port_id);
66786738ebeSSrujana Challa 			ev_vector_attr_update(vec, pkt);
66886738ebeSSrujana Challa 			vec->mbufs[j++] = pkt;
66986738ebeSSrujana Challa 		} else
67086738ebeSSrujana Challa 			free_pkts(&pkt, 1);
67186738ebeSSrujana Challa 	}
67286738ebeSSrujana Challa 
67386738ebeSSrujana Challa 	/* Route IPv6 packets */
67486738ebeSSrujana Challa 	for (i = 0; i < t->ip6.num; i++) {
67586738ebeSSrujana Challa 		pkt = t->ip6.pkts[i];
67686738ebeSSrujana Challa 		port_id = route6_pkt(pkt, rt->rt6_ctx);
67786738ebeSSrujana Challa 		if (port_id != RTE_MAX_ETHPORTS) {
67886738ebeSSrujana Challa 			/* Update mac addresses */
67958e2cf4cSNithin Dabilpuram 			ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
68058e2cf4cSNithin Dabilpuram 			update_mac_addrs(ethhdr, port_id);
68186738ebeSSrujana Challa 			/* Update the event with the dest port */
68286738ebeSSrujana Challa 			ipsec_event_pre_forward(pkt, port_id);
68386738ebeSSrujana Challa 			ev_vector_attr_update(vec, pkt);
68486738ebeSSrujana Challa 			vec->mbufs[j++] = pkt;
68586738ebeSSrujana Challa 		} else
68686738ebeSSrujana Challa 			free_pkts(&pkt, 1);
68786738ebeSSrujana Challa 	}
68886738ebeSSrujana Challa 
6891d5078c6SVolodymyr Fialko 	return j;
6901d5078c6SVolodymyr Fialko }
6911d5078c6SVolodymyr Fialko 
6921d5078c6SVolodymyr Fialko static inline int
6931d5078c6SVolodymyr Fialko ipsec_ev_inbound_route_pkts(struct rte_event_vector *vec,
6941d5078c6SVolodymyr Fialko 			    struct route_table *rt,
6951d5078c6SVolodymyr Fialko 			    struct ipsec_traffic *t,
6961d5078c6SVolodymyr Fialko 			    const struct eh_event_link_info *ev_link)
6971d5078c6SVolodymyr Fialko {
6981d5078c6SVolodymyr Fialko 	uint32_t ret, i, j, ev_len = 0;
6991d5078c6SVolodymyr Fialko 	struct rte_event events[MAX_PKTS];
7001d5078c6SVolodymyr Fialko 	struct rte_ipsec_session *sess;
7011d5078c6SVolodymyr Fialko 	struct rte_mbuf *pkt;
7021d5078c6SVolodymyr Fialko 	struct ipsec_sa *sa;
7031d5078c6SVolodymyr Fialko 
7041d5078c6SVolodymyr Fialko 	j = ipsec_ev_route_ip_pkts(vec, rt, t);
7051d5078c6SVolodymyr Fialko 
70686738ebeSSrujana Challa 	/* Route ESP packets */
70786738ebeSSrujana Challa 	for (i = 0; i < t->ipsec.num; i++) {
7081d5078c6SVolodymyr Fialko 		pkt = t->ipsec.pkts[i];
7091d5078c6SVolodymyr Fialko 		sa = ipsec_mask_saptr(t->ipsec.saptr[i]);
7101d5078c6SVolodymyr Fialko 		if (unlikely(sa == NULL)) {
7111d5078c6SVolodymyr Fialko 			free_pkts(&pkt, 1);
7121d5078c6SVolodymyr Fialko 			continue;
7131d5078c6SVolodymyr Fialko 		}
7141d5078c6SVolodymyr Fialko 		sess = ipsec_get_primary_session(sa);
7151d5078c6SVolodymyr Fialko 		crypto_prepare_event(pkt, sess, &events[ev_len]);
7161d5078c6SVolodymyr Fialko 		ev_len++;
7171d5078c6SVolodymyr Fialko 	}
7181d5078c6SVolodymyr Fialko 
7191d5078c6SVolodymyr Fialko 	if (ev_len) {
7201d5078c6SVolodymyr Fialko 		ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id,
7211d5078c6SVolodymyr Fialko 				ev_link->event_port_id, events, ev_len);
7221d5078c6SVolodymyr Fialko 		if (ret < ev_len) {
7231d5078c6SVolodymyr Fialko 			RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue events: %i (errno: %i)\n",
7241d5078c6SVolodymyr Fialko 					ev_len, rte_errno);
7251d5078c6SVolodymyr Fialko 			free_pkts_from_events(&events[ret], ev_len - ret);
7261d5078c6SVolodymyr Fialko 			return -rte_errno;
7271d5078c6SVolodymyr Fialko 		}
7281d5078c6SVolodymyr Fialko 	}
7291d5078c6SVolodymyr Fialko 
7301d5078c6SVolodymyr Fialko 	return j;
7311d5078c6SVolodymyr Fialko }
7321d5078c6SVolodymyr Fialko 
7331d5078c6SVolodymyr Fialko static inline int
7341d5078c6SVolodymyr Fialko ipsec_ev_outbound_route_pkts(struct rte_event_vector *vec, struct route_table *rt,
7351d5078c6SVolodymyr Fialko 		    struct ipsec_traffic *t, struct sa_ctx *sa_ctx,
7361d5078c6SVolodymyr Fialko 		    const struct eh_event_link_info *ev_link)
7371d5078c6SVolodymyr Fialko {
7381d5078c6SVolodymyr Fialko 	uint32_t sa_idx, ret, i, j, ev_len = 0;
7391d5078c6SVolodymyr Fialko 	struct rte_event events[MAX_PKTS];
7401d5078c6SVolodymyr Fialko 	struct rte_ipsec_session *sess;
7411d5078c6SVolodymyr Fialko 	struct rte_ether_hdr *ethhdr;
7421d5078c6SVolodymyr Fialko 	uint16_t port_id = 0;
7431d5078c6SVolodymyr Fialko 	struct rte_mbuf *pkt;
7441d5078c6SVolodymyr Fialko 	struct ipsec_sa *sa;
7451d5078c6SVolodymyr Fialko 
7461d5078c6SVolodymyr Fialko 	j = ipsec_ev_route_ip_pkts(vec, rt, t);
7471d5078c6SVolodymyr Fialko 
7481d5078c6SVolodymyr Fialko 	/* Handle IPsec packets.
7491d5078c6SVolodymyr Fialko 	 * For lookaside IPsec packets, submit to cryptodev queue.
7501d5078c6SVolodymyr Fialko 	 * For inline IPsec packets, route the packet.
7511d5078c6SVolodymyr Fialko 	 */
7521d5078c6SVolodymyr Fialko 	for (i = 0; i < t->ipsec.num; i++) {
75386738ebeSSrujana Challa 		/* Validate sa_idx */
75486738ebeSSrujana Challa 		sa_idx = t->ipsec.res[i];
75586738ebeSSrujana Challa 		pkt = t->ipsec.pkts[i];
7561d5078c6SVolodymyr Fialko 		if (unlikely(sa_idx >= sa_ctx->nb_sa)) {
75786738ebeSSrujana Challa 			free_pkts(&pkt, 1);
7581d5078c6SVolodymyr Fialko 			continue;
7591d5078c6SVolodymyr Fialko 		}
76086738ebeSSrujana Challa 		/* Else the packet has to be protected */
76186738ebeSSrujana Challa 		sa = &(sa_ctx->sa[sa_idx]);
76286738ebeSSrujana Challa 		/* Get IPsec session */
76386738ebeSSrujana Challa 		sess = ipsec_get_primary_session(sa);
7641d5078c6SVolodymyr Fialko 		switch (sess->type) {
7651d5078c6SVolodymyr Fialko 		case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
7661d5078c6SVolodymyr Fialko 			rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
7671d5078c6SVolodymyr Fialko 			crypto_prepare_event(pkt, sess, &events[ev_len]);
7681d5078c6SVolodymyr Fialko 			ev_len++;
7691d5078c6SVolodymyr Fialko 			break;
7701d5078c6SVolodymyr Fialko 		case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
77186738ebeSSrujana Challa 			rte_security_set_pkt_metadata(sess->security.ctx,
77286738ebeSSrujana Challa 						sess->security.ses, pkt, NULL);
77386738ebeSSrujana Challa 			pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD;
77486738ebeSSrujana Challa 			port_id = sa->portid;
77558e2cf4cSNithin Dabilpuram 
77658e2cf4cSNithin Dabilpuram 			/* Fetch outer ip type and update */
77758e2cf4cSNithin Dabilpuram 			ethhdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
77858e2cf4cSNithin Dabilpuram 			ethhdr->ether_type = (IS_IP4(sa->flags) ?
77958e2cf4cSNithin Dabilpuram 					      rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) :
78058e2cf4cSNithin Dabilpuram 					      rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6));
78158e2cf4cSNithin Dabilpuram 			update_mac_addrs(ethhdr, port_id);
78258e2cf4cSNithin Dabilpuram 
78386738ebeSSrujana Challa 			ipsec_event_pre_forward(pkt, port_id);
78486738ebeSSrujana Challa 			ev_vector_attr_update(vec, pkt);
78586738ebeSSrujana Challa 			vec->mbufs[j++] = pkt;
7861d5078c6SVolodymyr Fialko 			break;
7871d5078c6SVolodymyr Fialko 		default:
7881d5078c6SVolodymyr Fialko 			RTE_LOG(ERR, IPSEC, "SA type not supported\n");
7891d5078c6SVolodymyr Fialko 			free_pkts(&pkt, 1);
7901d5078c6SVolodymyr Fialko 			break;
7911d5078c6SVolodymyr Fialko 		}
7921d5078c6SVolodymyr Fialko 	}
7931d5078c6SVolodymyr Fialko 
7941d5078c6SVolodymyr Fialko 	if (ev_len) {
7951d5078c6SVolodymyr Fialko 		ret = rte_event_crypto_adapter_enqueue(ev_link->eventdev_id,
7961d5078c6SVolodymyr Fialko 				ev_link->event_port_id, events, ev_len);
7971d5078c6SVolodymyr Fialko 		if (ret < ev_len) {
7981d5078c6SVolodymyr Fialko 			RTE_LOG_DP(DEBUG, IPSEC, "Cannot enqueue events: %i (errno: %i)\n",
7991d5078c6SVolodymyr Fialko 				   ev_len, rte_errno);
8001d5078c6SVolodymyr Fialko 			free_pkts_from_events(&events[ret], ev_len - ret);
8011d5078c6SVolodymyr Fialko 			return -rte_errno;
80286738ebeSSrujana Challa 		}
80386738ebeSSrujana Challa 	}
80486738ebeSSrujana Challa 
80586738ebeSSrujana Challa 	return j;
80686738ebeSSrujana Challa }
80786738ebeSSrujana Challa 
80886738ebeSSrujana Challa static inline void
80986738ebeSSrujana Challa classify_pkt(struct rte_mbuf *pkt, struct ipsec_traffic *t)
81086738ebeSSrujana Challa {
81186738ebeSSrujana Challa 	enum pkt_type type;
81286738ebeSSrujana Challa 	uint8_t *nlp;
81386738ebeSSrujana Challa 
81486738ebeSSrujana Challa 	/* Check the packet type */
81586738ebeSSrujana Challa 	type = process_ipsec_get_pkt_type(pkt, &nlp);
81686738ebeSSrujana Challa 
81786738ebeSSrujana Challa 	switch (type) {
81886738ebeSSrujana Challa 	case PKT_TYPE_PLAIN_IPV4:
81986738ebeSSrujana Challa 		t->ip4.data[t->ip4.num] = nlp;
82086738ebeSSrujana Challa 		t->ip4.pkts[(t->ip4.num)++] = pkt;
82186738ebeSSrujana Challa 		break;
82286738ebeSSrujana Challa 	case PKT_TYPE_PLAIN_IPV6:
82386738ebeSSrujana Challa 		t->ip6.data[t->ip6.num] = nlp;
82486738ebeSSrujana Challa 		t->ip6.pkts[(t->ip6.num)++] = pkt;
82586738ebeSSrujana Challa 		break;
8261d5078c6SVolodymyr Fialko 	case PKT_TYPE_IPSEC_IPV4:
8271d5078c6SVolodymyr Fialko 		rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
8281d5078c6SVolodymyr Fialko 		ipv4_pkt_l3_len_set(pkt);
8291d5078c6SVolodymyr Fialko 		t->ipsec.pkts[(t->ipsec.num)++] = pkt;
8301d5078c6SVolodymyr Fialko 		break;
8311d5078c6SVolodymyr Fialko 	case PKT_TYPE_IPSEC_IPV6:
8321d5078c6SVolodymyr Fialko 		rte_pktmbuf_adj(pkt, RTE_ETHER_HDR_LEN);
8331d5078c6SVolodymyr Fialko 		if (ipv6_pkt_l3_len_set(pkt) != 0) {
8341d5078c6SVolodymyr Fialko 			free_pkts(&pkt, 1);
8351d5078c6SVolodymyr Fialko 			return;
8361d5078c6SVolodymyr Fialko 		}
8371d5078c6SVolodymyr Fialko 		t->ipsec.pkts[(t->ipsec.num)++] = pkt;
8381d5078c6SVolodymyr Fialko 		break;
83986738ebeSSrujana Challa 	default:
8405315b774SNithin Dabilpuram 		RTE_LOG_DP(DEBUG, IPSEC_ESP, "Unsupported packet type = %d\n",
8415315b774SNithin Dabilpuram 			   type);
84286738ebeSSrujana Challa 		free_pkts(&pkt, 1);
84386738ebeSSrujana Challa 		break;
84486738ebeSSrujana Challa 	}
84586738ebeSSrujana Challa }
84686738ebeSSrujana Challa 
84786738ebeSSrujana Challa static inline int
84886738ebeSSrujana Challa process_ipsec_ev_inbound_vector(struct ipsec_ctx *ctx, struct route_table *rt,
8491d5078c6SVolodymyr Fialko 				struct rte_event_vector *vec,
8501d5078c6SVolodymyr Fialko 				const struct eh_event_link_info *ev_link)
85186738ebeSSrujana Challa {
85286738ebeSSrujana Challa 	struct ipsec_traffic t;
85386738ebeSSrujana Challa 	struct rte_mbuf *pkt;
85486738ebeSSrujana Challa 	int i;
85586738ebeSSrujana Challa 
85686738ebeSSrujana Challa 	t.ip4.num = 0;
85786738ebeSSrujana Challa 	t.ip6.num = 0;
85886738ebeSSrujana Challa 	t.ipsec.num = 0;
85986738ebeSSrujana Challa 
86086738ebeSSrujana Challa 	for (i = 0; i < vec->nb_elem; i++) {
86186738ebeSSrujana Challa 		/* Get pkt from event */
86286738ebeSSrujana Challa 		pkt = vec->mbufs[i];
863d8d51d4fSRahul Bhansali 		if (is_ip_reassembly_incomplete(pkt) > 0) {
864d8d51d4fSRahul Bhansali 			free_reassembly_fail_pkt(pkt);
865d8d51d4fSRahul Bhansali 			continue;
866d8d51d4fSRahul Bhansali 		}
86786738ebeSSrujana Challa 
86886738ebeSSrujana Challa 		if (pkt->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) {
86986738ebeSSrujana Challa 			if (unlikely(pkt->ol_flags &
87086738ebeSSrujana Challa 				     RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
87186738ebeSSrujana Challa 				RTE_LOG(ERR, IPSEC,
87286738ebeSSrujana Challa 					"Inbound security offload failed\n");
87386738ebeSSrujana Challa 				free_pkts(&pkt, 1);
87486738ebeSSrujana Challa 				continue;
87586738ebeSSrujana Challa 			}
87686738ebeSSrujana Challa 		}
87786738ebeSSrujana Challa 
87886738ebeSSrujana Challa 		classify_pkt(pkt, &t);
87986738ebeSSrujana Challa 	}
88086738ebeSSrujana Challa 
88186738ebeSSrujana Challa 	check_sp_sa_bulk(ctx->sp4_ctx, ctx->sa_ctx, &t.ip4);
88286738ebeSSrujana Challa 	check_sp_sa_bulk(ctx->sp6_ctx, ctx->sa_ctx, &t.ip6);
88386738ebeSSrujana Challa 
8841d5078c6SVolodymyr Fialko 	if (t.ipsec.num != 0)
8851d5078c6SVolodymyr Fialko 		sad_lookup(&ctx->sa_ctx->sad, t.ipsec.pkts, t.ipsec.saptr, t.ipsec.num);
8861d5078c6SVolodymyr Fialko 
8871d5078c6SVolodymyr Fialko 	return ipsec_ev_inbound_route_pkts(vec, rt, &t, ev_link);
88886738ebeSSrujana Challa }
88986738ebeSSrujana Challa 
89086738ebeSSrujana Challa static inline int
89186738ebeSSrujana Challa process_ipsec_ev_outbound_vector(struct ipsec_ctx *ctx, struct route_table *rt,
8921d5078c6SVolodymyr Fialko 				 struct rte_event_vector *vec,
8931d5078c6SVolodymyr Fialko 				 const struct eh_event_link_info *ev_link)
89486738ebeSSrujana Challa {
89586738ebeSSrujana Challa 	struct ipsec_traffic t;
89686738ebeSSrujana Challa 	struct rte_mbuf *pkt;
89786738ebeSSrujana Challa 	uint32_t i;
89886738ebeSSrujana Challa 
89986738ebeSSrujana Challa 	t.ip4.num = 0;
90086738ebeSSrujana Challa 	t.ip6.num = 0;
90186738ebeSSrujana Challa 	t.ipsec.num = 0;
90286738ebeSSrujana Challa 
90386738ebeSSrujana Challa 	for (i = 0; i < vec->nb_elem; i++) {
90486738ebeSSrujana Challa 		/* Get pkt from event */
90586738ebeSSrujana Challa 		pkt = vec->mbufs[i];
90686738ebeSSrujana Challa 
90786738ebeSSrujana Challa 		classify_pkt(pkt, &t);
90886738ebeSSrujana Challa 
90986738ebeSSrujana Challa 		/* Provide L2 len for Outbound processing */
91086738ebeSSrujana Challa 		pkt->l2_len = RTE_ETHER_HDR_LEN;
91186738ebeSSrujana Challa 	}
91286738ebeSSrujana Challa 
91386738ebeSSrujana Challa 	check_sp_bulk(ctx->sp4_ctx, &t.ip4, &t.ipsec);
91486738ebeSSrujana Challa 	check_sp_bulk(ctx->sp6_ctx, &t.ip6, &t.ipsec);
91586738ebeSSrujana Challa 
9161d5078c6SVolodymyr Fialko 	return ipsec_ev_outbound_route_pkts(vec, rt, &t, ctx->sa_ctx, ev_link);
91786738ebeSSrujana Challa }
91886738ebeSSrujana Challa 
91986738ebeSSrujana Challa static inline int
92086738ebeSSrujana Challa process_ipsec_ev_drv_mode_outbound_vector(struct rte_event_vector *vec,
92186738ebeSSrujana Challa 					  struct port_drv_mode_data *data)
92286738ebeSSrujana Challa {
92386738ebeSSrujana Challa 	struct rte_mbuf *pkt;
92486738ebeSSrujana Challa 	int16_t port_id;
92586738ebeSSrujana Challa 	uint32_t i;
92686738ebeSSrujana Challa 	int j = 0;
92786738ebeSSrujana Challa 
92886738ebeSSrujana Challa 	for (i = 0; i < vec->nb_elem; i++) {
92986738ebeSSrujana Challa 		pkt = vec->mbufs[i];
93086738ebeSSrujana Challa 		port_id = pkt->port;
93186738ebeSSrujana Challa 
93286738ebeSSrujana Challa 		if (unlikely(!data[port_id].sess)) {
93386738ebeSSrujana Challa 			free_pkts(&pkt, 1);
93486738ebeSSrujana Challa 			continue;
93586738ebeSSrujana Challa 		}
93686738ebeSSrujana Challa 		ipsec_event_pre_forward(pkt, port_id);
93786738ebeSSrujana Challa 		/* Save security session */
93886738ebeSSrujana Challa 		rte_security_set_pkt_metadata(data[port_id].ctx,
93986738ebeSSrujana Challa 					      data[port_id].sess, pkt,
94086738ebeSSrujana Challa 					      NULL);
94186738ebeSSrujana Challa 
94286738ebeSSrujana Challa 		/* Mark the packet for Tx security offload */
94386738ebeSSrujana Challa 		pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD;
94486738ebeSSrujana Challa 
94586738ebeSSrujana Challa 		/* Provide L2 len for Outbound processing */
94686738ebeSSrujana Challa 		pkt->l2_len = RTE_ETHER_HDR_LEN;
94786738ebeSSrujana Challa 
94886738ebeSSrujana Challa 		vec->mbufs[j++] = pkt;
94986738ebeSSrujana Challa 	}
95086738ebeSSrujana Challa 
95186738ebeSSrujana Challa 	return j;
95286738ebeSSrujana Challa }
95386738ebeSSrujana Challa 
954ae279ac9SRahul Bhansali static void
955ae279ac9SRahul Bhansali ipsec_event_vector_free(struct rte_event *ev)
956ae279ac9SRahul Bhansali {
957ae279ac9SRahul Bhansali 	struct rte_event_vector *vec = ev->vec;
958991b0859SVidya Sagar Velumuri 
959991b0859SVidya Sagar Velumuri 	if (ev->event_type == RTE_EVENT_TYPE_CRYPTODEV_VECTOR) {
960991b0859SVidya Sagar Velumuri 		struct rte_crypto_op *cop;
961991b0859SVidya Sagar Velumuri 		int i;
962991b0859SVidya Sagar Velumuri 
963991b0859SVidya Sagar Velumuri 		for (i = 0; i < vec->nb_elem; i++) {
964991b0859SVidya Sagar Velumuri 			cop = vec->ptrs[i];
965991b0859SVidya Sagar Velumuri 			rte_pktmbuf_free(cop->sym->m_src);
966991b0859SVidya Sagar Velumuri 		}
967991b0859SVidya Sagar Velumuri 	} else {
968ae279ac9SRahul Bhansali 		rte_pktmbuf_free_bulk(vec->mbufs + vec->elem_offset, vec->nb_elem);
969991b0859SVidya Sagar Velumuri 	}
970ae279ac9SRahul Bhansali 	rte_mempool_put(rte_mempool_from_obj(vec), vec);
971ae279ac9SRahul Bhansali }
972ae279ac9SRahul Bhansali 
97386738ebeSSrujana Challa static inline void
97486738ebeSSrujana Challa ipsec_ev_vector_process(struct lcore_conf_ev_tx_int_port_wrkr *lconf,
97586738ebeSSrujana Challa 			struct eh_event_link_info *links,
97686738ebeSSrujana Challa 			struct rte_event *ev)
97786738ebeSSrujana Challa {
97886738ebeSSrujana Challa 	struct rte_event_vector *vec = ev->vec;
97986738ebeSSrujana Challa 	struct rte_mbuf *pkt;
98086738ebeSSrujana Challa 	int ret;
98186738ebeSSrujana Challa 
98286738ebeSSrujana Challa 	pkt = vec->mbufs[0];
98386738ebeSSrujana Challa 
98486738ebeSSrujana Challa 	ev_vector_attr_init(vec);
985f44481efSVolodymyr Fialko 	core_stats_update_rx(vec->nb_elem);
9861d5078c6SVolodymyr Fialko 
98786738ebeSSrujana Challa 	if (is_unprotected_port(pkt->port))
98886738ebeSSrujana Challa 		ret = process_ipsec_ev_inbound_vector(&lconf->inbound,
9891d5078c6SVolodymyr Fialko 						      &lconf->rt, vec, links);
99086738ebeSSrujana Challa 	else
99186738ebeSSrujana Challa 		ret = process_ipsec_ev_outbound_vector(&lconf->outbound,
9921d5078c6SVolodymyr Fialko 						       &lconf->rt, vec, links);
99386738ebeSSrujana Challa 
9945fb245baSNithin Dabilpuram 	if (likely(ret > 0)) {
995f44481efSVolodymyr Fialko 		core_stats_update_tx(vec->nb_elem);
99686738ebeSSrujana Challa 		vec->nb_elem = ret;
997ae279ac9SRahul Bhansali 		ret = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id,
998ae279ac9SRahul Bhansali 						       links[0].event_port_id, ev, 1, 0);
999ae279ac9SRahul Bhansali 		if (unlikely(ret == 0))
1000ae279ac9SRahul Bhansali 			ipsec_event_vector_free(ev);
10015fb245baSNithin Dabilpuram 	} else {
10025fb245baSNithin Dabilpuram 		rte_mempool_put(rte_mempool_from_obj(vec), vec);
100386738ebeSSrujana Challa 	}
100486738ebeSSrujana Challa }
100586738ebeSSrujana Challa 
100686738ebeSSrujana Challa static inline void
100786738ebeSSrujana Challa ipsec_ev_vector_drv_mode_process(struct eh_event_link_info *links,
100886738ebeSSrujana Challa 				 struct rte_event *ev,
100986738ebeSSrujana Challa 				 struct port_drv_mode_data *data)
101086738ebeSSrujana Challa {
101186738ebeSSrujana Challa 	struct rte_event_vector *vec = ev->vec;
101286738ebeSSrujana Challa 	struct rte_mbuf *pkt;
1013ae279ac9SRahul Bhansali 	uint16_t ret;
101486738ebeSSrujana Challa 
101586738ebeSSrujana Challa 	pkt = vec->mbufs[0];
1016ae279ac9SRahul Bhansali 	vec->attr_valid = 1;
1017ae279ac9SRahul Bhansali 	vec->port = pkt->port;
101886738ebeSSrujana Challa 
101986738ebeSSrujana Challa 	if (!is_unprotected_port(pkt->port))
102086738ebeSSrujana Challa 		vec->nb_elem = process_ipsec_ev_drv_mode_outbound_vector(vec,
102186738ebeSSrujana Challa 									 data);
1022ae279ac9SRahul Bhansali 	if (likely(vec->nb_elem > 0)) {
1023ae279ac9SRahul Bhansali 		ret = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id,
1024ae279ac9SRahul Bhansali 						       links[0].event_port_id, ev, 1, 0);
1025ae279ac9SRahul Bhansali 		if (unlikely(ret == 0))
1026ae279ac9SRahul Bhansali 			ipsec_event_vector_free(ev);
1027ae279ac9SRahul Bhansali 	} else
10285fb245baSNithin Dabilpuram 		rte_mempool_put(rte_mempool_from_obj(vec), vec);
102986738ebeSSrujana Challa }
103086738ebeSSrujana Challa 
10316938fc92SVolodymyr Fialko static inline int
10321d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_process_one_pkt(
10331d5078c6SVolodymyr Fialko 		const struct lcore_conf_ev_tx_int_port_wrkr *lconf,
10341d5078c6SVolodymyr Fialko 		const struct rte_crypto_op *cop, struct rte_mbuf *pkt)
10356938fc92SVolodymyr Fialko {
10366938fc92SVolodymyr Fialko 	struct rte_ether_hdr *ethhdr;
10376938fc92SVolodymyr Fialko 	uint16_t port_id;
10386938fc92SVolodymyr Fialko 	struct ip *ip;
10396938fc92SVolodymyr Fialko 
10401d5078c6SVolodymyr Fialko 	/* If operation was not successful, free the packet */
10416938fc92SVolodymyr Fialko 	if (unlikely(cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) {
10426938fc92SVolodymyr Fialko 		RTE_LOG_DP(INFO, IPSEC, "Crypto operation failed\n");
10436938fc92SVolodymyr Fialko 		free_pkts(&pkt, 1);
10441d5078c6SVolodymyr Fialko 		return -1;
10456938fc92SVolodymyr Fialko 	}
10466938fc92SVolodymyr Fialko 
10476938fc92SVolodymyr Fialko 	ip = rte_pktmbuf_mtod(pkt, struct ip *);
10486938fc92SVolodymyr Fialko 
10496938fc92SVolodymyr Fialko 	/* Prepend Ether layer */
10506938fc92SVolodymyr Fialko 	ethhdr = (struct rte_ether_hdr *)rte_pktmbuf_prepend(pkt, RTE_ETHER_HDR_LEN);
10516938fc92SVolodymyr Fialko 
10526938fc92SVolodymyr Fialko 	/* Route pkt and update required fields */
10536938fc92SVolodymyr Fialko 	if (ip->ip_v == IPVERSION) {
10546938fc92SVolodymyr Fialko 		pkt->ol_flags |= lconf->outbound.ipv4_offloads;
10556938fc92SVolodymyr Fialko 		pkt->l3_len = sizeof(struct ip);
10566938fc92SVolodymyr Fialko 		pkt->l2_len = RTE_ETHER_HDR_LEN;
10576938fc92SVolodymyr Fialko 
10586938fc92SVolodymyr Fialko 		ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
10596938fc92SVolodymyr Fialko 
10606938fc92SVolodymyr Fialko 		port_id = route4_pkt(pkt, lconf->rt.rt4_ctx);
10616938fc92SVolodymyr Fialko 	} else {
10626938fc92SVolodymyr Fialko 		pkt->ol_flags |= lconf->outbound.ipv6_offloads;
10636938fc92SVolodymyr Fialko 		pkt->l3_len = sizeof(struct ip6_hdr);
10646938fc92SVolodymyr Fialko 		pkt->l2_len = RTE_ETHER_HDR_LEN;
10656938fc92SVolodymyr Fialko 
10666938fc92SVolodymyr Fialko 		ethhdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
10676938fc92SVolodymyr Fialko 
10686938fc92SVolodymyr Fialko 		port_id = route6_pkt(pkt, lconf->rt.rt6_ctx);
10696938fc92SVolodymyr Fialko 	}
10706938fc92SVolodymyr Fialko 
10716938fc92SVolodymyr Fialko 	if (unlikely(port_id == RTE_MAX_ETHPORTS)) {
10726938fc92SVolodymyr Fialko 		RTE_LOG_DP(DEBUG, IPSEC, "Cannot route processed packet\n");
10736938fc92SVolodymyr Fialko 		free_pkts(&pkt, 1);
10741d5078c6SVolodymyr Fialko 		return -1;
10756938fc92SVolodymyr Fialko 	}
10766938fc92SVolodymyr Fialko 
10776938fc92SVolodymyr Fialko 	/* Update Ether with port's MAC addresses */
10786938fc92SVolodymyr Fialko 	memcpy(&ethhdr->src_addr, &ethaddr_tbl[port_id].src, sizeof(struct rte_ether_addr));
10796938fc92SVolodymyr Fialko 	memcpy(&ethhdr->dst_addr, &ethaddr_tbl[port_id].dst, sizeof(struct rte_ether_addr));
10806938fc92SVolodymyr Fialko 
10811d5078c6SVolodymyr Fialko 	ipsec_event_pre_forward(pkt, port_id);
10821d5078c6SVolodymyr Fialko 
10831d5078c6SVolodymyr Fialko 	return 0;
10841d5078c6SVolodymyr Fialko }
10851d5078c6SVolodymyr Fialko 
10861d5078c6SVolodymyr Fialko static inline void
10871d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_vector_process(
10881d5078c6SVolodymyr Fialko 		const struct lcore_conf_ev_tx_int_port_wrkr *lconf,
10891d5078c6SVolodymyr Fialko 		const struct eh_event_link_info *links,
10901d5078c6SVolodymyr Fialko 		struct rte_event *ev)
10911d5078c6SVolodymyr Fialko {
10921d5078c6SVolodymyr Fialko 	struct rte_event_vector *vec = ev->vec;
10931d5078c6SVolodymyr Fialko 	const uint16_t nb_events = 1;
10941d5078c6SVolodymyr Fialko 	struct rte_crypto_op *cop;
10951d5078c6SVolodymyr Fialko 	struct rte_mbuf *pkt;
10961d5078c6SVolodymyr Fialko 	uint16_t enqueued;
10971d5078c6SVolodymyr Fialko 	int i, n = 0;
10981d5078c6SVolodymyr Fialko 
10991d5078c6SVolodymyr Fialko 	ev_vector_attr_init(vec);
11001d5078c6SVolodymyr Fialko 	/* Transform cop vec into pkt vec */
11011d5078c6SVolodymyr Fialko 	for (i = 0; i < vec->nb_elem; i++) {
11021d5078c6SVolodymyr Fialko 		/* Get pkt data */
11031d5078c6SVolodymyr Fialko 		cop = vec->ptrs[i];
11041d5078c6SVolodymyr Fialko 		pkt = cop->sym->m_src;
11051d5078c6SVolodymyr Fialko 		if (ipsec_ev_cryptodev_process_one_pkt(lconf, cop, pkt))
11061d5078c6SVolodymyr Fialko 			continue;
11071d5078c6SVolodymyr Fialko 
11081d5078c6SVolodymyr Fialko 		vec->mbufs[n++] = pkt;
11091d5078c6SVolodymyr Fialko 		ev_vector_attr_update(vec, pkt);
11101d5078c6SVolodymyr Fialko 	}
11111d5078c6SVolodymyr Fialko 
11121d5078c6SVolodymyr Fialko 	if (n == 0) {
11131d5078c6SVolodymyr Fialko 		rte_mempool_put(rte_mempool_from_obj(vec), vec);
11141d5078c6SVolodymyr Fialko 		return;
11151d5078c6SVolodymyr Fialko 	}
11161d5078c6SVolodymyr Fialko 
11171d5078c6SVolodymyr Fialko 	vec->nb_elem = n;
11181d5078c6SVolodymyr Fialko 	enqueued = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id,
11191d5078c6SVolodymyr Fialko 			links[0].event_port_id, ev, nb_events, 0);
11201d5078c6SVolodymyr Fialko 	if (enqueued != nb_events) {
11211d5078c6SVolodymyr Fialko 		RTE_LOG_DP(DEBUG, IPSEC, "Failed to enqueue to tx, ret = %u,"
11221d5078c6SVolodymyr Fialko 				" errno = %i\n", enqueued, rte_errno);
11231d5078c6SVolodymyr Fialko 		free_pkts(vec->mbufs, vec->nb_elem);
11241d5078c6SVolodymyr Fialko 		rte_mempool_put(rte_mempool_from_obj(vec), vec);
11251d5078c6SVolodymyr Fialko 	} else {
11261d5078c6SVolodymyr Fialko 		core_stats_update_tx(n);
11271d5078c6SVolodymyr Fialko 	}
11281d5078c6SVolodymyr Fialko }
11291d5078c6SVolodymyr Fialko 
11301d5078c6SVolodymyr Fialko static inline int
11311d5078c6SVolodymyr Fialko ipsec_ev_cryptodev_process(const struct lcore_conf_ev_tx_int_port_wrkr *lconf,
11321d5078c6SVolodymyr Fialko 			   struct rte_event *ev)
11331d5078c6SVolodymyr Fialko {
11341d5078c6SVolodymyr Fialko 	struct rte_crypto_op *cop;
11351d5078c6SVolodymyr Fialko 	struct rte_mbuf *pkt;
11361d5078c6SVolodymyr Fialko 
11371d5078c6SVolodymyr Fialko 	/* Get pkt data */
11381d5078c6SVolodymyr Fialko 	cop = ev->event_ptr;
11391d5078c6SVolodymyr Fialko 	pkt = cop->sym->m_src;
11401d5078c6SVolodymyr Fialko 
11411d5078c6SVolodymyr Fialko 	if (ipsec_ev_cryptodev_process_one_pkt(lconf, cop, pkt))
11421d5078c6SVolodymyr Fialko 		return PKT_DROPPED;
11431d5078c6SVolodymyr Fialko 
11446938fc92SVolodymyr Fialko 	/* Update event */
11456938fc92SVolodymyr Fialko 	ev->mbuf = pkt;
11466938fc92SVolodymyr Fialko 
11476938fc92SVolodymyr Fialko 	return PKT_FORWARDED;
11486938fc92SVolodymyr Fialko }
11496938fc92SVolodymyr Fialko 
11504965dda0SLukasz Bartosik /*
11514965dda0SLukasz Bartosik  * Event mode exposes various operating modes depending on the
11524965dda0SLukasz Bartosik  * capabilities of the event device and the operating mode
11534965dda0SLukasz Bartosik  * selected.
11544965dda0SLukasz Bartosik  */
11554965dda0SLukasz Bartosik 
1156aae4f5e0SPavan Nikhilesh static void
1157aae4f5e0SPavan Nikhilesh ipsec_event_port_flush(uint8_t eventdev_id __rte_unused, struct rte_event ev,
1158aae4f5e0SPavan Nikhilesh 		       void *args __rte_unused)
1159aae4f5e0SPavan Nikhilesh {
1160ae279ac9SRahul Bhansali 	if (ev.event_type & RTE_EVENT_TYPE_VECTOR)
1161ae279ac9SRahul Bhansali 		ipsec_event_vector_free(&ev);
1162ae279ac9SRahul Bhansali 	else
1163aae4f5e0SPavan Nikhilesh 		rte_pktmbuf_free(ev.mbuf);
1164aae4f5e0SPavan Nikhilesh }
1165aae4f5e0SPavan Nikhilesh 
11664965dda0SLukasz Bartosik /* Workers registered */
11679ad50c29SLukasz Bartosik #define IPSEC_EVENTMODE_WORKERS		2
11684965dda0SLukasz Bartosik 
1169d8d51d4fSRahul Bhansali static void
1170d8d51d4fSRahul Bhansali ipsec_ip_reassembly_dyn_offset_get(void)
1171d8d51d4fSRahul Bhansali {
1172d8d51d4fSRahul Bhansali 	/* Retrieve reassembly dynfield offset if available */
1173d8d51d4fSRahul Bhansali 	if (ip_reassembly_dynfield_offset < 0)
1174d8d51d4fSRahul Bhansali 		ip_reassembly_dynfield_offset = rte_mbuf_dynfield_lookup(
1175d8d51d4fSRahul Bhansali 				RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME, NULL);
1176d8d51d4fSRahul Bhansali 
1177d8d51d4fSRahul Bhansali 	if (ip_reassembly_dynflag == 0) {
1178d8d51d4fSRahul Bhansali 		int ip_reassembly_dynflag_offset;
1179d8d51d4fSRahul Bhansali 		ip_reassembly_dynflag_offset = rte_mbuf_dynflag_lookup(
1180d8d51d4fSRahul Bhansali 				RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME, NULL);
1181d8d51d4fSRahul Bhansali 		if (ip_reassembly_dynflag_offset >= 0)
1182d8d51d4fSRahul Bhansali 			ip_reassembly_dynflag = RTE_BIT64(ip_reassembly_dynflag_offset);
1183d8d51d4fSRahul Bhansali 	}
1184d8d51d4fSRahul Bhansali }
1185d8d51d4fSRahul Bhansali 
11864965dda0SLukasz Bartosik /*
11874965dda0SLukasz Bartosik  * Event mode worker
11884965dda0SLukasz Bartosik  * Operating parameters : non-burst - Tx internal port - driver mode
11894965dda0SLukasz Bartosik  */
11904965dda0SLukasz Bartosik static void
11914965dda0SLukasz Bartosik ipsec_wrkr_non_burst_int_port_drv_mode(struct eh_event_link_info *links,
11924965dda0SLukasz Bartosik 		uint8_t nb_links)
11934965dda0SLukasz Bartosik {
1194ea28ab88SNithin Dabilpuram 	struct port_drv_mode_data data[RTE_MAX_ETHPORTS];
119522bfcba4SPavan Nikhilesh 	unsigned int nb_rx = 0, nb_tx;
11964965dda0SLukasz Bartosik 	struct rte_mbuf *pkt;
11974965dda0SLukasz Bartosik 	struct rte_event ev;
11984965dda0SLukasz Bartosik 	uint32_t lcore_id;
11994965dda0SLukasz Bartosik 	int32_t socket_id;
12004965dda0SLukasz Bartosik 	int16_t port_id;
12014965dda0SLukasz Bartosik 
12024965dda0SLukasz Bartosik 	/* Check if we have links registered for this lcore */
12034965dda0SLukasz Bartosik 	if (nb_links == 0) {
12044965dda0SLukasz Bartosik 		/* No links registered - exit */
12054965dda0SLukasz Bartosik 		return;
12064965dda0SLukasz Bartosik 	}
12074965dda0SLukasz Bartosik 
1208ea28ab88SNithin Dabilpuram 	memset(&data, 0, sizeof(struct port_drv_mode_data));
1209ea28ab88SNithin Dabilpuram 
12104965dda0SLukasz Bartosik 	/* Get core ID */
12114965dda0SLukasz Bartosik 	lcore_id = rte_lcore_id();
12124965dda0SLukasz Bartosik 
12134965dda0SLukasz Bartosik 	/* Get socket ID */
12144965dda0SLukasz Bartosik 	socket_id = rte_lcore_to_socket_id(lcore_id);
12154965dda0SLukasz Bartosik 
12164965dda0SLukasz Bartosik 	/*
12174965dda0SLukasz Bartosik 	 * Prepare security sessions table. In outbound driver mode
12184965dda0SLukasz Bartosik 	 * we always use first session configured for a given port
12194965dda0SLukasz Bartosik 	 */
1220ea28ab88SNithin Dabilpuram 	prepare_out_sessions_tbl(socket_ctx[socket_id].sa_out, data,
12214965dda0SLukasz Bartosik 				 RTE_MAX_ETHPORTS);
12224965dda0SLukasz Bartosik 
12234965dda0SLukasz Bartosik 	RTE_LOG(INFO, IPSEC,
12244965dda0SLukasz Bartosik 		"Launching event mode worker (non-burst - Tx internal port - "
12254965dda0SLukasz Bartosik 		"driver mode) on lcore %d\n", lcore_id);
12264965dda0SLukasz Bartosik 
12274965dda0SLukasz Bartosik 	/* We have valid links */
12284965dda0SLukasz Bartosik 
12294965dda0SLukasz Bartosik 	/* Check if it's single link */
12304965dda0SLukasz Bartosik 	if (nb_links != 1) {
12314965dda0SLukasz Bartosik 		RTE_LOG(INFO, IPSEC,
12324965dda0SLukasz Bartosik 			"Multiple links not supported. Using first link\n");
12334965dda0SLukasz Bartosik 	}
12344965dda0SLukasz Bartosik 
12354965dda0SLukasz Bartosik 	RTE_LOG(INFO, IPSEC, " -- lcoreid=%u event_port_id=%u\n", lcore_id,
12364965dda0SLukasz Bartosik 			links[0].event_port_id);
12374965dda0SLukasz Bartosik 	while (!force_quit) {
12384965dda0SLukasz Bartosik 		/* Read packet from event queues */
12394965dda0SLukasz Bartosik 		nb_rx = rte_event_dequeue_burst(links[0].eventdev_id,
12404965dda0SLukasz Bartosik 				links[0].event_port_id,
12414965dda0SLukasz Bartosik 				&ev,	/* events */
12424965dda0SLukasz Bartosik 				1,	/* nb_events */
12434965dda0SLukasz Bartosik 				0	/* timeout_ticks */);
12444965dda0SLukasz Bartosik 
12454965dda0SLukasz Bartosik 		if (nb_rx == 0)
12464965dda0SLukasz Bartosik 			continue;
12474965dda0SLukasz Bartosik 
124886738ebeSSrujana Challa 		switch (ev.event_type) {
124986738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR:
125086738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETHDEV_VECTOR:
125186738ebeSSrujana Challa 			ipsec_ev_vector_drv_mode_process(links, &ev, data);
125286738ebeSSrujana Challa 			continue;
125386738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETHDEV:
125486738ebeSSrujana Challa 			break;
125586738ebeSSrujana Challa 		default:
125686738ebeSSrujana Challa 			RTE_LOG(ERR, IPSEC, "Invalid event type %u",
125786738ebeSSrujana Challa 				ev.event_type);
125886738ebeSSrujana Challa 			continue;
125986738ebeSSrujana Challa 		}
126086738ebeSSrujana Challa 
12614965dda0SLukasz Bartosik 		pkt = ev.mbuf;
12624965dda0SLukasz Bartosik 		port_id = pkt->port;
12634965dda0SLukasz Bartosik 
12644965dda0SLukasz Bartosik 		rte_prefetch0(rte_pktmbuf_mtod(pkt, void *));
12654965dda0SLukasz Bartosik 
12664965dda0SLukasz Bartosik 		/* Process packet */
12674965dda0SLukasz Bartosik 		ipsec_event_pre_forward(pkt, port_id);
12684965dda0SLukasz Bartosik 
12694965dda0SLukasz Bartosik 		if (!is_unprotected_port(port_id)) {
12704965dda0SLukasz Bartosik 
1271ea28ab88SNithin Dabilpuram 			if (unlikely(!data[port_id].sess)) {
12724965dda0SLukasz Bartosik 				rte_pktmbuf_free(pkt);
12734965dda0SLukasz Bartosik 				continue;
12744965dda0SLukasz Bartosik 			}
12754965dda0SLukasz Bartosik 
12764965dda0SLukasz Bartosik 			/* Save security session */
1277ea28ab88SNithin Dabilpuram 			rte_security_set_pkt_metadata(data[port_id].ctx,
1278ea28ab88SNithin Dabilpuram 						      data[port_id].sess, pkt,
1279ea28ab88SNithin Dabilpuram 						      NULL);
12804965dda0SLukasz Bartosik 
12814965dda0SLukasz Bartosik 			/* Mark the packet for Tx security offload */
1282daa02b5cSOlivier Matz 			pkt->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD;
1283ea28ab88SNithin Dabilpuram 
1284ea28ab88SNithin Dabilpuram 			/* Provide L2 len for Outbound processing */
1285ea28ab88SNithin Dabilpuram 			pkt->l2_len = RTE_ETHER_HDR_LEN;
12864965dda0SLukasz Bartosik 		}
12874965dda0SLukasz Bartosik 
12884965dda0SLukasz Bartosik 		/*
12894965dda0SLukasz Bartosik 		 * Since tx internal port is available, events can be
12904965dda0SLukasz Bartosik 		 * directly enqueued to the adapter and it would be
12914965dda0SLukasz Bartosik 		 * internally submitted to the eth device.
12924965dda0SLukasz Bartosik 		 */
129322bfcba4SPavan Nikhilesh 		nb_tx = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id,
12944965dda0SLukasz Bartosik 							 links[0].event_port_id,
12954965dda0SLukasz Bartosik 							 &ev, /* events */
12964965dda0SLukasz Bartosik 							 1,   /* nb_events */
12974965dda0SLukasz Bartosik 							 0 /* flags */);
129822bfcba4SPavan Nikhilesh 		if (!nb_tx)
129922bfcba4SPavan Nikhilesh 			rte_pktmbuf_free(ev.mbuf);
130022bfcba4SPavan Nikhilesh 	}
130122bfcba4SPavan Nikhilesh 
130222bfcba4SPavan Nikhilesh 	if (ev.u64) {
130322bfcba4SPavan Nikhilesh 		ev.op = RTE_EVENT_OP_RELEASE;
130422bfcba4SPavan Nikhilesh 		rte_event_enqueue_burst(links[0].eventdev_id,
130522bfcba4SPavan Nikhilesh 					links[0].event_port_id, &ev, 1);
13064965dda0SLukasz Bartosik 	}
1307aae4f5e0SPavan Nikhilesh 
1308aae4f5e0SPavan Nikhilesh 	rte_event_port_quiesce(links[0].eventdev_id, links[0].event_port_id,
1309aae4f5e0SPavan Nikhilesh 			       ipsec_event_port_flush, NULL);
13104965dda0SLukasz Bartosik }
13114965dda0SLukasz Bartosik 
13129ad50c29SLukasz Bartosik /*
13139ad50c29SLukasz Bartosik  * Event mode worker
13149ad50c29SLukasz Bartosik  * Operating parameters : non-burst - Tx internal port - app mode
13159ad50c29SLukasz Bartosik  */
13169ad50c29SLukasz Bartosik static void
13179ad50c29SLukasz Bartosik ipsec_wrkr_non_burst_int_port_app_mode(struct eh_event_link_info *links,
13189ad50c29SLukasz Bartosik 		uint8_t nb_links)
13199ad50c29SLukasz Bartosik {
13209ad50c29SLukasz Bartosik 	struct lcore_conf_ev_tx_int_port_wrkr lconf;
132122bfcba4SPavan Nikhilesh 	unsigned int nb_rx = 0, nb_tx;
13229ad50c29SLukasz Bartosik 	struct rte_event ev;
13239ad50c29SLukasz Bartosik 	uint32_t lcore_id;
13249ad50c29SLukasz Bartosik 	int32_t socket_id;
13259ad50c29SLukasz Bartosik 	int ret;
13269ad50c29SLukasz Bartosik 
13279ad50c29SLukasz Bartosik 	/* Check if we have links registered for this lcore */
13289ad50c29SLukasz Bartosik 	if (nb_links == 0) {
13299ad50c29SLukasz Bartosik 		/* No links registered - exit */
13309ad50c29SLukasz Bartosik 		return;
13319ad50c29SLukasz Bartosik 	}
13329ad50c29SLukasz Bartosik 
13339ad50c29SLukasz Bartosik 	/* We have valid links */
13349ad50c29SLukasz Bartosik 
13359ad50c29SLukasz Bartosik 	/* Get core ID */
13369ad50c29SLukasz Bartosik 	lcore_id = rte_lcore_id();
13379ad50c29SLukasz Bartosik 
13389ad50c29SLukasz Bartosik 	/* Get socket ID */
13399ad50c29SLukasz Bartosik 	socket_id = rte_lcore_to_socket_id(lcore_id);
13409ad50c29SLukasz Bartosik 
13419ad50c29SLukasz Bartosik 	/* Save routing table */
13429ad50c29SLukasz Bartosik 	lconf.rt.rt4_ctx = socket_ctx[socket_id].rt_ip4;
13439ad50c29SLukasz Bartosik 	lconf.rt.rt6_ctx = socket_ctx[socket_id].rt_ip6;
13449ad50c29SLukasz Bartosik 	lconf.inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in;
13459ad50c29SLukasz Bartosik 	lconf.inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in;
13469ad50c29SLukasz Bartosik 	lconf.inbound.sa_ctx = socket_ctx[socket_id].sa_in;
1347a8ade121SVolodymyr Fialko 	lconf.inbound.lcore_id = lcore_id;
13489ad50c29SLukasz Bartosik 	lconf.outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out;
13499ad50c29SLukasz Bartosik 	lconf.outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out;
13509ad50c29SLukasz Bartosik 	lconf.outbound.sa_ctx = socket_ctx[socket_id].sa_out;
1351b1a6b1e9SVolodymyr Fialko 	lconf.outbound.ipv4_offloads = tx_offloads.ipv4_offloads;
1352b1a6b1e9SVolodymyr Fialko 	lconf.outbound.ipv6_offloads = tx_offloads.ipv6_offloads;
1353a8ade121SVolodymyr Fialko 	lconf.outbound.lcore_id = lcore_id;
13549ad50c29SLukasz Bartosik 
13559ad50c29SLukasz Bartosik 	RTE_LOG(INFO, IPSEC,
13569ad50c29SLukasz Bartosik 		"Launching event mode worker (non-burst - Tx internal port - "
13579ad50c29SLukasz Bartosik 		"app mode) on lcore %d\n", lcore_id);
13589ad50c29SLukasz Bartosik 
13596938fc92SVolodymyr Fialko 	ret = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz);
13606938fc92SVolodymyr Fialko 	if (ret != 0) {
13616938fc92SVolodymyr Fialko 		RTE_LOG(ERR, IPSEC,
13626938fc92SVolodymyr Fialko 			"SAD cache init on lcore %u, failed with code: %d\n",
13636938fc92SVolodymyr Fialko 			lcore_id, ret);
13646938fc92SVolodymyr Fialko 		return;
13656938fc92SVolodymyr Fialko 	}
13666938fc92SVolodymyr Fialko 
13679ad50c29SLukasz Bartosik 	/* Check if it's single link */
13689ad50c29SLukasz Bartosik 	if (nb_links != 1) {
13699ad50c29SLukasz Bartosik 		RTE_LOG(INFO, IPSEC,
13709ad50c29SLukasz Bartosik 			"Multiple links not supported. Using first link\n");
13719ad50c29SLukasz Bartosik 	}
13729ad50c29SLukasz Bartosik 
13739ad50c29SLukasz Bartosik 	RTE_LOG(INFO, IPSEC, " -- lcoreid=%u event_port_id=%u\n", lcore_id,
13749ad50c29SLukasz Bartosik 		links[0].event_port_id);
13759ad50c29SLukasz Bartosik 
1376d8d51d4fSRahul Bhansali 	ipsec_ip_reassembly_dyn_offset_get();
1377d8d51d4fSRahul Bhansali 
13789ad50c29SLukasz Bartosik 	while (!force_quit) {
13799ad50c29SLukasz Bartosik 		/* Read packet from event queues */
13809ad50c29SLukasz Bartosik 		nb_rx = rte_event_dequeue_burst(links[0].eventdev_id,
13819ad50c29SLukasz Bartosik 				links[0].event_port_id,
13829ad50c29SLukasz Bartosik 				&ev,     /* events */
13839ad50c29SLukasz Bartosik 				1,       /* nb_events */
13849ad50c29SLukasz Bartosik 				0        /* timeout_ticks */);
13859ad50c29SLukasz Bartosik 
13869ad50c29SLukasz Bartosik 		if (nb_rx == 0)
13879ad50c29SLukasz Bartosik 			continue;
13889ad50c29SLukasz Bartosik 
138986738ebeSSrujana Challa 		switch (ev.event_type) {
139086738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR:
139186738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETHDEV_VECTOR:
139286738ebeSSrujana Challa 			ipsec_ev_vector_process(&lconf, links, &ev);
139386738ebeSSrujana Challa 			continue;
139486738ebeSSrujana Challa 		case RTE_EVENT_TYPE_ETHDEV:
1395f44481efSVolodymyr Fialko 			core_stats_update_rx(1);
13966938fc92SVolodymyr Fialko 			if (is_unprotected_port(ev.mbuf->port))
13976938fc92SVolodymyr Fialko 				ret = process_ipsec_ev_inbound(&lconf.inbound,
13986938fc92SVolodymyr Fialko 								&lconf.rt, links, &ev);
13996938fc92SVolodymyr Fialko 			else
14006938fc92SVolodymyr Fialko 				ret = process_ipsec_ev_outbound(&lconf.outbound,
14016938fc92SVolodymyr Fialko 								&lconf.rt, links, &ev);
14026938fc92SVolodymyr Fialko 			if (ret != 1)
14036938fc92SVolodymyr Fialko 				/* The pkt has been dropped or posted */
14046938fc92SVolodymyr Fialko 				continue;
14056938fc92SVolodymyr Fialko 			break;
14066938fc92SVolodymyr Fialko 		case RTE_EVENT_TYPE_CRYPTODEV:
14076938fc92SVolodymyr Fialko 			ret = ipsec_ev_cryptodev_process(&lconf, &ev);
14086938fc92SVolodymyr Fialko 			if (unlikely(ret != PKT_FORWARDED))
14096938fc92SVolodymyr Fialko 				continue;
141086738ebeSSrujana Challa 			break;
14111d5078c6SVolodymyr Fialko 		case RTE_EVENT_TYPE_CRYPTODEV_VECTOR:
14121d5078c6SVolodymyr Fialko 			ipsec_ev_cryptodev_vector_process(&lconf, links, &ev);
14131d5078c6SVolodymyr Fialko 			continue;
141486738ebeSSrujana Challa 		default:
14159ad50c29SLukasz Bartosik 			RTE_LOG(ERR, IPSEC, "Invalid event type %u",
14169ad50c29SLukasz Bartosik 				ev.event_type);
14179ad50c29SLukasz Bartosik 			continue;
14189ad50c29SLukasz Bartosik 		}
14199ad50c29SLukasz Bartosik 
1420f44481efSVolodymyr Fialko 		core_stats_update_tx(1);
14219ad50c29SLukasz Bartosik 		/*
14229ad50c29SLukasz Bartosik 		 * Since tx internal port is available, events can be
14239ad50c29SLukasz Bartosik 		 * directly enqueued to the adapter and it would be
14249ad50c29SLukasz Bartosik 		 * internally submitted to the eth device.
14259ad50c29SLukasz Bartosik 		 */
142622bfcba4SPavan Nikhilesh 		nb_tx = rte_event_eth_tx_adapter_enqueue(links[0].eventdev_id,
14279ad50c29SLukasz Bartosik 							 links[0].event_port_id,
14289ad50c29SLukasz Bartosik 							 &ev, /* events */
14299ad50c29SLukasz Bartosik 							 1,   /* nb_events */
14309ad50c29SLukasz Bartosik 							 0 /* flags */);
143122bfcba4SPavan Nikhilesh 		if (!nb_tx)
143222bfcba4SPavan Nikhilesh 			rte_pktmbuf_free(ev.mbuf);
143322bfcba4SPavan Nikhilesh 	}
143422bfcba4SPavan Nikhilesh 
143522bfcba4SPavan Nikhilesh 	if (ev.u64) {
143622bfcba4SPavan Nikhilesh 		ev.op = RTE_EVENT_OP_RELEASE;
143722bfcba4SPavan Nikhilesh 		rte_event_enqueue_burst(links[0].eventdev_id,
143822bfcba4SPavan Nikhilesh 					links[0].event_port_id, &ev, 1);
14399ad50c29SLukasz Bartosik 	}
1440aae4f5e0SPavan Nikhilesh 
1441aae4f5e0SPavan Nikhilesh 	rte_event_port_quiesce(links[0].eventdev_id, links[0].event_port_id,
1442aae4f5e0SPavan Nikhilesh 			       ipsec_event_port_flush, NULL);
14439ad50c29SLukasz Bartosik }
14449ad50c29SLukasz Bartosik 
14454965dda0SLukasz Bartosik static uint8_t
14464965dda0SLukasz Bartosik ipsec_eventmode_populate_wrkr_params(struct eh_app_worker_params *wrkrs)
14474965dda0SLukasz Bartosik {
14484965dda0SLukasz Bartosik 	struct eh_app_worker_params *wrkr;
14494965dda0SLukasz Bartosik 	uint8_t nb_wrkr_param = 0;
14504965dda0SLukasz Bartosik 
14514965dda0SLukasz Bartosik 	/* Save workers */
14524965dda0SLukasz Bartosik 	wrkr = wrkrs;
14534965dda0SLukasz Bartosik 
14544965dda0SLukasz Bartosik 	/* Non-burst - Tx internal port - driver mode */
14554965dda0SLukasz Bartosik 	wrkr->cap.burst = EH_RX_TYPE_NON_BURST;
14564965dda0SLukasz Bartosik 	wrkr->cap.tx_internal_port = EH_TX_TYPE_INTERNAL_PORT;
14574965dda0SLukasz Bartosik 	wrkr->cap.ipsec_mode = EH_IPSEC_MODE_TYPE_DRIVER;
14584965dda0SLukasz Bartosik 	wrkr->worker_thread = ipsec_wrkr_non_burst_int_port_drv_mode;
14594965dda0SLukasz Bartosik 	wrkr++;
14609ad50c29SLukasz Bartosik 	nb_wrkr_param++;
14619ad50c29SLukasz Bartosik 
14629ad50c29SLukasz Bartosik 	/* Non-burst - Tx internal port - app mode */
14639ad50c29SLukasz Bartosik 	wrkr->cap.burst = EH_RX_TYPE_NON_BURST;
14649ad50c29SLukasz Bartosik 	wrkr->cap.tx_internal_port = EH_TX_TYPE_INTERNAL_PORT;
14659ad50c29SLukasz Bartosik 	wrkr->cap.ipsec_mode = EH_IPSEC_MODE_TYPE_APP;
14669ad50c29SLukasz Bartosik 	wrkr->worker_thread = ipsec_wrkr_non_burst_int_port_app_mode;
14679ad50c29SLukasz Bartosik 	nb_wrkr_param++;
14684965dda0SLukasz Bartosik 
14694965dda0SLukasz Bartosik 	return nb_wrkr_param;
14704965dda0SLukasz Bartosik }
14714965dda0SLukasz Bartosik 
14724965dda0SLukasz Bartosik static void
14734965dda0SLukasz Bartosik ipsec_eventmode_worker(struct eh_conf *conf)
14744965dda0SLukasz Bartosik {
14754965dda0SLukasz Bartosik 	struct eh_app_worker_params ipsec_wrkr[IPSEC_EVENTMODE_WORKERS] = {
14764965dda0SLukasz Bartosik 					{{{0} }, NULL } };
14774965dda0SLukasz Bartosik 	uint8_t nb_wrkr_param;
14784965dda0SLukasz Bartosik 
14794965dda0SLukasz Bartosik 	/* Populate l2fwd_wrkr params */
14804965dda0SLukasz Bartosik 	nb_wrkr_param = ipsec_eventmode_populate_wrkr_params(ipsec_wrkr);
14814965dda0SLukasz Bartosik 
14824965dda0SLukasz Bartosik 	/*
14834965dda0SLukasz Bartosik 	 * Launch correct worker after checking
14844965dda0SLukasz Bartosik 	 * the event device's capabilities.
14854965dda0SLukasz Bartosik 	 */
14864965dda0SLukasz Bartosik 	eh_launch_worker(conf, ipsec_wrkr, nb_wrkr_param);
14874965dda0SLukasz Bartosik }
14884965dda0SLukasz Bartosik 
14890d76e22dSNithin Dabilpuram static __rte_always_inline void
14900d76e22dSNithin Dabilpuram outb_inl_pro_spd_process(struct sp_ctx *sp,
14910d76e22dSNithin Dabilpuram 			 struct sa_ctx *sa_ctx,
14920d76e22dSNithin Dabilpuram 			 struct traffic_type *ip,
14930d76e22dSNithin Dabilpuram 			 struct traffic_type *match,
14940d76e22dSNithin Dabilpuram 			 struct traffic_type *mismatch,
14950d76e22dSNithin Dabilpuram 			 bool match_flag,
14960d76e22dSNithin Dabilpuram 			 struct ipsec_spd_stats *stats)
14970d76e22dSNithin Dabilpuram {
14980d76e22dSNithin Dabilpuram 	uint32_t prev_sa_idx = UINT32_MAX;
14990d76e22dSNithin Dabilpuram 	struct rte_mbuf *ipsec[MAX_PKT_BURST];
15000d76e22dSNithin Dabilpuram 	struct rte_ipsec_session *ips;
15010d76e22dSNithin Dabilpuram 	uint32_t i, j, j_mis, sa_idx;
15020d76e22dSNithin Dabilpuram 	struct ipsec_sa *sa = NULL;
15030d76e22dSNithin Dabilpuram 	uint32_t ipsec_num = 0;
15040d76e22dSNithin Dabilpuram 	struct rte_mbuf *m;
15050d76e22dSNithin Dabilpuram 	uint64_t satp;
15060d76e22dSNithin Dabilpuram 
15070d76e22dSNithin Dabilpuram 	if (ip->num == 0 || sp == NULL)
15080d76e22dSNithin Dabilpuram 		return;
15090d76e22dSNithin Dabilpuram 
15100d76e22dSNithin Dabilpuram 	rte_acl_classify((struct rte_acl_ctx *)sp, ip->data, ip->res,
15110d76e22dSNithin Dabilpuram 			ip->num, DEFAULT_MAX_CATEGORIES);
15120d76e22dSNithin Dabilpuram 
15130d76e22dSNithin Dabilpuram 	j = match->num;
15140d76e22dSNithin Dabilpuram 	j_mis = mismatch->num;
15150d76e22dSNithin Dabilpuram 
15160d76e22dSNithin Dabilpuram 	for (i = 0; i < ip->num; i++) {
15170d76e22dSNithin Dabilpuram 		m = ip->pkts[i];
15180d76e22dSNithin Dabilpuram 		sa_idx = ip->res[i] - 1;
15190d76e22dSNithin Dabilpuram 
15200d76e22dSNithin Dabilpuram 		if (unlikely(ip->res[i] == DISCARD)) {
15210d76e22dSNithin Dabilpuram 			free_pkts(&m, 1);
15220d76e22dSNithin Dabilpuram 
15230d76e22dSNithin Dabilpuram 			stats->discard++;
15240d76e22dSNithin Dabilpuram 		} else if (unlikely(ip->res[i] == BYPASS)) {
15250d76e22dSNithin Dabilpuram 			match->pkts[j++] = m;
15260d76e22dSNithin Dabilpuram 
15270d76e22dSNithin Dabilpuram 			stats->bypass++;
15280d76e22dSNithin Dabilpuram 		} else {
15290d76e22dSNithin Dabilpuram 			if (prev_sa_idx == UINT32_MAX) {
15300d76e22dSNithin Dabilpuram 				prev_sa_idx = sa_idx;
15310d76e22dSNithin Dabilpuram 				sa = &sa_ctx->sa[sa_idx];
15320d76e22dSNithin Dabilpuram 				ips = ipsec_get_primary_session(sa);
15330d76e22dSNithin Dabilpuram 				satp = rte_ipsec_sa_type(ips->sa);
15340d76e22dSNithin Dabilpuram 			}
15350d76e22dSNithin Dabilpuram 
15360d76e22dSNithin Dabilpuram 			if (sa_idx != prev_sa_idx) {
15370d76e22dSNithin Dabilpuram 				prep_process_group(sa, ipsec, ipsec_num);
15380d76e22dSNithin Dabilpuram 
15390d76e22dSNithin Dabilpuram 				/* Prepare packets for outbound */
15400d76e22dSNithin Dabilpuram 				rte_ipsec_pkt_process(ips, ipsec, ipsec_num);
15410d76e22dSNithin Dabilpuram 
15420d76e22dSNithin Dabilpuram 				/* Copy to current tr or a different tr */
15430d76e22dSNithin Dabilpuram 				if (SATP_OUT_IPV4(satp) == match_flag) {
15440d76e22dSNithin Dabilpuram 					memcpy(&match->pkts[j], ipsec,
15450d76e22dSNithin Dabilpuram 					       ipsec_num * sizeof(void *));
15460d76e22dSNithin Dabilpuram 					j += ipsec_num;
15470d76e22dSNithin Dabilpuram 				} else {
15480d76e22dSNithin Dabilpuram 					memcpy(&mismatch->pkts[j_mis], ipsec,
15490d76e22dSNithin Dabilpuram 					       ipsec_num * sizeof(void *));
15500d76e22dSNithin Dabilpuram 					j_mis += ipsec_num;
15510d76e22dSNithin Dabilpuram 				}
15520d76e22dSNithin Dabilpuram 
15530d76e22dSNithin Dabilpuram 				/* Update to new SA */
15540d76e22dSNithin Dabilpuram 				sa = &sa_ctx->sa[sa_idx];
15550d76e22dSNithin Dabilpuram 				ips = ipsec_get_primary_session(sa);
15560d76e22dSNithin Dabilpuram 				satp = rte_ipsec_sa_type(ips->sa);
15570d76e22dSNithin Dabilpuram 				ipsec_num = 0;
15580d76e22dSNithin Dabilpuram 			}
15590d76e22dSNithin Dabilpuram 
15600d76e22dSNithin Dabilpuram 			ipsec[ipsec_num++] = m;
15610d76e22dSNithin Dabilpuram 			stats->protect++;
15620d76e22dSNithin Dabilpuram 		}
15630d76e22dSNithin Dabilpuram 	}
15640d76e22dSNithin Dabilpuram 
15650d76e22dSNithin Dabilpuram 	if (ipsec_num) {
15660d76e22dSNithin Dabilpuram 		prep_process_group(sa, ipsec, ipsec_num);
15670d76e22dSNithin Dabilpuram 
15680d76e22dSNithin Dabilpuram 		/* Prepare pacekts for outbound */
15690d76e22dSNithin Dabilpuram 		rte_ipsec_pkt_process(ips, ipsec, ipsec_num);
15700d76e22dSNithin Dabilpuram 
15710d76e22dSNithin Dabilpuram 		/* Copy to current tr or a different tr */
15720d76e22dSNithin Dabilpuram 		if (SATP_OUT_IPV4(satp) == match_flag) {
15730d76e22dSNithin Dabilpuram 			memcpy(&match->pkts[j], ipsec,
15740d76e22dSNithin Dabilpuram 			       ipsec_num * sizeof(void *));
15750d76e22dSNithin Dabilpuram 			j += ipsec_num;
15760d76e22dSNithin Dabilpuram 		} else {
15770d76e22dSNithin Dabilpuram 			memcpy(&mismatch->pkts[j_mis], ipsec,
15780d76e22dSNithin Dabilpuram 			       ipsec_num * sizeof(void *));
15790d76e22dSNithin Dabilpuram 			j_mis += ipsec_num;
15800d76e22dSNithin Dabilpuram 		}
15810d76e22dSNithin Dabilpuram 	}
15820d76e22dSNithin Dabilpuram 	match->num = j;
15830d76e22dSNithin Dabilpuram 	mismatch->num = j_mis;
15840d76e22dSNithin Dabilpuram }
15850d76e22dSNithin Dabilpuram 
15860d76e22dSNithin Dabilpuram /* Poll mode worker when all SA's are of type inline protocol */
15870d76e22dSNithin Dabilpuram void
15880d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_inl_pr(void)
15890d76e22dSNithin Dabilpuram {
15900d76e22dSNithin Dabilpuram 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
15910d76e22dSNithin Dabilpuram 			/ US_PER_S * BURST_TX_DRAIN_US;
15920d76e22dSNithin Dabilpuram 	struct sp_ctx *sp4_in, *sp6_in, *sp4_out, *sp6_out;
15930d76e22dSNithin Dabilpuram 	struct rte_mbuf *pkts[MAX_PKT_BURST];
15940d76e22dSNithin Dabilpuram 	uint64_t prev_tsc, diff_tsc, cur_tsc;
15950d76e22dSNithin Dabilpuram 	struct ipsec_core_statistics *stats;
15960d76e22dSNithin Dabilpuram 	struct rt_ctx *rt4_ctx, *rt6_ctx;
15970d76e22dSNithin Dabilpuram 	struct sa_ctx *sa_in, *sa_out;
15980d76e22dSNithin Dabilpuram 	struct traffic_type ip4, ip6;
15990d76e22dSNithin Dabilpuram 	struct lcore_rx_queue *rxql;
16000d76e22dSNithin Dabilpuram 	struct rte_mbuf **v4, **v6;
16010d76e22dSNithin Dabilpuram 	struct ipsec_traffic trf;
16020d76e22dSNithin Dabilpuram 	struct lcore_conf *qconf;
16030d76e22dSNithin Dabilpuram 	uint16_t v4_num, v6_num;
16040d76e22dSNithin Dabilpuram 	int32_t socket_id;
16050d76e22dSNithin Dabilpuram 	uint32_t lcore_id;
16060d76e22dSNithin Dabilpuram 	int32_t i, nb_rx;
1607b23c5bd7SSivaprasad Tummala 	uint16_t portid, queueid;
16080d76e22dSNithin Dabilpuram 
16090d76e22dSNithin Dabilpuram 	prev_tsc = 0;
16100d76e22dSNithin Dabilpuram 	lcore_id = rte_lcore_id();
16110d76e22dSNithin Dabilpuram 	qconf = &lcore_conf[lcore_id];
16120d76e22dSNithin Dabilpuram 	rxql = qconf->rx_queue_list;
16130d76e22dSNithin Dabilpuram 	socket_id = rte_lcore_to_socket_id(lcore_id);
16140d76e22dSNithin Dabilpuram 	stats = &core_statistics[lcore_id];
16150d76e22dSNithin Dabilpuram 
16160d76e22dSNithin Dabilpuram 	rt4_ctx = socket_ctx[socket_id].rt_ip4;
16170d76e22dSNithin Dabilpuram 	rt6_ctx = socket_ctx[socket_id].rt_ip6;
16180d76e22dSNithin Dabilpuram 
16190d76e22dSNithin Dabilpuram 	sp4_in = socket_ctx[socket_id].sp_ip4_in;
16200d76e22dSNithin Dabilpuram 	sp6_in = socket_ctx[socket_id].sp_ip6_in;
16210d76e22dSNithin Dabilpuram 	sa_in = socket_ctx[socket_id].sa_in;
16220d76e22dSNithin Dabilpuram 
16230d76e22dSNithin Dabilpuram 	sp4_out = socket_ctx[socket_id].sp_ip4_out;
16240d76e22dSNithin Dabilpuram 	sp6_out = socket_ctx[socket_id].sp_ip6_out;
16250d76e22dSNithin Dabilpuram 	sa_out = socket_ctx[socket_id].sa_out;
16260d76e22dSNithin Dabilpuram 
16270d76e22dSNithin Dabilpuram 	qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;
16280d76e22dSNithin Dabilpuram 
16290d76e22dSNithin Dabilpuram 	if (qconf->nb_rx_queue == 0) {
16300d76e22dSNithin Dabilpuram 		RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n",
16310d76e22dSNithin Dabilpuram 			lcore_id);
16320d76e22dSNithin Dabilpuram 		return;
16330d76e22dSNithin Dabilpuram 	}
16340d76e22dSNithin Dabilpuram 
16350d76e22dSNithin Dabilpuram 	RTE_LOG(INFO, IPSEC, "entering main loop on lcore %u\n", lcore_id);
16360d76e22dSNithin Dabilpuram 
16370d76e22dSNithin Dabilpuram 	for (i = 0; i < qconf->nb_rx_queue; i++) {
16380d76e22dSNithin Dabilpuram 		portid = rxql[i].port_id;
16390d76e22dSNithin Dabilpuram 		queueid = rxql[i].queue_id;
16400d76e22dSNithin Dabilpuram 		RTE_LOG(INFO, IPSEC,
1641b23c5bd7SSivaprasad Tummala 			" -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n",
16420d76e22dSNithin Dabilpuram 			lcore_id, portid, queueid);
16430d76e22dSNithin Dabilpuram 	}
16440d76e22dSNithin Dabilpuram 
1645d8d51d4fSRahul Bhansali 	ipsec_ip_reassembly_dyn_offset_get();
1646d8d51d4fSRahul Bhansali 
16470d76e22dSNithin Dabilpuram 	while (!force_quit) {
16480d76e22dSNithin Dabilpuram 		cur_tsc = rte_rdtsc();
16490d76e22dSNithin Dabilpuram 
16500d76e22dSNithin Dabilpuram 		/* TX queue buffer drain */
16510d76e22dSNithin Dabilpuram 		diff_tsc = cur_tsc - prev_tsc;
16520d76e22dSNithin Dabilpuram 
16530d76e22dSNithin Dabilpuram 		if (unlikely(diff_tsc > drain_tsc)) {
16540d76e22dSNithin Dabilpuram 			drain_tx_buffers(qconf);
16550d76e22dSNithin Dabilpuram 			prev_tsc = cur_tsc;
16560d76e22dSNithin Dabilpuram 		}
16570d76e22dSNithin Dabilpuram 
16580d76e22dSNithin Dabilpuram 		for (i = 0; i < qconf->nb_rx_queue; ++i) {
16590d76e22dSNithin Dabilpuram 			/* Read packets from RX queues */
16600d76e22dSNithin Dabilpuram 			portid = rxql[i].port_id;
16610d76e22dSNithin Dabilpuram 			queueid = rxql[i].queue_id;
16620d76e22dSNithin Dabilpuram 			nb_rx = rte_eth_rx_burst(portid, queueid,
16630d76e22dSNithin Dabilpuram 					pkts, MAX_PKT_BURST);
16640d76e22dSNithin Dabilpuram 
16650d76e22dSNithin Dabilpuram 			if (nb_rx <= 0)
16660d76e22dSNithin Dabilpuram 				continue;
16670d76e22dSNithin Dabilpuram 
16680d76e22dSNithin Dabilpuram 			core_stats_update_rx(nb_rx);
16690d76e22dSNithin Dabilpuram 
16700d76e22dSNithin Dabilpuram 			prepare_traffic(rxql[i].sec_ctx, pkts, &trf, nb_rx);
16710d76e22dSNithin Dabilpuram 
16720d76e22dSNithin Dabilpuram 			/* Drop any IPsec traffic */
16730d76e22dSNithin Dabilpuram 			free_pkts(trf.ipsec.pkts, trf.ipsec.num);
16740d76e22dSNithin Dabilpuram 
16750d76e22dSNithin Dabilpuram 			if (is_unprotected_port(portid)) {
16760d76e22dSNithin Dabilpuram 				inbound_sp_sa(sp4_in, sa_in, &trf.ip4,
16770d76e22dSNithin Dabilpuram 					      trf.ip4.num,
16780d76e22dSNithin Dabilpuram 					      &stats->inbound.spd4);
16790d76e22dSNithin Dabilpuram 
16800d76e22dSNithin Dabilpuram 				inbound_sp_sa(sp6_in, sa_in, &trf.ip6,
16810d76e22dSNithin Dabilpuram 					      trf.ip6.num,
16820d76e22dSNithin Dabilpuram 					      &stats->inbound.spd6);
16830d76e22dSNithin Dabilpuram 
16840d76e22dSNithin Dabilpuram 				v4 = trf.ip4.pkts;
16850d76e22dSNithin Dabilpuram 				v4_num = trf.ip4.num;
16860d76e22dSNithin Dabilpuram 				v6 = trf.ip6.pkts;
16870d76e22dSNithin Dabilpuram 				v6_num = trf.ip6.num;
16880d76e22dSNithin Dabilpuram 			} else {
16890d76e22dSNithin Dabilpuram 				ip4.num = 0;
16900d76e22dSNithin Dabilpuram 				ip6.num = 0;
16910d76e22dSNithin Dabilpuram 
16920d76e22dSNithin Dabilpuram 				outb_inl_pro_spd_process(sp4_out, sa_out,
16930d76e22dSNithin Dabilpuram 							 &trf.ip4, &ip4, &ip6,
16940d76e22dSNithin Dabilpuram 							 true,
16950d76e22dSNithin Dabilpuram 							 &stats->outbound.spd4);
16960d76e22dSNithin Dabilpuram 
16970d76e22dSNithin Dabilpuram 				outb_inl_pro_spd_process(sp6_out, sa_out,
16980d76e22dSNithin Dabilpuram 							 &trf.ip6, &ip6, &ip4,
16990d76e22dSNithin Dabilpuram 							 false,
17000d76e22dSNithin Dabilpuram 							 &stats->outbound.spd6);
17010d76e22dSNithin Dabilpuram 				v4 = ip4.pkts;
17020d76e22dSNithin Dabilpuram 				v4_num = ip4.num;
17030d76e22dSNithin Dabilpuram 				v6 = ip6.pkts;
17040d76e22dSNithin Dabilpuram 				v6_num = ip6.num;
17050d76e22dSNithin Dabilpuram 			}
17060d76e22dSNithin Dabilpuram 
17076eb3ba03SRahul Bhansali #if defined __ARM_NEON
17086eb3ba03SRahul Bhansali 			route4_pkts_neon(rt4_ctx, v4, v4_num, 0, false);
17096eb3ba03SRahul Bhansali 			route6_pkts_neon(rt6_ctx, v6, v6_num);
17106eb3ba03SRahul Bhansali #else
17110d76e22dSNithin Dabilpuram 			route4_pkts(rt4_ctx, v4, v4_num, 0, false);
17120d76e22dSNithin Dabilpuram 			route6_pkts(rt6_ctx, v6, v6_num);
17136eb3ba03SRahul Bhansali #endif
17140d76e22dSNithin Dabilpuram 		}
17150d76e22dSNithin Dabilpuram 	}
17160d76e22dSNithin Dabilpuram }
17170d76e22dSNithin Dabilpuram 
17180d76e22dSNithin Dabilpuram /* Poll mode worker when all SA's are of type inline protocol
17190d76e22dSNithin Dabilpuram  * and single sa mode is enabled.
17200d76e22dSNithin Dabilpuram  */
17210d76e22dSNithin Dabilpuram void
17220d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_inl_pr_ss(void)
17230d76e22dSNithin Dabilpuram {
17240d76e22dSNithin Dabilpuram 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
17250d76e22dSNithin Dabilpuram 			/ US_PER_S * BURST_TX_DRAIN_US;
17260d76e22dSNithin Dabilpuram 	uint16_t sa_out_portid = 0, sa_out_proto = 0;
17270d76e22dSNithin Dabilpuram 	struct rte_mbuf *pkts[MAX_PKT_BURST], *pkt;
17280d76e22dSNithin Dabilpuram 	uint64_t prev_tsc, diff_tsc, cur_tsc;
17290d76e22dSNithin Dabilpuram 	struct rte_ipsec_session *ips = NULL;
17300d76e22dSNithin Dabilpuram 	struct lcore_rx_queue *rxql;
17310d76e22dSNithin Dabilpuram 	struct ipsec_sa *sa = NULL;
17320d76e22dSNithin Dabilpuram 	struct lcore_conf *qconf;
17330d76e22dSNithin Dabilpuram 	struct sa_ctx *sa_out;
17340d76e22dSNithin Dabilpuram 	uint32_t i, nb_rx, j;
17350d76e22dSNithin Dabilpuram 	int32_t socket_id;
17360d76e22dSNithin Dabilpuram 	uint32_t lcore_id;
1737b23c5bd7SSivaprasad Tummala 	uint16_t portid, queueid;
17380d76e22dSNithin Dabilpuram 
17390d76e22dSNithin Dabilpuram 	prev_tsc = 0;
17400d76e22dSNithin Dabilpuram 	lcore_id = rte_lcore_id();
17410d76e22dSNithin Dabilpuram 	qconf = &lcore_conf[lcore_id];
17420d76e22dSNithin Dabilpuram 	rxql = qconf->rx_queue_list;
17430d76e22dSNithin Dabilpuram 	socket_id = rte_lcore_to_socket_id(lcore_id);
17440d76e22dSNithin Dabilpuram 
17450d76e22dSNithin Dabilpuram 	/* Get SA info */
17460d76e22dSNithin Dabilpuram 	sa_out = socket_ctx[socket_id].sa_out;
17470d76e22dSNithin Dabilpuram 	if (sa_out && single_sa_idx < sa_out->nb_sa) {
17480d76e22dSNithin Dabilpuram 		sa = &sa_out->sa[single_sa_idx];
17490d76e22dSNithin Dabilpuram 		ips = ipsec_get_primary_session(sa);
17500d76e22dSNithin Dabilpuram 		sa_out_portid = sa->portid;
17510d76e22dSNithin Dabilpuram 		if (sa->flags & IP6_TUNNEL)
17520d76e22dSNithin Dabilpuram 			sa_out_proto = IPPROTO_IPV6;
17530d76e22dSNithin Dabilpuram 		else
17540d76e22dSNithin Dabilpuram 			sa_out_proto = IPPROTO_IP;
17550d76e22dSNithin Dabilpuram 	}
17560d76e22dSNithin Dabilpuram 
17570d76e22dSNithin Dabilpuram 	qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;
17580d76e22dSNithin Dabilpuram 
17590d76e22dSNithin Dabilpuram 	if (qconf->nb_rx_queue == 0) {
17600d76e22dSNithin Dabilpuram 		RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n",
17610d76e22dSNithin Dabilpuram 			lcore_id);
17620d76e22dSNithin Dabilpuram 		return;
17630d76e22dSNithin Dabilpuram 	}
17640d76e22dSNithin Dabilpuram 
17650d76e22dSNithin Dabilpuram 	RTE_LOG(INFO, IPSEC, "entering main loop on lcore %u\n", lcore_id);
17660d76e22dSNithin Dabilpuram 
17670d76e22dSNithin Dabilpuram 	for (i = 0; i < qconf->nb_rx_queue; i++) {
17680d76e22dSNithin Dabilpuram 		portid = rxql[i].port_id;
17690d76e22dSNithin Dabilpuram 		queueid = rxql[i].queue_id;
17700d76e22dSNithin Dabilpuram 		RTE_LOG(INFO, IPSEC,
1771b23c5bd7SSivaprasad Tummala 			" -- lcoreid=%u portid=%u rxqueueid=%" PRIu16 "\n",
17720d76e22dSNithin Dabilpuram 			lcore_id, portid, queueid);
17730d76e22dSNithin Dabilpuram 	}
17740d76e22dSNithin Dabilpuram 
17750d76e22dSNithin Dabilpuram 	while (!force_quit) {
17760d76e22dSNithin Dabilpuram 		cur_tsc = rte_rdtsc();
17770d76e22dSNithin Dabilpuram 
17780d76e22dSNithin Dabilpuram 		/* TX queue buffer drain */
17790d76e22dSNithin Dabilpuram 		diff_tsc = cur_tsc - prev_tsc;
17800d76e22dSNithin Dabilpuram 
17810d76e22dSNithin Dabilpuram 		if (unlikely(diff_tsc > drain_tsc)) {
17820d76e22dSNithin Dabilpuram 			drain_tx_buffers(qconf);
17830d76e22dSNithin Dabilpuram 			prev_tsc = cur_tsc;
17840d76e22dSNithin Dabilpuram 		}
17850d76e22dSNithin Dabilpuram 
17860d76e22dSNithin Dabilpuram 		for (i = 0; i < qconf->nb_rx_queue; ++i) {
17870d76e22dSNithin Dabilpuram 			/* Read packets from RX queues */
17880d76e22dSNithin Dabilpuram 			portid = rxql[i].port_id;
17890d76e22dSNithin Dabilpuram 			queueid = rxql[i].queue_id;
17900d76e22dSNithin Dabilpuram 			nb_rx = rte_eth_rx_burst(portid, queueid,
17910d76e22dSNithin Dabilpuram 						 pkts, MAX_PKT_BURST);
17920d76e22dSNithin Dabilpuram 
17930d76e22dSNithin Dabilpuram 			if (nb_rx <= 0)
17940d76e22dSNithin Dabilpuram 				continue;
17950d76e22dSNithin Dabilpuram 
17960d76e22dSNithin Dabilpuram 			core_stats_update_rx(nb_rx);
17970d76e22dSNithin Dabilpuram 
17980d76e22dSNithin Dabilpuram 			if (is_unprotected_port(portid)) {
17990d76e22dSNithin Dabilpuram 				/* Nothing much to do for inbound inline
18000d76e22dSNithin Dabilpuram 				 * decrypted traffic.
18010d76e22dSNithin Dabilpuram 				 */
18020d76e22dSNithin Dabilpuram 				for (j = 0; j < nb_rx; j++) {
18030d76e22dSNithin Dabilpuram 					uint32_t ptype, proto;
18040d76e22dSNithin Dabilpuram 
18050d76e22dSNithin Dabilpuram 					pkt = pkts[j];
18060d76e22dSNithin Dabilpuram 					ptype = pkt->packet_type &
18070d76e22dSNithin Dabilpuram 						RTE_PTYPE_L3_MASK;
18080d76e22dSNithin Dabilpuram 					if (ptype == RTE_PTYPE_L3_IPV4)
18090d76e22dSNithin Dabilpuram 						proto = IPPROTO_IP;
18100d76e22dSNithin Dabilpuram 					else
18110d76e22dSNithin Dabilpuram 						proto = IPPROTO_IPV6;
18120d76e22dSNithin Dabilpuram 
18130d76e22dSNithin Dabilpuram 					send_single_packet(pkt, portid, proto);
18140d76e22dSNithin Dabilpuram 				}
18150d76e22dSNithin Dabilpuram 
18160d76e22dSNithin Dabilpuram 				continue;
18170d76e22dSNithin Dabilpuram 			}
18180d76e22dSNithin Dabilpuram 
18190d76e22dSNithin Dabilpuram 			/* Free packets if there are no outbound sessions */
18200d76e22dSNithin Dabilpuram 			if (unlikely(!ips)) {
18210d76e22dSNithin Dabilpuram 				rte_pktmbuf_free_bulk(pkts, nb_rx);
18220d76e22dSNithin Dabilpuram 				continue;
18230d76e22dSNithin Dabilpuram 			}
18240d76e22dSNithin Dabilpuram 
18250d76e22dSNithin Dabilpuram 			rte_ipsec_pkt_process(ips, pkts, nb_rx);
18260d76e22dSNithin Dabilpuram 
18270d76e22dSNithin Dabilpuram 			/* Send pkts out */
18280d76e22dSNithin Dabilpuram 			for (j = 0; j < nb_rx; j++) {
18290d76e22dSNithin Dabilpuram 				pkt = pkts[j];
18300d76e22dSNithin Dabilpuram 
18310d76e22dSNithin Dabilpuram 				pkt->l2_len = RTE_ETHER_HDR_LEN;
18320d76e22dSNithin Dabilpuram 				send_single_packet(pkt, sa_out_portid,
18330d76e22dSNithin Dabilpuram 						   sa_out_proto);
18340d76e22dSNithin Dabilpuram 			}
18350d76e22dSNithin Dabilpuram 		}
18360d76e22dSNithin Dabilpuram 	}
18370d76e22dSNithin Dabilpuram }
18380d76e22dSNithin Dabilpuram 
18390d76e22dSNithin Dabilpuram static void
18400d76e22dSNithin Dabilpuram ipsec_poll_mode_wrkr_launch(void)
18410d76e22dSNithin Dabilpuram {
18420d76e22dSNithin Dabilpuram 	static ipsec_worker_fn_t poll_mode_wrkrs[MAX_F] = {
18430d76e22dSNithin Dabilpuram 		[INL_PR_F]        = ipsec_poll_mode_wrkr_inl_pr,
18440d76e22dSNithin Dabilpuram 		[INL_PR_F | SS_F] = ipsec_poll_mode_wrkr_inl_pr_ss,
18450d76e22dSNithin Dabilpuram 	};
18460d76e22dSNithin Dabilpuram 	ipsec_worker_fn_t fn;
18470d76e22dSNithin Dabilpuram 
18480d76e22dSNithin Dabilpuram 	if (!app_sa_prm.enable) {
18490d76e22dSNithin Dabilpuram 		fn = ipsec_poll_mode_worker;
18500d76e22dSNithin Dabilpuram 	} else {
18510d76e22dSNithin Dabilpuram 		fn = poll_mode_wrkrs[wrkr_flags];
18520d76e22dSNithin Dabilpuram 
18530d76e22dSNithin Dabilpuram 		/* Always default to all mode worker */
18540d76e22dSNithin Dabilpuram 		if (!fn)
18550d76e22dSNithin Dabilpuram 			fn = ipsec_poll_mode_worker;
18560d76e22dSNithin Dabilpuram 	}
18570d76e22dSNithin Dabilpuram 
18580d76e22dSNithin Dabilpuram 	/* Launch worker */
18590d76e22dSNithin Dabilpuram 	(*fn)();
18600d76e22dSNithin Dabilpuram }
18610d76e22dSNithin Dabilpuram 
18624965dda0SLukasz Bartosik int ipsec_launch_one_lcore(void *args)
18634965dda0SLukasz Bartosik {
18644965dda0SLukasz Bartosik 	struct eh_conf *conf;
18654965dda0SLukasz Bartosik 
18664965dda0SLukasz Bartosik 	conf = (struct eh_conf *)args;
18674965dda0SLukasz Bartosik 
18684965dda0SLukasz Bartosik 	if (conf->mode == EH_PKT_TRANSFER_MODE_POLL) {
18694965dda0SLukasz Bartosik 		/* Run in poll mode */
18700d76e22dSNithin Dabilpuram 		ipsec_poll_mode_wrkr_launch();
18714965dda0SLukasz Bartosik 	} else if (conf->mode == EH_PKT_TRANSFER_MODE_EVENT) {
18724965dda0SLukasz Bartosik 		/* Run in event mode */
18734965dda0SLukasz Bartosik 		ipsec_eventmode_worker(conf);
18744965dda0SLukasz Bartosik 	}
18754965dda0SLukasz Bartosik 	return 0;
18764965dda0SLukasz Bartosik }
1877