xref: /dpdk/examples/ipsec-secgw/sa.c (revision 9ac91e2f7339e66658ef55b756a06b328e336fde)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
25139d5d9SMarcin Smoczynski  * Copyright(c) 2016-2020 Intel Corporation
3d299106eSSergio Gonzalez Monroy  */
4d299106eSSergio Gonzalez Monroy 
5d299106eSSergio Gonzalez Monroy /*
6d299106eSSergio Gonzalez Monroy  * Security Associations
7d299106eSSergio Gonzalez Monroy  */
872b452c5SDmitry Kozlyuk #include <stdlib.h>
955d4c775SDaniel Mrzyglod #include <sys/types.h>
1055d4c775SDaniel Mrzyglod #include <netinet/in.h>
11d299106eSSergio Gonzalez Monroy #include <netinet/ip.h>
12906257e9SSergio Gonzalez Monroy #include <netinet/ip6.h>
13d299106eSSergio Gonzalez Monroy 
14d299106eSSergio Gonzalez Monroy #include <rte_memzone.h>
15d299106eSSergio Gonzalez Monroy #include <rte_crypto.h>
16ec17993aSAkhil Goyal #include <rte_security.h>
17d299106eSSergio Gonzalez Monroy #include <rte_cryptodev.h>
18d299106eSSergio Gonzalez Monroy #include <rte_byteorder.h>
19d299106eSSergio Gonzalez Monroy #include <rte_errno.h>
20906257e9SSergio Gonzalez Monroy #include <rte_ip.h>
219ae86b4cSRadu Nicolau #include <rte_udp.h>
2250d75caeSSergio Gonzalez Monroy #include <rte_random.h>
23ec17993aSAkhil Goyal #include <rte_ethdev.h>
245a032a71SKonstantin Ananyev #include <rte_malloc.h>
25d299106eSSergio Gonzalez Monroy 
26d299106eSSergio Gonzalez Monroy #include "ipsec.h"
27d299106eSSergio Gonzalez Monroy #include "esp.h"
280d547ed0SFan Zhang #include "parser.h"
29df3e1d94SVladimir Medvedkin #include "sad.h"
30d299106eSSergio Gonzalez Monroy 
31ec17993aSAkhil Goyal #define IPDEFTTL 64
32ec17993aSAkhil Goyal 
33b1a3ac78SMariusz Drost #define IP4_FULL_MASK (sizeof(((struct ip_addr *)NULL)->ip.ip4) * CHAR_BIT)
34b1a3ac78SMariusz Drost 
35*9ac91e2fSRobin Jarry #define IP6_FULL_MASK RTE_IPV6_MAX_DEPTH
36b1a3ac78SMariusz Drost 
37daa02b5cSOlivier Matz #define MBUF_NO_SEC_OFFLOAD(m) ((m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) == 0)
38ba66534fSMarcin Smoczynski 
390d547ed0SFan Zhang struct supported_cipher_algo {
400d547ed0SFan Zhang 	const char *keyword;
410d547ed0SFan Zhang 	enum rte_crypto_cipher_algorithm algo;
420d547ed0SFan Zhang 	uint16_t iv_len;
430d547ed0SFan Zhang 	uint16_t block_size;
440d547ed0SFan Zhang 	uint16_t key_len;
450d547ed0SFan Zhang };
460d547ed0SFan Zhang 
470d547ed0SFan Zhang struct supported_auth_algo {
480d547ed0SFan Zhang 	const char *keyword;
490d547ed0SFan Zhang 	enum rte_crypto_auth_algorithm algo;
509413c390SRadu Nicolau 	uint16_t iv_len;
510d547ed0SFan Zhang 	uint16_t digest_len;
520d547ed0SFan Zhang 	uint16_t key_len;
53a9121c40SSergio Gonzalez Monroy 	uint8_t key_not_req;
540d547ed0SFan Zhang };
550d547ed0SFan Zhang 
56501e9c22SPablo de Lara struct supported_aead_algo {
57501e9c22SPablo de Lara 	const char *keyword;
58501e9c22SPablo de Lara 	enum rte_crypto_aead_algorithm algo;
59501e9c22SPablo de Lara 	uint16_t iv_len;
60501e9c22SPablo de Lara 	uint16_t block_size;
61501e9c22SPablo de Lara 	uint16_t digest_len;
62501e9c22SPablo de Lara 	uint16_t key_len;
63501e9c22SPablo de Lara 	uint8_t aad_len;
64501e9c22SPablo de Lara };
65501e9c22SPablo de Lara 
66501e9c22SPablo de Lara 
670d547ed0SFan Zhang const struct supported_cipher_algo cipher_algos[] = {
68c64278c0SSergio Gonzalez Monroy 	{
690d547ed0SFan Zhang 		.keyword = "null",
700d547ed0SFan Zhang 		.algo = RTE_CRYPTO_CIPHER_NULL,
71c64278c0SSergio Gonzalez Monroy 		.iv_len = 0,
72c64278c0SSergio Gonzalez Monroy 		.block_size = 4,
730d547ed0SFan Zhang 		.key_len = 0
74906257e9SSergio Gonzalez Monroy 	},
75906257e9SSergio Gonzalez Monroy 	{
760d547ed0SFan Zhang 		.keyword = "aes-128-cbc",
770d547ed0SFan Zhang 		.algo = RTE_CRYPTO_CIPHER_AES_CBC,
780d547ed0SFan Zhang 		.iv_len = 16,
790d547ed0SFan Zhang 		.block_size = 16,
800d547ed0SFan Zhang 		.key_len = 16
81a9121c40SSergio Gonzalez Monroy 	},
82a9121c40SSergio Gonzalez Monroy 	{
83a8af994bSAnoob Joseph 		.keyword = "aes-192-cbc",
84a8af994bSAnoob Joseph 		.algo = RTE_CRYPTO_CIPHER_AES_CBC,
85a8af994bSAnoob Joseph 		.iv_len = 16,
86a8af994bSAnoob Joseph 		.block_size = 16,
87a8af994bSAnoob Joseph 		.key_len = 24
88a8af994bSAnoob Joseph 	},
89a8af994bSAnoob Joseph 	{
90fa908884SAnoob Joseph 		.keyword = "aes-256-cbc",
91fa908884SAnoob Joseph 		.algo = RTE_CRYPTO_CIPHER_AES_CBC,
92fa908884SAnoob Joseph 		.iv_len = 16,
93fa908884SAnoob Joseph 		.block_size = 16,
94fa908884SAnoob Joseph 		.key_len = 32
95fa908884SAnoob Joseph 	},
96fa908884SAnoob Joseph 	{
974470c22dSSergio Gonzalez Monroy 		.keyword = "aes-128-ctr",
984470c22dSSergio Gonzalez Monroy 		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
9935a0dcabSTejasree Kondoj 		/* Per packet IV length */
10035a0dcabSTejasree Kondoj 		.iv_len = 8,
1018d9a2225SFan Zhang 		.block_size = 4,
10250d75caeSSergio Gonzalez Monroy 		.key_len = 20
1031bc489caSHemant Agrawal 	},
1041bc489caSHemant Agrawal 	{
1059413c390SRadu Nicolau 		.keyword = "aes-192-ctr",
1069413c390SRadu Nicolau 		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
1079413c390SRadu Nicolau 		.iv_len = 16,
1089413c390SRadu Nicolau 		.block_size = 16,
1099413c390SRadu Nicolau 		.key_len = 28
1109413c390SRadu Nicolau 	},
1119413c390SRadu Nicolau 	{
1129413c390SRadu Nicolau 		.keyword = "aes-256-ctr",
1139413c390SRadu Nicolau 		.algo = RTE_CRYPTO_CIPHER_AES_CTR,
1149413c390SRadu Nicolau 		.iv_len = 16,
1159413c390SRadu Nicolau 		.block_size = 16,
1169413c390SRadu Nicolau 		.key_len = 36
1179413c390SRadu Nicolau 	},
1189413c390SRadu Nicolau 	{
1191bc489caSHemant Agrawal 		.keyword = "3des-cbc",
1201bc489caSHemant Agrawal 		.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
1211bc489caSHemant Agrawal 		.iv_len = 8,
1221bc489caSHemant Agrawal 		.block_size = 8,
1231bc489caSHemant Agrawal 		.key_len = 24
124923b5f27SGagandeep Singh 	},
125923b5f27SGagandeep Singh 	{
126923b5f27SGagandeep Singh 		.keyword = "des-cbc",
127923b5f27SGagandeep Singh 		.algo = RTE_CRYPTO_CIPHER_DES_CBC,
128923b5f27SGagandeep Singh 		.iv_len = 8,
129923b5f27SGagandeep Singh 		.block_size = 8,
130923b5f27SGagandeep Singh 		.key_len = 8
1310d547ed0SFan Zhang 	}
1320d547ed0SFan Zhang };
1330d547ed0SFan Zhang 
1340d547ed0SFan Zhang const struct supported_auth_algo auth_algos[] = {
1350d547ed0SFan Zhang 	{
1360d547ed0SFan Zhang 		.keyword = "null",
1370d547ed0SFan Zhang 		.algo = RTE_CRYPTO_AUTH_NULL,
138906257e9SSergio Gonzalez Monroy 		.digest_len = 0,
139a9121c40SSergio Gonzalez Monroy 		.key_len = 0,
140a9121c40SSergio Gonzalez Monroy 		.key_not_req = 1
141906257e9SSergio Gonzalez Monroy 	},
142906257e9SSergio Gonzalez Monroy 	{
1430d547ed0SFan Zhang 		.keyword = "sha1-hmac",
1440d547ed0SFan Zhang 		.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
145906257e9SSergio Gonzalez Monroy 		.digest_len = 12,
1460d547ed0SFan Zhang 		.key_len = 20
147a9121c40SSergio Gonzalez Monroy 	},
148a9121c40SSergio Gonzalez Monroy 	{
149b5350285SZbigniew Bodek 		.keyword = "sha256-hmac",
150b5350285SZbigniew Bodek 		.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
1512fcf3f70SVakul Garg 		.digest_len = 16,
152b5350285SZbigniew Bodek 		.key_len = 32
1539413c390SRadu Nicolau 	},
1549413c390SRadu Nicolau 	{
1559413c390SRadu Nicolau 		.keyword = "sha384-hmac",
1569413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
1579413c390SRadu Nicolau 		.digest_len = 24,
1589413c390SRadu Nicolau 		.key_len = 48
1599413c390SRadu Nicolau 	},
1609413c390SRadu Nicolau 	{
1619413c390SRadu Nicolau 		.keyword = "sha512-hmac",
1629413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
1639413c390SRadu Nicolau 		.digest_len = 32,
1649413c390SRadu Nicolau 		.key_len = 64
1659413c390SRadu Nicolau 	},
1669413c390SRadu Nicolau 	{
1679413c390SRadu Nicolau 		.keyword = "aes-gmac",
1689413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AUTH_AES_GMAC,
1699413c390SRadu Nicolau 		.iv_len = 8,
1709413c390SRadu Nicolau 		.digest_len = 16,
1719413c390SRadu Nicolau 		.key_len = 20
1729413c390SRadu Nicolau 	},
1739413c390SRadu Nicolau 	{
1749413c390SRadu Nicolau 		.keyword = "aes-xcbc-mac-96",
1759413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
1769413c390SRadu Nicolau 		.digest_len = 12,
1779413c390SRadu Nicolau 		.key_len = 16
17866085224SPablo de Lara 	}
179d299106eSSergio Gonzalez Monroy };
180d299106eSSergio Gonzalez Monroy 
181b79e4c00SPablo de Lara const struct supported_aead_algo aead_algos[] = {
182b79e4c00SPablo de Lara 	{
183b79e4c00SPablo de Lara 		.keyword = "aes-128-gcm",
184b79e4c00SPablo de Lara 		.algo = RTE_CRYPTO_AEAD_AES_GCM,
185b79e4c00SPablo de Lara 		.iv_len = 8,
186b79e4c00SPablo de Lara 		.block_size = 4,
187b79e4c00SPablo de Lara 		.key_len = 20,
188b79e4c00SPablo de Lara 		.digest_len = 16,
189b79e4c00SPablo de Lara 		.aad_len = 8,
190a8af994bSAnoob Joseph 	},
191a8af994bSAnoob Joseph 	{
192a8af994bSAnoob Joseph 		.keyword = "aes-192-gcm",
193a8af994bSAnoob Joseph 		.algo = RTE_CRYPTO_AEAD_AES_GCM,
194a8af994bSAnoob Joseph 		.iv_len = 8,
195a8af994bSAnoob Joseph 		.block_size = 4,
196a8af994bSAnoob Joseph 		.key_len = 28,
197a8af994bSAnoob Joseph 		.digest_len = 16,
198a8af994bSAnoob Joseph 		.aad_len = 8,
199a8af994bSAnoob Joseph 	},
200a8af994bSAnoob Joseph 	{
201a8af994bSAnoob Joseph 		.keyword = "aes-256-gcm",
202a8af994bSAnoob Joseph 		.algo = RTE_CRYPTO_AEAD_AES_GCM,
203a8af994bSAnoob Joseph 		.iv_len = 8,
204a8af994bSAnoob Joseph 		.block_size = 4,
205a8af994bSAnoob Joseph 		.key_len = 36,
206a8af994bSAnoob Joseph 		.digest_len = 16,
207a8af994bSAnoob Joseph 		.aad_len = 8,
2089413c390SRadu Nicolau 	},
2099413c390SRadu Nicolau 	{
2109413c390SRadu Nicolau 		.keyword = "aes-128-ccm",
2119413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AEAD_AES_CCM,
2129413c390SRadu Nicolau 		.iv_len = 8,
2139413c390SRadu Nicolau 		.block_size = 4,
2149413c390SRadu Nicolau 		.key_len = 20,
2159413c390SRadu Nicolau 		.digest_len = 16,
2169413c390SRadu Nicolau 		.aad_len = 8,
2179413c390SRadu Nicolau 	},
2189413c390SRadu Nicolau 	{
2199413c390SRadu Nicolau 		.keyword = "aes-192-ccm",
2209413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AEAD_AES_CCM,
2219413c390SRadu Nicolau 		.iv_len = 8,
2229413c390SRadu Nicolau 		.block_size = 4,
2239413c390SRadu Nicolau 		.key_len = 28,
2249413c390SRadu Nicolau 		.digest_len = 16,
2259413c390SRadu Nicolau 		.aad_len = 8,
2269413c390SRadu Nicolau 	},
2279413c390SRadu Nicolau 	{
2289413c390SRadu Nicolau 		.keyword = "aes-256-ccm",
2299413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AEAD_AES_CCM,
2309413c390SRadu Nicolau 		.iv_len = 8,
2319413c390SRadu Nicolau 		.block_size = 4,
2329413c390SRadu Nicolau 		.key_len = 36,
2339413c390SRadu Nicolau 		.digest_len = 16,
2349413c390SRadu Nicolau 		.aad_len = 8,
2359413c390SRadu Nicolau 	},
2369413c390SRadu Nicolau 	{
2379413c390SRadu Nicolau 		.keyword = "chacha20-poly1305",
2389413c390SRadu Nicolau 		.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
2399413c390SRadu Nicolau 		.iv_len = 12,
2409413c390SRadu Nicolau 		.block_size = 64,
2419413c390SRadu Nicolau 		.key_len = 36,
2429413c390SRadu Nicolau 		.digest_len = 16,
2439413c390SRadu Nicolau 		.aad_len = 8,
244b79e4c00SPablo de Lara 	}
245b79e4c00SPablo de Lara };
246501e9c22SPablo de Lara 
247e1143d7dSVladimir Medvedkin #define SA_INIT_NB	128
248e1143d7dSVladimir Medvedkin 
24904fa1906SVladimir Medvedkin static uint32_t nb_crypto_sessions;
25065e3a202SLukasz Bartosik struct ipsec_sa *sa_out;
25165e3a202SLukasz Bartosik uint32_t nb_sa_out;
252e1143d7dSVladimir Medvedkin static uint32_t sa_out_sz;
253df3e1d94SVladimir Medvedkin static struct ipsec_sa_cnt sa_out_cnt;
254d299106eSSergio Gonzalez Monroy 
25565e3a202SLukasz Bartosik struct ipsec_sa *sa_in;
25665e3a202SLukasz Bartosik uint32_t nb_sa_in;
257e1143d7dSVladimir Medvedkin static uint32_t sa_in_sz;
258df3e1d94SVladimir Medvedkin static struct ipsec_sa_cnt sa_in_cnt;
259d299106eSSergio Gonzalez Monroy 
2600d547ed0SFan Zhang static const struct supported_cipher_algo *
2610d547ed0SFan Zhang find_match_cipher_algo(const char *cipher_keyword)
2620d547ed0SFan Zhang {
2630d547ed0SFan Zhang 	size_t i;
264d299106eSSergio Gonzalez Monroy 
2650d547ed0SFan Zhang 	for (i = 0; i < RTE_DIM(cipher_algos); i++) {
2660d547ed0SFan Zhang 		const struct supported_cipher_algo *algo =
2670d547ed0SFan Zhang 			&cipher_algos[i];
268d299106eSSergio Gonzalez Monroy 
2690d547ed0SFan Zhang 		if (strcmp(cipher_keyword, algo->keyword) == 0)
2700d547ed0SFan Zhang 			return algo;
27166085224SPablo de Lara 	}
272d299106eSSergio Gonzalez Monroy 
2730d547ed0SFan Zhang 	return NULL;
27466085224SPablo de Lara }
2750d547ed0SFan Zhang 
2760d547ed0SFan Zhang static const struct supported_auth_algo *
2770d547ed0SFan Zhang find_match_auth_algo(const char *auth_keyword)
2780d547ed0SFan Zhang {
2790d547ed0SFan Zhang 	size_t i;
2800d547ed0SFan Zhang 
2810d547ed0SFan Zhang 	for (i = 0; i < RTE_DIM(auth_algos); i++) {
2820d547ed0SFan Zhang 		const struct supported_auth_algo *algo =
2830d547ed0SFan Zhang 			&auth_algos[i];
2840d547ed0SFan Zhang 
2850d547ed0SFan Zhang 		if (strcmp(auth_keyword, algo->keyword) == 0)
2860d547ed0SFan Zhang 			return algo;
2870d547ed0SFan Zhang 	}
2880d547ed0SFan Zhang 
2890d547ed0SFan Zhang 	return NULL;
2900d547ed0SFan Zhang }
2910d547ed0SFan Zhang 
292501e9c22SPablo de Lara static const struct supported_aead_algo *
293501e9c22SPablo de Lara find_match_aead_algo(const char *aead_keyword)
294501e9c22SPablo de Lara {
295501e9c22SPablo de Lara 	size_t i;
296501e9c22SPablo de Lara 
297501e9c22SPablo de Lara 	for (i = 0; i < RTE_DIM(aead_algos); i++) {
298501e9c22SPablo de Lara 		const struct supported_aead_algo *algo =
299501e9c22SPablo de Lara 			&aead_algos[i];
300501e9c22SPablo de Lara 
301501e9c22SPablo de Lara 		if (strcmp(aead_keyword, algo->keyword) == 0)
302501e9c22SPablo de Lara 			return algo;
303501e9c22SPablo de Lara 	}
304501e9c22SPablo de Lara 
305501e9c22SPablo de Lara 	return NULL;
306501e9c22SPablo de Lara }
307501e9c22SPablo de Lara 
3080d547ed0SFan Zhang /** parse_key_string
3090d547ed0SFan Zhang  *  parse x:x:x:x.... hex number key string into uint8_t *key
3100d547ed0SFan Zhang  *  return:
3110d547ed0SFan Zhang  *  > 0: number of bytes parsed
3120d547ed0SFan Zhang  *  0:   failed
3130d547ed0SFan Zhang  */
3140d547ed0SFan Zhang static uint32_t
3150d547ed0SFan Zhang parse_key_string(const char *key_str, uint8_t *key)
3160d547ed0SFan Zhang {
3170d547ed0SFan Zhang 	const char *pt_start = key_str, *pt_end = key_str;
3180d547ed0SFan Zhang 	uint32_t nb_bytes = 0;
3190d547ed0SFan Zhang 
3200d547ed0SFan Zhang 	while (pt_end != NULL) {
32163e8c07cSFan Zhang 		char sub_str[3] = {0};
32263e8c07cSFan Zhang 
3230d547ed0SFan Zhang 		pt_end = strchr(pt_start, ':');
3240d547ed0SFan Zhang 
32563e8c07cSFan Zhang 		if (pt_end == NULL) {
32663e8c07cSFan Zhang 			if (strlen(pt_start) > 2)
32763e8c07cSFan Zhang 				return 0;
32863e8c07cSFan Zhang 			strncpy(sub_str, pt_start, 2);
32963e8c07cSFan Zhang 		} else {
3300d547ed0SFan Zhang 			if (pt_end - pt_start > 2)
3310d547ed0SFan Zhang 				return 0;
3320d547ed0SFan Zhang 
3330d547ed0SFan Zhang 			strncpy(sub_str, pt_start, pt_end - pt_start);
3340d547ed0SFan Zhang 			pt_start = pt_end + 1;
3350d547ed0SFan Zhang 		}
3360d547ed0SFan Zhang 
3370d547ed0SFan Zhang 		key[nb_bytes++] = strtol(sub_str, NULL, 16);
3380d547ed0SFan Zhang 	}
3390d547ed0SFan Zhang 
3400d547ed0SFan Zhang 	return nb_bytes;
3410d547ed0SFan Zhang }
3420d547ed0SFan Zhang 
343e1143d7dSVladimir Medvedkin static int
344e1143d7dSVladimir Medvedkin extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
345e1143d7dSVladimir Medvedkin {
346e1143d7dSVladimir Medvedkin 	if (*sa_tbl == NULL) {
347e1143d7dSVladimir Medvedkin 		*sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa));
348e1143d7dSVladimir Medvedkin 		if (*sa_tbl == NULL)
349e1143d7dSVladimir Medvedkin 			return -1;
350e1143d7dSVladimir Medvedkin 		*cur_sz = SA_INIT_NB;
351e1143d7dSVladimir Medvedkin 		return 0;
352e1143d7dSVladimir Medvedkin 	}
353e1143d7dSVladimir Medvedkin 
354e1143d7dSVladimir Medvedkin 	if (cur_cnt >= *cur_sz) {
355e1143d7dSVladimir Medvedkin 		*sa_tbl = realloc(*sa_tbl,
356e1143d7dSVladimir Medvedkin 			*cur_sz * sizeof(struct ipsec_sa) * 2);
357e1143d7dSVladimir Medvedkin 		if (*sa_tbl == NULL)
358e1143d7dSVladimir Medvedkin 			return -1;
359e1143d7dSVladimir Medvedkin 		/* clean reallocated extra space */
360e1143d7dSVladimir Medvedkin 		memset(&(*sa_tbl)[*cur_sz], 0,
361e1143d7dSVladimir Medvedkin 			*cur_sz * sizeof(struct ipsec_sa));
362e1143d7dSVladimir Medvedkin 		*cur_sz *= 2;
363e1143d7dSVladimir Medvedkin 	}
364e1143d7dSVladimir Medvedkin 
365e1143d7dSVladimir Medvedkin 	return 0;
366e1143d7dSVladimir Medvedkin }
367e1143d7dSVladimir Medvedkin 
3680d547ed0SFan Zhang void
3690d547ed0SFan Zhang parse_sa_tokens(char **tokens, uint32_t n_tokens,
3700d547ed0SFan Zhang 	struct parse_status *status)
3710d547ed0SFan Zhang {
3720d547ed0SFan Zhang 	struct ipsec_sa *rule = NULL;
3734a67af84SMarcin Smoczynski 	struct rte_ipsec_session *ips;
3740d547ed0SFan Zhang 	uint32_t ti; /*token index*/
3750d547ed0SFan Zhang 	uint32_t *ri /*rule index*/;
376df3e1d94SVladimir Medvedkin 	struct ipsec_sa_cnt *sa_cnt;
3770d547ed0SFan Zhang 	uint32_t cipher_algo_p = 0;
3780d547ed0SFan Zhang 	uint32_t auth_algo_p = 0;
379501e9c22SPablo de Lara 	uint32_t aead_algo_p = 0;
3800d547ed0SFan Zhang 	uint32_t src_p = 0;
3810d547ed0SFan Zhang 	uint32_t dst_p = 0;
3820d547ed0SFan Zhang 	uint32_t mode_p = 0;
383ec17993aSAkhil Goyal 	uint32_t type_p = 0;
384ec17993aSAkhil Goyal 	uint32_t portid_p = 0;
385ba66534fSMarcin Smoczynski 	uint32_t fallback_p = 0;
3866738c0a9SPraveen Shetty 	int16_t status_p = 0;
3879a1cc8f1STejasree Kondoj 	uint16_t udp_encap_p = 0;
3880d547ed0SFan Zhang 
3890d547ed0SFan Zhang 	if (strcmp(tokens[0], "in") == 0) {
3900d547ed0SFan Zhang 		ri = &nb_sa_in;
391df3e1d94SVladimir Medvedkin 		sa_cnt = &sa_in_cnt;
392e1143d7dSVladimir Medvedkin 		if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0)
3930d547ed0SFan Zhang 			return;
3940d547ed0SFan Zhang 		rule = &sa_in[*ri];
395ba66534fSMarcin Smoczynski 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
3960d547ed0SFan Zhang 	} else {
3970d547ed0SFan Zhang 		ri = &nb_sa_out;
398df3e1d94SVladimir Medvedkin 		sa_cnt = &sa_out_cnt;
399e1143d7dSVladimir Medvedkin 		if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0)
4000d547ed0SFan Zhang 			return;
4010d547ed0SFan Zhang 		rule = &sa_out[*ri];
402ba66534fSMarcin Smoczynski 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
4030d547ed0SFan Zhang 	}
4040d547ed0SFan Zhang 
4050d547ed0SFan Zhang 	/* spi number */
4060d547ed0SFan Zhang 	APP_CHECK_TOKEN_IS_NUM(tokens, 1, status);
4070d547ed0SFan Zhang 	if (status->status < 0)
4080d547ed0SFan Zhang 		return;
4092a5106afSAkhil Goyal 	if (atoi(tokens[1]) == INVALID_SPI)
4102a5106afSAkhil Goyal 		return;
4113e7b7dd8SRadu Nicolau 	rule->flags = 0;
4120d547ed0SFan Zhang 	rule->spi = atoi(tokens[1]);
4136738c0a9SPraveen Shetty 	rule->portid = UINT16_MAX;
414ba66534fSMarcin Smoczynski 	ips = ipsec_get_primary_session(rule);
4150d547ed0SFan Zhang 
4160d547ed0SFan Zhang 	for (ti = 2; ti < n_tokens; ti++) {
4170d547ed0SFan Zhang 		if (strcmp(tokens[ti], "mode") == 0) {
4180d547ed0SFan Zhang 			APP_CHECK_PRESENCE(mode_p, tokens[ti], status);
4190d547ed0SFan Zhang 			if (status->status < 0)
4200d547ed0SFan Zhang 				return;
4210d547ed0SFan Zhang 
4220d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4230d547ed0SFan Zhang 			if (status->status < 0)
4240d547ed0SFan Zhang 				return;
4250d547ed0SFan Zhang 
426df3e1d94SVladimir Medvedkin 			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
427df3e1d94SVladimir Medvedkin 				sa_cnt->nb_v4++;
4283e7b7dd8SRadu Nicolau 				rule->flags |= IP4_TUNNEL;
429df3e1d94SVladimir Medvedkin 			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
430df3e1d94SVladimir Medvedkin 				sa_cnt->nb_v6++;
4313e7b7dd8SRadu Nicolau 				rule->flags |= IP6_TUNNEL;
432df3e1d94SVladimir Medvedkin 			} else if (strcmp(tokens[ti], "transport") == 0) {
433df3e1d94SVladimir Medvedkin 				sa_cnt->nb_v4++;
434df3e1d94SVladimir Medvedkin 				sa_cnt->nb_v6++;
4353e7b7dd8SRadu Nicolau 				rule->flags |= TRANSPORT;
436df3e1d94SVladimir Medvedkin 			} else {
4370d547ed0SFan Zhang 				APP_CHECK(0, status, "unrecognized "
4380d547ed0SFan Zhang 					"input \"%s\"", tokens[ti]);
4390d547ed0SFan Zhang 				return;
4400d547ed0SFan Zhang 			}
4410d547ed0SFan Zhang 
4420d547ed0SFan Zhang 			mode_p = 1;
4430d547ed0SFan Zhang 			continue;
4440d547ed0SFan Zhang 		}
4450d547ed0SFan Zhang 
4463e7b7dd8SRadu Nicolau 		if (strcmp(tokens[ti], "telemetry") == 0) {
4473e7b7dd8SRadu Nicolau 			rule->flags |= SA_TELEMETRY_ENABLE;
4483e7b7dd8SRadu Nicolau 			continue;
4493e7b7dd8SRadu Nicolau 		}
4503e7b7dd8SRadu Nicolau 
4510d547ed0SFan Zhang 		if (strcmp(tokens[ti], "cipher_algo") == 0) {
4520d547ed0SFan Zhang 			const struct supported_cipher_algo *algo;
4530d547ed0SFan Zhang 			uint32_t key_len;
4540d547ed0SFan Zhang 
4550d547ed0SFan Zhang 			APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti],
4560d547ed0SFan Zhang 				status);
4570d547ed0SFan Zhang 			if (status->status < 0)
4580d547ed0SFan Zhang 				return;
4590d547ed0SFan Zhang 
4600d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4610d547ed0SFan Zhang 			if (status->status < 0)
4620d547ed0SFan Zhang 				return;
4630d547ed0SFan Zhang 
4640d547ed0SFan Zhang 			algo = find_match_cipher_algo(tokens[ti]);
4650d547ed0SFan Zhang 
4660d547ed0SFan Zhang 			APP_CHECK(algo != NULL, status, "unrecognized "
4670d547ed0SFan Zhang 				"input \"%s\"", tokens[ti]);
4680d547ed0SFan Zhang 
46971d9e6fbSSavinay Dharmappa 			if (status->status < 0)
47071d9e6fbSSavinay Dharmappa 				return;
47171d9e6fbSSavinay Dharmappa 
4720d547ed0SFan Zhang 			rule->cipher_algo = algo->algo;
4730d547ed0SFan Zhang 			rule->block_size = algo->block_size;
4740d547ed0SFan Zhang 			rule->iv_len = algo->iv_len;
4750d547ed0SFan Zhang 			rule->cipher_key_len = algo->key_len;
4760d547ed0SFan Zhang 
477a9121c40SSergio Gonzalez Monroy 			/* for NULL algorithm, no cipher key required */
4780d547ed0SFan Zhang 			if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
4790d547ed0SFan Zhang 				cipher_algo_p = 1;
4800d547ed0SFan Zhang 				continue;
4810d547ed0SFan Zhang 			}
4820d547ed0SFan Zhang 
4830d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4840d547ed0SFan Zhang 			if (status->status < 0)
4850d547ed0SFan Zhang 				return;
4860d547ed0SFan Zhang 
4870d547ed0SFan Zhang 			APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0,
4880d547ed0SFan Zhang 				status, "unrecognized input \"%s\", "
4890d547ed0SFan Zhang 				"expect \"cipher_key\"", tokens[ti]);
4900d547ed0SFan Zhang 			if (status->status < 0)
4910d547ed0SFan Zhang 				return;
4920d547ed0SFan Zhang 
4930d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4940d547ed0SFan Zhang 			if (status->status < 0)
4950d547ed0SFan Zhang 				return;
4960d547ed0SFan Zhang 
4970d547ed0SFan Zhang 			key_len = parse_key_string(tokens[ti],
4980d547ed0SFan Zhang 				rule->cipher_key);
4990d547ed0SFan Zhang 			APP_CHECK(key_len == rule->cipher_key_len, status,
5000d547ed0SFan Zhang 				"unrecognized input \"%s\"", tokens[ti]);
5010d547ed0SFan Zhang 			if (status->status < 0)
5020d547ed0SFan Zhang 				return;
5030d547ed0SFan Zhang 
5041bc489caSHemant Agrawal 			if (algo->algo == RTE_CRYPTO_CIPHER_AES_CBC ||
5051bc489caSHemant Agrawal 				algo->algo == RTE_CRYPTO_CIPHER_3DES_CBC)
50650d75caeSSergio Gonzalez Monroy 				rule->salt = (uint32_t)rte_rand();
50750d75caeSSergio Gonzalez Monroy 
508b79e4c00SPablo de Lara 			if (algo->algo == RTE_CRYPTO_CIPHER_AES_CTR) {
50950d75caeSSergio Gonzalez Monroy 				key_len -= 4;
51050d75caeSSergio Gonzalez Monroy 				rule->cipher_key_len = key_len;
5117f9b2c92SVladimir Medvedkin 				memcpy(&rule->salt,
5127f9b2c92SVladimir Medvedkin 					&rule->cipher_key[key_len], 4);
51350d75caeSSergio Gonzalez Monroy 			}
51450d75caeSSergio Gonzalez Monroy 
5150d547ed0SFan Zhang 			cipher_algo_p = 1;
5160d547ed0SFan Zhang 			continue;
5170d547ed0SFan Zhang 		}
5180d547ed0SFan Zhang 
5190d547ed0SFan Zhang 		if (strcmp(tokens[ti], "auth_algo") == 0) {
5200d547ed0SFan Zhang 			const struct supported_auth_algo *algo;
5210d547ed0SFan Zhang 			uint32_t key_len;
5220d547ed0SFan Zhang 
5230d547ed0SFan Zhang 			APP_CHECK_PRESENCE(auth_algo_p, tokens[ti],
5240d547ed0SFan Zhang 				status);
5250d547ed0SFan Zhang 			if (status->status < 0)
5260d547ed0SFan Zhang 				return;
5270d547ed0SFan Zhang 
5280d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
5290d547ed0SFan Zhang 			if (status->status < 0)
5300d547ed0SFan Zhang 				return;
5310d547ed0SFan Zhang 
5320d547ed0SFan Zhang 			algo = find_match_auth_algo(tokens[ti]);
5330d547ed0SFan Zhang 			APP_CHECK(algo != NULL, status, "unrecognized "
5340d547ed0SFan Zhang 				"input \"%s\"", tokens[ti]);
5350d547ed0SFan Zhang 
53671d9e6fbSSavinay Dharmappa 			if (status->status < 0)
53771d9e6fbSSavinay Dharmappa 				return;
53871d9e6fbSSavinay Dharmappa 
5390d547ed0SFan Zhang 			rule->auth_algo = algo->algo;
5400d547ed0SFan Zhang 			rule->auth_key_len = algo->key_len;
5410d547ed0SFan Zhang 			rule->digest_len = algo->digest_len;
5420d547ed0SFan Zhang 
543a9121c40SSergio Gonzalez Monroy 			/* NULL algorithm and combined algos do not
544a9121c40SSergio Gonzalez Monroy 			 * require auth key
545a9121c40SSergio Gonzalez Monroy 			 */
546a9121c40SSergio Gonzalez Monroy 			if (algo->key_not_req) {
5470d547ed0SFan Zhang 				auth_algo_p = 1;
5480d547ed0SFan Zhang 				continue;
5490d547ed0SFan Zhang 			}
5500d547ed0SFan Zhang 
5510d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
5520d547ed0SFan Zhang 			if (status->status < 0)
5530d547ed0SFan Zhang 				return;
5540d547ed0SFan Zhang 
5550d547ed0SFan Zhang 			APP_CHECK(strcmp(tokens[ti], "auth_key") == 0,
5560d547ed0SFan Zhang 				status, "unrecognized input \"%s\", "
5570d547ed0SFan Zhang 				"expect \"auth_key\"", tokens[ti]);
5580d547ed0SFan Zhang 			if (status->status < 0)
5590d547ed0SFan Zhang 				return;
5600d547ed0SFan Zhang 
5610d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
5620d547ed0SFan Zhang 			if (status->status < 0)
5630d547ed0SFan Zhang 				return;
5640d547ed0SFan Zhang 
5650d547ed0SFan Zhang 			key_len = parse_key_string(tokens[ti],
5660d547ed0SFan Zhang 				rule->auth_key);
5670d547ed0SFan Zhang 			APP_CHECK(key_len == rule->auth_key_len, status,
5680d547ed0SFan Zhang 				"unrecognized input \"%s\"", tokens[ti]);
5690d547ed0SFan Zhang 			if (status->status < 0)
5700d547ed0SFan Zhang 				return;
5710d547ed0SFan Zhang 
5729413c390SRadu Nicolau 			if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) {
5739413c390SRadu Nicolau 				key_len -= 4;
5749413c390SRadu Nicolau 				rule->auth_key_len = key_len;
5759413c390SRadu Nicolau 				rule->iv_len = algo->iv_len;
5767f9b2c92SVladimir Medvedkin 				memcpy(&rule->salt,
5777f9b2c92SVladimir Medvedkin 					&rule->auth_key[key_len], 4);
5789413c390SRadu Nicolau 			}
5799413c390SRadu Nicolau 
5800d547ed0SFan Zhang 			auth_algo_p = 1;
5810d547ed0SFan Zhang 			continue;
5820d547ed0SFan Zhang 		}
5830d547ed0SFan Zhang 
584501e9c22SPablo de Lara 		if (strcmp(tokens[ti], "aead_algo") == 0) {
585501e9c22SPablo de Lara 			const struct supported_aead_algo *algo;
586501e9c22SPablo de Lara 			uint32_t key_len;
587501e9c22SPablo de Lara 
588501e9c22SPablo de Lara 			APP_CHECK_PRESENCE(aead_algo_p, tokens[ti],
589501e9c22SPablo de Lara 				status);
590501e9c22SPablo de Lara 			if (status->status < 0)
591501e9c22SPablo de Lara 				return;
592501e9c22SPablo de Lara 
593501e9c22SPablo de Lara 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
594501e9c22SPablo de Lara 			if (status->status < 0)
595501e9c22SPablo de Lara 				return;
596501e9c22SPablo de Lara 
597501e9c22SPablo de Lara 			algo = find_match_aead_algo(tokens[ti]);
598501e9c22SPablo de Lara 
599501e9c22SPablo de Lara 			APP_CHECK(algo != NULL, status, "unrecognized "
600501e9c22SPablo de Lara 				"input \"%s\"", tokens[ti]);
601501e9c22SPablo de Lara 
60271d9e6fbSSavinay Dharmappa 			if (status->status < 0)
60371d9e6fbSSavinay Dharmappa 				return;
60471d9e6fbSSavinay Dharmappa 
605501e9c22SPablo de Lara 			rule->aead_algo = algo->algo;
606501e9c22SPablo de Lara 			rule->cipher_key_len = algo->key_len;
607501e9c22SPablo de Lara 			rule->digest_len = algo->digest_len;
60840401260SAviad Yehezkel 			rule->aad_len = algo->aad_len;
609501e9c22SPablo de Lara 			rule->block_size = algo->block_size;
610501e9c22SPablo de Lara 			rule->iv_len = algo->iv_len;
611501e9c22SPablo de Lara 
612501e9c22SPablo de Lara 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
613501e9c22SPablo de Lara 			if (status->status < 0)
614501e9c22SPablo de Lara 				return;
615501e9c22SPablo de Lara 
616501e9c22SPablo de Lara 			APP_CHECK(strcmp(tokens[ti], "aead_key") == 0,
617501e9c22SPablo de Lara 				status, "unrecognized input \"%s\", "
618501e9c22SPablo de Lara 				"expect \"aead_key\"", tokens[ti]);
619501e9c22SPablo de Lara 			if (status->status < 0)
620501e9c22SPablo de Lara 				return;
621501e9c22SPablo de Lara 
622501e9c22SPablo de Lara 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
623501e9c22SPablo de Lara 			if (status->status < 0)
624501e9c22SPablo de Lara 				return;
625501e9c22SPablo de Lara 
626501e9c22SPablo de Lara 			key_len = parse_key_string(tokens[ti],
627501e9c22SPablo de Lara 				rule->cipher_key);
628501e9c22SPablo de Lara 			APP_CHECK(key_len == rule->cipher_key_len, status,
629501e9c22SPablo de Lara 				"unrecognized input \"%s\"", tokens[ti]);
630501e9c22SPablo de Lara 			if (status->status < 0)
631501e9c22SPablo de Lara 				return;
632501e9c22SPablo de Lara 
633501e9c22SPablo de Lara 			key_len -= 4;
634501e9c22SPablo de Lara 			rule->cipher_key_len = key_len;
6357f9b2c92SVladimir Medvedkin 			memcpy(&rule->salt,
6367f9b2c92SVladimir Medvedkin 				&rule->cipher_key[key_len], 4);
637501e9c22SPablo de Lara 
638501e9c22SPablo de Lara 			aead_algo_p = 1;
639501e9c22SPablo de Lara 			continue;
640501e9c22SPablo de Lara 		}
641501e9c22SPablo de Lara 
6420d547ed0SFan Zhang 		if (strcmp(tokens[ti], "src") == 0) {
6430d547ed0SFan Zhang 			APP_CHECK_PRESENCE(src_p, tokens[ti], status);
6440d547ed0SFan Zhang 			if (status->status < 0)
6450d547ed0SFan Zhang 				return;
6460d547ed0SFan Zhang 
6470d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
6480d547ed0SFan Zhang 			if (status->status < 0)
6490d547ed0SFan Zhang 				return;
6500d547ed0SFan Zhang 
651b1a3ac78SMariusz Drost 			if (IS_IP4_TUNNEL(rule->flags)) {
6520d547ed0SFan Zhang 				struct in_addr ip;
6530d547ed0SFan Zhang 
6540d547ed0SFan Zhang 				APP_CHECK(parse_ipv4_addr(tokens[ti],
6550d547ed0SFan Zhang 					&ip, NULL) == 0, status,
6560d547ed0SFan Zhang 					"unrecognized input \"%s\", "
6570d547ed0SFan Zhang 					"expect valid ipv4 addr",
6580d547ed0SFan Zhang 					tokens[ti]);
6590d547ed0SFan Zhang 				if (status->status < 0)
6600d547ed0SFan Zhang 					return;
6610d547ed0SFan Zhang 				rule->src.ip.ip4 = rte_bswap32(
6620d547ed0SFan Zhang 					(uint32_t)ip.s_addr);
663b1a3ac78SMariusz Drost 			} else if (IS_IP6_TUNNEL(rule->flags)) {
664*9ac91e2fSRobin Jarry 				struct rte_ipv6_addr ip;
6650d547ed0SFan Zhang 
6660d547ed0SFan Zhang 				APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
6670d547ed0SFan Zhang 					NULL) == 0, status,
6680d547ed0SFan Zhang 					"unrecognized input \"%s\", "
6690d547ed0SFan Zhang 					"expect valid ipv6 addr",
6700d547ed0SFan Zhang 					tokens[ti]);
6710d547ed0SFan Zhang 				if (status->status < 0)
6720d547ed0SFan Zhang 					return;
673*9ac91e2fSRobin Jarry 
674*9ac91e2fSRobin Jarry 				rule->src.ip.ip6 = ip;
675b1a3ac78SMariusz Drost 			} else if (IS_TRANSPORT(rule->flags)) {
6760d547ed0SFan Zhang 				APP_CHECK(0, status, "unrecognized input "
6770d547ed0SFan Zhang 					"\"%s\"", tokens[ti]);
6780d547ed0SFan Zhang 				return;
6790d547ed0SFan Zhang 			}
6800d547ed0SFan Zhang 
6810d547ed0SFan Zhang 			src_p = 1;
6820d547ed0SFan Zhang 			continue;
6830d547ed0SFan Zhang 		}
6840d547ed0SFan Zhang 
6850d547ed0SFan Zhang 		if (strcmp(tokens[ti], "dst") == 0) {
6860d547ed0SFan Zhang 			APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
6870d547ed0SFan Zhang 			if (status->status < 0)
6880d547ed0SFan Zhang 				return;
6890d547ed0SFan Zhang 
6900d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
6910d547ed0SFan Zhang 			if (status->status < 0)
6920d547ed0SFan Zhang 				return;
6930d547ed0SFan Zhang 
694b1a3ac78SMariusz Drost 			if (IS_IP4_TUNNEL(rule->flags)) {
6950d547ed0SFan Zhang 				struct in_addr ip;
6960d547ed0SFan Zhang 
6970d547ed0SFan Zhang 				APP_CHECK(parse_ipv4_addr(tokens[ti],
6980d547ed0SFan Zhang 					&ip, NULL) == 0, status,
6990d547ed0SFan Zhang 					"unrecognized input \"%s\", "
7000d547ed0SFan Zhang 					"expect valid ipv4 addr",
7010d547ed0SFan Zhang 					tokens[ti]);
7020d547ed0SFan Zhang 				if (status->status < 0)
7030d547ed0SFan Zhang 					return;
7040d547ed0SFan Zhang 				rule->dst.ip.ip4 = rte_bswap32(
7050d547ed0SFan Zhang 					(uint32_t)ip.s_addr);
706b1a3ac78SMariusz Drost 			} else if (IS_IP6_TUNNEL(rule->flags)) {
707*9ac91e2fSRobin Jarry 				struct rte_ipv6_addr ip;
7080d547ed0SFan Zhang 
7090d547ed0SFan Zhang 				APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
7100d547ed0SFan Zhang 					NULL) == 0, status,
7110d547ed0SFan Zhang 					"unrecognized input \"%s\", "
7120d547ed0SFan Zhang 					"expect valid ipv6 addr",
7130d547ed0SFan Zhang 					tokens[ti]);
7140d547ed0SFan Zhang 				if (status->status < 0)
7150d547ed0SFan Zhang 					return;
716*9ac91e2fSRobin Jarry 
717*9ac91e2fSRobin Jarry 				rule->dst.ip.ip6 = ip;
718b1a3ac78SMariusz Drost 			} else if (IS_TRANSPORT(rule->flags)) {
7190d547ed0SFan Zhang 				APP_CHECK(0, status, "unrecognized "
7200d547ed0SFan Zhang 					"input \"%s\"",	tokens[ti]);
7210d547ed0SFan Zhang 				return;
7220d547ed0SFan Zhang 			}
7230d547ed0SFan Zhang 
7240d547ed0SFan Zhang 			dst_p = 1;
7250d547ed0SFan Zhang 			continue;
7260d547ed0SFan Zhang 		}
7270d547ed0SFan Zhang 
728ec17993aSAkhil Goyal 		if (strcmp(tokens[ti], "type") == 0) {
729ec17993aSAkhil Goyal 			APP_CHECK_PRESENCE(type_p, tokens[ti], status);
730ec17993aSAkhil Goyal 			if (status->status < 0)
731ec17993aSAkhil Goyal 				return;
732ec17993aSAkhil Goyal 
733ec17993aSAkhil Goyal 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
734ec17993aSAkhil Goyal 			if (status->status < 0)
735ec17993aSAkhil Goyal 				return;
736ec17993aSAkhil Goyal 
737ec17993aSAkhil Goyal 			if (strcmp(tokens[ti], "inline-crypto-offload") == 0)
7384a67af84SMarcin Smoczynski 				ips->type =
739ec17993aSAkhil Goyal 					RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO;
740ec17993aSAkhil Goyal 			else if (strcmp(tokens[ti],
741ec17993aSAkhil Goyal 					"inline-protocol-offload") == 0)
7424a67af84SMarcin Smoczynski 				ips->type =
743ec17993aSAkhil Goyal 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL;
744ec17993aSAkhil Goyal 			else if (strcmp(tokens[ti],
745ec17993aSAkhil Goyal 					"lookaside-protocol-offload") == 0)
7464a67af84SMarcin Smoczynski 				ips->type =
747ec17993aSAkhil Goyal 				RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
748ec17993aSAkhil Goyal 			else if (strcmp(tokens[ti], "no-offload") == 0)
7494a67af84SMarcin Smoczynski 				ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
7505139d5d9SMarcin Smoczynski 			else if (strcmp(tokens[ti], "cpu-crypto") == 0)
7515139d5d9SMarcin Smoczynski 				ips->type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO;
752ec17993aSAkhil Goyal 			else {
753ec17993aSAkhil Goyal 				APP_CHECK(0, status, "Invalid input \"%s\"",
754ec17993aSAkhil Goyal 						tokens[ti]);
755ec17993aSAkhil Goyal 				return;
756ec17993aSAkhil Goyal 			}
757ec17993aSAkhil Goyal 
758ec17993aSAkhil Goyal 			type_p = 1;
759ec17993aSAkhil Goyal 			continue;
760ec17993aSAkhil Goyal 		}
761ec17993aSAkhil Goyal 
762ec17993aSAkhil Goyal 		if (strcmp(tokens[ti], "port_id") == 0) {
763ec17993aSAkhil Goyal 			APP_CHECK_PRESENCE(portid_p, tokens[ti], status);
764ec17993aSAkhil Goyal 			if (status->status < 0)
765ec17993aSAkhil Goyal 				return;
766ec17993aSAkhil Goyal 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
767ec17993aSAkhil Goyal 			if (status->status < 0)
768ec17993aSAkhil Goyal 				return;
7696738c0a9SPraveen Shetty 			if (rule->portid == UINT16_MAX)
770ec17993aSAkhil Goyal 				rule->portid = atoi(tokens[ti]);
7716738c0a9SPraveen Shetty 			else if (rule->portid != atoi(tokens[ti])) {
7726738c0a9SPraveen Shetty 				APP_CHECK(0, status,
7736738c0a9SPraveen Shetty 					"portid %s not matching with already assigned portid %u",
7746738c0a9SPraveen Shetty 					tokens[ti], rule->portid);
775ec17993aSAkhil Goyal 				return;
7766738c0a9SPraveen Shetty 			}
777ec17993aSAkhil Goyal 			portid_p = 1;
778ec17993aSAkhil Goyal 			continue;
779ec17993aSAkhil Goyal 		}
780ec17993aSAkhil Goyal 
781a7f32947SRadu Nicolau 		if (strcmp(tokens[ti], "mss") == 0) {
782a7f32947SRadu Nicolau 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
783a7f32947SRadu Nicolau 			if (status->status < 0)
784a7f32947SRadu Nicolau 				return;
785a7f32947SRadu Nicolau 			rule->mss = atoi(tokens[ti]);
786a7f32947SRadu Nicolau 			if (status->status < 0)
787a7f32947SRadu Nicolau 				return;
788a7f32947SRadu Nicolau 			continue;
789a7f32947SRadu Nicolau 		}
790a7f32947SRadu Nicolau 
791d8d51d4fSRahul Bhansali 		if (strcmp(tokens[ti], "reassembly_en") == 0) {
792d8d51d4fSRahul Bhansali 			rule->flags |= SA_REASSEMBLY_ENABLE;
793d8d51d4fSRahul Bhansali 			continue;
794d8d51d4fSRahul Bhansali 		}
795d8d51d4fSRahul Bhansali 
796560029d5SRadu Nicolau 		if (strcmp(tokens[ti], "esn") == 0) {
797560029d5SRadu Nicolau 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
798560029d5SRadu Nicolau 			if (status->status < 0)
799560029d5SRadu Nicolau 				return;
800560029d5SRadu Nicolau 			rule->esn = atoll(tokens[ti]);
801560029d5SRadu Nicolau 			if (status->status < 0)
802560029d5SRadu Nicolau 				return;
803560029d5SRadu Nicolau 			continue;
804560029d5SRadu Nicolau 		}
805560029d5SRadu Nicolau 
806ba66534fSMarcin Smoczynski 		if (strcmp(tokens[ti], "fallback") == 0) {
807ba66534fSMarcin Smoczynski 			struct rte_ipsec_session *fb;
808ba66534fSMarcin Smoczynski 
809ba66534fSMarcin Smoczynski 			APP_CHECK(app_sa_prm.enable, status, "Fallback session "
810ba66534fSMarcin Smoczynski 				"not allowed for legacy mode.");
811ba66534fSMarcin Smoczynski 			if (status->status < 0)
812ba66534fSMarcin Smoczynski 				return;
813ba66534fSMarcin Smoczynski 			APP_CHECK(ips->type ==
814ba66534fSMarcin Smoczynski 				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO, status,
815ba66534fSMarcin Smoczynski 				"Fallback session allowed if primary session "
816ba66534fSMarcin Smoczynski 				"is of type inline-crypto-offload only.");
817ba66534fSMarcin Smoczynski 			if (status->status < 0)
818ba66534fSMarcin Smoczynski 				return;
819ba66534fSMarcin Smoczynski 			APP_CHECK(rule->direction ==
820ba66534fSMarcin Smoczynski 				RTE_SECURITY_IPSEC_SA_DIR_INGRESS, status,
821ba66534fSMarcin Smoczynski 				"Fallback session not allowed for egress "
822ba66534fSMarcin Smoczynski 				"rule");
823ba66534fSMarcin Smoczynski 			if (status->status < 0)
824ba66534fSMarcin Smoczynski 				return;
825ba66534fSMarcin Smoczynski 			APP_CHECK_PRESENCE(fallback_p, tokens[ti], status);
826ba66534fSMarcin Smoczynski 			if (status->status < 0)
827ba66534fSMarcin Smoczynski 				return;
828ba66534fSMarcin Smoczynski 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
829ba66534fSMarcin Smoczynski 			if (status->status < 0)
830ba66534fSMarcin Smoczynski 				return;
831ba66534fSMarcin Smoczynski 			fb = ipsec_get_fallback_session(rule);
832053e1f3cSMariusz Drost 			if (strcmp(tokens[ti], "lookaside-none") == 0)
833ba66534fSMarcin Smoczynski 				fb->type = RTE_SECURITY_ACTION_TYPE_NONE;
834053e1f3cSMariusz Drost 			else if (strcmp(tokens[ti], "cpu-crypto") == 0)
835053e1f3cSMariusz Drost 				fb->type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO;
836053e1f3cSMariusz Drost 			else {
837ba66534fSMarcin Smoczynski 				APP_CHECK(0, status, "unrecognized fallback "
838ba66534fSMarcin Smoczynski 					"type %s.", tokens[ti]);
839ba66534fSMarcin Smoczynski 				return;
840ba66534fSMarcin Smoczynski 			}
841ba66534fSMarcin Smoczynski 
842ba66534fSMarcin Smoczynski 			rule->fallback_sessions = 1;
84304fa1906SVladimir Medvedkin 			nb_crypto_sessions++;
844ba66534fSMarcin Smoczynski 			fallback_p = 1;
845ba66534fSMarcin Smoczynski 			continue;
846ba66534fSMarcin Smoczynski 		}
8476738c0a9SPraveen Shetty 		if (strcmp(tokens[ti], "flow-direction") == 0) {
8486738c0a9SPraveen Shetty 			switch (ips->type) {
8496738c0a9SPraveen Shetty 			case RTE_SECURITY_ACTION_TYPE_NONE:
8506738c0a9SPraveen Shetty 			case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
8516738c0a9SPraveen Shetty 				rule->fdir_flag = 1;
8526738c0a9SPraveen Shetty 				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
8536738c0a9SPraveen Shetty 				if (status->status < 0)
8546738c0a9SPraveen Shetty 					return;
8556738c0a9SPraveen Shetty 				if (rule->portid == UINT16_MAX)
8566738c0a9SPraveen Shetty 					rule->portid = atoi(tokens[ti]);
8576738c0a9SPraveen Shetty 				else if (rule->portid != atoi(tokens[ti])) {
8586738c0a9SPraveen Shetty 					APP_CHECK(0, status,
8596738c0a9SPraveen Shetty 						"portid %s not matching with already assigned portid %u",
8606738c0a9SPraveen Shetty 						tokens[ti], rule->portid);
8616738c0a9SPraveen Shetty 					return;
8626738c0a9SPraveen Shetty 				}
8636738c0a9SPraveen Shetty 				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
8646738c0a9SPraveen Shetty 				if (status->status < 0)
8656738c0a9SPraveen Shetty 					return;
8666738c0a9SPraveen Shetty 				rule->fdir_qid = atoi(tokens[ti]);
8676738c0a9SPraveen Shetty 				/* validating portid and queueid */
8686738c0a9SPraveen Shetty 				status_p = check_flow_params(rule->portid,
8696738c0a9SPraveen Shetty 						rule->fdir_qid);
8706738c0a9SPraveen Shetty 				if (status_p < 0) {
8716738c0a9SPraveen Shetty 					printf("port id %u / queue id %u is "
8726738c0a9SPraveen Shetty 						"not valid\n", rule->portid,
8736738c0a9SPraveen Shetty 						 rule->fdir_qid);
8746738c0a9SPraveen Shetty 				}
8756738c0a9SPraveen Shetty 				break;
8766738c0a9SPraveen Shetty 			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
8776738c0a9SPraveen Shetty 			case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
8786738c0a9SPraveen Shetty 			case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
8796738c0a9SPraveen Shetty 			default:
8806738c0a9SPraveen Shetty 				APP_CHECK(0, status,
8816738c0a9SPraveen Shetty 					"flow director not supported for security session type %d",
8826738c0a9SPraveen Shetty 					ips->type);
8836738c0a9SPraveen Shetty 				return;
8846738c0a9SPraveen Shetty 			}
8856738c0a9SPraveen Shetty 			continue;
8866738c0a9SPraveen Shetty 		}
8879a1cc8f1STejasree Kondoj 		if (strcmp(tokens[ti], "udp-encap") == 0) {
8886425d95aSSrujana Challa 			switch (ips->type) {
8896425d95aSSrujana Challa 			case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
8906425d95aSSrujana Challa 			case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
8916425d95aSSrujana Challa 				APP_CHECK_PRESENCE(udp_encap_p, tokens[ti],
8926425d95aSSrujana Challa 						   status);
8939a1cc8f1STejasree Kondoj 				if (status->status < 0)
8949a1cc8f1STejasree Kondoj 					return;
8959a1cc8f1STejasree Kondoj 
8969a1cc8f1STejasree Kondoj 				rule->udp_encap = 1;
8979a1cc8f1STejasree Kondoj 				app_sa_prm.udp_encap = 1;
8989a1cc8f1STejasree Kondoj 				udp_encap_p = 1;
8996425d95aSSrujana Challa 				break;
9009ae86b4cSRadu Nicolau 			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
9019ae86b4cSRadu Nicolau 				rule->udp_encap = 1;
9029ae86b4cSRadu Nicolau 				rule->udp.sport = 0;
9039ae86b4cSRadu Nicolau 				rule->udp.dport = 4500;
9049ae86b4cSRadu Nicolau 				break;
9056425d95aSSrujana Challa 			default:
9066425d95aSSrujana Challa 				APP_CHECK(0, status,
9076425d95aSSrujana Challa 					"UDP encapsulation not supported for "
9086425d95aSSrujana Challa 					"security session type %d",
9096425d95aSSrujana Challa 					ips->type);
9106425d95aSSrujana Challa 				return;
9116425d95aSSrujana Challa 			}
9129a1cc8f1STejasree Kondoj 			continue;
9139a1cc8f1STejasree Kondoj 		}
914ba66534fSMarcin Smoczynski 
9157be78d02SJosh Soref 		/* unrecognizable input */
9160d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognized input \"%s\"",
9170d547ed0SFan Zhang 			tokens[ti]);
9180d547ed0SFan Zhang 		return;
9190d547ed0SFan Zhang 	}
9200d547ed0SFan Zhang 
921501e9c22SPablo de Lara 	if (aead_algo_p) {
922501e9c22SPablo de Lara 		APP_CHECK(cipher_algo_p == 0, status,
923501e9c22SPablo de Lara 				"AEAD used, no need for cipher options");
9240d547ed0SFan Zhang 		if (status->status < 0)
9250d547ed0SFan Zhang 			return;
9260d547ed0SFan Zhang 
927501e9c22SPablo de Lara 		APP_CHECK(auth_algo_p == 0, status,
928501e9c22SPablo de Lara 				"AEAD used, no need for auth options");
9290d547ed0SFan Zhang 		if (status->status < 0)
9300d547ed0SFan Zhang 			return;
931501e9c22SPablo de Lara 	} else {
932501e9c22SPablo de Lara 		APP_CHECK(cipher_algo_p == 1, status, "missing cipher or AEAD options");
933501e9c22SPablo de Lara 		if (status->status < 0)
934501e9c22SPablo de Lara 			return;
935501e9c22SPablo de Lara 
936501e9c22SPablo de Lara 		APP_CHECK(auth_algo_p == 1, status, "missing auth or AEAD options");
937501e9c22SPablo de Lara 		if (status->status < 0)
938501e9c22SPablo de Lara 			return;
939501e9c22SPablo de Lara 	}
9400d547ed0SFan Zhang 
9410d547ed0SFan Zhang 	APP_CHECK(mode_p == 1, status, "missing mode option");
9420d547ed0SFan Zhang 	if (status->status < 0)
9430d547ed0SFan Zhang 		return;
9440d547ed0SFan Zhang 
9455139d5d9SMarcin Smoczynski 	if ((ips->type != RTE_SECURITY_ACTION_TYPE_NONE && ips->type !=
9465139d5d9SMarcin Smoczynski 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) && (portid_p == 0))
947ec17993aSAkhil Goyal 		printf("Missing portid option, falling back to non-offload\n");
948ec17993aSAkhil Goyal 
9495139d5d9SMarcin Smoczynski 	if (!type_p || (!portid_p && ips->type !=
9505139d5d9SMarcin Smoczynski 			RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) {
9514a67af84SMarcin Smoczynski 		ips->type = RTE_SECURITY_ACTION_TYPE_NONE;
952ec17993aSAkhil Goyal 	}
953ec17993aSAkhil Goyal 
9540d76e22dSNithin Dabilpuram 	if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)
9550d76e22dSNithin Dabilpuram 		wrkr_flags |= INL_CR_F;
9560d76e22dSNithin Dabilpuram 	else if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
9570d76e22dSNithin Dabilpuram 		wrkr_flags |= INL_PR_F;
9580d76e22dSNithin Dabilpuram 	else if (ips->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
9590d76e22dSNithin Dabilpuram 		wrkr_flags |= LA_PR_F;
9600d76e22dSNithin Dabilpuram 	else
9610d76e22dSNithin Dabilpuram 		wrkr_flags |= LA_ANY_F;
9620d76e22dSNithin Dabilpuram 
96304fa1906SVladimir Medvedkin 	nb_crypto_sessions++;
9640d547ed0SFan Zhang 	*ri = *ri + 1;
9650d547ed0SFan Zhang }
9660d547ed0SFan Zhang 
96749757b68SKonstantin Ananyev static void
9680d547ed0SFan Zhang print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
9690d547ed0SFan Zhang {
9700d547ed0SFan Zhang 	uint32_t i;
9710d547ed0SFan Zhang 	uint8_t a, b, c, d;
9724a67af84SMarcin Smoczynski 	const struct rte_ipsec_session *ips;
973ba66534fSMarcin Smoczynski 	const struct rte_ipsec_session *fallback_ips;
9740d547ed0SFan Zhang 
9750d547ed0SFan Zhang 	printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi);
9760d547ed0SFan Zhang 
9770d547ed0SFan Zhang 	for (i = 0; i < RTE_DIM(cipher_algos); i++) {
97863f6da4dSRadu Nicolau 		if (cipher_algos[i].algo == sa->cipher_algo &&
97963f6da4dSRadu Nicolau 				cipher_algos[i].key_len == sa->cipher_key_len) {
9800d547ed0SFan Zhang 			printf("%s ", cipher_algos[i].keyword);
9810d547ed0SFan Zhang 			break;
9820d547ed0SFan Zhang 		}
9830d547ed0SFan Zhang 	}
9840d547ed0SFan Zhang 
9850d547ed0SFan Zhang 	for (i = 0; i < RTE_DIM(auth_algos); i++) {
9860d547ed0SFan Zhang 		if (auth_algos[i].algo == sa->auth_algo) {
9870d547ed0SFan Zhang 			printf("%s ", auth_algos[i].keyword);
9880d547ed0SFan Zhang 			break;
9890d547ed0SFan Zhang 		}
9900d547ed0SFan Zhang 	}
9910d547ed0SFan Zhang 
992501e9c22SPablo de Lara 	for (i = 0; i < RTE_DIM(aead_algos); i++) {
993a8af994bSAnoob Joseph 		if (aead_algos[i].algo == sa->aead_algo &&
994a8af994bSAnoob Joseph 				aead_algos[i].key_len-4 == sa->cipher_key_len) {
995501e9c22SPablo de Lara 			printf("%s ", aead_algos[i].keyword);
996501e9c22SPablo de Lara 			break;
997501e9c22SPablo de Lara 		}
998501e9c22SPablo de Lara 	}
999501e9c22SPablo de Lara 
10000d547ed0SFan Zhang 	printf("mode:");
10019ae86b4cSRadu Nicolau 	if (sa->udp_encap)
10029ae86b4cSRadu Nicolau 		printf("UDP encapsulated ");
10030d547ed0SFan Zhang 
1004b1a3ac78SMariusz Drost 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
10050d547ed0SFan Zhang 	case IP4_TUNNEL:
10060d547ed0SFan Zhang 		printf("IP4Tunnel ");
10070d547ed0SFan Zhang 		uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d);
10080d547ed0SFan Zhang 		printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a);
10090d547ed0SFan Zhang 		uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d);
10100d547ed0SFan Zhang 		printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a);
10110d547ed0SFan Zhang 		break;
10120d547ed0SFan Zhang 	case IP6_TUNNEL:
10130d547ed0SFan Zhang 		printf("IP6Tunnel ");
1014*9ac91e2fSRobin Jarry 		printf(RTE_IPV6_ADDR_FMT, RTE_IPV6_ADDR_SPLIT(&sa->src.ip.ip6));
10150d547ed0SFan Zhang 		printf(" ");
1016*9ac91e2fSRobin Jarry 		printf(RTE_IPV6_ADDR_FMT, RTE_IPV6_ADDR_SPLIT(&sa->dst.ip.ip6));
10170d547ed0SFan Zhang 		break;
10180d547ed0SFan Zhang 	case TRANSPORT:
10190d547ed0SFan Zhang 		printf("Transport ");
10200d547ed0SFan Zhang 		break;
10210d547ed0SFan Zhang 	}
10224a67af84SMarcin Smoczynski 
1023ba66534fSMarcin Smoczynski 	ips = &sa->sessions[IPSEC_SESSION_PRIMARY];
1024da7a540eSBernard Iremonger 	printf(" type:");
10254a67af84SMarcin Smoczynski 	switch (ips->type) {
1026da7a540eSBernard Iremonger 	case RTE_SECURITY_ACTION_TYPE_NONE:
1027da7a540eSBernard Iremonger 		printf("no-offload ");
1028da7a540eSBernard Iremonger 		break;
1029da7a540eSBernard Iremonger 	case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
1030da7a540eSBernard Iremonger 		printf("inline-crypto-offload ");
1031da7a540eSBernard Iremonger 		break;
1032da7a540eSBernard Iremonger 	case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
1033da7a540eSBernard Iremonger 		printf("inline-protocol-offload ");
1034da7a540eSBernard Iremonger 		break;
1035da7a540eSBernard Iremonger 	case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL:
1036da7a540eSBernard Iremonger 		printf("lookaside-protocol-offload ");
1037da7a540eSBernard Iremonger 		break;
10385139d5d9SMarcin Smoczynski 	case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
10395139d5d9SMarcin Smoczynski 		printf("cpu-crypto-accelerated ");
10405139d5d9SMarcin Smoczynski 		break;
1041da7a540eSBernard Iremonger 	}
1042ba66534fSMarcin Smoczynski 
1043ba66534fSMarcin Smoczynski 	fallback_ips = &sa->sessions[IPSEC_SESSION_FALLBACK];
1044ba66534fSMarcin Smoczynski 	if (fallback_ips != NULL && sa->fallback_sessions > 0) {
1045ba66534fSMarcin Smoczynski 		printf("inline fallback: ");
10465139d5d9SMarcin Smoczynski 		switch (fallback_ips->type) {
10475139d5d9SMarcin Smoczynski 		case RTE_SECURITY_ACTION_TYPE_NONE:
1048ba66534fSMarcin Smoczynski 			printf("lookaside-none");
10495139d5d9SMarcin Smoczynski 			break;
10505139d5d9SMarcin Smoczynski 		case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO:
10515139d5d9SMarcin Smoczynski 			printf("cpu-crypto-accelerated");
10525139d5d9SMarcin Smoczynski 			break;
10535139d5d9SMarcin Smoczynski 		default:
1054ba66534fSMarcin Smoczynski 			printf("invalid");
10555139d5d9SMarcin Smoczynski 			break;
10565139d5d9SMarcin Smoczynski 		}
1057ba66534fSMarcin Smoczynski 	}
10586738c0a9SPraveen Shetty 	if (sa->fdir_flag == 1)
10596738c0a9SPraveen Shetty 		printf("flow-direction port %d queue %d", sa->portid,
10606738c0a9SPraveen Shetty 				sa->fdir_qid);
10616738c0a9SPraveen Shetty 
10620d547ed0SFan Zhang 	printf("\n");
10630d547ed0SFan Zhang }
1064d299106eSSergio Gonzalez Monroy 
1065d299106eSSergio Gonzalez Monroy static struct sa_ctx *
1066df3e1d94SVladimir Medvedkin sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)
1067d299106eSSergio Gonzalez Monroy {
1068d299106eSSergio Gonzalez Monroy 	char s[PATH_MAX];
1069d299106eSSergio Gonzalez Monroy 	struct sa_ctx *sa_ctx;
1070906257e9SSergio Gonzalez Monroy 	uint32_t mz_size;
1071d299106eSSergio Gonzalez Monroy 	const struct rte_memzone *mz;
1072d299106eSSergio Gonzalez Monroy 
1073d299106eSSergio Gonzalez Monroy 	snprintf(s, sizeof(s), "%s_%u", name, socket_id);
1074d299106eSSergio Gonzalez Monroy 
1075df3e1d94SVladimir Medvedkin 	/* Create SA context */
1076da7a540eSBernard Iremonger 	printf("Creating SA context with %u maximum entries on socket %d\n",
1077df3e1d94SVladimir Medvedkin 			nb_sa, socket_id);
1078d299106eSSergio Gonzalez Monroy 
1079df3e1d94SVladimir Medvedkin 	mz_size = sizeof(struct ipsec_xf) * nb_sa;
1080d299106eSSergio Gonzalez Monroy 	mz = rte_memzone_reserve(s, mz_size, socket_id,
1081d299106eSSergio Gonzalez Monroy 			RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY);
1082d299106eSSergio Gonzalez Monroy 	if (mz == NULL) {
1083df3e1d94SVladimir Medvedkin 		printf("Failed to allocate SA XFORM memory\n");
10844fbf3324SDilshod Urazov 		rte_errno = ENOMEM;
1085d299106eSSergio Gonzalez Monroy 		return NULL;
1086d299106eSSergio Gonzalez Monroy 	}
1087d299106eSSergio Gonzalez Monroy 
10882cf67788SVladimir Medvedkin 	sa_ctx = rte_zmalloc(NULL, sizeof(struct sa_ctx) +
1089df3e1d94SVladimir Medvedkin 		sizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);
1090df3e1d94SVladimir Medvedkin 
1091df3e1d94SVladimir Medvedkin 	if (sa_ctx == NULL) {
1092df3e1d94SVladimir Medvedkin 		printf("Failed to allocate SA CTX memory\n");
1093df3e1d94SVladimir Medvedkin 		rte_errno = ENOMEM;
1094df3e1d94SVladimir Medvedkin 		rte_memzone_free(mz);
1095df3e1d94SVladimir Medvedkin 		return NULL;
1096df3e1d94SVladimir Medvedkin 	}
1097df3e1d94SVladimir Medvedkin 
1098df3e1d94SVladimir Medvedkin 	sa_ctx->xf = (struct ipsec_xf *)mz->addr;
1099df3e1d94SVladimir Medvedkin 	sa_ctx->nb_sa = nb_sa;
1100d299106eSSergio Gonzalez Monroy 
1101d299106eSSergio Gonzalez Monroy 	return sa_ctx;
1102d299106eSSergio Gonzalez Monroy }
1103d299106eSSergio Gonzalez Monroy 
1104d299106eSSergio Gonzalez Monroy static int
1105a7f32947SRadu Nicolau check_eth_dev_caps(uint16_t portid, uint32_t inbound, uint32_t tso)
1106ec17993aSAkhil Goyal {
1107ec17993aSAkhil Goyal 	struct rte_eth_dev_info dev_info;
110803ad0e5cSIvan Ilchenko 	int retval;
1109ec17993aSAkhil Goyal 
111003ad0e5cSIvan Ilchenko 	retval = rte_eth_dev_info_get(portid, &dev_info);
111103ad0e5cSIvan Ilchenko 	if (retval != 0) {
111203ad0e5cSIvan Ilchenko 		RTE_LOG(ERR, IPSEC,
111303ad0e5cSIvan Ilchenko 			"Error during getting device (port %u) info: %s\n",
111403ad0e5cSIvan Ilchenko 			portid, strerror(-retval));
111503ad0e5cSIvan Ilchenko 
111603ad0e5cSIvan Ilchenko 		return retval;
111703ad0e5cSIvan Ilchenko 	}
1118ec17993aSAkhil Goyal 
1119ec17993aSAkhil Goyal 	if (inbound) {
1120ec17993aSAkhil Goyal 		if ((dev_info.rx_offload_capa &
1121295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_SECURITY) == 0) {
1122f2d5afbbSStephen Hemminger 			RTE_LOG(WARNING, IPSEC,
1123ec17993aSAkhil Goyal 				"hardware RX IPSec offload is not supported\n");
1124ec17993aSAkhil Goyal 			return -EINVAL;
1125ec17993aSAkhil Goyal 		}
1126ec17993aSAkhil Goyal 
1127ec17993aSAkhil Goyal 	} else { /* outbound */
1128ec17993aSAkhil Goyal 		if ((dev_info.tx_offload_capa &
1129295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_SECURITY) == 0) {
1130f2d5afbbSStephen Hemminger 			RTE_LOG(WARNING, IPSEC,
1131ec17993aSAkhil Goyal 				"hardware TX IPSec offload is not supported\n");
1132ec17993aSAkhil Goyal 			return -EINVAL;
1133ec17993aSAkhil Goyal 		}
1134a7f32947SRadu Nicolau 		if (tso && (dev_info.tx_offload_capa &
1135a7f32947SRadu Nicolau 				RTE_ETH_TX_OFFLOAD_TCP_TSO) == 0) {
1136f2d5afbbSStephen Hemminger 			RTE_LOG(WARNING, IPSEC,
1137a7f32947SRadu Nicolau 				"hardware TCP TSO offload is not supported\n");
1138a7f32947SRadu Nicolau 			return -EINVAL;
1139a7f32947SRadu Nicolau 		}
1140ec17993aSAkhil Goyal 	}
1141ec17993aSAkhil Goyal 	return 0;
1142ec17993aSAkhil Goyal }
1143ec17993aSAkhil Goyal 
1144b1a3ac78SMariusz Drost /*
1145b1a3ac78SMariusz Drost  * Helper function, tries to determine next_proto for SPI
1146b1a3ac78SMariusz Drost  * by searching though SP rules.
1147b1a3ac78SMariusz Drost  */
1148b1a3ac78SMariusz Drost static int
1149b1a3ac78SMariusz Drost get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir,
1150b1a3ac78SMariusz Drost 		struct ip_addr ip_addr[2], uint32_t mask[2])
1151b1a3ac78SMariusz Drost {
1152b1a3ac78SMariusz Drost 	int32_t rc4, rc6;
1153b1a3ac78SMariusz Drost 
1154b1a3ac78SMariusz Drost 	rc4 = sp4_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1155b1a3ac78SMariusz Drost 				ip_addr, mask);
1156b1a3ac78SMariusz Drost 	rc6 = sp6_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1157b1a3ac78SMariusz Drost 				ip_addr, mask);
1158b1a3ac78SMariusz Drost 
1159b1a3ac78SMariusz Drost 	if (rc4 >= 0) {
1160b1a3ac78SMariusz Drost 		if (rc6 >= 0) {
1161b1a3ac78SMariusz Drost 			RTE_LOG(ERR, IPSEC,
11627be78d02SJosh Soref 				"%s: SPI %u used simultaneously by "
1163b1a3ac78SMariusz Drost 				"IPv4(%d) and IPv6 (%d) SP rules\n",
1164b1a3ac78SMariusz Drost 				__func__, spi, rc4, rc6);
1165b1a3ac78SMariusz Drost 			return -EINVAL;
1166b1a3ac78SMariusz Drost 		} else
1167b1a3ac78SMariusz Drost 			return IPPROTO_IPIP;
1168b1a3ac78SMariusz Drost 	} else if (rc6 < 0) {
1169b1a3ac78SMariusz Drost 		RTE_LOG(ERR, IPSEC,
1170b1a3ac78SMariusz Drost 			"%s: SPI %u is not used by any SP rule\n",
1171b1a3ac78SMariusz Drost 			__func__, spi);
1172b1a3ac78SMariusz Drost 		return -EINVAL;
1173b1a3ac78SMariusz Drost 	} else
1174b1a3ac78SMariusz Drost 		return IPPROTO_IPV6;
1175b1a3ac78SMariusz Drost }
1176b1a3ac78SMariusz Drost 
1177b1a3ac78SMariusz Drost /*
1178b1a3ac78SMariusz Drost  * Helper function for getting source and destination IP addresses
1179b1a3ac78SMariusz Drost  * from SP. Needed for inline crypto transport mode, as addresses are not
1180b1a3ac78SMariusz Drost  * provided in config file for that mode. It checks if SP for current SA exists,
1181b1a3ac78SMariusz Drost  * and based on what type of protocol is returned, it stores appropriate
1182b1a3ac78SMariusz Drost  * addresses got from SP into SA.
1183b1a3ac78SMariusz Drost  */
1184b1a3ac78SMariusz Drost static int
1185b1a3ac78SMariusz Drost sa_add_address_inline_crypto(struct ipsec_sa *sa)
1186b1a3ac78SMariusz Drost {
1187b1a3ac78SMariusz Drost 	int protocol;
1188b1a3ac78SMariusz Drost 	struct ip_addr ip_addr[2];
1189b1a3ac78SMariusz Drost 	uint32_t mask[2];
1190b1a3ac78SMariusz Drost 
1191b1a3ac78SMariusz Drost 	protocol = get_spi_proto(sa->spi, sa->direction, ip_addr, mask);
1192b1a3ac78SMariusz Drost 	if (protocol < 0)
1193b1a3ac78SMariusz Drost 		return protocol;
1194b1a3ac78SMariusz Drost 	else if (protocol == IPPROTO_IPIP) {
1195b1a3ac78SMariusz Drost 		sa->flags |= IP4_TRANSPORT;
1196b1a3ac78SMariusz Drost 		if (mask[0] == IP4_FULL_MASK &&
1197b1a3ac78SMariusz Drost 				mask[1] == IP4_FULL_MASK &&
1198b1a3ac78SMariusz Drost 				ip_addr[0].ip.ip4 != 0 &&
1199b1a3ac78SMariusz Drost 				ip_addr[1].ip.ip4 != 0) {
1200b1a3ac78SMariusz Drost 
1201b1a3ac78SMariusz Drost 			sa->src.ip.ip4 = ip_addr[0].ip.ip4;
1202b1a3ac78SMariusz Drost 			sa->dst.ip.ip4 = ip_addr[1].ip.ip4;
1203b1a3ac78SMariusz Drost 		} else {
1204b1a3ac78SMariusz Drost 			RTE_LOG(ERR, IPSEC,
1205b1a3ac78SMariusz Drost 			"%s: No valid address or mask entry in"
1206b1a3ac78SMariusz Drost 			" IPv4 SP rule for SPI %u\n",
1207b1a3ac78SMariusz Drost 			__func__, sa->spi);
1208b1a3ac78SMariusz Drost 			return -EINVAL;
1209b1a3ac78SMariusz Drost 		}
1210b1a3ac78SMariusz Drost 	} else if (protocol == IPPROTO_IPV6) {
1211b1a3ac78SMariusz Drost 		sa->flags |= IP6_TRANSPORT;
1212b1a3ac78SMariusz Drost 		if (mask[0] == IP6_FULL_MASK &&
1213b1a3ac78SMariusz Drost 				mask[1] == IP6_FULL_MASK &&
1214*9ac91e2fSRobin Jarry 				!rte_ipv6_addr_is_unspec(&ip_addr[0].ip.ip6) &&
1215*9ac91e2fSRobin Jarry 				!rte_ipv6_addr_is_unspec(&ip_addr[1].ip.ip6)) {
1216b1a3ac78SMariusz Drost 
1217b1a3ac78SMariusz Drost 			sa->src.ip.ip6 = ip_addr[0].ip.ip6;
1218b1a3ac78SMariusz Drost 			sa->dst.ip.ip6 = ip_addr[1].ip.ip6;
1219b1a3ac78SMariusz Drost 		} else {
1220b1a3ac78SMariusz Drost 			RTE_LOG(ERR, IPSEC,
1221b1a3ac78SMariusz Drost 			"%s: No valid address or mask entry in"
1222b1a3ac78SMariusz Drost 			" IPv6 SP rule for SPI %u\n",
1223b1a3ac78SMariusz Drost 			__func__, sa->spi);
1224b1a3ac78SMariusz Drost 			return -EINVAL;
1225b1a3ac78SMariusz Drost 		}
1226b1a3ac78SMariusz Drost 	}
1227b1a3ac78SMariusz Drost 	return 0;
1228b1a3ac78SMariusz Drost }
1229ec17993aSAkhil Goyal 
1230ec17993aSAkhil Goyal static int
1231d299106eSSergio Gonzalez Monroy sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
12323a690d5aSBernard Iremonger 		uint32_t nb_entries, uint32_t inbound,
1233a8ade121SVolodymyr Fialko 		struct socket_ctx *skt_ctx,
12346938fc92SVolodymyr Fialko 		struct ipsec_ctx *ips_ctx[],
12356938fc92SVolodymyr Fialko 		const struct eventmode_conf *em_conf)
1236d299106eSSergio Gonzalez Monroy {
1237d299106eSSergio Gonzalez Monroy 	struct ipsec_sa *sa;
1238906257e9SSergio Gonzalez Monroy 	uint32_t i, idx;
12395a032a71SKonstantin Ananyev 	uint16_t iv_length, aad_length;
124056af1858SAkhil Goyal 	uint16_t auth_iv_length = 0;
1241b1a3ac78SMariusz Drost 	int inline_status;
12423a690d5aSBernard Iremonger 	int32_t rc;
12434a67af84SMarcin Smoczynski 	struct rte_ipsec_session *ips;
12445a032a71SKonstantin Ananyev 
12455a032a71SKonstantin Ananyev 	/* for ESN upper 32 bits of SQN also need to be part of AAD */
12465a032a71SKonstantin Ananyev 	aad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;
1247d299106eSSergio Gonzalez Monroy 
1248d299106eSSergio Gonzalez Monroy 	for (i = 0; i < nb_entries; i++) {
1249df3e1d94SVladimir Medvedkin 		idx = i;
1250d299106eSSergio Gonzalez Monroy 		sa = &sa_ctx->sa[idx];
1251d299106eSSergio Gonzalez Monroy 		if (sa->spi != 0) {
1252d299106eSSergio Gonzalez Monroy 			printf("Index %u already in use by SPI %u\n",
1253d299106eSSergio Gonzalez Monroy 					idx, sa->spi);
1254d299106eSSergio Gonzalez Monroy 			return -EINVAL;
1255d299106eSSergio Gonzalez Monroy 		}
1256d299106eSSergio Gonzalez Monroy 		*sa = entries[i];
1257df3e1d94SVladimir Medvedkin 
1258df3e1d94SVladimir Medvedkin 		if (inbound) {
1259df3e1d94SVladimir Medvedkin 			rc = ipsec_sad_add(&sa_ctx->sad, sa);
1260df3e1d94SVladimir Medvedkin 			if (rc != 0)
1261df3e1d94SVladimir Medvedkin 				return rc;
1262df3e1d94SVladimir Medvedkin 		}
1263df3e1d94SVladimir Medvedkin 
1264906257e9SSergio Gonzalez Monroy 		sa->seq = 0;
1265ba66534fSMarcin Smoczynski 		ips = ipsec_get_primary_session(sa);
1266906257e9SSergio Gonzalez Monroy 
12674a67af84SMarcin Smoczynski 		if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
12684a67af84SMarcin Smoczynski 			ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
1269a7f32947SRadu Nicolau 			if (check_eth_dev_caps(sa->portid, inbound, sa->mss))
1270ec17993aSAkhil Goyal 				return -EINVAL;
1271ec17993aSAkhil Goyal 		}
1272ec17993aSAkhil Goyal 
1273b1a3ac78SMariusz Drost 		switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
1274906257e9SSergio Gonzalez Monroy 		case IP4_TUNNEL:
127596362fadSSergio Gonzalez Monroy 			sa->src.ip.ip4 = rte_cpu_to_be_32(sa->src.ip.ip4);
127696362fadSSergio Gonzalez Monroy 			sa->dst.ip.ip4 = rte_cpu_to_be_32(sa->dst.ip.ip4);
1277b1a3ac78SMariusz Drost 			break;
1278b1a3ac78SMariusz Drost 		case TRANSPORT:
12794a67af84SMarcin Smoczynski 			if (ips->type ==
1280b1a3ac78SMariusz Drost 				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
1281b1a3ac78SMariusz Drost 				inline_status =
1282b1a3ac78SMariusz Drost 					sa_add_address_inline_crypto(sa);
1283b1a3ac78SMariusz Drost 				if (inline_status < 0)
1284b1a3ac78SMariusz Drost 					return inline_status;
1285b1a3ac78SMariusz Drost 			}
1286b1a3ac78SMariusz Drost 			break;
1287906257e9SSergio Gonzalez Monroy 		}
1288906257e9SSergio Gonzalez Monroy 
12899413c390SRadu Nicolau 
12909413c390SRadu Nicolau 		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM ||
12919413c390SRadu Nicolau 			sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM ||
12929413c390SRadu Nicolau 			sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
12939413c390SRadu Nicolau 
12949413c390SRadu Nicolau 			if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
12959413c390SRadu Nicolau 				iv_length = 11;
12969413c390SRadu Nicolau 			else
1297ce00b504SMarcin Smoczynski 				iv_length = 12;
1298b79e4c00SPablo de Lara 
1299b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1300b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.algo = sa->aead_algo;
1301b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.key.data = sa->cipher_key;
1302b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.key.length =
1303b79e4c00SPablo de Lara 				sa->cipher_key_len;
1304ec17993aSAkhil Goyal 			sa_ctx->xf[idx].a.aead.op = (inbound == 1) ?
1305ec17993aSAkhil Goyal 				RTE_CRYPTO_AEAD_OP_DECRYPT :
1306b79e4c00SPablo de Lara 				RTE_CRYPTO_AEAD_OP_ENCRYPT;
1307b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.next = NULL;
1308b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.iv.offset = IV_OFFSET;
1309b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.iv.length = iv_length;
131046a0547fSPablo de Lara 			sa_ctx->xf[idx].a.aead.aad_length =
13115a032a71SKonstantin Ananyev 				sa->aad_len + aad_length;
1312b79e4c00SPablo de Lara 			sa_ctx->xf[idx].a.aead.digest_length =
1313b79e4c00SPablo de Lara 				sa->digest_len;
1314b79e4c00SPablo de Lara 
1315b79e4c00SPablo de Lara 			sa->xforms = &sa_ctx->xf[idx].a;
1316b79e4c00SPablo de Lara 		} else {
13170fbd75a9SPablo de Lara 			switch (sa->cipher_algo) {
13180fbd75a9SPablo de Lara 			case RTE_CRYPTO_CIPHER_NULL:
1319923b5f27SGagandeep Singh 			case RTE_CRYPTO_CIPHER_DES_CBC:
13201bc489caSHemant Agrawal 			case RTE_CRYPTO_CIPHER_3DES_CBC:
13210fbd75a9SPablo de Lara 			case RTE_CRYPTO_CIPHER_AES_CBC:
13229413c390SRadu Nicolau 				iv_length = sa->iv_len;
13230fbd75a9SPablo de Lara 				break;
132435a0dcabSTejasree Kondoj 			case RTE_CRYPTO_CIPHER_AES_CTR:
132535a0dcabSTejasree Kondoj 				/* Length includes 8B per packet IV, 4B nonce and
132635a0dcabSTejasree Kondoj 				 * 4B counter as populated in datapath.
132735a0dcabSTejasree Kondoj 				 */
132835a0dcabSTejasree Kondoj 				iv_length = 16;
132935a0dcabSTejasree Kondoj 				break;
13300fbd75a9SPablo de Lara 			default:
1331b79e4c00SPablo de Lara 				RTE_LOG(ERR, IPSEC_ESP,
1332b79e4c00SPablo de Lara 						"unsupported cipher algorithm %u\n",
13330fbd75a9SPablo de Lara 						sa->cipher_algo);
13340fbd75a9SPablo de Lara 				return -EINVAL;
13350fbd75a9SPablo de Lara 			}
13360fbd75a9SPablo de Lara 
13379413c390SRadu Nicolau 			/* AES_GMAC uses salt like AEAD algorithms */
13389413c390SRadu Nicolau 			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC)
133956af1858SAkhil Goyal 				auth_iv_length = 12;
13409413c390SRadu Nicolau 
1341d299106eSSergio Gonzalez Monroy 			if (inbound) {
13420d547ed0SFan Zhang 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
13430d547ed0SFan Zhang 				sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo;
13440d547ed0SFan Zhang 				sa_ctx->xf[idx].b.cipher.key.data = sa->cipher_key;
13450d547ed0SFan Zhang 				sa_ctx->xf[idx].b.cipher.key.length =
13460d547ed0SFan Zhang 					sa->cipher_key_len;
13470d547ed0SFan Zhang 				sa_ctx->xf[idx].b.cipher.op =
13480d547ed0SFan Zhang 					RTE_CRYPTO_CIPHER_OP_DECRYPT;
1349b79e4c00SPablo de Lara 				sa_ctx->xf[idx].b.next = NULL;
13500fbd75a9SPablo de Lara 				sa_ctx->xf[idx].b.cipher.iv.offset = IV_OFFSET;
13510fbd75a9SPablo de Lara 				sa_ctx->xf[idx].b.cipher.iv.length = iv_length;
13520d547ed0SFan Zhang 
13530d547ed0SFan Zhang 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AUTH;
13540d547ed0SFan Zhang 				sa_ctx->xf[idx].a.auth.algo = sa->auth_algo;
13550d547ed0SFan Zhang 				sa_ctx->xf[idx].a.auth.key.data = sa->auth_key;
13560d547ed0SFan Zhang 				sa_ctx->xf[idx].a.auth.key.length =
13570d547ed0SFan Zhang 					sa->auth_key_len;
13580d547ed0SFan Zhang 				sa_ctx->xf[idx].a.auth.digest_length =
13590d547ed0SFan Zhang 					sa->digest_len;
13600d547ed0SFan Zhang 				sa_ctx->xf[idx].a.auth.op =
13610d547ed0SFan Zhang 					RTE_CRYPTO_AUTH_OP_VERIFY;
13629413c390SRadu Nicolau 				sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET;
136356af1858SAkhil Goyal 				sa_ctx->xf[idx].a.auth.iv.length = auth_iv_length;
13649413c390SRadu Nicolau 
1365d299106eSSergio Gonzalez Monroy 			} else { /* outbound */
13660d547ed0SFan Zhang 				sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
13670d547ed0SFan Zhang 				sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo;
13680d547ed0SFan Zhang 				sa_ctx->xf[idx].a.cipher.key.data = sa->cipher_key;
13690d547ed0SFan Zhang 				sa_ctx->xf[idx].a.cipher.key.length =
13700d547ed0SFan Zhang 					sa->cipher_key_len;
13710d547ed0SFan Zhang 				sa_ctx->xf[idx].a.cipher.op =
13720d547ed0SFan Zhang 					RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1373b79e4c00SPablo de Lara 				sa_ctx->xf[idx].a.next = NULL;
13740fbd75a9SPablo de Lara 				sa_ctx->xf[idx].a.cipher.iv.offset = IV_OFFSET;
13750fbd75a9SPablo de Lara 				sa_ctx->xf[idx].a.cipher.iv.length = iv_length;
13760d547ed0SFan Zhang 
13770d547ed0SFan Zhang 				sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_AUTH;
13780d547ed0SFan Zhang 				sa_ctx->xf[idx].b.auth.algo = sa->auth_algo;
13790d547ed0SFan Zhang 				sa_ctx->xf[idx].b.auth.key.data = sa->auth_key;
13800d547ed0SFan Zhang 				sa_ctx->xf[idx].b.auth.key.length =
13810d547ed0SFan Zhang 					sa->auth_key_len;
13820d547ed0SFan Zhang 				sa_ctx->xf[idx].b.auth.digest_length =
13830d547ed0SFan Zhang 					sa->digest_len;
13840d547ed0SFan Zhang 				sa_ctx->xf[idx].b.auth.op =
13850d547ed0SFan Zhang 					RTE_CRYPTO_AUTH_OP_GENERATE;
13869413c390SRadu Nicolau 				sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET;
138756af1858SAkhil Goyal 				sa_ctx->xf[idx].b.auth.iv.length = auth_iv_length;
13889413c390SRadu Nicolau 
1389d299106eSSergio Gonzalez Monroy 			}
13900d547ed0SFan Zhang 
13919413c390SRadu Nicolau 			if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
13929413c390SRadu Nicolau 				sa->xforms = inbound ?
13939413c390SRadu Nicolau 					&sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b;
13949413c390SRadu Nicolau 				sa->xforms->next = NULL;
13959413c390SRadu Nicolau 
13969413c390SRadu Nicolau 			} else {
1397d299106eSSergio Gonzalez Monroy 				sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
1398d299106eSSergio Gonzalez Monroy 				sa_ctx->xf[idx].b.next = NULL;
1399d299106eSSergio Gonzalez Monroy 				sa->xforms = &sa_ctx->xf[idx].a;
14005139d5d9SMarcin Smoczynski 			}
14019413c390SRadu Nicolau 		}
14020d547ed0SFan Zhang 
1403b685f931SAnkur Dwivedi 		if (ips->type ==
1404b685f931SAnkur Dwivedi 			RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
1405b685f931SAnkur Dwivedi 			ips->type ==
1406b685f931SAnkur Dwivedi 			RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
1407b685f931SAnkur Dwivedi 			rc = create_inline_session(skt_ctx, sa, ips);
1408b685f931SAnkur Dwivedi 			if (rc != 0) {
1409b685f931SAnkur Dwivedi 				RTE_LOG(ERR, IPSEC_ESP,
1410b685f931SAnkur Dwivedi 					"create_inline_session() failed\n");
1411b685f931SAnkur Dwivedi 				return -EINVAL;
1412b685f931SAnkur Dwivedi 			}
1413a8ade121SVolodymyr Fialko 		} else {
14146938fc92SVolodymyr Fialko 			rc = create_lookaside_session(ips_ctx, skt_ctx,
14156938fc92SVolodymyr Fialko 						      em_conf, sa, ips);
1416a8ade121SVolodymyr Fialko 			if (rc != 0) {
1417a8ade121SVolodymyr Fialko 				RTE_LOG(ERR, IPSEC_ESP,
1418a8ade121SVolodymyr Fialko 					"create_lookaside_session() failed\n");
1419a8ade121SVolodymyr Fialko 				return -EINVAL;
1420a8ade121SVolodymyr Fialko 			}
1421b685f931SAnkur Dwivedi 		}
1422b685f931SAnkur Dwivedi 
14236738c0a9SPraveen Shetty 		if (sa->fdir_flag && inbound) {
14246738c0a9SPraveen Shetty 			rc = create_ipsec_esp_flow(sa);
14256738c0a9SPraveen Shetty 			if (rc != 0)
14266738c0a9SPraveen Shetty 				RTE_LOG(ERR, IPSEC_ESP,
14275ec3eb3bSPraveen Shetty 					"create_ipsec_esp_flow() failed\n");
14286738c0a9SPraveen Shetty 		}
14290d547ed0SFan Zhang 		print_one_sa_rule(sa, inbound);
1430d299106eSSergio Gonzalez Monroy 	}
1431d299106eSSergio Gonzalez Monroy 
1432d299106eSSergio Gonzalez Monroy 	return 0;
1433d299106eSSergio Gonzalez Monroy }
1434d299106eSSergio Gonzalez Monroy 
1435d299106eSSergio Gonzalez Monroy static inline int
1436d299106eSSergio Gonzalez Monroy sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
1437a8ade121SVolodymyr Fialko 		uint32_t nb_entries, struct socket_ctx *skt_ctx,
14386938fc92SVolodymyr Fialko 		struct ipsec_ctx *ips_ctx[],
14396938fc92SVolodymyr Fialko 		const struct eventmode_conf *em_conf)
1440d299106eSSergio Gonzalez Monroy {
14416938fc92SVolodymyr Fialko 	return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx, ips_ctx, em_conf);
1442d299106eSSergio Gonzalez Monroy }
1443d299106eSSergio Gonzalez Monroy 
1444d299106eSSergio Gonzalez Monroy static inline int
1445d299106eSSergio Gonzalez Monroy sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
1446a8ade121SVolodymyr Fialko 		uint32_t nb_entries, struct socket_ctx *skt_ctx,
14476938fc92SVolodymyr Fialko 		struct ipsec_ctx *ips_ctx[],
14486938fc92SVolodymyr Fialko 		const struct eventmode_conf *em_conf)
1449d299106eSSergio Gonzalez Monroy {
14506938fc92SVolodymyr Fialko 	return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx, ips_ctx, em_conf);
1451d299106eSSergio Gonzalez Monroy }
1452d299106eSSergio Gonzalez Monroy 
14535a032a71SKonstantin Ananyev /*
14545a032a71SKonstantin Ananyev  * helper function, fills parameters that are identical for all SAs
14555a032a71SKonstantin Ananyev  */
14565a032a71SKonstantin Ananyev static void
14575a032a71SKonstantin Ananyev fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
14585a032a71SKonstantin Ananyev 	const struct app_sa_prm *app_prm)
14595a032a71SKonstantin Ananyev {
14605a032a71SKonstantin Ananyev 	memset(prm, 0, sizeof(*prm));
14615a032a71SKonstantin Ananyev 
14625a032a71SKonstantin Ananyev 	prm->flags = app_prm->flags;
14635a032a71SKonstantin Ananyev 	prm->ipsec_xform.options.esn = app_prm->enable_esn;
14640f56ca1aSHemant Agrawal 	prm->ipsec_xform.replay_win_sz = app_prm->window_size;
14655a032a71SKonstantin Ananyev }
14665a032a71SKonstantin Ananyev 
14675a032a71SKonstantin Ananyev static int
14685a032a71SKonstantin Ananyev fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
1469a7c528e5SOlivier Matz 	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
14705a032a71SKonstantin Ananyev {
14715a032a71SKonstantin Ananyev 	int32_t rc;
14725a032a71SKonstantin Ananyev 
14735a032a71SKonstantin Ananyev 	/*
14745a032a71SKonstantin Ananyev 	 * Try to get SPI next proto by searching that SPI in SPD.
14755a032a71SKonstantin Ananyev 	 * probably not the optimal way, but there seems nothing
14765a032a71SKonstantin Ananyev 	 * better right now.
14775a032a71SKonstantin Ananyev 	 */
1478b1a3ac78SMariusz Drost 	rc = get_spi_proto(ss->spi, ss->direction, NULL, NULL);
14795a032a71SKonstantin Ananyev 	if (rc < 0)
14805a032a71SKonstantin Ananyev 		return rc;
14815a032a71SKonstantin Ananyev 
14825a032a71SKonstantin Ananyev 	fill_ipsec_app_sa_prm(prm, &app_sa_prm);
14835a032a71SKonstantin Ananyev 	prm->userdata = (uintptr_t)ss;
14845a032a71SKonstantin Ananyev 
14855a032a71SKonstantin Ananyev 	/* setup ipsec xform */
14865a032a71SKonstantin Ananyev 	prm->ipsec_xform.spi = ss->spi;
14875a032a71SKonstantin Ananyev 	prm->ipsec_xform.salt = ss->salt;
14885a032a71SKonstantin Ananyev 	prm->ipsec_xform.direction = ss->direction;
14895a032a71SKonstantin Ananyev 	prm->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
1490b1a3ac78SMariusz Drost 	prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
14915a032a71SKonstantin Ananyev 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
14925a032a71SKonstantin Ananyev 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
14939ae86b4cSRadu Nicolau 	prm->ipsec_xform.options.udp_encap = ss->udp_encap;
14945051dc42SRadu Nicolau 	prm->ipsec_xform.udp.dport = ss->udp.dport;
14955051dc42SRadu Nicolau 	prm->ipsec_xform.udp.sport = ss->udp.sport;
14961cfd1559SFan Zhang 	prm->ipsec_xform.options.ecn = 1;
14971cfd1559SFan Zhang 	prm->ipsec_xform.options.copy_dscp = 1;
14985a032a71SKonstantin Ananyev 
14993e534bc8SRadu Nicolau 	if (ss->esn > 0) {
15003e534bc8SRadu Nicolau 		prm->ipsec_xform.options.esn = 1;
15013e534bc8SRadu Nicolau 		prm->ipsec_xform.esn.value = ss->esn;
15023e534bc8SRadu Nicolau 	}
15033e534bc8SRadu Nicolau 
1504b1a3ac78SMariusz Drost 	if (IS_IP4_TUNNEL(ss->flags)) {
15055a032a71SKonstantin Ananyev 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
15065a032a71SKonstantin Ananyev 		prm->tun.hdr_len = sizeof(*v4);
15075a032a71SKonstantin Ananyev 		prm->tun.next_proto = rc;
15085a032a71SKonstantin Ananyev 		prm->tun.hdr = v4;
1509b1a3ac78SMariusz Drost 	} else if (IS_IP6_TUNNEL(ss->flags)) {
15105a032a71SKonstantin Ananyev 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
15115a032a71SKonstantin Ananyev 		prm->tun.hdr_len = sizeof(*v6);
15125a032a71SKonstantin Ananyev 		prm->tun.next_proto = rc;
15135a032a71SKonstantin Ananyev 		prm->tun.hdr = v6;
15145a032a71SKonstantin Ananyev 	} else {
15155a032a71SKonstantin Ananyev 		/* transport mode */
15165a032a71SKonstantin Ananyev 		prm->trs.proto = rc;
15175a032a71SKonstantin Ananyev 	}
15185a032a71SKonstantin Ananyev 
15195a032a71SKonstantin Ananyev 	/* setup crypto section */
15205a032a71SKonstantin Ananyev 	prm->crypto_xform = ss->xforms;
15215a032a71SKonstantin Ananyev 	return 0;
15225a032a71SKonstantin Ananyev }
15235a032a71SKonstantin Ananyev 
15243a690d5aSBernard Iremonger static int
15254a67af84SMarcin Smoczynski fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa)
15265a032a71SKonstantin Ananyev {
15273a690d5aSBernard Iremonger 	int32_t rc = 0;
15283a690d5aSBernard Iremonger 
15295a032a71SKonstantin Ananyev 	ss->sa = sa;
15303a690d5aSBernard Iremonger 
15313a690d5aSBernard Iremonger 	rc = rte_ipsec_session_prepare(ss);
15323a690d5aSBernard Iremonger 	if (rc != 0)
15333a690d5aSBernard Iremonger 		memset(ss, 0, sizeof(*ss));
15343a690d5aSBernard Iremonger 
15353a690d5aSBernard Iremonger 	return rc;
15365a032a71SKonstantin Ananyev }
15375a032a71SKonstantin Ananyev 
15385a032a71SKonstantin Ananyev /*
15395a032a71SKonstantin Ananyev  * Initialise related rte_ipsec_sa object.
15405a032a71SKonstantin Ananyev  */
15415a032a71SKonstantin Ananyev static int
1542577c85e9SRadu Nicolau ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size,
15436938fc92SVolodymyr Fialko 		struct socket_ctx *skt_ctx, struct ipsec_ctx *ips_ctx[],
15446938fc92SVolodymyr Fialko 		const struct eventmode_conf *em_conf)
15455a032a71SKonstantin Ananyev {
15465a032a71SKonstantin Ananyev 	int rc;
15475a032a71SKonstantin Ananyev 	struct rte_ipsec_sa_prm prm;
15484a67af84SMarcin Smoczynski 	struct rte_ipsec_session *ips;
1549a7c528e5SOlivier Matz 	struct rte_ipv4_hdr v4  = {
15505a032a71SKonstantin Ananyev 		.version_ihl = IPVERSION << 4 |
155124ac604eSOlivier Matz 			sizeof(v4) / RTE_IPV4_IHL_MULTIPLIER,
15525a032a71SKonstantin Ananyev 		.time_to_live = IPDEFTTL,
15535051dc42SRadu Nicolau 		.next_proto_id = lsa->udp_encap ? IPPROTO_UDP : IPPROTO_ESP,
15545a032a71SKonstantin Ananyev 		.src_addr = lsa->src.ip.ip4,
15555a032a71SKonstantin Ananyev 		.dst_addr = lsa->dst.ip.ip4,
15565a032a71SKonstantin Ananyev 	};
1557a7c528e5SOlivier Matz 	struct rte_ipv6_hdr v6 = {
15585a032a71SKonstantin Ananyev 		.vtc_flow = htonl(IP6_VERSION << 28),
15595051dc42SRadu Nicolau 		.proto = lsa->udp_encap ? IPPROTO_UDP : IPPROTO_ESP,
15605a032a71SKonstantin Ananyev 	};
15615a032a71SKonstantin Ananyev 
1562b1a3ac78SMariusz Drost 	if (IS_IP6_TUNNEL(lsa->flags)) {
1563*9ac91e2fSRobin Jarry 		v6.src_addr = lsa->src.ip.ip6;
1564*9ac91e2fSRobin Jarry 		v6.dst_addr = lsa->dst.ip.ip6;
15655a032a71SKonstantin Ananyev 	}
15665a032a71SKonstantin Ananyev 
15675a032a71SKonstantin Ananyev 	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
15685a032a71SKonstantin Ananyev 	if (rc == 0)
15695a032a71SKonstantin Ananyev 		rc = rte_ipsec_sa_init(sa, &prm, sa_size);
15705a032a71SKonstantin Ananyev 	if (rc < 0)
15715a032a71SKonstantin Ananyev 		return rc;
15725a032a71SKonstantin Ananyev 
15733e7b7dd8SRadu Nicolau 	if (lsa->flags & SA_TELEMETRY_ENABLE)
15743e7b7dd8SRadu Nicolau 		rte_ipsec_telemetry_sa_add(sa);
15753e7b7dd8SRadu Nicolau 
1576ba66534fSMarcin Smoczynski 	/* init primary processing session */
1577ba66534fSMarcin Smoczynski 	ips = ipsec_get_primary_session(lsa);
15784a67af84SMarcin Smoczynski 	rc = fill_ipsec_session(ips, sa);
1579ba66534fSMarcin Smoczynski 	if (rc != 0)
1580ba66534fSMarcin Smoczynski 		return rc;
1581ba66534fSMarcin Smoczynski 
1582ba66534fSMarcin Smoczynski 	/* init inline fallback processing session */
1583577c85e9SRadu Nicolau 	if (lsa->fallback_sessions == 1) {
1584577c85e9SRadu Nicolau 		struct rte_ipsec_session *ipfs = ipsec_get_fallback_session(lsa);
1585577c85e9SRadu Nicolau 		if (ipfs->security.ses == NULL) {
15866938fc92SVolodymyr Fialko 			rc = create_lookaside_session(ips_ctx, skt_ctx, em_conf, lsa, ipfs);
1587577c85e9SRadu Nicolau 			if (rc != 0)
1588577c85e9SRadu Nicolau 				return rc;
1589577c85e9SRadu Nicolau 		}
1590577c85e9SRadu Nicolau 		rc = fill_ipsec_session(ipfs, sa);
1591577c85e9SRadu Nicolau 	}
15924a67af84SMarcin Smoczynski 
15933a690d5aSBernard Iremonger 	return rc;
15945a032a71SKonstantin Ananyev }
15955a032a71SKonstantin Ananyev 
15965a032a71SKonstantin Ananyev /*
15977be78d02SJosh Soref  * Allocate space and init rte_ipsec_sa structures,
15985a032a71SKonstantin Ananyev  * one per session.
15995a032a71SKonstantin Ananyev  */
16005a032a71SKonstantin Ananyev static int
1601577c85e9SRadu Nicolau ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket,
16026938fc92SVolodymyr Fialko 		struct socket_ctx *skt_ctx, struct ipsec_ctx *ips_ctx[],
16036938fc92SVolodymyr Fialko 		const struct eventmode_conf *em_conf)
16045a032a71SKonstantin Ananyev {
16055a032a71SKonstantin Ananyev 	int32_t rc, sz;
16065a032a71SKonstantin Ananyev 	uint32_t i, idx;
16075a032a71SKonstantin Ananyev 	size_t tsz;
16085a032a71SKonstantin Ananyev 	struct rte_ipsec_sa *sa;
16095a032a71SKonstantin Ananyev 	struct ipsec_sa *lsa;
16105a032a71SKonstantin Ananyev 	struct rte_ipsec_sa_prm prm;
16115a032a71SKonstantin Ananyev 
16125a032a71SKonstantin Ananyev 	/* determine SA size */
1613df3e1d94SVladimir Medvedkin 	idx = 0;
16145a032a71SKonstantin Ananyev 	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
16155a032a71SKonstantin Ananyev 	sz = rte_ipsec_sa_size(&prm);
16165a032a71SKonstantin Ananyev 	if (sz < 0) {
16175a032a71SKonstantin Ananyev 		RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
16185a032a71SKonstantin Ananyev 			"failed to determine SA size, error code: %d\n",
16195a032a71SKonstantin Ananyev 			__func__, ctx, nb_ent, socket, sz);
16205a032a71SKonstantin Ananyev 		return sz;
16215a032a71SKonstantin Ananyev 	}
16225a032a71SKonstantin Ananyev 
16235a032a71SKonstantin Ananyev 	tsz = sz * nb_ent;
16245a032a71SKonstantin Ananyev 
16255a032a71SKonstantin Ananyev 	ctx->satbl = rte_zmalloc_socket(NULL, tsz, RTE_CACHE_LINE_SIZE, socket);
16265a032a71SKonstantin Ananyev 	if (ctx->satbl == NULL) {
16275a032a71SKonstantin Ananyev 		RTE_LOG(ERR, IPSEC,
16285a032a71SKonstantin Ananyev 			"%s(%p, %u, %d): failed to allocate %zu bytes\n",
16295a032a71SKonstantin Ananyev 			__func__,  ctx, nb_ent, socket, tsz);
16305a032a71SKonstantin Ananyev 		return -ENOMEM;
16315a032a71SKonstantin Ananyev 	}
16325a032a71SKonstantin Ananyev 
16335a032a71SKonstantin Ananyev 	rc = 0;
16345a032a71SKonstantin Ananyev 	for (i = 0; i != nb_ent && rc == 0; i++) {
16355a032a71SKonstantin Ananyev 
1636df3e1d94SVladimir Medvedkin 		idx = i;
16375a032a71SKonstantin Ananyev 
16385a032a71SKonstantin Ananyev 		sa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i);
16395a032a71SKonstantin Ananyev 		lsa = ctx->sa + idx;
16405a032a71SKonstantin Ananyev 
16416938fc92SVolodymyr Fialko 		rc = ipsec_sa_init(lsa, sa, sz, skt_ctx, ips_ctx, em_conf);
16425a032a71SKonstantin Ananyev 	}
16435a032a71SKonstantin Ananyev 
16445a032a71SKonstantin Ananyev 	return rc;
16455a032a71SKonstantin Ananyev }
16465a032a71SKonstantin Ananyev 
1647e1143d7dSVladimir Medvedkin static int
1648e1143d7dSVladimir Medvedkin sa_cmp(const void *p, const void *q)
1649e1143d7dSVladimir Medvedkin {
1650e1143d7dSVladimir Medvedkin 	uint32_t spi1 = ((const struct ipsec_sa *)p)->spi;
1651e1143d7dSVladimir Medvedkin 	uint32_t spi2 = ((const struct ipsec_sa *)q)->spi;
1652e1143d7dSVladimir Medvedkin 
1653e1143d7dSVladimir Medvedkin 	return (int)(spi1 - spi2);
1654e1143d7dSVladimir Medvedkin }
1655e1143d7dSVladimir Medvedkin 
165649757b68SKonstantin Ananyev /*
165749757b68SKonstantin Ananyev  * Walk through all SA rules to find an SA with given SPI
165849757b68SKonstantin Ananyev  */
165949757b68SKonstantin Ananyev int
1660df3e1d94SVladimir Medvedkin sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
166149757b68SKonstantin Ananyev {
1662e1143d7dSVladimir Medvedkin 	uint32_t num;
1663e1143d7dSVladimir Medvedkin 	struct ipsec_sa *sa;
1664e1143d7dSVladimir Medvedkin 	struct ipsec_sa tmpl;
166549757b68SKonstantin Ananyev 	const struct ipsec_sa *sar;
166649757b68SKonstantin Ananyev 
1667df3e1d94SVladimir Medvedkin 	sar = sa_ctx->sa;
1668df3e1d94SVladimir Medvedkin 	if (inbound != 0)
166949757b68SKonstantin Ananyev 		num = nb_sa_in;
1670df3e1d94SVladimir Medvedkin 	else
167149757b68SKonstantin Ananyev 		num = nb_sa_out;
167249757b68SKonstantin Ananyev 
1673e1143d7dSVladimir Medvedkin 	tmpl.spi = spi;
1674e1143d7dSVladimir Medvedkin 
1675e1143d7dSVladimir Medvedkin 	sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp);
1676e1143d7dSVladimir Medvedkin 	if (sa != NULL)
1677e1143d7dSVladimir Medvedkin 		return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa);
167849757b68SKonstantin Ananyev 
167949757b68SKonstantin Ananyev 	return -ENOENT;
168049757b68SKonstantin Ananyev }
168149757b68SKonstantin Ananyev 
1682d299106eSSergio Gonzalez Monroy void
1683a8ade121SVolodymyr Fialko sa_init(struct socket_ctx *ctx, int32_t socket_id,
16846938fc92SVolodymyr Fialko 	struct lcore_conf *lcore_conf,
16856938fc92SVolodymyr Fialko 	const struct eventmode_conf *em_conf)
1686d299106eSSergio Gonzalez Monroy {
16875a032a71SKonstantin Ananyev 	int32_t rc;
1688d299106eSSergio Gonzalez Monroy 	const char *name;
1689a8ade121SVolodymyr Fialko 	uint32_t lcore_id;
1690a8ade121SVolodymyr Fialko 	struct ipsec_ctx *ipsec_ctx[RTE_MAX_LCORE];
1691d299106eSSergio Gonzalez Monroy 
1692d299106eSSergio Gonzalez Monroy 	if (ctx == NULL)
1693d299106eSSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "NULL context.\n");
1694d299106eSSergio Gonzalez Monroy 
1695906257e9SSergio Gonzalez Monroy 	if (ctx->sa_in != NULL)
1696d299106eSSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already "
1697d299106eSSergio Gonzalez Monroy 				"initialized\n", socket_id);
1698d299106eSSergio Gonzalez Monroy 
1699906257e9SSergio Gonzalez Monroy 	if (ctx->sa_out != NULL)
1700d299106eSSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
1701d299106eSSergio Gonzalez Monroy 				"initialized\n", socket_id);
1702d299106eSSergio Gonzalez Monroy 
17030d547ed0SFan Zhang 	if (nb_sa_in > 0) {
1704906257e9SSergio Gonzalez Monroy 		name = "sa_in";
1705df3e1d94SVladimir Medvedkin 		ctx->sa_in = sa_create(name, socket_id, nb_sa_in);
1706906257e9SSergio Gonzalez Monroy 		if (ctx->sa_in == NULL)
17070d547ed0SFan Zhang 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
17080d547ed0SFan Zhang 				"context %s in socket %d\n", rte_errno,
17090d547ed0SFan Zhang 				name, socket_id);
1710d299106eSSergio Gonzalez Monroy 
1711df3e1d94SVladimir Medvedkin 		rc = ipsec_sad_create(name, &ctx->sa_in->sad, socket_id,
1712df3e1d94SVladimir Medvedkin 				&sa_in_cnt);
1713df3e1d94SVladimir Medvedkin 		if (rc != 0)
1714df3e1d94SVladimir Medvedkin 			rte_exit(EXIT_FAILURE, "failed to init SAD\n");
1715a8ade121SVolodymyr Fialko 		RTE_LCORE_FOREACH(lcore_id)
1716a8ade121SVolodymyr Fialko 			ipsec_ctx[lcore_id] = &lcore_conf[lcore_id].inbound;
17176938fc92SVolodymyr Fialko 		sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx, ipsec_ctx, em_conf);
17185a032a71SKonstantin Ananyev 
17195a032a71SKonstantin Ananyev 		if (app_sa_prm.enable != 0) {
1720df3e1d94SVladimir Medvedkin 			rc = ipsec_satbl_init(ctx->sa_in, nb_sa_in,
17216938fc92SVolodymyr Fialko 				socket_id, ctx, ipsec_ctx, em_conf);
17225a032a71SKonstantin Ananyev 			if (rc != 0)
17235a032a71SKonstantin Ananyev 				rte_exit(EXIT_FAILURE,
17245a032a71SKonstantin Ananyev 					"failed to init inbound SAs\n");
17255a032a71SKonstantin Ananyev 		}
17260d547ed0SFan Zhang 	} else
17270d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n");
17280d547ed0SFan Zhang 
17290d547ed0SFan Zhang 	if (nb_sa_out > 0) {
1730906257e9SSergio Gonzalez Monroy 		name = "sa_out";
1731df3e1d94SVladimir Medvedkin 		ctx->sa_out = sa_create(name, socket_id, nb_sa_out);
1732906257e9SSergio Gonzalez Monroy 		if (ctx->sa_out == NULL)
17330d547ed0SFan Zhang 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
17340d547ed0SFan Zhang 				"context %s in socket %d\n", rte_errno,
17350d547ed0SFan Zhang 				name, socket_id);
1736d299106eSSergio Gonzalez Monroy 
1737a8ade121SVolodymyr Fialko 		RTE_LCORE_FOREACH(lcore_id)
1738a8ade121SVolodymyr Fialko 			ipsec_ctx[lcore_id] = &lcore_conf[lcore_id].outbound;
17396938fc92SVolodymyr Fialko 		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx, ipsec_ctx, em_conf);
17405a032a71SKonstantin Ananyev 
17415a032a71SKonstantin Ananyev 		if (app_sa_prm.enable != 0) {
1742df3e1d94SVladimir Medvedkin 			rc = ipsec_satbl_init(ctx->sa_out, nb_sa_out,
17436938fc92SVolodymyr Fialko 				socket_id, ctx, ipsec_ctx, em_conf);
17445a032a71SKonstantin Ananyev 			if (rc != 0)
17455a032a71SKonstantin Ananyev 				rte_exit(EXIT_FAILURE,
17465a032a71SKonstantin Ananyev 					"failed to init outbound SAs\n");
17475a032a71SKonstantin Ananyev 		}
17480d547ed0SFan Zhang 	} else
17490d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No SA Outbound rule "
17500d547ed0SFan Zhang 			"specified\n");
1751d299106eSSergio Gonzalez Monroy }
1752d299106eSSergio Gonzalez Monroy 
1753d299106eSSergio Gonzalez Monroy int
1754d299106eSSergio Gonzalez Monroy inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
1755d299106eSSergio Gonzalez Monroy {
1756d299106eSSergio Gonzalez Monroy 	struct ipsec_mbuf_metadata *priv;
1757e0dac065SKonstantin Ananyev 	struct ipsec_sa *sa;
1758d299106eSSergio Gonzalez Monroy 
1759b1d295e6SDan Gora 	priv = get_priv(m);
1760e0dac065SKonstantin Ananyev 	sa = priv->sa;
1761e0dac065SKonstantin Ananyev 	if (sa != NULL)
1762e0dac065SKonstantin Ananyev 		return (sa_ctx->sa[sa_idx].spi == sa->spi);
1763d299106eSSergio Gonzalez Monroy 
1764e0dac065SKonstantin Ananyev 	RTE_LOG(ERR, IPSEC, "SA not saved in private data\n");
1765e0dac065SKonstantin Ananyev 	return 0;
1766d299106eSSergio Gonzalez Monroy }
1767d299106eSSergio Gonzalez Monroy 
1768df3e1d94SVladimir Medvedkin void
1769df3e1d94SVladimir Medvedkin inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
1770df3e1d94SVladimir Medvedkin 		void *sa_arr[], uint16_t nb_pkts)
1771906257e9SSergio Gonzalez Monroy {
1772df3e1d94SVladimir Medvedkin 	uint32_t i;
1773ba66534fSMarcin Smoczynski 	void *result_sa;
1774df3e1d94SVladimir Medvedkin 	struct ipsec_sa *sa;
1775906257e9SSergio Gonzalez Monroy 
1776df3e1d94SVladimir Medvedkin 	sad_lookup(&sa_ctx->sad, pkts, sa_arr, nb_pkts);
1777906257e9SSergio Gonzalez Monroy 
1778ba66534fSMarcin Smoczynski 	/*
1779ba66534fSMarcin Smoczynski 	 * Mark need for inline offload fallback on the LSB of SA pointer.
1780ba66534fSMarcin Smoczynski 	 * Thanks to packet grouping mechanism which ipsec_process is using
1781ba66534fSMarcin Smoczynski 	 * packets marked for fallback processing will form separate group.
1782ba66534fSMarcin Smoczynski 	 *
1783ba66534fSMarcin Smoczynski 	 * Because it is not safe to use SA pointer it is casted to generic
1784ba66534fSMarcin Smoczynski 	 * pointer to prevent from unintentional use. Use ipsec_mask_saptr
1785ba66534fSMarcin Smoczynski 	 * to get valid struct pointer.
1786ba66534fSMarcin Smoczynski 	 */
1787df3e1d94SVladimir Medvedkin 	for (i = 0; i < nb_pkts; i++) {
1788df3e1d94SVladimir Medvedkin 		if (sa_arr[i] == NULL)
1789df3e1d94SVladimir Medvedkin 			continue;
1790df3e1d94SVladimir Medvedkin 
1791df3e1d94SVladimir Medvedkin 		result_sa = sa = sa_arr[i];
1792df3e1d94SVladimir Medvedkin 		if (MBUF_NO_SEC_OFFLOAD(pkts[i]) &&
1793df3e1d94SVladimir Medvedkin 			sa->fallback_sessions > 0) {
1794ba66534fSMarcin Smoczynski 			uintptr_t intsa = (uintptr_t)sa;
1795ba66534fSMarcin Smoczynski 			intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
1796ba66534fSMarcin Smoczynski 			result_sa = (void *)intsa;
1797ba66534fSMarcin Smoczynski 		}
1798df3e1d94SVladimir Medvedkin 		sa_arr[i] = result_sa;
1799906257e9SSergio Gonzalez Monroy 	}
1800d299106eSSergio Gonzalez Monroy }
1801d299106eSSergio Gonzalez Monroy 
1802d299106eSSergio Gonzalez Monroy void
1803d299106eSSergio Gonzalez Monroy outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
1804ba66534fSMarcin Smoczynski 		void *sa[], uint16_t nb_pkts)
1805d299106eSSergio Gonzalez Monroy {
1806906257e9SSergio Gonzalez Monroy 	uint32_t i;
1807d299106eSSergio Gonzalez Monroy 
1808d299106eSSergio Gonzalez Monroy 	for (i = 0; i < nb_pkts; i++)
1809d299106eSSergio Gonzalez Monroy 		sa[i] = &sa_ctx->sa[sa_idx[i]];
1810d299106eSSergio Gonzalez Monroy }
181103128be4SKonstantin Ananyev 
181203128be4SKonstantin Ananyev /*
181303128be4SKonstantin Ananyev  * Select HW offloads to be used.
181403128be4SKonstantin Ananyev  */
181503128be4SKonstantin Ananyev int
181603128be4SKonstantin Ananyev sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
1817d8d51d4fSRahul Bhansali 		uint64_t *tx_offloads, uint8_t *hw_reassembly)
181803128be4SKonstantin Ananyev {
181903128be4SKonstantin Ananyev 	struct ipsec_sa *rule;
182003128be4SKonstantin Ananyev 	uint32_t idx_sa;
18214a67af84SMarcin Smoczynski 	enum rte_security_session_action_type rule_type;
1822d24471e5SNithin Dabilpuram 	struct rte_eth_dev_info dev_info;
1823d24471e5SNithin Dabilpuram 	int ret;
182403128be4SKonstantin Ananyev 
182503128be4SKonstantin Ananyev 	*rx_offloads = 0;
182603128be4SKonstantin Ananyev 	*tx_offloads = 0;
1827e9a4d497SNithin Dabilpuram 	*hw_reassembly = 0;
182803128be4SKonstantin Ananyev 
1829d24471e5SNithin Dabilpuram 	ret = rte_eth_dev_info_get(port_id, &dev_info);
1830d24471e5SNithin Dabilpuram 	if (ret != 0)
1831d24471e5SNithin Dabilpuram 		rte_exit(EXIT_FAILURE,
1832d24471e5SNithin Dabilpuram 			"Error during getting device (port %u) info: %s\n",
1833d24471e5SNithin Dabilpuram 			port_id, strerror(-ret));
1834d24471e5SNithin Dabilpuram 
183503128be4SKonstantin Ananyev 	/* Check for inbound rules that use offloads and use this port */
183603128be4SKonstantin Ananyev 	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
183703128be4SKonstantin Ananyev 		rule = &sa_in[idx_sa];
18384a67af84SMarcin Smoczynski 		rule_type = ipsec_get_action_type(rule);
18394a67af84SMarcin Smoczynski 		if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
18404a67af84SMarcin Smoczynski 				rule_type ==
184103128be4SKonstantin Ananyev 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
184203128be4SKonstantin Ananyev 				&& rule->portid == port_id)
1843295968d1SFerruh Yigit 			*rx_offloads |= RTE_ETH_RX_OFFLOAD_SECURITY;
1844d8d51d4fSRahul Bhansali 		if (IS_HW_REASSEMBLY_EN(rule->flags)) {
1845d8d51d4fSRahul Bhansali 			*tx_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
1846d8d51d4fSRahul Bhansali 			*hw_reassembly = 1;
1847d8d51d4fSRahul Bhansali 		}
184803128be4SKonstantin Ananyev 	}
184903128be4SKonstantin Ananyev 
185003128be4SKonstantin Ananyev 	/* Check for outbound rules that use offloads and use this port */
185103128be4SKonstantin Ananyev 	for (idx_sa = 0; idx_sa < nb_sa_out; idx_sa++) {
185203128be4SKonstantin Ananyev 		rule = &sa_out[idx_sa];
18534a67af84SMarcin Smoczynski 		rule_type = ipsec_get_action_type(rule);
185465bd9c7aSRadu Nicolau 		if (rule->portid == port_id) {
1855d24471e5SNithin Dabilpuram 			switch (rule_type) {
1856d24471e5SNithin Dabilpuram 			case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
185765bd9c7aSRadu Nicolau 				/* Checksum offload is not needed for inline
185865bd9c7aSRadu Nicolau 				 * protocol as all processing for Outbound IPSec
185965bd9c7aSRadu Nicolau 				 * packets will be implicitly taken care and for
186065bd9c7aSRadu Nicolau 				 * non-IPSec packets, there is no need of
186165bd9c7aSRadu Nicolau 				 * IPv4 Checksum offload.
1862d24471e5SNithin Dabilpuram 				 */
1863295968d1SFerruh Yigit 				*tx_offloads |= RTE_ETH_TX_OFFLOAD_SECURITY;
1864a7f32947SRadu Nicolau 				if (rule->mss)
1865d24471e5SNithin Dabilpuram 					*tx_offloads |= (RTE_ETH_TX_OFFLOAD_TCP_TSO |
1866d24471e5SNithin Dabilpuram 							 RTE_ETH_TX_OFFLOAD_IPV4_CKSUM);
1867d24471e5SNithin Dabilpuram 				break;
1868d24471e5SNithin Dabilpuram 			case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
1869d24471e5SNithin Dabilpuram 				*tx_offloads |= RTE_ETH_TX_OFFLOAD_SECURITY;
1870d24471e5SNithin Dabilpuram 				if (rule->mss)
1871d24471e5SNithin Dabilpuram 					*tx_offloads |=
1872d24471e5SNithin Dabilpuram 						RTE_ETH_TX_OFFLOAD_TCP_TSO;
187365bd9c7aSRadu Nicolau 				if (dev_info.tx_offload_capa &
187465bd9c7aSRadu Nicolau 						RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)
187565bd9c7aSRadu Nicolau 					*tx_offloads |=
187665bd9c7aSRadu Nicolau 						RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
1877d24471e5SNithin Dabilpuram 				break;
1878d24471e5SNithin Dabilpuram 			default:
187965bd9c7aSRadu Nicolau 				/* Enable IPv4 checksum offload even if
188065bd9c7aSRadu Nicolau 				 * one of lookaside SA's are present.
1881d24471e5SNithin Dabilpuram 				 */
1882d24471e5SNithin Dabilpuram 				if (dev_info.tx_offload_capa &
1883d24471e5SNithin Dabilpuram 				    RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)
1884d24471e5SNithin Dabilpuram 					*tx_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
1885d24471e5SNithin Dabilpuram 				break;
1886a7f32947SRadu Nicolau 			}
188765bd9c7aSRadu Nicolau 		} else {
188865bd9c7aSRadu Nicolau 			if (dev_info.tx_offload_capa &
188965bd9c7aSRadu Nicolau 			    RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)
189065bd9c7aSRadu Nicolau 				*tx_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
189165bd9c7aSRadu Nicolau 		}
189203128be4SKonstantin Ananyev 	}
189303128be4SKonstantin Ananyev 	return 0;
189403128be4SKonstantin Ananyev }
1895e1143d7dSVladimir Medvedkin 
1896e1143d7dSVladimir Medvedkin void
1897e1143d7dSVladimir Medvedkin sa_sort_arr(void)
1898e1143d7dSVladimir Medvedkin {
1899e1143d7dSVladimir Medvedkin 	qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp);
1900e1143d7dSVladimir Medvedkin 	qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp);
1901e1143d7dSVladimir Medvedkin }
190204fa1906SVladimir Medvedkin 
190304fa1906SVladimir Medvedkin uint32_t
190404fa1906SVladimir Medvedkin get_nb_crypto_sessions(void)
190504fa1906SVladimir Medvedkin {
190604fa1906SVladimir Medvedkin 	return nb_crypto_sessions;
190704fa1906SVladimir Medvedkin }
1908