xref: /dpdk/drivers/net/nfp/nfp_ipsec.c (revision 08966fe7f79fdaa5019b7559eebe84a1e3787b89)
154713740SChang Miao /* SPDX-License-Identifier: BSD-3-Clause
254713740SChang Miao  * Copyright (c) 2023 Corigine Systems, Inc.
354713740SChang Miao  * All rights reserved.
454713740SChang Miao  */
554713740SChang Miao 
6*08966fe7STyler Retzlaff #include <stdalign.h>
7*08966fe7STyler Retzlaff 
854713740SChang Miao #include "nfp_ipsec.h"
954713740SChang Miao 
10e6d69ea0SShihong Wang #include <rte_cryptodev.h>
1154713740SChang Miao #include <rte_malloc.h>
1254713740SChang Miao #include <rte_security_driver.h>
1354713740SChang Miao 
1454713740SChang Miao #include <ethdev_driver.h>
1554713740SChang Miao #include <ethdev_pci.h>
1654713740SChang Miao 
1754713740SChang Miao #include "nfp_logs.h"
1811e9eae4SChaoyong He #include "nfp_net_common.h"
19e2018e37SChaoyong He #include "nfp_net_ctrl.h"
2054713740SChang Miao #include "nfp_rxtx.h"
2154713740SChang Miao 
223d21da66SChang Miao #define NFP_UDP_ESP_PORT            4500
233d21da66SChang Miao 
24e6d69ea0SShihong Wang static const struct rte_cryptodev_capabilities nfp_crypto_caps[] = {
25e6d69ea0SShihong Wang 	{
26e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
27e6d69ea0SShihong Wang 		.sym = {
28e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
29e6d69ea0SShihong Wang 			.auth = {
30e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
31e6d69ea0SShihong Wang 				.block_size = 64,
32e6d69ea0SShihong Wang 				.key_size = {
33e6d69ea0SShihong Wang 					.min = 16,
34e6d69ea0SShihong Wang 					.max = 16,
35e6d69ea0SShihong Wang 					.increment = 0
36e6d69ea0SShihong Wang 				},
37e6d69ea0SShihong Wang 				.digest_size = {
38e6d69ea0SShihong Wang 					.min = 12,
39e6d69ea0SShihong Wang 					.max = 16,
40e6d69ea0SShihong Wang 					.increment = 4
41e6d69ea0SShihong Wang 				},
42e6d69ea0SShihong Wang 			},
43e6d69ea0SShihong Wang 		},
44e6d69ea0SShihong Wang 	},
45e6d69ea0SShihong Wang 	{
46e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
47e6d69ea0SShihong Wang 		.sym = {
48e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
49e6d69ea0SShihong Wang 			.auth = {
50e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
51e6d69ea0SShihong Wang 				.block_size = 64,
52e6d69ea0SShihong Wang 				.key_size = {
53e6d69ea0SShihong Wang 					.min = 20,
54e6d69ea0SShihong Wang 					.max = 64,
55e6d69ea0SShihong Wang 					.increment = 1
56e6d69ea0SShihong Wang 				},
57e6d69ea0SShihong Wang 				.digest_size = {
58e6d69ea0SShihong Wang 					.min = 10,
59e6d69ea0SShihong Wang 					.max = 12,
60e6d69ea0SShihong Wang 					.increment = 2
61e6d69ea0SShihong Wang 				},
62e6d69ea0SShihong Wang 			},
63e6d69ea0SShihong Wang 		},
64e6d69ea0SShihong Wang 	},
65e6d69ea0SShihong Wang 	{
66e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
67e6d69ea0SShihong Wang 		.sym = {
68e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
69e6d69ea0SShihong Wang 			.auth = {
70e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
71e6d69ea0SShihong Wang 				.block_size = 64,
72e6d69ea0SShihong Wang 				.key_size = {
73e6d69ea0SShihong Wang 					.min = 32,
74e6d69ea0SShihong Wang 					.max = 32,
75e6d69ea0SShihong Wang 					.increment = 0
76e6d69ea0SShihong Wang 				},
77e6d69ea0SShihong Wang 				.digest_size = {
78e6d69ea0SShihong Wang 					.min = 12,
79e6d69ea0SShihong Wang 					.max = 16,
80e6d69ea0SShihong Wang 					.increment = 4
81e6d69ea0SShihong Wang 				},
82e6d69ea0SShihong Wang 			},
83e6d69ea0SShihong Wang 		},
84e6d69ea0SShihong Wang 	},
85e6d69ea0SShihong Wang 	{
86e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
87e6d69ea0SShihong Wang 		.sym = {
88e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
89e6d69ea0SShihong Wang 			.auth = {
90e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
91e6d69ea0SShihong Wang 				.block_size = 128,
92e6d69ea0SShihong Wang 				.key_size = {
93e6d69ea0SShihong Wang 					.min = 48,
94e6d69ea0SShihong Wang 					.max = 48,
95e6d69ea0SShihong Wang 					.increment = 0
96e6d69ea0SShihong Wang 				},
97e6d69ea0SShihong Wang 				.digest_size = {
98e6d69ea0SShihong Wang 					.min = 12,
99e6d69ea0SShihong Wang 					.max = 24,
100e6d69ea0SShihong Wang 					.increment = 12
101e6d69ea0SShihong Wang 				},
102e6d69ea0SShihong Wang 			},
103e6d69ea0SShihong Wang 		},
104e6d69ea0SShihong Wang 	},
105e6d69ea0SShihong Wang 	{
106e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
107e6d69ea0SShihong Wang 		.sym = {
108e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
109e6d69ea0SShihong Wang 			.auth = {
110e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
111e6d69ea0SShihong Wang 				.block_size = 128,
112e6d69ea0SShihong Wang 				.key_size = {
113e6d69ea0SShihong Wang 					.min = 64,
114e6d69ea0SShihong Wang 					.max = 64,
115e6d69ea0SShihong Wang 					.increment = 1
116e6d69ea0SShihong Wang 				},
117e6d69ea0SShihong Wang 				.digest_size = {
118e6d69ea0SShihong Wang 					.min = 12,
119e6d69ea0SShihong Wang 					.max = 32,
120e6d69ea0SShihong Wang 					.increment = 4
121e6d69ea0SShihong Wang 				},
122e6d69ea0SShihong Wang 			},
123e6d69ea0SShihong Wang 		},
124e6d69ea0SShihong Wang 	},
125e6d69ea0SShihong Wang 	{
126e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
127e6d69ea0SShihong Wang 		.sym = {
128e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
129e6d69ea0SShihong Wang 			.cipher = {
130e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_CIPHER_3DES_CBC,
131e6d69ea0SShihong Wang 				.block_size = 8,
132e6d69ea0SShihong Wang 				.key_size = {
133e6d69ea0SShihong Wang 					.min = 24,
134e6d69ea0SShihong Wang 					.max = 24,
135e6d69ea0SShihong Wang 					.increment = 0
136e6d69ea0SShihong Wang 				},
137e6d69ea0SShihong Wang 				.iv_size = {
138e6d69ea0SShihong Wang 					.min = 8,
139e6d69ea0SShihong Wang 					.max = 16,
140e6d69ea0SShihong Wang 					.increment = 8
141e6d69ea0SShihong Wang 				},
142e6d69ea0SShihong Wang 			},
143e6d69ea0SShihong Wang 		},
144e6d69ea0SShihong Wang 	},
145e6d69ea0SShihong Wang 	{
146e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
147e6d69ea0SShihong Wang 		.sym = {
148e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
149e6d69ea0SShihong Wang 			.cipher = {
150e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
151e6d69ea0SShihong Wang 				.block_size = 16,
152e6d69ea0SShihong Wang 				.key_size = {
153e6d69ea0SShihong Wang 					.min = 16,
154e6d69ea0SShihong Wang 					.max = 32,
155e6d69ea0SShihong Wang 					.increment = 8
156e6d69ea0SShihong Wang 				},
157e6d69ea0SShihong Wang 				.iv_size = {
158e6d69ea0SShihong Wang 					.min = 8,
159e6d69ea0SShihong Wang 					.max = 16,
160e6d69ea0SShihong Wang 					.increment = 8
161e6d69ea0SShihong Wang 				},
162e6d69ea0SShihong Wang 			},
163e6d69ea0SShihong Wang 		},
164e6d69ea0SShihong Wang 	},
165e6d69ea0SShihong Wang 	{
166e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
167e6d69ea0SShihong Wang 		.sym = {
168e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
169e6d69ea0SShihong Wang 			.aead = {
170e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AEAD_AES_GCM,
171e6d69ea0SShihong Wang 				.block_size = 16,
172e6d69ea0SShihong Wang 				.key_size = {
173e6d69ea0SShihong Wang 					.min = 16,
174e6d69ea0SShihong Wang 					.max = 32,
175e6d69ea0SShihong Wang 					.increment = 8
176e6d69ea0SShihong Wang 				},
177e6d69ea0SShihong Wang 				.digest_size = {
178e6d69ea0SShihong Wang 					.min = 16,
179e6d69ea0SShihong Wang 					.max = 16,
180e6d69ea0SShihong Wang 					.increment = 0
181e6d69ea0SShihong Wang 				},
182e6d69ea0SShihong Wang 				.aad_size = {
183e6d69ea0SShihong Wang 					.min = 0,
184e6d69ea0SShihong Wang 					.max = 1024,
185e6d69ea0SShihong Wang 					.increment = 1
186e6d69ea0SShihong Wang 				},
187e6d69ea0SShihong Wang 				.iv_size = {
188e6d69ea0SShihong Wang 					.min = 8,
189e6d69ea0SShihong Wang 					.max = 16,
190e6d69ea0SShihong Wang 					.increment = 4
191e6d69ea0SShihong Wang 				}
192e6d69ea0SShihong Wang 			},
193e6d69ea0SShihong Wang 		},
194e6d69ea0SShihong Wang 	},
195e6d69ea0SShihong Wang 	{
196e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
197e6d69ea0SShihong Wang 		.sym = {
198e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
199e6d69ea0SShihong Wang 			.aead = {
200e6d69ea0SShihong Wang 				.algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
201e6d69ea0SShihong Wang 				.block_size = 16,
202e6d69ea0SShihong Wang 				.key_size = {
203e6d69ea0SShihong Wang 					.min = 32,
204e6d69ea0SShihong Wang 					.max = 32,
205e6d69ea0SShihong Wang 					.increment = 0
206e6d69ea0SShihong Wang 				},
207e6d69ea0SShihong Wang 				.digest_size = {
208e6d69ea0SShihong Wang 					.min = 16,
209e6d69ea0SShihong Wang 					.max = 16,
210e6d69ea0SShihong Wang 					.increment = 0
211e6d69ea0SShihong Wang 				},
212e6d69ea0SShihong Wang 				.aad_size = {
213e6d69ea0SShihong Wang 					.min = 0,
214e6d69ea0SShihong Wang 					.max = 1024,
215e6d69ea0SShihong Wang 					.increment = 1
216e6d69ea0SShihong Wang 				},
217e6d69ea0SShihong Wang 				.iv_size = {
218e6d69ea0SShihong Wang 					.min = 8,
219e6d69ea0SShihong Wang 					.max = 16,
220e6d69ea0SShihong Wang 					.increment = 4
221e6d69ea0SShihong Wang 				}
222e6d69ea0SShihong Wang 			},
223e6d69ea0SShihong Wang 		},
224e6d69ea0SShihong Wang 	},
225e6d69ea0SShihong Wang 	{
226e6d69ea0SShihong Wang 		.op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
227e6d69ea0SShihong Wang 		.sym = {
228e6d69ea0SShihong Wang 			.xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
229e6d69ea0SShihong Wang 		},
230e6d69ea0SShihong Wang 	}
231e6d69ea0SShihong Wang };
232e6d69ea0SShihong Wang 
233e6d69ea0SShihong Wang static const struct rte_security_capability nfp_security_caps[] = {
234e6d69ea0SShihong Wang 	{ /* IPsec Inline Crypto Tunnel Egress */
235e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
236e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
237e6d69ea0SShihong Wang 		.ipsec = {
238e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
239e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
240e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
241e6d69ea0SShihong Wang 			.options = {
242e6d69ea0SShihong Wang 				.udp_encap = 1,
243e6d69ea0SShihong Wang 				.stats = 1,
244e6d69ea0SShihong Wang 				.esn = 1
245e6d69ea0SShihong Wang 				}
246e6d69ea0SShihong Wang 		},
24768287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps,
24868287e9bSShihong Wang 		.ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
249e6d69ea0SShihong Wang 	},
250e6d69ea0SShihong Wang 	{ /* IPsec Inline Crypto Tunnel Ingress */
251e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
252e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
253e6d69ea0SShihong Wang 		.ipsec = {
254e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
255e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
256e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
257e6d69ea0SShihong Wang 			.options = {
258e6d69ea0SShihong Wang 				.udp_encap = 1,
259e6d69ea0SShihong Wang 				.stats = 1,
260e6d69ea0SShihong Wang 				.esn = 1
261e6d69ea0SShihong Wang 				}
262e6d69ea0SShihong Wang 		},
26368287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps
264e6d69ea0SShihong Wang 	},
265e6d69ea0SShihong Wang 	{ /* IPsec Inline Crypto Transport Egress */
266e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
267e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
268e6d69ea0SShihong Wang 		.ipsec = {
269e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
270e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
271e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
272e6d69ea0SShihong Wang 			.options = {
273e6d69ea0SShihong Wang 				.udp_encap = 1,
274e6d69ea0SShihong Wang 				.stats = 1,
275e6d69ea0SShihong Wang 				.esn = 1
276e6d69ea0SShihong Wang 				}
277e6d69ea0SShihong Wang 		},
27868287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps,
27968287e9bSShihong Wang 		.ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
280e6d69ea0SShihong Wang 	},
281e6d69ea0SShihong Wang 	{ /* IPsec Inline Crypto Transport Ingress */
282e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
283e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
284e6d69ea0SShihong Wang 		.ipsec = {
285e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
286e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
287e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
288e6d69ea0SShihong Wang 			.options = {
289e6d69ea0SShihong Wang 				.udp_encap = 1,
290e6d69ea0SShihong Wang 				.stats = 1,
291e6d69ea0SShihong Wang 				.esn = 1
292e6d69ea0SShihong Wang 				}
293e6d69ea0SShihong Wang 		},
29468287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps
295e6d69ea0SShihong Wang 	},
296e6d69ea0SShihong Wang 	{ /* IPsec Inline Protocol Tunnel Egress */
297e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
298e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
299e6d69ea0SShihong Wang 		.ipsec = {
300e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
301e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
302e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
303e6d69ea0SShihong Wang 			.options = {
304e6d69ea0SShihong Wang 				.udp_encap = 1,
305e6d69ea0SShihong Wang 				.stats = 1,
306e6d69ea0SShihong Wang 				.esn = 1
307e6d69ea0SShihong Wang 				}
308e6d69ea0SShihong Wang 		},
30968287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps,
31068287e9bSShihong Wang 		.ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
311e6d69ea0SShihong Wang 	},
312e6d69ea0SShihong Wang 	{ /* IPsec Inline Protocol Tunnel Ingress */
313e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
314e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
315e6d69ea0SShihong Wang 		.ipsec = {
316e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
317e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
318e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
319e6d69ea0SShihong Wang 			.options = {
320e6d69ea0SShihong Wang 				.udp_encap = 1,
321e6d69ea0SShihong Wang 				.stats = 1,
322e6d69ea0SShihong Wang 				.esn = 1
323e6d69ea0SShihong Wang 				}
324e6d69ea0SShihong Wang 		},
32568287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps
326e6d69ea0SShihong Wang 	},
327e6d69ea0SShihong Wang 	{ /* IPsec Inline Protocol Transport Egress */
328e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
329e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
330e6d69ea0SShihong Wang 		.ipsec = {
331e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
332e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
333e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
334e6d69ea0SShihong Wang 			.options = {
335e6d69ea0SShihong Wang 				.udp_encap = 1,
336e6d69ea0SShihong Wang 				.stats = 1,
337e6d69ea0SShihong Wang 				.esn = 1
338e6d69ea0SShihong Wang 				}
339e6d69ea0SShihong Wang 		},
34068287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps,
34168287e9bSShihong Wang 		.ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
342e6d69ea0SShihong Wang 	},
343e6d69ea0SShihong Wang 	{ /* IPsec Inline Protocol Transport Ingress */
344e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
345e6d69ea0SShihong Wang 		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
346e6d69ea0SShihong Wang 		.ipsec = {
347e6d69ea0SShihong Wang 			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
348e6d69ea0SShihong Wang 			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
349e6d69ea0SShihong Wang 			.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
350e6d69ea0SShihong Wang 			.options = {
351e6d69ea0SShihong Wang 				.udp_encap = 1,
352e6d69ea0SShihong Wang 				.stats = 1,
353e6d69ea0SShihong Wang 				.esn = 1
354e6d69ea0SShihong Wang 				}
355e6d69ea0SShihong Wang 		},
35668287e9bSShihong Wang 		.crypto_capabilities = nfp_crypto_caps
357e6d69ea0SShihong Wang 	},
358e6d69ea0SShihong Wang 	{
359e6d69ea0SShihong Wang 		.action = RTE_SECURITY_ACTION_TYPE_NONE
360e6d69ea0SShihong Wang 	}
361e6d69ea0SShihong Wang };
362e6d69ea0SShihong Wang 
3637fb333e9SShihong Wang /* IPsec config message cmd codes */
3647fb333e9SShihong Wang enum nfp_ipsec_cfg_msg_cmd_codes {
3657fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_ADD_SA,       /**< Add a new SA */
3667fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_INV_SA,       /**< Invalidate an existing SA */
3677fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_MODIFY_SA,    /**< Modify an existing SA */
3687fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_GET_SA_STATS, /**< Report SA counters, flags, etc. */
3697fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_GET_SEQ_NUMS, /**< Allocate sequence numbers */
3707fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_LAST
3717fb333e9SShihong Wang };
3727fb333e9SShihong Wang 
3737fb333e9SShihong Wang enum nfp_ipsec_cfg_msg_rsp_codes {
3747fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_OK,
3757fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_FAILED,
3767fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_SA_VALID,
3777fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED,
3787fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED,
3797fb333e9SShihong Wang 	NFP_IPSEC_CFG_MSG_SA_INVALID_CMD
3807fb333e9SShihong Wang };
3817fb333e9SShihong Wang 
3823d21da66SChang Miao enum nfp_ipsec_mode {
3833d21da66SChang Miao 	NFP_IPSEC_MODE_TRANSPORT,
3843d21da66SChang Miao 	NFP_IPSEC_MODE_TUNNEL,
3853d21da66SChang Miao };
3863d21da66SChang Miao 
3873d21da66SChang Miao enum nfp_ipsec_protocol {
3883d21da66SChang Miao 	NFP_IPSEC_PROTOCOL_AH,
3893d21da66SChang Miao 	NFP_IPSEC_PROTOCOL_ESP,
3903d21da66SChang Miao };
3913d21da66SChang Miao 
3923d21da66SChang Miao /* Cipher modes */
3933d21da66SChang Miao enum nfp_ipsec_cimode {
3943d21da66SChang Miao 	NFP_IPSEC_CIMODE_ECB,
3953d21da66SChang Miao 	NFP_IPSEC_CIMODE_CBC,
3963d21da66SChang Miao 	NFP_IPSEC_CIMODE_CFB,
3973d21da66SChang Miao 	NFP_IPSEC_CIMODE_OFB,
3983d21da66SChang Miao 	NFP_IPSEC_CIMODE_CTR,
3993d21da66SChang Miao };
4003d21da66SChang Miao 
4013d21da66SChang Miao /* Hash types */
4023d21da66SChang Miao enum nfp_ipsec_hash_type {
4033d21da66SChang Miao 	NFP_IPSEC_HASH_NONE,
4043d21da66SChang Miao 	NFP_IPSEC_HASH_MD5_96,
4053d21da66SChang Miao 	NFP_IPSEC_HASH_SHA1_96,
4063d21da66SChang Miao 	NFP_IPSEC_HASH_SHA256_96,
4073d21da66SChang Miao 	NFP_IPSEC_HASH_SHA384_96,
4083d21da66SChang Miao 	NFP_IPSEC_HASH_SHA512_96,
4093d21da66SChang Miao 	NFP_IPSEC_HASH_MD5_128,
4103d21da66SChang Miao 	NFP_IPSEC_HASH_SHA1_80,
4113d21da66SChang Miao 	NFP_IPSEC_HASH_SHA256_128,
4123d21da66SChang Miao 	NFP_IPSEC_HASH_SHA384_192,
4133d21da66SChang Miao 	NFP_IPSEC_HASH_SHA512_256,
4143d21da66SChang Miao 	NFP_IPSEC_HASH_GF128_128,
4153d21da66SChang Miao 	NFP_IPSEC_HASH_POLY1305_128,
4163d21da66SChang Miao };
4173d21da66SChang Miao 
4183d21da66SChang Miao /* Cipher types */
4193d21da66SChang Miao enum nfp_ipsec_cipher_type {
4203d21da66SChang Miao 	NFP_IPSEC_CIPHER_NULL,
4213d21da66SChang Miao 	NFP_IPSEC_CIPHER_3DES,
4223d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES128,
4233d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES192,
4243d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES256,
4253d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES128_NULL,
4263d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES192_NULL,
4273d21da66SChang Miao 	NFP_IPSEC_CIPHER_AES256_NULL,
4283d21da66SChang Miao 	NFP_IPSEC_CIPHER_CHACHA20,
4293d21da66SChang Miao };
4303d21da66SChang Miao 
4313d21da66SChang Miao /* Don't Fragment types */
4323d21da66SChang Miao enum nfp_ipsec_df_type {
4333d21da66SChang Miao 	NFP_IPSEC_DF_CLEAR,
4343d21da66SChang Miao 	NFP_IPSEC_DF_SET,
4353d21da66SChang Miao 	NFP_IPSEC_DF_COPY,
4363d21da66SChang Miao };
4373d21da66SChang Miao 
4387fb333e9SShihong Wang static int
4394a9bb682SChaoyong He nfp_ipsec_cfg_cmd_issue(struct nfp_net_hw *net_hw,
4407fb333e9SShihong Wang 		struct nfp_ipsec_msg *msg)
4417fb333e9SShihong Wang {
4427fb333e9SShihong Wang 	int ret;
4437fb333e9SShihong Wang 	uint32_t i;
4447fb333e9SShihong Wang 	uint32_t msg_size;
4457fb333e9SShihong Wang 
4467fb333e9SShihong Wang 	msg_size = RTE_DIM(msg->raw);
4477fb333e9SShihong Wang 	msg->rsp = NFP_IPSEC_CFG_MSG_OK;
4487fb333e9SShihong Wang 
4497fb333e9SShihong Wang 	for (i = 0; i < msg_size; i++)
4504a9bb682SChaoyong He 		nn_cfg_writel(&net_hw->super, NFP_NET_CFG_MBOX_VAL + 4 * i, msg->raw[i]);
4517fb333e9SShihong Wang 
4524a9bb682SChaoyong He 	ret = nfp_net_mbox_reconfig(net_hw, NFP_NET_CFG_MBOX_CMD_IPSEC);
4537fb333e9SShihong Wang 	if (ret < 0) {
4547fb333e9SShihong Wang 		PMD_DRV_LOG(ERR, "Failed to IPsec reconfig mbox");
4557fb333e9SShihong Wang 		return ret;
4567fb333e9SShihong Wang 	}
4577fb333e9SShihong Wang 
4587fb333e9SShihong Wang 	/*
4597fb333e9SShihong Wang 	 * Not all commands and callers make use of response message data. But
4607fb333e9SShihong Wang 	 * leave this up to the caller and always read and store the full
4617fb333e9SShihong Wang 	 * response. One example where the data is needed is for statistics.
4627fb333e9SShihong Wang 	 */
4637fb333e9SShihong Wang 	for (i = 0; i < msg_size; i++)
4644a9bb682SChaoyong He 		msg->raw[i] = nn_cfg_readl(&net_hw->super, NFP_NET_CFG_MBOX_VAL + 4 * i);
4657fb333e9SShihong Wang 
4667fb333e9SShihong Wang 	switch (msg->rsp) {
4677fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_OK:
4687fb333e9SShihong Wang 		ret = 0;
4697fb333e9SShihong Wang 		break;
4707fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_SA_INVALID_CMD:
4717fb333e9SShihong Wang 		ret = -EINVAL;
4727fb333e9SShihong Wang 		break;
4737fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_SA_VALID:
4747fb333e9SShihong Wang 		ret = -EEXIST;
4757fb333e9SShihong Wang 		break;
4767fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_FAILED:
4777fb333e9SShihong Wang 		/* FALLTHROUGH */
4787fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_SA_HASH_ADD_FAILED:
4797fb333e9SShihong Wang 		/* FALLTHROUGH */
4807fb333e9SShihong Wang 	case NFP_IPSEC_CFG_MSG_SA_HASH_DEL_FAILED:
4817fb333e9SShihong Wang 		ret = -EIO;
4827fb333e9SShihong Wang 		break;
4837fb333e9SShihong Wang 	default:
4847fb333e9SShihong Wang 		ret = -EDOM;
4857fb333e9SShihong Wang 	}
4867fb333e9SShihong Wang 
4877fb333e9SShihong Wang 	return ret;
4887fb333e9SShihong Wang }
4897fb333e9SShihong Wang 
4907fb333e9SShihong Wang /**
4913d21da66SChang Miao  * Get valid SA index from SA table
4923d21da66SChang Miao  *
4933d21da66SChang Miao  * @param data
4943d21da66SChang Miao  *   SA table pointer
4953d21da66SChang Miao  * @param sa_idx
4963d21da66SChang Miao  *   SA table index pointer
4973d21da66SChang Miao  *
4983d21da66SChang Miao  * @return
4993d21da66SChang Miao  *   Negative number on full or repeat, 0 on success
5003d21da66SChang Miao  *
5013d21da66SChang Miao  * Note: multiple sockets may create same SA session.
5023d21da66SChang Miao  */
5033d21da66SChang Miao static void
5043d21da66SChang Miao nfp_get_sa_entry(struct nfp_net_ipsec_data *data,
5053d21da66SChang Miao 		int *sa_idx)
5063d21da66SChang Miao {
5073d21da66SChang Miao 	uint32_t i;
5083d21da66SChang Miao 
5093d21da66SChang Miao 	for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
5103d21da66SChang Miao 		if (data->sa_entries[i] == NULL) {
5113d21da66SChang Miao 			*sa_idx = i;
5123d21da66SChang Miao 			break;
5133d21da66SChang Miao 		}
5143d21da66SChang Miao 	}
5153d21da66SChang Miao }
5163d21da66SChang Miao 
5173d21da66SChang Miao static void
5183d21da66SChang Miao nfp_aesgcm_iv_update(struct ipsec_add_sa *cfg,
5193d21da66SChang Miao 		uint16_t iv_len,
5203d21da66SChang Miao 		const char *iv_string)
5213d21da66SChang Miao {
5223d21da66SChang Miao 	int i;
5233d21da66SChang Miao 	char *save;
5243d21da66SChang Miao 	char *iv_b;
5253d21da66SChang Miao 	char *iv_str;
5263d21da66SChang Miao 	uint8_t *cfg_iv;
5273d21da66SChang Miao 
5283d21da66SChang Miao 	iv_str = strdup(iv_string);
5293d21da66SChang Miao 	cfg_iv = (uint8_t *)cfg->aesgcm_fields.iv;
5303d21da66SChang Miao 
5313d21da66SChang Miao 	for (i = 0; i < iv_len; i++) {
5323d21da66SChang Miao 		iv_b = strtok_r(i ? NULL : iv_str, ",", &save);
5333d21da66SChang Miao 		if (iv_b == NULL)
5343d21da66SChang Miao 			break;
5353d21da66SChang Miao 
5363d21da66SChang Miao 		cfg_iv[i] = strtoul(iv_b, NULL, 0);
5373d21da66SChang Miao 	}
5383d21da66SChang Miao 
5393d21da66SChang Miao 	*(uint32_t *)cfg_iv = rte_be_to_cpu_32(*(uint32_t *)cfg_iv);
5403d21da66SChang Miao 	*(uint32_t *)&cfg_iv[4] = rte_be_to_cpu_32(*(uint32_t *)&cfg_iv[4]);
5413d21da66SChang Miao 
5423d21da66SChang Miao 	free(iv_str);
5433d21da66SChang Miao }
5443d21da66SChang Miao 
5453d21da66SChang Miao static int
5463d21da66SChang Miao set_aes_keylen(uint32_t key_length,
5473d21da66SChang Miao 		struct ipsec_add_sa *cfg)
5483d21da66SChang Miao {
5493d21da66SChang Miao 	switch (key_length << 3) {
5503d21da66SChang Miao 	case 128:
5513d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES128;
5523d21da66SChang Miao 		break;
5533d21da66SChang Miao 	case 192:
5543d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES192;
5553d21da66SChang Miao 		break;
5563d21da66SChang Miao 	case 256:
5573d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_AES256;
5583d21da66SChang Miao 		break;
5593d21da66SChang Miao 	default:
5603d21da66SChang Miao 		PMD_DRV_LOG(ERR, "AES cipher key length is illegal!");
5613d21da66SChang Miao 		return -EINVAL;
5623d21da66SChang Miao 	}
5633d21da66SChang Miao 
5643d21da66SChang Miao 	return 0;
5653d21da66SChang Miao }
5663d21da66SChang Miao 
5673d21da66SChang Miao /* Map rte_security_session_conf aead algo to NFP aead algo */
5683d21da66SChang Miao static int
5693d21da66SChang Miao nfp_aead_map(struct rte_eth_dev *eth_dev,
5703d21da66SChang Miao 		struct rte_crypto_aead_xform *aead,
5713d21da66SChang Miao 		uint32_t key_length,
5723d21da66SChang Miao 		struct ipsec_add_sa *cfg)
5733d21da66SChang Miao {
5743d21da66SChang Miao 	int ret;
5753d21da66SChang Miao 	uint32_t i;
5763d21da66SChang Miao 	uint32_t index;
5773d21da66SChang Miao 	uint16_t iv_len;
5783d21da66SChang Miao 	uint32_t offset;
5793d21da66SChang Miao 	uint32_t device_id;
5803d21da66SChang Miao 	const char *iv_str;
5813d21da66SChang Miao 	const uint32_t *key;
5824a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
5833d21da66SChang Miao 
5849d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
5854a9bb682SChaoyong He 	device_id = net_hw->device_id;
5863d21da66SChang Miao 	offset = 0;
5873d21da66SChang Miao 
5883d21da66SChang Miao 	switch (aead->algo) {
5893d21da66SChang Miao 	case RTE_CRYPTO_AEAD_AES_GCM:
5903d21da66SChang Miao 		if (aead->digest_length != 16) {
5913d21da66SChang Miao 			PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_AES_GCM!");
5923d21da66SChang Miao 			return -EINVAL;
5933d21da66SChang Miao 		}
5943d21da66SChang Miao 
5953d21da66SChang Miao 		cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CTR;
5963d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_GF128_128;
5973d21da66SChang Miao 
5983d21da66SChang Miao 		ret = set_aes_keylen(key_length, cfg);
5993d21da66SChang Miao 		if (ret < 0) {
6003d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to set AES_GCM key length!");
6013d21da66SChang Miao 			return -EINVAL;
6023d21da66SChang Miao 		}
6033d21da66SChang Miao 
6043d21da66SChang Miao 		break;
6053d21da66SChang Miao 	case RTE_CRYPTO_AEAD_CHACHA20_POLY1305:
6063d21da66SChang Miao 		if (device_id != PCI_DEVICE_ID_NFP3800_PF_NIC) {
6073d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported aead CHACHA20_POLY1305 algorithm!");
6083d21da66SChang Miao 			return -EINVAL;
6093d21da66SChang Miao 		}
6103d21da66SChang Miao 
6113d21da66SChang Miao 		if (aead->digest_length != 16) {
6123d21da66SChang Miao 			PMD_DRV_LOG(ERR, "ICV must be 128bit with RTE_CRYPTO_AEAD_CHACHA20_POLY1305");
6133d21da66SChang Miao 			return -EINVAL;
6143d21da66SChang Miao 		}
6153d21da66SChang Miao 
6163d21da66SChang Miao 		/* Aead->alg_key_len includes 32-bit salt */
6173d21da66SChang Miao 		if (key_length != 32) {
6183d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported CHACHA20 key length");
6193d21da66SChang Miao 			return -EINVAL;
6203d21da66SChang Miao 		}
6213d21da66SChang Miao 
6223d21da66SChang Miao 		/* The CHACHA20's mode is not configured */
6233d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_POLY1305_128;
6243d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_CHACHA20;
6253d21da66SChang Miao 		break;
6263d21da66SChang Miao 	default:
6273d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported aead algorithm!");
6283d21da66SChang Miao 		return -EINVAL;
6293d21da66SChang Miao 	}
6303d21da66SChang Miao 
6313d21da66SChang Miao 	key = (const uint32_t *)(aead->key.data);
6323d21da66SChang Miao 
6333d21da66SChang Miao 	/*
6343d21da66SChang Miao 	 * The CHACHA20's key order needs to be adjusted based on hardware design.
6353d21da66SChang Miao 	 * Unadjusted order: {K0, K1, K2, K3, K4, K5, K6, K7}
6363d21da66SChang Miao 	 * Adjusted order: {K4, K5, K6, K7, K0, K1, K2, K3}
6373d21da66SChang Miao 	 */
6383d21da66SChang Miao 	if (aead->algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305)
6393d21da66SChang Miao 		offset = key_length / sizeof(cfg->cipher_key[0]) << 1;
6403d21da66SChang Miao 
6413d21da66SChang Miao 	for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++) {
6423d21da66SChang Miao 		index = (i + offset) % (key_length / sizeof(cfg->cipher_key[0]));
6433d21da66SChang Miao 		cfg->cipher_key[index] = rte_cpu_to_be_32(*key++);
6443d21da66SChang Miao 	}
6453d21da66SChang Miao 
6463d21da66SChang Miao 	/*
6473d21da66SChang Miao 	 * The iv of the FW is equal to ESN by default. Reading the
6483d21da66SChang Miao 	 * iv of the configuration information is not supported.
6493d21da66SChang Miao 	 */
6503d21da66SChang Miao 	iv_str = getenv("ETH_SEC_IV_OVR");
6513d21da66SChang Miao 	if (iv_str != NULL) {
6523d21da66SChang Miao 		iv_len = aead->iv.length;
6533d21da66SChang Miao 		nfp_aesgcm_iv_update(cfg, iv_len, iv_str);
6543d21da66SChang Miao 	}
6553d21da66SChang Miao 
6563d21da66SChang Miao 	return 0;
6573d21da66SChang Miao }
6583d21da66SChang Miao 
6593d21da66SChang Miao /* Map rte_security_session_conf cipher algo to NFP cipher algo */
6603d21da66SChang Miao static int
6613d21da66SChang Miao nfp_cipher_map(struct rte_eth_dev *eth_dev,
6623d21da66SChang Miao 		struct rte_crypto_cipher_xform *cipher,
6633d21da66SChang Miao 		uint32_t key_length,
6643d21da66SChang Miao 		struct ipsec_add_sa *cfg)
6653d21da66SChang Miao {
6663d21da66SChang Miao 	int ret;
6673d21da66SChang Miao 	uint32_t i;
6683d21da66SChang Miao 	uint32_t device_id;
6693d21da66SChang Miao 	const uint32_t *key;
6704a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
6713d21da66SChang Miao 
6729d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
6734a9bb682SChaoyong He 	device_id = net_hw->device_id;
6743d21da66SChang Miao 
6753d21da66SChang Miao 	switch (cipher->algo) {
6763d21da66SChang Miao 	case RTE_CRYPTO_CIPHER_NULL:
6773d21da66SChang Miao 		cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
6783d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_NULL;
6793d21da66SChang Miao 		break;
6803d21da66SChang Miao 	case RTE_CRYPTO_CIPHER_3DES_CBC:
6813d21da66SChang Miao 		if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
6823d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported 3DESCBC encryption algorithm!");
6833d21da66SChang Miao 			return -EINVAL;
6843d21da66SChang Miao 		}
6853d21da66SChang Miao 
6863d21da66SChang Miao 		cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
6873d21da66SChang Miao 		cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_3DES;
6883d21da66SChang Miao 		break;
6893d21da66SChang Miao 	case RTE_CRYPTO_CIPHER_AES_CBC:
6903d21da66SChang Miao 		cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
6913d21da66SChang Miao 		ret = set_aes_keylen(key_length, cfg);
6923d21da66SChang Miao 		if (ret < 0) {
6933d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to set cipher key length!");
6943d21da66SChang Miao 			return -EINVAL;
6953d21da66SChang Miao 		}
6963d21da66SChang Miao 
6973d21da66SChang Miao 		break;
6983d21da66SChang Miao 	default:
6993d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported cipher alg!");
7003d21da66SChang Miao 		return -EINVAL;
7013d21da66SChang Miao 	}
7023d21da66SChang Miao 
7033d21da66SChang Miao 	key = (const uint32_t  *)(cipher->key.data);
7043d21da66SChang Miao 	if (key_length > sizeof(cfg->cipher_key)) {
7053d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Insufficient space for offloaded key");
7063d21da66SChang Miao 		return -EINVAL;
7073d21da66SChang Miao 	}
7083d21da66SChang Miao 
7093d21da66SChang Miao 	for (i = 0; i < key_length / sizeof(cfg->cipher_key[0]); i++)
7103d21da66SChang Miao 		cfg->cipher_key[i] = rte_cpu_to_be_32(*key++);
7113d21da66SChang Miao 
7123d21da66SChang Miao 	return 0;
7133d21da66SChang Miao }
7143d21da66SChang Miao 
7153d21da66SChang Miao static void
7163d21da66SChang Miao set_md5hmac(struct ipsec_add_sa *cfg,
7173d21da66SChang Miao 		uint32_t *digest_length)
7183d21da66SChang Miao {
7193d21da66SChang Miao 	switch (*digest_length) {
7203d21da66SChang Miao 	case 96:
7213d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_96;
7223d21da66SChang Miao 		break;
7233d21da66SChang Miao 	case 128:
7243d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_MD5_128;
7253d21da66SChang Miao 		break;
7263d21da66SChang Miao 	default:
7273d21da66SChang Miao 		*digest_length = 0;
7283d21da66SChang Miao 	}
7293d21da66SChang Miao }
7303d21da66SChang Miao 
7313d21da66SChang Miao static void
7323d21da66SChang Miao set_sha1hmac(struct ipsec_add_sa *cfg,
7333d21da66SChang Miao 		uint32_t *digest_length)
7343d21da66SChang Miao {
7353d21da66SChang Miao 	switch (*digest_length) {
7363d21da66SChang Miao 	case 96:
7373d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_96;
7383d21da66SChang Miao 		break;
7393d21da66SChang Miao 	case 80:
7403d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA1_80;
7413d21da66SChang Miao 		break;
7423d21da66SChang Miao 	default:
7433d21da66SChang Miao 		*digest_length = 0;
7443d21da66SChang Miao 	}
7453d21da66SChang Miao }
7463d21da66SChang Miao 
7473d21da66SChang Miao static void
7483d21da66SChang Miao set_sha2_256hmac(struct ipsec_add_sa *cfg,
7493d21da66SChang Miao 		uint32_t *digest_length)
7503d21da66SChang Miao {
7513d21da66SChang Miao 	switch (*digest_length) {
7523d21da66SChang Miao 	case 96:
7533d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_96;
7543d21da66SChang Miao 		break;
7553d21da66SChang Miao 	case 128:
7563d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA256_128;
7573d21da66SChang Miao 		break;
7583d21da66SChang Miao 	default:
7593d21da66SChang Miao 		*digest_length = 0;
7603d21da66SChang Miao 	}
7613d21da66SChang Miao }
7623d21da66SChang Miao 
7633d21da66SChang Miao static void
7643d21da66SChang Miao set_sha2_384hmac(struct ipsec_add_sa *cfg,
7653d21da66SChang Miao 		uint32_t *digest_length)
7663d21da66SChang Miao {
7673d21da66SChang Miao 	switch (*digest_length) {
7683d21da66SChang Miao 	case 96:
7693d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_96;
7703d21da66SChang Miao 		break;
7713d21da66SChang Miao 	case 192:
7723d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA384_192;
7733d21da66SChang Miao 		break;
7743d21da66SChang Miao 	default:
7753d21da66SChang Miao 		*digest_length = 0;
7763d21da66SChang Miao 	}
7773d21da66SChang Miao }
7783d21da66SChang Miao 
7793d21da66SChang Miao static void
7803d21da66SChang Miao set_sha2_512hmac(struct ipsec_add_sa *cfg,
7813d21da66SChang Miao 		uint32_t *digest_length)
7823d21da66SChang Miao {
7833d21da66SChang Miao 	switch (*digest_length) {
7843d21da66SChang Miao 	case 96:
7853d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_96;
7863d21da66SChang Miao 		break;
7873d21da66SChang Miao 	case 256:
7883d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_SHA512_256;
7893d21da66SChang Miao 		break;
7903d21da66SChang Miao 	default:
7913d21da66SChang Miao 		*digest_length = 0;
7923d21da66SChang Miao 	}
7933d21da66SChang Miao }
7943d21da66SChang Miao 
7953d21da66SChang Miao /* Map rte_security_session_conf auth algo to NFP auth algo */
7963d21da66SChang Miao static int
7973d21da66SChang Miao nfp_auth_map(struct rte_eth_dev *eth_dev,
7983d21da66SChang Miao 		struct rte_crypto_auth_xform *auth,
7993d21da66SChang Miao 		uint32_t digest_length,
8003d21da66SChang Miao 		struct ipsec_add_sa *cfg)
8013d21da66SChang Miao {
8023d21da66SChang Miao 	uint32_t i;
8033d21da66SChang Miao 	uint8_t key_length;
8043d21da66SChang Miao 	uint32_t device_id;
8053d21da66SChang Miao 	const uint32_t *key;
8064a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
8073d21da66SChang Miao 
8083d21da66SChang Miao 	if (digest_length == 0) {
8093d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Auth digest length is illegal!");
8103d21da66SChang Miao 		return -EINVAL;
8113d21da66SChang Miao 	}
8123d21da66SChang Miao 
8139d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
8144a9bb682SChaoyong He 	device_id = net_hw->device_id;
8153d21da66SChang Miao 	digest_length = digest_length << 3;
8163d21da66SChang Miao 
8173d21da66SChang Miao 	switch (auth->algo) {
8183d21da66SChang Miao 	case RTE_CRYPTO_AUTH_NULL:
8193d21da66SChang Miao 		cfg->ctrl_word.hash = NFP_IPSEC_HASH_NONE;
8203d21da66SChang Miao 		digest_length = 1;
8213d21da66SChang Miao 		break;
8223d21da66SChang Miao 	case RTE_CRYPTO_AUTH_MD5_HMAC:
8233d21da66SChang Miao 		if (device_id == PCI_DEVICE_ID_NFP3800_PF_NIC) {
8243d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported MD5HMAC authentication algorithm!");
8253d21da66SChang Miao 			return -EINVAL;
8263d21da66SChang Miao 		}
8273d21da66SChang Miao 
8283d21da66SChang Miao 		set_md5hmac(cfg, &digest_length);
8293d21da66SChang Miao 		break;
8303d21da66SChang Miao 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
8313d21da66SChang Miao 		set_sha1hmac(cfg, &digest_length);
8323d21da66SChang Miao 		break;
8333d21da66SChang Miao 	case RTE_CRYPTO_AUTH_SHA256_HMAC:
8343d21da66SChang Miao 		set_sha2_256hmac(cfg, &digest_length);
8353d21da66SChang Miao 		break;
8363d21da66SChang Miao 	case RTE_CRYPTO_AUTH_SHA384_HMAC:
8373d21da66SChang Miao 		set_sha2_384hmac(cfg, &digest_length);
8383d21da66SChang Miao 		break;
8393d21da66SChang Miao 	case RTE_CRYPTO_AUTH_SHA512_HMAC:
8403d21da66SChang Miao 		set_sha2_512hmac(cfg, &digest_length);
8413d21da66SChang Miao 		break;
8423d21da66SChang Miao 	default:
8433d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported auth alg!");
8443d21da66SChang Miao 		return -EINVAL;
8453d21da66SChang Miao 	}
8463d21da66SChang Miao 
8473d21da66SChang Miao 	if (digest_length == 0) {
8483d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported authentication algorithm digest length");
8493d21da66SChang Miao 		return -EINVAL;
8503d21da66SChang Miao 	}
8513d21da66SChang Miao 
8523d21da66SChang Miao 	key = (const uint32_t *)(auth->key.data);
8533d21da66SChang Miao 	key_length = auth->key.length;
8543d21da66SChang Miao 	if (key_length > sizeof(cfg->auth_key)) {
8553d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Insufficient space for offloaded auth key!");
8563d21da66SChang Miao 		return -EINVAL;
8573d21da66SChang Miao 	}
8583d21da66SChang Miao 
8593d21da66SChang Miao 	for (i = 0; i < key_length / sizeof(cfg->auth_key[0]); i++)
8603d21da66SChang Miao 		cfg->auth_key[i] = rte_cpu_to_be_32(*key++);
8613d21da66SChang Miao 
8623d21da66SChang Miao 	return 0;
8633d21da66SChang Miao }
8643d21da66SChang Miao 
8653d21da66SChang Miao static int
8663d21da66SChang Miao nfp_crypto_msg_build(struct rte_eth_dev *eth_dev,
8673d21da66SChang Miao 		struct rte_security_session_conf *conf,
8683d21da66SChang Miao 		struct nfp_ipsec_msg *msg)
8693d21da66SChang Miao {
8703d21da66SChang Miao 	int ret;
8713d21da66SChang Miao 	struct ipsec_add_sa *cfg;
8723d21da66SChang Miao 	struct rte_crypto_sym_xform *cur;
8733d21da66SChang Miao 	struct rte_crypto_sym_xform *next;
8743d21da66SChang Miao 	enum rte_security_ipsec_sa_direction direction;
8753d21da66SChang Miao 
8763d21da66SChang Miao 	cur = conf->crypto_xform;
8773d21da66SChang Miao 	if (cur == NULL) {
8783d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported crypto_xform is NULL!");
8793d21da66SChang Miao 		return -EINVAL;
8803d21da66SChang Miao 	}
8813d21da66SChang Miao 
8823d21da66SChang Miao 	next = cur->next;
8833d21da66SChang Miao 	direction = conf->ipsec.direction;
8843d21da66SChang Miao 	cfg = &msg->cfg_add_sa;
8853d21da66SChang Miao 
8863d21da66SChang Miao 	switch (cur->type) {
8873d21da66SChang Miao 	case RTE_CRYPTO_SYM_XFORM_AEAD:
8883d21da66SChang Miao 		/* Aead transforms can be used for either inbound/outbound IPsec SAs */
8893d21da66SChang Miao 		if (next != NULL) {
8903d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Next crypto_xform type should be NULL!");
8913d21da66SChang Miao 			return -EINVAL;
8923d21da66SChang Miao 		}
8933d21da66SChang Miao 
8943d21da66SChang Miao 		ret = nfp_aead_map(eth_dev, &cur->aead, cur->aead.key.length, cfg);
8953d21da66SChang Miao 		if (ret < 0) {
8963d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to map aead alg!");
8973d21da66SChang Miao 			return ret;
8983d21da66SChang Miao 		}
8993d21da66SChang Miao 
9003d21da66SChang Miao 		cfg->aesgcm_fields.salt = rte_cpu_to_be_32(conf->ipsec.salt);
9013d21da66SChang Miao 		break;
9023d21da66SChang Miao 	case RTE_CRYPTO_SYM_XFORM_AUTH:
9033d21da66SChang Miao 		/* Only support Auth + Cipher for inbound */
9043d21da66SChang Miao 		if (direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
9053d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Direction should be INGRESS, but it is not!");
9063d21da66SChang Miao 			return -EINVAL;
9073d21da66SChang Miao 		}
9083d21da66SChang Miao 
9093d21da66SChang Miao 		if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
9103d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Next crypto_xfrm should be cipher, but it is not!");
9113d21da66SChang Miao 			return -EINVAL;
9123d21da66SChang Miao 		}
9133d21da66SChang Miao 
9143d21da66SChang Miao 		ret = nfp_auth_map(eth_dev, &cur->auth, cur->auth.digest_length, cfg);
9153d21da66SChang Miao 		if (ret < 0) {
9163d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to map auth alg!");
9173d21da66SChang Miao 			return ret;
9183d21da66SChang Miao 		}
9193d21da66SChang Miao 
9203d21da66SChang Miao 		ret = nfp_cipher_map(eth_dev, &next->cipher, next->cipher.key.length, cfg);
9213d21da66SChang Miao 		if (ret < 0) {
9223d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
9233d21da66SChang Miao 			return ret;
9243d21da66SChang Miao 		}
9253d21da66SChang Miao 
9263d21da66SChang Miao 		break;
9273d21da66SChang Miao 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
9283d21da66SChang Miao 		/* Only support Cipher + Auth for outbound */
9293d21da66SChang Miao 		if (direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
9303d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Direction should be EGRESS, but it is not!");
9313d21da66SChang Miao 			return -EINVAL;
9323d21da66SChang Miao 		}
9333d21da66SChang Miao 
9343d21da66SChang Miao 		if (next == NULL || next->type != RTE_CRYPTO_SYM_XFORM_AUTH) {
9353d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Next crypto_xfrm should be auth, but it is not!");
9363d21da66SChang Miao 			return -EINVAL;
9373d21da66SChang Miao 		}
9383d21da66SChang Miao 
9393d21da66SChang Miao 		ret = nfp_cipher_map(eth_dev, &cur->cipher, cur->cipher.key.length, cfg);
9403d21da66SChang Miao 		if (ret < 0) {
9413d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to map cipher alg!");
9423d21da66SChang Miao 			return ret;
9433d21da66SChang Miao 		}
9443d21da66SChang Miao 
9453d21da66SChang Miao 		ret = nfp_auth_map(eth_dev, &next->auth, next->auth.digest_length, cfg);
9463d21da66SChang Miao 		if (ret < 0) {
9473d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Failed to map auth alg!");
9483d21da66SChang Miao 			return ret;
9493d21da66SChang Miao 		}
9503d21da66SChang Miao 
9513d21da66SChang Miao 		break;
9523d21da66SChang Miao 	default:
9533d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported crypto_xform type!");
9543d21da66SChang Miao 		return -EINVAL;
9553d21da66SChang Miao 	}
9563d21da66SChang Miao 
9573d21da66SChang Miao 	return 0;
9583d21da66SChang Miao }
9593d21da66SChang Miao 
9603d21da66SChang Miao static int
9613d21da66SChang Miao nfp_ipsec_msg_build(struct rte_eth_dev *eth_dev,
9623d21da66SChang Miao 		struct rte_security_session_conf *conf,
9633d21da66SChang Miao 		struct nfp_ipsec_msg *msg)
9643d21da66SChang Miao {
9653d21da66SChang Miao 	int ret;
9663d21da66SChang Miao 	struct ipsec_add_sa *cfg;
9673d21da66SChang Miao 	enum rte_security_ipsec_tunnel_type type;
9683d21da66SChang Miao 
9693d21da66SChang Miao 	cfg = &msg->cfg_add_sa;
9703d21da66SChang Miao 	cfg->spi = conf->ipsec.spi;
9713d21da66SChang Miao 	cfg->pmtu_limit = 0xffff;
9723d21da66SChang Miao 
9733d21da66SChang Miao 	/*
9743d21da66SChang Miao 	 * UDP encapsulation
9753d21da66SChang Miao 	 *
9763d21da66SChang Miao 	 * 1: Do UDP encapsulation/decapsulation
9773d21da66SChang Miao 	 * 0: No UDP encapsulation
9783d21da66SChang Miao 	 */
9793d21da66SChang Miao 	if (conf->ipsec.options.udp_encap == 1) {
9803d21da66SChang Miao 		cfg->udp_enable = 1;
9813d21da66SChang Miao 		cfg->natt_dst_port = NFP_UDP_ESP_PORT;
9823d21da66SChang Miao 		cfg->natt_src_port = NFP_UDP_ESP_PORT;
9833d21da66SChang Miao 	}
9843d21da66SChang Miao 
9853d21da66SChang Miao 	if (conf->ipsec.options.copy_df == 1)
9863d21da66SChang Miao 		cfg->df_ctrl = NFP_IPSEC_DF_COPY;
9873d21da66SChang Miao 	else if (conf->ipsec.tunnel.ipv4.df != 0)
9883d21da66SChang Miao 		cfg->df_ctrl = NFP_IPSEC_DF_SET;
9893d21da66SChang Miao 	else
9903d21da66SChang Miao 		cfg->df_ctrl = NFP_IPSEC_DF_CLEAR;
9913d21da66SChang Miao 
9923d21da66SChang Miao 	switch (conf->action_type) {
9933d21da66SChang Miao 	case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
9943d21da66SChang Miao 		cfg->ctrl_word.encap_dsbl = 1;
9953d21da66SChang Miao 		break;
9963d21da66SChang Miao 	case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL:
9973d21da66SChang Miao 		cfg->ctrl_word.encap_dsbl = 0;
9983d21da66SChang Miao 		break;
9993d21da66SChang Miao 	default:
10003d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported IPsec action for offload, action: %d",
10013d21da66SChang Miao 				conf->action_type);
10023d21da66SChang Miao 		return -EINVAL;
10033d21da66SChang Miao 	}
10043d21da66SChang Miao 
10053d21da66SChang Miao 	switch (conf->ipsec.proto) {
10063d21da66SChang Miao 	case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
10073d21da66SChang Miao 		cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_ESP;
10083d21da66SChang Miao 		break;
10093d21da66SChang Miao 	case RTE_SECURITY_IPSEC_SA_PROTO_AH:
10103d21da66SChang Miao 		cfg->ctrl_word.proto = NFP_IPSEC_PROTOCOL_AH;
10113d21da66SChang Miao 		break;
10123d21da66SChang Miao 	default:
10133d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported IPsec protocol for offload, protocol: %d",
10143d21da66SChang Miao 				conf->ipsec.proto);
10153d21da66SChang Miao 		return -EINVAL;
10163d21da66SChang Miao 	}
10173d21da66SChang Miao 
10183d21da66SChang Miao 	switch (conf->ipsec.mode) {
10193d21da66SChang Miao 	case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
10203d21da66SChang Miao 		type = conf->ipsec.tunnel.type;
10213d21da66SChang Miao 		cfg->ctrl_word.mode = NFP_IPSEC_MODE_TUNNEL;
10223d21da66SChang Miao 		if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
10233d21da66SChang Miao 			cfg->src_ip.v4 = conf->ipsec.tunnel.ipv4.src_ip;
10243d21da66SChang Miao 			cfg->dst_ip.v4 = conf->ipsec.tunnel.ipv4.dst_ip;
10253d21da66SChang Miao 			cfg->ipv6 = 0;
10263d21da66SChang Miao 		} else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
10273d21da66SChang Miao 			cfg->src_ip.v6 = conf->ipsec.tunnel.ipv6.src_addr;
10283d21da66SChang Miao 			cfg->dst_ip.v6 = conf->ipsec.tunnel.ipv6.dst_addr;
10293d21da66SChang Miao 			cfg->ipv6 = 1;
10303d21da66SChang Miao 		} else {
10313d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported address family!");
10323d21da66SChang Miao 			return -EINVAL;
10333d21da66SChang Miao 		}
10343d21da66SChang Miao 
10353d21da66SChang Miao 		break;
10363d21da66SChang Miao 	case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
10373d21da66SChang Miao 		type = conf->ipsec.tunnel.type;
10383d21da66SChang Miao 		cfg->ctrl_word.mode = NFP_IPSEC_MODE_TRANSPORT;
10393d21da66SChang Miao 		if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
10403d21da66SChang Miao 			memset(&cfg->src_ip, 0, sizeof(cfg->src_ip));
10413d21da66SChang Miao 			cfg->ipv6 = 0;
10423d21da66SChang Miao 		} else if (type == RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
10433d21da66SChang Miao 			memset(&cfg->src_ip, 0, sizeof(cfg->src_ip));
10443d21da66SChang Miao 			cfg->ipv6 = 1;
10453d21da66SChang Miao 		} else {
10463d21da66SChang Miao 			PMD_DRV_LOG(ERR, "Unsupported address family!");
10473d21da66SChang Miao 			return -EINVAL;
10483d21da66SChang Miao 		}
10493d21da66SChang Miao 
10503d21da66SChang Miao 		break;
10513d21da66SChang Miao 	default:
10523d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported IPsec mode for offload, mode: %d",
10533d21da66SChang Miao 				conf->ipsec.mode);
10543d21da66SChang Miao 		return -EINVAL;
10553d21da66SChang Miao 	}
10563d21da66SChang Miao 
10573d21da66SChang Miao 	ret = nfp_crypto_msg_build(eth_dev, conf, msg);
10583d21da66SChang Miao 	if (ret < 0) {
10593d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Failed to build auth/crypto/aead msg!");
10603d21da66SChang Miao 		return ret;
10613d21da66SChang Miao 	}
10623d21da66SChang Miao 
10633d21da66SChang Miao 	return 0;
10643d21da66SChang Miao }
10653d21da66SChang Miao 
10663d21da66SChang Miao static int
10673d21da66SChang Miao nfp_crypto_create_session(void *device,
10683d21da66SChang Miao 		struct rte_security_session_conf *conf,
10693d21da66SChang Miao 		struct rte_security_session *session)
10703d21da66SChang Miao {
10713d21da66SChang Miao 	int ret;
10723d21da66SChang Miao 	int sa_idx;
10734a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
10743d21da66SChang Miao 	struct nfp_ipsec_msg msg;
10753d21da66SChang Miao 	struct rte_eth_dev *eth_dev;
10763d21da66SChang Miao 	struct nfp_ipsec_session *priv_session;
10773d21da66SChang Miao 
10783d21da66SChang Miao 	/* Only support IPsec at present */
10793d21da66SChang Miao 	if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
10803d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Unsupported non-IPsec offload!");
10813d21da66SChang Miao 		return -EINVAL;
10823d21da66SChang Miao 	}
10833d21da66SChang Miao 
10843d21da66SChang Miao 	sa_idx = -1;
10853d21da66SChang Miao 	eth_dev = device;
10863d21da66SChang Miao 	priv_session = SECURITY_GET_SESS_PRIV(session);
10879d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
10883d21da66SChang Miao 
10894a9bb682SChaoyong He 	if (net_hw->ipsec_data->sa_free_cnt == 0) {
10903d21da66SChang Miao 		PMD_DRV_LOG(ERR, "No space in SA table, spi: %d", conf->ipsec.spi);
10913d21da66SChang Miao 		return -EINVAL;
10923d21da66SChang Miao 	}
10933d21da66SChang Miao 
10944a9bb682SChaoyong He 	nfp_get_sa_entry(net_hw->ipsec_data, &sa_idx);
10953d21da66SChang Miao 
10963d21da66SChang Miao 	if (sa_idx < 0) {
10973d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Failed to get SA entry!");
10983d21da66SChang Miao 		return -EINVAL;
10993d21da66SChang Miao 	}
11003d21da66SChang Miao 
11013d21da66SChang Miao 	memset(&msg, 0, sizeof(msg));
11023d21da66SChang Miao 	ret = nfp_ipsec_msg_build(eth_dev, conf, &msg);
11033d21da66SChang Miao 	if (ret < 0) {
11043d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Failed to build IPsec msg!");
11053d21da66SChang Miao 		return -EINVAL;
11063d21da66SChang Miao 	}
11073d21da66SChang Miao 
11083d21da66SChang Miao 	msg.cmd = NFP_IPSEC_CFG_MSG_ADD_SA;
11093d21da66SChang Miao 	msg.sa_idx = sa_idx;
11104a9bb682SChaoyong He 	ret = nfp_ipsec_cfg_cmd_issue(net_hw, &msg);
11113d21da66SChang Miao 	if (ret < 0) {
11123d21da66SChang Miao 		PMD_DRV_LOG(ERR, "Failed to add SA to nic");
11133d21da66SChang Miao 		return -EINVAL;
11143d21da66SChang Miao 	}
11153d21da66SChang Miao 
11163d21da66SChang Miao 	priv_session->action = conf->action_type;
11173d21da66SChang Miao 	priv_session->ipsec = conf->ipsec;
11183d21da66SChang Miao 	priv_session->msg = msg.cfg_add_sa;
11193d21da66SChang Miao 	priv_session->sa_index = sa_idx;
11203d21da66SChang Miao 	priv_session->dev = eth_dev;
11213d21da66SChang Miao 	priv_session->user_data = conf->userdata;
11223d21da66SChang Miao 
11234a9bb682SChaoyong He 	net_hw->ipsec_data->sa_free_cnt--;
11244a9bb682SChaoyong He 	net_hw->ipsec_data->sa_entries[sa_idx] = priv_session;
11253d21da66SChang Miao 
11263d21da66SChang Miao 	return 0;
11273d21da66SChang Miao }
11283d21da66SChang Miao 
11297e6c8063SShihong Wang static int
11307e6c8063SShihong Wang nfp_crypto_update_session(void *device __rte_unused,
11317e6c8063SShihong Wang 		struct rte_security_session *session,
11327e6c8063SShihong Wang 		struct rte_security_session_conf *conf)
11337e6c8063SShihong Wang {
11347e6c8063SShihong Wang 	struct nfp_ipsec_session *priv_session;
11357e6c8063SShihong Wang 
11367e6c8063SShihong Wang 	priv_session = SECURITY_GET_SESS_PRIV(session);
11377e6c8063SShihong Wang 	if (priv_session == NULL)
11387e6c8063SShihong Wang 		return -EINVAL;
11397e6c8063SShihong Wang 
11407e6c8063SShihong Wang 	/* Update IPsec ESN value */
11417e6c8063SShihong Wang 	if (priv_session->msg.ctrl_word.ext_seq != 0 && conf->ipsec.options.esn != 0) {
11427e6c8063SShihong Wang 		/*
11437e6c8063SShihong Wang 		 * Store in nfp_ipsec_session for outbound SA for use
11447e6c8063SShihong Wang 		 * in nfp_security_set_pkt_metadata() function.
11457e6c8063SShihong Wang 		 */
11467e6c8063SShihong Wang 		priv_session->ipsec.esn.hi = conf->ipsec.esn.hi;
11477e6c8063SShihong Wang 		priv_session->ipsec.esn.low = conf->ipsec.esn.low;
11487e6c8063SShihong Wang 	}
11497e6c8063SShihong Wang 
11507e6c8063SShihong Wang 	return 0;
11517e6c8063SShihong Wang }
11527e6c8063SShihong Wang 
1153310a1780SShihong Wang static int
1154310a1780SShihong Wang nfp_security_set_pkt_metadata(void *device,
1155310a1780SShihong Wang 		struct rte_security_session *session,
1156310a1780SShihong Wang 		struct rte_mbuf *m,
1157310a1780SShihong Wang 		void *params)
1158310a1780SShihong Wang {
1159310a1780SShihong Wang 	int offset;
1160310a1780SShihong Wang 	uint64_t *sqn;
11614a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
1162310a1780SShihong Wang 	struct rte_eth_dev *eth_dev;
1163310a1780SShihong Wang 	struct nfp_ipsec_session *priv_session;
1164310a1780SShihong Wang 
1165310a1780SShihong Wang 	sqn = params;
1166310a1780SShihong Wang 	eth_dev = device;
1167310a1780SShihong Wang 	priv_session = SECURITY_GET_SESS_PRIV(session);
11689d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
1169310a1780SShihong Wang 
1170310a1780SShihong Wang 	if (priv_session->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
1171310a1780SShihong Wang 		struct nfp_tx_ipsec_desc_msg *desc_md;
1172310a1780SShihong Wang 
11734a9bb682SChaoyong He 		offset = net_hw->ipsec_data->pkt_dynfield_offset;
1174310a1780SShihong Wang 		desc_md = RTE_MBUF_DYNFIELD(m, offset, struct nfp_tx_ipsec_desc_msg *);
1175310a1780SShihong Wang 
1176310a1780SShihong Wang 		if (priv_session->msg.ctrl_word.ext_seq != 0 && sqn != NULL) {
1177310a1780SShihong Wang 			desc_md->esn.low = rte_cpu_to_be_32(*sqn);
1178310a1780SShihong Wang 			desc_md->esn.hi = rte_cpu_to_be_32(*sqn >> 32);
1179310a1780SShihong Wang 		} else if (priv_session->msg.ctrl_word.ext_seq != 0) {
1180310a1780SShihong Wang 			desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.low);
1181310a1780SShihong Wang 			desc_md->esn.hi = rte_cpu_to_be_32(priv_session->ipsec.esn.hi);
1182310a1780SShihong Wang 		} else {
1183310a1780SShihong Wang 			desc_md->esn.low = rte_cpu_to_be_32(priv_session->ipsec.esn.value);
1184310a1780SShihong Wang 			desc_md->esn.hi = 0;
1185310a1780SShihong Wang 		}
1186310a1780SShihong Wang 
1187310a1780SShihong Wang 		desc_md->enc = 1;
1188310a1780SShihong Wang 		desc_md->sa_idx = rte_cpu_to_be_32(priv_session->sa_index);
1189310a1780SShihong Wang 	}
1190310a1780SShihong Wang 
1191310a1780SShihong Wang 	return 0;
1192310a1780SShihong Wang }
1193310a1780SShihong Wang 
11943d21da66SChang Miao /**
11957fb333e9SShihong Wang  * Get discards packet statistics for each SA
11967fb333e9SShihong Wang  *
11977fb333e9SShihong Wang  * The sa_discard_stats contains the statistics of discards packets
11987fb333e9SShihong Wang  * of an SA. This function calculates the sum total of discarded packets.
11997fb333e9SShihong Wang  *
12007fb333e9SShihong Wang  * @param errors
12017fb333e9SShihong Wang  *   The value is SA discards packet sum total
12027fb333e9SShihong Wang  * @param sa_discard_stats
12037fb333e9SShihong Wang  *   The struct is SA discards packet Statistics
12047fb333e9SShihong Wang  */
12057fb333e9SShihong Wang static void
12067fb333e9SShihong Wang nfp_get_errorstats(uint64_t *errors,
12077fb333e9SShihong Wang 		struct ipsec_discard_stats *sa_discard_stats)
12087fb333e9SShihong Wang {
12097fb333e9SShihong Wang 	uint32_t i;
12107fb333e9SShihong Wang 	uint32_t len;
12117fb333e9SShihong Wang 	uint32_t *perror;
12127fb333e9SShihong Wang 
12137fb333e9SShihong Wang 	perror = &sa_discard_stats->discards_auth;
12147fb333e9SShihong Wang 	len = sizeof(struct ipsec_discard_stats) / sizeof(uint32_t);
12157fb333e9SShihong Wang 
12167fb333e9SShihong Wang 	for (i = 0; i < len; i++)
12177fb333e9SShihong Wang 		*errors += *perror++;
12187fb333e9SShihong Wang 
12197fb333e9SShihong Wang 	*errors -= sa_discard_stats->ipv4_id_counter;
12207fb333e9SShihong Wang }
12217fb333e9SShihong Wang 
12227fb333e9SShihong Wang static int
12237fb333e9SShihong Wang nfp_security_session_get_stats(void *device,
12247fb333e9SShihong Wang 		struct rte_security_session *session,
12257fb333e9SShihong Wang 		struct rte_security_stats *stats)
12267fb333e9SShihong Wang {
12277fb333e9SShihong Wang 	int ret;
12284a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
12297fb333e9SShihong Wang 	struct nfp_ipsec_msg msg;
12307fb333e9SShihong Wang 	struct rte_eth_dev *eth_dev;
12317fb333e9SShihong Wang 	struct ipsec_get_sa_stats *cfg_s;
12327fb333e9SShihong Wang 	struct rte_security_ipsec_stats *ips_s;
12337fb333e9SShihong Wang 	struct nfp_ipsec_session *priv_session;
12347fb333e9SShihong Wang 	enum rte_security_ipsec_sa_direction direction;
12357fb333e9SShihong Wang 
12367fb333e9SShihong Wang 	eth_dev = device;
12377fb333e9SShihong Wang 	priv_session = SECURITY_GET_SESS_PRIV(session);
12387fb333e9SShihong Wang 	memset(&msg, 0, sizeof(msg));
12397fb333e9SShihong Wang 	msg.cmd = NFP_IPSEC_CFG_MSG_GET_SA_STATS;
12407fb333e9SShihong Wang 	msg.sa_idx = priv_session->sa_index;
12419d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
12427fb333e9SShihong Wang 
12434a9bb682SChaoyong He 	ret = nfp_ipsec_cfg_cmd_issue(net_hw, &msg);
12447fb333e9SShihong Wang 	if (ret < 0) {
12457fb333e9SShihong Wang 		PMD_DRV_LOG(ERR, "Failed to get SA stats");
12467fb333e9SShihong Wang 		return ret;
12477fb333e9SShihong Wang 	}
12487fb333e9SShihong Wang 
12497fb333e9SShihong Wang 	cfg_s = &msg.cfg_get_stats;
12507fb333e9SShihong Wang 	direction = priv_session->ipsec.direction;
12517fb333e9SShihong Wang 	memset(stats, 0, sizeof(struct rte_security_stats)); /* Start with zeros */
12527fb333e9SShihong Wang 	stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
12537fb333e9SShihong Wang 	ips_s = &stats->ipsec;
12547fb333e9SShihong Wang 
12557fb333e9SShihong Wang 	/* Only display SA if any counters are non-zero */
12567fb333e9SShihong Wang 	if (cfg_s->lifetime_byte_count != 0 || cfg_s->pkt_count != 0) {
12577fb333e9SShihong Wang 		if (direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
12587fb333e9SShihong Wang 			ips_s->ipackets = cfg_s->pkt_count;
12597fb333e9SShihong Wang 			ips_s->ibytes = cfg_s->lifetime_byte_count;
12607fb333e9SShihong Wang 			nfp_get_errorstats(&ips_s->ierrors, &cfg_s->sa_discard_stats);
12617fb333e9SShihong Wang 		} else {
12627fb333e9SShihong Wang 			ips_s->opackets = cfg_s->pkt_count;
12637fb333e9SShihong Wang 			ips_s->obytes = cfg_s->lifetime_byte_count;
12647fb333e9SShihong Wang 			nfp_get_errorstats(&ips_s->oerrors, &cfg_s->sa_discard_stats);
12657fb333e9SShihong Wang 		}
12667fb333e9SShihong Wang 	}
12677fb333e9SShihong Wang 
12687fb333e9SShihong Wang 	return 0;
12697fb333e9SShihong Wang }
12707fb333e9SShihong Wang 
1271e6d69ea0SShihong Wang static const struct rte_security_capability *
1272e6d69ea0SShihong Wang nfp_crypto_capabilities_get(void *device __rte_unused)
1273e6d69ea0SShihong Wang {
1274e6d69ea0SShihong Wang 	return nfp_security_caps;
1275e6d69ea0SShihong Wang }
1276e6d69ea0SShihong Wang 
1277e6d69ea0SShihong Wang static uint32_t
1278e6d69ea0SShihong Wang nfp_security_session_get_size(void *device __rte_unused)
1279e6d69ea0SShihong Wang {
1280e6d69ea0SShihong Wang 	return sizeof(struct nfp_ipsec_session);
1281e6d69ea0SShihong Wang }
1282e6d69ea0SShihong Wang 
1283eaf38c9bSShihong Wang static int
1284eaf38c9bSShihong Wang nfp_crypto_remove_sa(struct rte_eth_dev *eth_dev,
1285eaf38c9bSShihong Wang 		struct nfp_ipsec_session *priv_session)
1286eaf38c9bSShihong Wang {
1287eaf38c9bSShihong Wang 	int ret;
1288eaf38c9bSShihong Wang 	uint32_t sa_index;
12894a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
1290eaf38c9bSShihong Wang 	struct nfp_ipsec_msg cfg;
1291eaf38c9bSShihong Wang 
1292eaf38c9bSShihong Wang 	sa_index = priv_session->sa_index;
12939d723baaSChaoyong He 	net_hw = eth_dev->data->dev_private;
1294eaf38c9bSShihong Wang 
1295eaf38c9bSShihong Wang 	cfg.cmd = NFP_IPSEC_CFG_MSG_INV_SA;
1296eaf38c9bSShihong Wang 	cfg.sa_idx = sa_index;
12974a9bb682SChaoyong He 	ret = nfp_ipsec_cfg_cmd_issue(net_hw, &cfg);
1298eaf38c9bSShihong Wang 	if (ret < 0) {
1299eaf38c9bSShihong Wang 		PMD_DRV_LOG(ERR, "Failed to remove SA!");
1300eaf38c9bSShihong Wang 		return -EINVAL;
1301eaf38c9bSShihong Wang 	}
1302eaf38c9bSShihong Wang 
13034a9bb682SChaoyong He 	net_hw->ipsec_data->sa_free_cnt++;
13044a9bb682SChaoyong He 	net_hw->ipsec_data->sa_entries[sa_index] = NULL;
1305eaf38c9bSShihong Wang 
1306eaf38c9bSShihong Wang 	return 0;
1307eaf38c9bSShihong Wang }
1308eaf38c9bSShihong Wang 
1309eaf38c9bSShihong Wang static int
1310eaf38c9bSShihong Wang nfp_crypto_remove_session(void *device,
1311eaf38c9bSShihong Wang 		struct rte_security_session *session)
1312eaf38c9bSShihong Wang {
1313eaf38c9bSShihong Wang 	int ret;
1314eaf38c9bSShihong Wang 	struct rte_eth_dev *eth_dev;
1315eaf38c9bSShihong Wang 	struct nfp_ipsec_session *priv_session;
1316eaf38c9bSShihong Wang 
1317eaf38c9bSShihong Wang 	eth_dev = device;
1318eaf38c9bSShihong Wang 	priv_session = SECURITY_GET_SESS_PRIV(session);
1319eaf38c9bSShihong Wang 	if (eth_dev != priv_session->dev) {
1320eaf38c9bSShihong Wang 		PMD_DRV_LOG(ERR, "Session not bound to this device");
1321eaf38c9bSShihong Wang 		return -ENODEV;
1322eaf38c9bSShihong Wang 	}
1323eaf38c9bSShihong Wang 
1324eaf38c9bSShihong Wang 	ret = nfp_crypto_remove_sa(eth_dev, priv_session);
1325eaf38c9bSShihong Wang 	if (ret < 0) {
1326eaf38c9bSShihong Wang 		PMD_DRV_LOG(ERR, "Failed to remove session");
1327eaf38c9bSShihong Wang 		return -EFAULT;
1328eaf38c9bSShihong Wang 	}
1329eaf38c9bSShihong Wang 
1330eaf38c9bSShihong Wang 	memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
1331eaf38c9bSShihong Wang 
1332eaf38c9bSShihong Wang 	return 0;
1333eaf38c9bSShihong Wang }
1334eaf38c9bSShihong Wang 
1335e6d69ea0SShihong Wang static const struct rte_security_ops nfp_security_ops = {
13363d21da66SChang Miao 	.session_create = nfp_crypto_create_session,
13377e6c8063SShihong Wang 	.session_update = nfp_crypto_update_session,
1338e6d69ea0SShihong Wang 	.session_get_size = nfp_security_session_get_size,
13397fb333e9SShihong Wang 	.session_stats_get = nfp_security_session_get_stats,
1340eaf38c9bSShihong Wang 	.session_destroy = nfp_crypto_remove_session,
1341310a1780SShihong Wang 	.set_pkt_metadata = nfp_security_set_pkt_metadata,
1342e6d69ea0SShihong Wang 	.capabilities_get = nfp_crypto_capabilities_get,
1343e6d69ea0SShihong Wang };
134454713740SChang Miao 
134554713740SChang Miao static int
134654713740SChang Miao nfp_ipsec_ctx_create(struct rte_eth_dev *dev,
134754713740SChang Miao 		struct nfp_net_ipsec_data *data)
134854713740SChang Miao {
134954713740SChang Miao 	struct rte_security_ctx *ctx;
135054713740SChang Miao 	static const struct rte_mbuf_dynfield pkt_md_dynfield = {
135154713740SChang Miao 		.name = "nfp_ipsec_crypto_pkt_metadata",
135254713740SChang Miao 		.size = sizeof(struct nfp_tx_ipsec_desc_msg),
1353*08966fe7STyler Retzlaff 		.align = alignof(struct nfp_tx_ipsec_desc_msg),
135454713740SChang Miao 	};
135554713740SChang Miao 
135654713740SChang Miao 	ctx = rte_zmalloc("security_ctx",
135754713740SChang Miao 			sizeof(struct rte_security_ctx), 0);
135854713740SChang Miao 	if (ctx == NULL) {
135954713740SChang Miao 		PMD_INIT_LOG(ERR, "Failed to malloc security_ctx");
136054713740SChang Miao 		return -ENOMEM;
136154713740SChang Miao 	}
136254713740SChang Miao 
136354713740SChang Miao 	ctx->device = dev;
136454713740SChang Miao 	ctx->ops = &nfp_security_ops;
136554713740SChang Miao 	ctx->sess_cnt = 0;
136654713740SChang Miao 	dev->security_ctx = ctx;
136754713740SChang Miao 
136854713740SChang Miao 	data->pkt_dynfield_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
136954713740SChang Miao 	if (data->pkt_dynfield_offset < 0) {
137054713740SChang Miao 		PMD_INIT_LOG(ERR, "Failed to register mbuf esn_dynfield");
137154713740SChang Miao 		return -ENOMEM;
137254713740SChang Miao 	}
137354713740SChang Miao 
137454713740SChang Miao 	return 0;
137554713740SChang Miao }
137654713740SChang Miao 
137754713740SChang Miao int
137854713740SChang Miao nfp_ipsec_init(struct rte_eth_dev *dev)
137954713740SChang Miao {
138054713740SChang Miao 	int ret;
138154713740SChang Miao 	uint32_t cap_extend;
13824a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
138354713740SChang Miao 	struct nfp_net_ipsec_data *data;
138454713740SChang Miao 
13859d723baaSChaoyong He 	net_hw = dev->data->dev_private;
138654713740SChang Miao 
13874a9bb682SChaoyong He 	cap_extend = net_hw->super.cap_ext;
138854713740SChang Miao 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
138954713740SChang Miao 		PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
139054713740SChang Miao 		return 0;
139154713740SChang Miao 	}
139254713740SChang Miao 
139354713740SChang Miao 	data = rte_zmalloc("ipsec_data", sizeof(struct nfp_net_ipsec_data), 0);
139454713740SChang Miao 	if (data == NULL) {
139554713740SChang Miao 		PMD_INIT_LOG(ERR, "Failed to malloc ipsec_data");
139654713740SChang Miao 		return -ENOMEM;
139754713740SChang Miao 	}
139854713740SChang Miao 
139954713740SChang Miao 	data->pkt_dynfield_offset = -1;
140054713740SChang Miao 	data->sa_free_cnt = NFP_NET_IPSEC_MAX_SA_CNT;
14014a9bb682SChaoyong He 	net_hw->ipsec_data = data;
140254713740SChang Miao 
140354713740SChang Miao 	ret = nfp_ipsec_ctx_create(dev, data);
140454713740SChang Miao 	if (ret != 0) {
140554713740SChang Miao 		PMD_INIT_LOG(ERR, "Failed to create IPsec ctx");
140654713740SChang Miao 		goto ipsec_cleanup;
140754713740SChang Miao 	}
140854713740SChang Miao 
140954713740SChang Miao 	return 0;
141054713740SChang Miao 
141154713740SChang Miao ipsec_cleanup:
141254713740SChang Miao 	nfp_ipsec_uninit(dev);
141354713740SChang Miao 
141454713740SChang Miao 	return ret;
141554713740SChang Miao }
141654713740SChang Miao 
141754713740SChang Miao static void
141854713740SChang Miao nfp_ipsec_ctx_destroy(struct rte_eth_dev *dev)
141954713740SChang Miao {
142054713740SChang Miao 	rte_free(dev->security_ctx);
142154713740SChang Miao }
142254713740SChang Miao 
142354713740SChang Miao void
142454713740SChang Miao nfp_ipsec_uninit(struct rte_eth_dev *dev)
142554713740SChang Miao {
142654713740SChang Miao 	uint16_t i;
142754713740SChang Miao 	uint32_t cap_extend;
14284a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
142954713740SChang Miao 	struct nfp_ipsec_session *priv_session;
143054713740SChang Miao 
14319d723baaSChaoyong He 	net_hw = dev->data->dev_private;
143254713740SChang Miao 
14334a9bb682SChaoyong He 	cap_extend = net_hw->super.cap_ext;
143454713740SChang Miao 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) == 0) {
143554713740SChang Miao 		PMD_INIT_LOG(INFO, "Unsupported IPsec extend capability");
143654713740SChang Miao 		return;
143754713740SChang Miao 	}
143854713740SChang Miao 
143954713740SChang Miao 	nfp_ipsec_ctx_destroy(dev);
144054713740SChang Miao 
14414a9bb682SChaoyong He 	if (net_hw->ipsec_data == NULL) {
144254713740SChang Miao 		PMD_INIT_LOG(INFO, "IPsec data is NULL!");
144354713740SChang Miao 		return;
144454713740SChang Miao 	}
144554713740SChang Miao 
144654713740SChang Miao 	for (i = 0; i < NFP_NET_IPSEC_MAX_SA_CNT; i++) {
14474a9bb682SChaoyong He 		priv_session = net_hw->ipsec_data->sa_entries[i];
144854713740SChang Miao 		if (priv_session != NULL)
144954713740SChang Miao 			memset(priv_session, 0, sizeof(struct nfp_ipsec_session));
145054713740SChang Miao 	}
145154713740SChang Miao 
14524a9bb682SChaoyong He 	rte_free(net_hw->ipsec_data);
145354713740SChang Miao }
145454713740SChang Miao 
1455