Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : :
5 : : #include <stdalign.h>
6 : :
7 : : #include <rte_cryptodev.h>
8 : : #include <rte_ethdev.h>
9 : : #include <rte_security_driver.h>
10 : : #include <rte_security.h>
11 : :
12 : : #include "iavf.h"
13 : : #include "iavf_rxtx.h"
14 : : #include "iavf_log.h"
15 : : #include "iavf_generic_flow.h"
16 : :
17 : : #include "iavf_ipsec_crypto.h"
18 : : #include "iavf_ipsec_crypto_capabilities.h"
19 : :
20 : : /**
21 : : * iAVF IPsec Crypto Security Context
22 : : */
23 : : struct iavf_security_ctx {
24 : : struct iavf_adapter *adapter;
25 : : int pkt_md_offset;
26 : : struct rte_cryptodev_capabilities *crypto_capabilities;
27 : : };
28 : :
29 : : /**
30 : : * iAVF IPsec Crypto Security Session Parameters
31 : : */
32 : : struct iavf_security_session {
33 : : struct iavf_adapter *adapter;
34 : :
35 : : enum rte_security_ipsec_sa_mode mode;
36 : : enum rte_security_ipsec_tunnel_type type;
37 : : enum rte_security_ipsec_sa_direction direction;
38 : :
39 : : struct {
40 : : uint32_t spi; /* Security Parameter Index */
41 : : uint32_t hw_idx; /* SA Index in hardware table */
42 : : } sa;
43 : :
44 : : struct {
45 : : uint8_t enabled :1;
46 : : union {
47 : : uint64_t value;
48 : : struct {
49 : : uint32_t hi;
50 : : uint32_t low;
51 : : };
52 : : };
53 : : } esn;
54 : :
55 : : struct {
56 : : uint8_t enabled :1;
57 : : } udp_encap;
58 : :
59 : : size_t iv_sz;
60 : : size_t icv_sz;
61 : : size_t block_sz;
62 : :
63 : : struct iavf_ipsec_crypto_pkt_metadata pkt_metadata_template;
64 : : };
65 : : /**
66 : : * IV Length field in IPsec Tx Desc uses the following encoding:
67 : : *
68 : : * 0B - 0
69 : : * 4B - 1
70 : : * 8B - 2
71 : : * 16B - 3
72 : : *
73 : : * but we also need the IV Length for TSO to correctly calculate the total
74 : : * header length so placing it in the upper 6-bits here for easier retrieval.
75 : : */
76 : : static inline uint8_t
77 : : calc_ipsec_desc_iv_len_field(uint16_t iv_sz)
78 : : {
79 : : uint8_t iv_length = IAVF_IPSEC_IV_LEN_NONE;
80 : :
81 : : switch (iv_sz) {
82 : : case 4:
83 : : iv_length = IAVF_IPSEC_IV_LEN_DW;
84 : : break;
85 : : case 8:
86 : : iv_length = IAVF_IPSEC_IV_LEN_DDW;
87 : : break;
88 : : case 16:
89 : : iv_length = IAVF_IPSEC_IV_LEN_QDW;
90 : : break;
91 : : }
92 : :
93 : 0 : return (iv_sz << 2) | iv_length;
94 : : }
95 : :
96 : : static unsigned int
97 : 0 : iavf_ipsec_crypto_session_size_get(void *device __rte_unused)
98 : : {
99 : 0 : return sizeof(struct iavf_security_session);
100 : : }
101 : :
102 : : static const struct rte_cryptodev_symmetric_capability *
103 : : get_capability(struct iavf_security_ctx *iavf_sctx __rte_unused,
104 : : uint32_t algo, uint32_t type)
105 : : {
106 : : const struct rte_cryptodev_capabilities *capability;
107 : : int i = 0;
108 : :
109 : : capability = &iavf_crypto_capabilities[i];
110 : :
111 [ # # # # : 0 : while (capability->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
# # # # #
# # # # #
# # # # ]
112 [ # # # # : 0 : if (capability->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
# # # # #
# # # # #
# # # # ]
113 [ # # # # : 0 : (uint32_t)capability->sym.xform_type == type &&
# # # # #
# # # # #
# # # # ]
114 [ # # # # : 0 : (uint32_t)capability->sym.cipher.algo == algo)
# # # # #
# # # # #
# # # # ]
115 : 0 : return &capability->sym;
116 : : /** try next capability */
117 : 0 : capability = &iavf_crypto_capabilities[i++];
118 : : }
119 : :
120 : : return NULL;
121 : : }
122 : :
123 : : static const struct rte_cryptodev_symmetric_capability *
124 : : get_auth_capability(struct iavf_security_ctx *iavf_sctx,
125 : : enum rte_crypto_auth_algorithm algo)
126 : : {
127 : : return get_capability(iavf_sctx, algo, RTE_CRYPTO_SYM_XFORM_AUTH);
128 : : }
129 : :
130 : : static const struct rte_cryptodev_symmetric_capability *
131 : : get_cipher_capability(struct iavf_security_ctx *iavf_sctx,
132 : : enum rte_crypto_cipher_algorithm algo)
133 : : {
134 : : return get_capability(iavf_sctx, algo, RTE_CRYPTO_SYM_XFORM_CIPHER);
135 : : }
136 : : static const struct rte_cryptodev_symmetric_capability *
137 : : get_aead_capability(struct iavf_security_ctx *iavf_sctx,
138 : : enum rte_crypto_aead_algorithm algo)
139 : : {
140 : : return get_capability(iavf_sctx, algo, RTE_CRYPTO_SYM_XFORM_AEAD);
141 : : }
142 : :
143 : : static uint16_t
144 : : get_cipher_blocksize(struct iavf_security_ctx *iavf_sctx,
145 : : enum rte_crypto_cipher_algorithm algo)
146 : : {
147 : : const struct rte_cryptodev_symmetric_capability *capability;
148 : :
149 : : capability = get_cipher_capability(iavf_sctx, algo);
150 [ # # # # ]: 0 : if (capability == NULL)
151 : : return 0;
152 : :
153 : 0 : return capability->cipher.block_size;
154 : : }
155 : :
156 : : static uint16_t
157 : : get_aead_blocksize(struct iavf_security_ctx *iavf_sctx,
158 : : enum rte_crypto_aead_algorithm algo)
159 : : {
160 : : const struct rte_cryptodev_symmetric_capability *capability;
161 : :
162 : : capability = get_aead_capability(iavf_sctx, algo);
163 [ # # ]: 0 : if (capability == NULL)
164 : : return 0;
165 : :
166 : 0 : return capability->cipher.block_size;
167 : : }
168 : :
169 : : static uint16_t
170 : : get_auth_blocksize(struct iavf_security_ctx *iavf_sctx,
171 : : enum rte_crypto_auth_algorithm algo)
172 : : {
173 : : const struct rte_cryptodev_symmetric_capability *capability;
174 : :
175 : : capability = get_auth_capability(iavf_sctx, algo);
176 [ # # ]: 0 : if (capability == NULL)
177 : : return 0;
178 : :
179 : 0 : return capability->auth.block_size;
180 : : }
181 : :
182 : : static uint8_t
183 : : calc_context_desc_cipherblock_sz(size_t len)
184 : : {
185 : 0 : switch (len) {
186 : : case 8:
187 : : return 0x2;
188 : 0 : case 16:
189 : 0 : return 0x3;
190 : 0 : default:
191 : 0 : return 0x0;
192 : : }
193 : : }
194 : :
195 : : static int
196 : : valid_length(uint32_t len, uint32_t min, uint32_t max, uint32_t increment)
197 : : {
198 : 0 : if (len < min || len > max)
199 : : return false;
200 : :
201 [ # # # # : 0 : if (increment == 0)
# # ]
202 : : return true;
203 : :
204 [ # # # # : 0 : if ((len - min) % increment)
# # ]
205 : : return false;
206 : :
207 : : /* make sure it fits in the key array */
208 [ # # # # : 0 : if (len > VIRTCHNL_IPSEC_MAX_KEY_LEN)
# # ]
209 : : return false;
210 : :
211 : : return true;
212 : : }
213 : :
214 : : static int
215 : 0 : valid_auth_xform(struct iavf_security_ctx *iavf_sctx,
216 : : struct rte_crypto_auth_xform *auth)
217 : : {
218 : : const struct rte_cryptodev_symmetric_capability *capability;
219 : :
220 : 0 : capability = get_auth_capability(iavf_sctx, auth->algo);
221 [ # # ]: 0 : if (capability == NULL)
222 : : return false;
223 : :
224 : : /* verify key size */
225 : 0 : if (!valid_length(auth->key.length,
226 : 0 : capability->auth.key_size.min,
227 : 0 : capability->auth.key_size.max,
228 [ # # ]: 0 : capability->aead.key_size.increment))
229 : 0 : return false;
230 : :
231 : : return true;
232 : : }
233 : :
234 : : static int
235 : 0 : valid_cipher_xform(struct iavf_security_ctx *iavf_sctx,
236 : : struct rte_crypto_cipher_xform *cipher)
237 : : {
238 : : const struct rte_cryptodev_symmetric_capability *capability;
239 : :
240 : 0 : capability = get_cipher_capability(iavf_sctx, cipher->algo);
241 [ # # ]: 0 : if (capability == NULL)
242 : : return false;
243 : :
244 : : /* verify key size */
245 : 0 : if (!valid_length(cipher->key.length,
246 : 0 : capability->cipher.key_size.min,
247 : 0 : capability->cipher.key_size.max,
248 [ # # ]: 0 : capability->cipher.key_size.increment))
249 : 0 : return false;
250 : :
251 : : return true;
252 : : }
253 : :
254 : : static int
255 : 0 : valid_aead_xform(struct iavf_security_ctx *iavf_sctx,
256 : : struct rte_crypto_aead_xform *aead)
257 : : {
258 : : const struct rte_cryptodev_symmetric_capability *capability;
259 : :
260 : 0 : capability = get_aead_capability(iavf_sctx, aead->algo);
261 [ # # ]: 0 : if (capability == NULL)
262 : : return false;
263 : :
264 : : /* verify key size */
265 : 0 : if (!valid_length(aead->key.length,
266 : 0 : capability->aead.key_size.min,
267 : 0 : capability->aead.key_size.max,
268 [ # # ]: 0 : capability->aead.key_size.increment))
269 : 0 : return false;
270 : :
271 : : return true;
272 : : }
273 : :
274 : : static int
275 : 0 : iavf_ipsec_crypto_session_validate_conf(struct iavf_security_ctx *iavf_sctx,
276 : : struct rte_security_session_conf *conf)
277 : : {
278 : : /** validate security action/protocol selection */
279 [ # # ]: 0 : if (conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
280 : : conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
281 : 0 : PMD_DRV_LOG(ERR, "Invalid action / protocol specified");
282 : 0 : return -EINVAL;
283 : : }
284 : :
285 : : /** validate IPsec protocol selection */
286 [ # # ]: 0 : if (conf->ipsec.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
287 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec protocol specified");
288 : 0 : return -EINVAL;
289 : : }
290 : :
291 : : /** validate selected options */
292 : 0 : if (conf->ipsec.options.copy_dscp ||
293 : : conf->ipsec.options.copy_flabel ||
294 : : conf->ipsec.options.copy_df ||
295 : : conf->ipsec.options.dec_ttl ||
296 [ # # ]: 0 : conf->ipsec.options.ecn ||
297 : : conf->ipsec.options.stats) {
298 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
299 : 0 : return -EINVAL;
300 : : }
301 : :
302 : : /**
303 : : * Validate crypto xforms parameters.
304 : : *
305 : : * AEAD transforms can be used for either inbound/outbound IPsec SAs,
306 : : * for non-AEAD crypto transforms we explicitly only support CIPHER/AUTH
307 : : * for outbound and AUTH/CIPHER chained transforms for inbound IPsec.
308 : : */
309 [ # # ]: 0 : if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
310 [ # # ]: 0 : if (!valid_aead_xform(iavf_sctx, &conf->crypto_xform->aead)) {
311 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
312 : 0 : return -EINVAL;
313 : : }
314 [ # # # # ]: 0 : } else if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
315 : 0 : conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
316 [ # # ]: 0 : conf->crypto_xform->next &&
317 [ # # ]: 0 : conf->crypto_xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
318 [ # # ]: 0 : if (!valid_cipher_xform(iavf_sctx,
319 : : &conf->crypto_xform->cipher)) {
320 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
321 : 0 : return -EINVAL;
322 : : }
323 : :
324 [ # # ]: 0 : if (!valid_auth_xform(iavf_sctx,
325 : : &conf->crypto_xform->next->auth)) {
326 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
327 : 0 : return -EINVAL;
328 : : }
329 [ # # # # ]: 0 : } else if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
330 : 0 : conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
331 [ # # ]: 0 : conf->crypto_xform->next &&
332 [ # # ]: 0 : conf->crypto_xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
333 [ # # ]: 0 : if (!valid_auth_xform(iavf_sctx, &conf->crypto_xform->auth)) {
334 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
335 : 0 : return -EINVAL;
336 : : }
337 : :
338 [ # # ]: 0 : if (!valid_cipher_xform(iavf_sctx,
339 : : &conf->crypto_xform->next->cipher)) {
340 : 0 : PMD_DRV_LOG(ERR, "Invalid IPsec option specified");
341 : 0 : return -EINVAL;
342 : : }
343 : : }
344 : :
345 : : return 0;
346 : : }
347 : :
348 : : static void
349 : 0 : sa_add_set_aead_params(struct virtchnl_ipsec_crypto_cfg_item *cfg,
350 : : struct rte_crypto_aead_xform *aead, uint32_t salt)
351 : : {
352 : 0 : cfg->crypto_type = VIRTCHNL_AEAD;
353 : :
354 [ # # # # ]: 0 : switch (aead->algo) {
355 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
356 : 0 : cfg->algo_type = VIRTCHNL_AES_CCM; break;
357 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
358 : 0 : cfg->algo_type = VIRTCHNL_AES_GCM; break;
359 : 0 : case RTE_CRYPTO_AEAD_CHACHA20_POLY1305:
360 : 0 : cfg->algo_type = VIRTCHNL_CHACHA20_POLY1305; break;
361 : 0 : default:
362 : 0 : PMD_DRV_LOG(ERR, "Invalid AEAD parameters");
363 : 0 : break;
364 : : }
365 : :
366 : 0 : cfg->key_len = aead->key.length;
367 : 0 : cfg->iv_len = sizeof(uint64_t); /* iv.length includes salt len */
368 : 0 : cfg->digest_len = aead->digest_length;
369 : 0 : cfg->salt = salt;
370 : :
371 : 0 : memcpy(cfg->key_data, aead->key.data, cfg->key_len);
372 : 0 : }
373 : :
374 : : static void
375 : 0 : sa_add_set_cipher_params(struct virtchnl_ipsec_crypto_cfg_item *cfg,
376 : : struct rte_crypto_cipher_xform *cipher, uint32_t salt)
377 : : {
378 : 0 : cfg->crypto_type = VIRTCHNL_CIPHER;
379 : :
380 [ # # # # : 0 : switch (cipher->algo) {
# ]
381 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
382 : 0 : cfg->algo_type = VIRTCHNL_AES_CBC; break;
383 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
384 : 0 : cfg->algo_type = VIRTCHNL_3DES_CBC; break;
385 : 0 : case RTE_CRYPTO_CIPHER_NULL:
386 : 0 : cfg->algo_type = VIRTCHNL_CIPHER_NO_ALG; break;
387 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
388 : 0 : cfg->algo_type = VIRTCHNL_AES_CTR;
389 : : cfg->salt = salt;
390 : 0 : break;
391 : 0 : default:
392 : 0 : PMD_DRV_LOG(ERR, "Invalid cipher parameters");
393 : 0 : break;
394 : : }
395 : :
396 : 0 : cfg->key_len = cipher->key.length;
397 : 0 : cfg->iv_len = cipher->iv.length;
398 : 0 : cfg->salt = salt;
399 : :
400 : 0 : memcpy(cfg->key_data, cipher->key.data, cfg->key_len);
401 : 0 : }
402 : :
403 : : static void
404 : 0 : sa_add_set_auth_params(struct virtchnl_ipsec_crypto_cfg_item *cfg,
405 : : struct rte_crypto_auth_xform *auth, uint32_t salt)
406 : : {
407 : 0 : cfg->crypto_type = VIRTCHNL_AUTH;
408 : :
409 [ # # # # : 0 : switch (auth->algo) {
# # # # #
# # # ]
410 : 0 : case RTE_CRYPTO_AUTH_NULL:
411 : 0 : cfg->algo_type = VIRTCHNL_HASH_NO_ALG; break;
412 : 0 : case RTE_CRYPTO_AUTH_AES_CBC_MAC:
413 : 0 : cfg->algo_type = VIRTCHNL_AES_CBC_MAC; break;
414 : 0 : case RTE_CRYPTO_AUTH_AES_CMAC:
415 : 0 : cfg->algo_type = VIRTCHNL_AES_CMAC; break;
416 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
417 : 0 : cfg->algo_type = VIRTCHNL_AES_XCBC_MAC; break;
418 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
419 : 0 : cfg->algo_type = VIRTCHNL_MD5_HMAC; break;
420 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
421 : 0 : cfg->algo_type = VIRTCHNL_SHA1_HMAC; break;
422 : 0 : case RTE_CRYPTO_AUTH_SHA224_HMAC:
423 : 0 : cfg->algo_type = VIRTCHNL_SHA224_HMAC; break;
424 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
425 : 0 : cfg->algo_type = VIRTCHNL_SHA256_HMAC; break;
426 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
427 : 0 : cfg->algo_type = VIRTCHNL_SHA384_HMAC; break;
428 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
429 : 0 : cfg->algo_type = VIRTCHNL_SHA512_HMAC; break;
430 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
431 : 0 : cfg->algo_type = VIRTCHNL_AES_GMAC;
432 : 0 : cfg->salt = salt;
433 : 0 : break;
434 : 0 : default:
435 : 0 : PMD_DRV_LOG(ERR, "Invalid auth parameters");
436 : 0 : break;
437 : : }
438 : :
439 : 0 : cfg->key_len = auth->key.length;
440 : : /* special case for RTE_CRYPTO_AUTH_AES_GMAC */
441 [ # # ]: 0 : if (auth->algo == RTE_CRYPTO_AUTH_AES_GMAC)
442 : 0 : cfg->iv_len = sizeof(uint64_t); /* iv.length includes salt */
443 : : else
444 : 0 : cfg->iv_len = auth->iv.length;
445 : 0 : cfg->digest_len = auth->digest_length;
446 : :
447 : 0 : memcpy(cfg->key_data, auth->key.data, cfg->key_len);
448 : 0 : }
449 : :
450 : : /**
451 : : * Send SA add virtual channel request to Inline IPsec driver.
452 : : *
453 : : * Inline IPsec driver expects SPI and destination IP address to be in host
454 : : * order, but DPDK APIs are network order, therefore we need to do a htonl
455 : : * conversion of these parameters.
456 : : */
457 : : static uint32_t
458 : 0 : iavf_ipsec_crypto_security_association_add(struct iavf_adapter *adapter,
459 : : struct rte_security_session_conf *conf)
460 : : {
461 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
462 : : struct virtchnl_ipsec_sa_cfg *sa_cfg;
463 : : size_t request_len, response_len;
464 : :
465 : : int rc;
466 : :
467 : : request_len = sizeof(struct inline_ipsec_msg) +
468 : : sizeof(struct virtchnl_ipsec_sa_cfg);
469 : :
470 : 0 : request = rte_malloc("iavf-sad-add-request", request_len, 0);
471 [ # # ]: 0 : if (request == NULL) {
472 : : rc = -ENOMEM;
473 : 0 : goto update_cleanup;
474 : : }
475 : :
476 : : response_len = sizeof(struct inline_ipsec_msg) +
477 : : sizeof(struct virtchnl_ipsec_sa_cfg_resp);
478 : 0 : response = rte_malloc("iavf-sad-add-response", response_len, 0);
479 [ # # ]: 0 : if (response == NULL) {
480 : : rc = -ENOMEM;
481 : 0 : goto update_cleanup;
482 : : }
483 : :
484 : : /* set msg header params */
485 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SA_CREATE;
486 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
487 : :
488 : : /* set SA configuration params */
489 : : sa_cfg = (struct virtchnl_ipsec_sa_cfg *)(request + 1);
490 : :
491 : 0 : sa_cfg->spi = conf->ipsec.spi;
492 : 0 : sa_cfg->virtchnl_protocol_type = VIRTCHNL_PROTO_ESP;
493 : 0 : sa_cfg->virtchnl_direction =
494 [ # # ]: 0 : conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS ?
495 : : VIRTCHNL_DIR_INGRESS : VIRTCHNL_DIR_EGRESS;
496 : :
497 [ # # ]: 0 : if (conf->ipsec.options.esn) {
498 : 0 : sa_cfg->esn_enabled = 1;
499 : 0 : sa_cfg->esn_hi = conf->ipsec.esn.hi;
500 : 0 : sa_cfg->esn_low = conf->ipsec.esn.low;
501 : : }
502 : :
503 [ # # ]: 0 : if (conf->ipsec.options.udp_encap)
504 : 0 : sa_cfg->udp_encap_enabled = 1;
505 : :
506 : : /* Set outer IP params */
507 [ # # ]: 0 : if (conf->ipsec.tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
508 : 0 : sa_cfg->virtchnl_ip_type = VIRTCHNL_IPV4;
509 : :
510 : 0 : *((uint32_t *)sa_cfg->dst_addr) =
511 : 0 : htonl(conf->ipsec.tunnel.ipv4.dst_ip.s_addr);
512 : : } else {
513 : : uint32_t *v6_dst_addr =
514 : : (uint32_t *)conf->ipsec.tunnel.ipv6.dst_addr.s6_addr;
515 : :
516 : 0 : sa_cfg->virtchnl_ip_type = VIRTCHNL_IPV6;
517 : :
518 : 0 : ((uint32_t *)sa_cfg->dst_addr)[0] = htonl(v6_dst_addr[0]);
519 : 0 : ((uint32_t *)sa_cfg->dst_addr)[1] = htonl(v6_dst_addr[1]);
520 : 0 : ((uint32_t *)sa_cfg->dst_addr)[2] = htonl(v6_dst_addr[2]);
521 : 0 : ((uint32_t *)sa_cfg->dst_addr)[3] = htonl(v6_dst_addr[3]);
522 : : }
523 : :
524 : : /* set crypto params */
525 [ # # ]: 0 : if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
526 : 0 : sa_add_set_aead_params(&sa_cfg->crypto_cfg.items[0],
527 : : &conf->crypto_xform->aead, conf->ipsec.salt);
528 : :
529 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
530 : 0 : sa_add_set_cipher_params(&sa_cfg->crypto_cfg.items[0],
531 : : &conf->crypto_xform->cipher, conf->ipsec.salt);
532 : 0 : sa_add_set_auth_params(&sa_cfg->crypto_cfg.items[1],
533 : 0 : &conf->crypto_xform->next->auth, conf->ipsec.salt);
534 : :
535 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
536 : 0 : sa_add_set_auth_params(&sa_cfg->crypto_cfg.items[0],
537 : : &conf->crypto_xform->auth, conf->ipsec.salt);
538 [ # # ]: 0 : if (conf->crypto_xform->auth.algo != RTE_CRYPTO_AUTH_AES_GMAC)
539 : 0 : sa_add_set_cipher_params(&sa_cfg->crypto_cfg.items[1],
540 : 0 : &conf->crypto_xform->next->cipher, conf->ipsec.salt);
541 : : }
542 : :
543 : : /* send virtual channel request to add SA to hardware database */
544 : 0 : rc = iavf_ipsec_crypto_request(adapter,
545 : : (uint8_t *)request, request_len,
546 : : (uint8_t *)response, response_len);
547 [ # # ]: 0 : if (rc)
548 : 0 : goto update_cleanup;
549 : :
550 : : /* verify response id */
551 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
552 [ # # ]: 0 : response->req_id != request->req_id)
553 : : rc = -EFAULT;
554 : : else
555 : 0 : rc = response->ipsec_data.sa_cfg_resp->sa_handle;
556 : 0 : update_cleanup:
557 : 0 : rte_free(response);
558 : 0 : rte_free(request);
559 : :
560 : 0 : return rc;
561 : : }
562 : :
563 : : static void
564 : 0 : set_pkt_metadata_template(struct iavf_ipsec_crypto_pkt_metadata *template,
565 : : struct iavf_security_session *sess)
566 : : {
567 : 0 : template->sa_idx = sess->sa.hw_idx;
568 : :
569 [ # # ]: 0 : if (sess->udp_encap.enabled)
570 : 0 : template->ol_flags = IAVF_IPSEC_CRYPTO_OL_FLAGS_NATT;
571 : :
572 [ # # ]: 0 : if (sess->esn.enabled)
573 : 0 : template->ol_flags = IAVF_IPSEC_CRYPTO_OL_FLAGS_ESN;
574 : :
575 [ # # ]: 0 : template->len_iv = calc_ipsec_desc_iv_len_field(sess->iv_sz);
576 : 0 : template->ctx_desc_ipsec_params =
577 [ # # # ]: 0 : calc_context_desc_cipherblock_sz(sess->block_sz) |
578 : 0 : ((uint8_t)(sess->icv_sz >> 2) << 3);
579 : 0 : }
580 : :
581 : : static void
582 : 0 : set_session_parameter(struct iavf_security_ctx *iavf_sctx,
583 : : struct iavf_security_session *sess,
584 : : struct rte_security_session_conf *conf, uint32_t sa_idx)
585 : : {
586 : 0 : sess->adapter = iavf_sctx->adapter;
587 : :
588 : 0 : sess->mode = conf->ipsec.mode;
589 : 0 : sess->direction = conf->ipsec.direction;
590 : :
591 [ # # ]: 0 : if (sess->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
592 : 0 : sess->type = conf->ipsec.tunnel.type;
593 : :
594 : 0 : sess->sa.spi = conf->ipsec.spi;
595 : 0 : sess->sa.hw_idx = sa_idx;
596 : :
597 [ # # ]: 0 : if (conf->ipsec.options.esn) {
598 : 0 : sess->esn.enabled = 1;
599 : 0 : sess->esn.value = conf->ipsec.esn.value;
600 : : }
601 : :
602 [ # # ]: 0 : if (conf->ipsec.options.udp_encap)
603 : 0 : sess->udp_encap.enabled = 1;
604 : :
605 [ # # ]: 0 : if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
606 : 0 : sess->block_sz = get_aead_blocksize(iavf_sctx,
607 : : conf->crypto_xform->aead.algo);
608 : 0 : sess->iv_sz = sizeof(uint64_t); /* iv.length includes salt */
609 : 0 : sess->icv_sz = conf->crypto_xform->aead.digest_length;
610 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
611 : 0 : sess->block_sz = get_cipher_blocksize(iavf_sctx,
612 : : conf->crypto_xform->cipher.algo);
613 : 0 : sess->iv_sz = conf->crypto_xform->cipher.iv.length;
614 : 0 : sess->icv_sz = conf->crypto_xform->next->auth.digest_length;
615 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
616 [ # # ]: 0 : if (conf->crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
617 : 0 : sess->block_sz = get_auth_blocksize(iavf_sctx,
618 : : conf->crypto_xform->auth.algo);
619 : 0 : sess->iv_sz = sizeof(uint64_t); /* iv len inc. salt */
620 : 0 : sess->icv_sz = conf->crypto_xform->auth.digest_length;
621 : : } else {
622 : 0 : sess->block_sz = get_cipher_blocksize(iavf_sctx,
623 : 0 : conf->crypto_xform->next->cipher.algo);
624 : 0 : sess->iv_sz =
625 : 0 : conf->crypto_xform->next->cipher.iv.length;
626 : 0 : sess->icv_sz = conf->crypto_xform->auth.digest_length;
627 : : }
628 : : }
629 : :
630 : 0 : set_pkt_metadata_template(&sess->pkt_metadata_template, sess);
631 : 0 : }
632 : :
633 : : /**
634 : : * Create IPsec Security Association for inline IPsec Crypto offload.
635 : : *
636 : : * 1. validate session configuration parameters
637 : : * 2. allocate session memory from mempool
638 : : * 3. add SA to hardware database
639 : : * 4. set session parameters
640 : : * 5. create packet metadata template for datapath
641 : : */
642 : : static int
643 : 0 : iavf_ipsec_crypto_session_create(void *device,
644 : : struct rte_security_session_conf *conf,
645 : : struct rte_security_session *session)
646 : : {
647 : : struct rte_eth_dev *ethdev = device;
648 : 0 : struct iavf_adapter *adapter =
649 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
650 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
651 : 0 : struct iavf_security_session *iavf_session = SECURITY_GET_SESS_PRIV(session);
652 : : int sa_idx;
653 : : int ret = 0;
654 : :
655 : : /* validate that all SA parameters are valid for device */
656 : 0 : ret = iavf_ipsec_crypto_session_validate_conf(iavf_sctx, conf);
657 [ # # ]: 0 : if (ret)
658 : : return ret;
659 : :
660 : : /* add SA to hardware database */
661 : 0 : sa_idx = iavf_ipsec_crypto_security_association_add(adapter, conf);
662 [ # # ]: 0 : if (sa_idx < 0) {
663 [ # # # # ]: 0 : PMD_DRV_LOG(ERR,
664 : : "Failed to add SA (spi: %d, mode: %s, direction: %s)",
665 : : conf->ipsec.spi,
666 : : conf->ipsec.mode ==
667 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT ?
668 : : "transport" : "tunnel",
669 : : conf->ipsec.direction ==
670 : : RTE_SECURITY_IPSEC_SA_DIR_INGRESS ?
671 : : "inbound" : "outbound");
672 : :
673 : 0 : return -EFAULT;
674 : : }
675 : :
676 : : /* save data plane required session parameters */
677 : 0 : set_session_parameter(iavf_sctx, iavf_session, conf, sa_idx);
678 : :
679 : 0 : return 0;
680 : : }
681 : :
682 : : /**
683 : : * Check if valid ipsec crypto action.
684 : : * SPI must be non-zero and SPI in session must match SPI value
685 : : * passed into function.
686 : : *
687 : : * returns: 0 if invalid session or SPI value equal zero
688 : : * returns: 1 if valid
689 : : */
690 : : uint32_t
691 : 0 : iavf_ipsec_crypto_action_valid(struct rte_eth_dev *ethdev,
692 : : const struct rte_security_session *session, uint32_t spi)
693 : : {
694 : 0 : struct iavf_adapter *adapter =
695 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
696 : : const struct iavf_security_session *sess = (const void *)session->driver_priv_data;
697 : :
698 : : /* verify we have a valid session and that it belong to this adapter */
699 [ # # ]: 0 : if (unlikely(sess == NULL || sess->adapter != adapter))
700 : : return false;
701 : :
702 : : /* SPI value must be non-zero and must match flow SPI*/
703 [ # # # # ]: 0 : if (spi == 0 || (htonl(sess->sa.spi) != spi))
704 : 0 : return false;
705 : :
706 : : return true;
707 : : }
708 : :
709 : : /**
710 : : * Send virtual channel security policy add request to IES driver.
711 : : *
712 : : * IES driver expects SPI and destination IP address to be in host
713 : : * order, but DPDK APIs are network order, therefore we need to do a htonl
714 : : * conversion of these parameters.
715 : : */
716 : : int
717 : 0 : iavf_ipsec_crypto_inbound_security_policy_add(struct iavf_adapter *adapter,
718 : : uint32_t esp_spi,
719 : : uint8_t is_v4,
720 : : rte_be32_t v4_dst_addr,
721 : : uint8_t *v6_dst_addr,
722 : : uint8_t drop,
723 : : bool is_udp,
724 : : uint16_t udp_port)
725 : : {
726 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
727 : : size_t request_len, response_len;
728 : : int rc = 0;
729 : :
730 : : request_len = sizeof(struct inline_ipsec_msg) +
731 : : sizeof(struct virtchnl_ipsec_sp_cfg);
732 : 0 : request = rte_malloc("iavf-inbound-security-policy-add-request",
733 : : request_len, 0);
734 [ # # ]: 0 : if (request == NULL) {
735 : : rc = -ENOMEM;
736 : 0 : goto update_cleanup;
737 : : }
738 : :
739 : : /* set msg header params */
740 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SP_CREATE;
741 [ # # ]: 0 : request->req_id = (uint16_t)0xDEADBEEF;
742 : :
743 : : /* ESP SPI */
744 : 0 : request->ipsec_data.sp_cfg->spi = htonl(esp_spi);
745 : :
746 : : /* Destination IP */
747 [ # # ]: 0 : if (is_v4) {
748 : 0 : request->ipsec_data.sp_cfg->table_id =
749 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV4;
750 : 0 : request->ipsec_data.sp_cfg->dip[0] = htonl(v4_dst_addr);
751 : : } else {
752 : 0 : request->ipsec_data.sp_cfg->table_id =
753 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV6;
754 : 0 : request->ipsec_data.sp_cfg->dip[0] =
755 : 0 : htonl(((uint32_t *)v6_dst_addr)[0]);
756 : 0 : request->ipsec_data.sp_cfg->dip[1] =
757 : 0 : htonl(((uint32_t *)v6_dst_addr)[1]);
758 : 0 : request->ipsec_data.sp_cfg->dip[2] =
759 : 0 : htonl(((uint32_t *)v6_dst_addr)[2]);
760 : 0 : request->ipsec_data.sp_cfg->dip[3] =
761 : 0 : htonl(((uint32_t *)v6_dst_addr)[3]);
762 : : }
763 : :
764 : 0 : request->ipsec_data.sp_cfg->drop = drop;
765 : :
766 : : /** Traffic Class/Congestion Domain currently not support */
767 : 0 : request->ipsec_data.sp_cfg->set_tc = 0;
768 : 0 : request->ipsec_data.sp_cfg->cgd = 0;
769 : 0 : request->ipsec_data.sp_cfg->is_udp = is_udp;
770 : 0 : request->ipsec_data.sp_cfg->udp_port = htons(udp_port);
771 : :
772 : : response_len = sizeof(struct inline_ipsec_msg) +
773 : : sizeof(struct virtchnl_ipsec_sp_cfg_resp);
774 : 0 : response = rte_malloc("iavf-inbound-security-policy-add-response",
775 : : response_len, 0);
776 [ # # ]: 0 : if (response == NULL) {
777 : : rc = -ENOMEM;
778 : 0 : goto update_cleanup;
779 : : }
780 : :
781 : : /* send virtual channel request to add SA to hardware database */
782 : 0 : rc = iavf_ipsec_crypto_request(adapter,
783 : : (uint8_t *)request, request_len,
784 : : (uint8_t *)response, response_len);
785 [ # # ]: 0 : if (rc)
786 : 0 : goto update_cleanup;
787 : :
788 : : /* verify response */
789 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
790 [ # # ]: 0 : response->req_id != request->req_id)
791 : : rc = -EFAULT;
792 : : else
793 : 0 : rc = response->ipsec_data.sp_cfg_resp->rule_id;
794 : :
795 : 0 : update_cleanup:
796 : 0 : rte_free(request);
797 : 0 : rte_free(response);
798 : :
799 : 0 : return rc;
800 : : }
801 : :
802 : : static uint32_t
803 : 0 : iavf_ipsec_crypto_sa_update_esn(struct iavf_adapter *adapter,
804 : : struct iavf_security_session *sess)
805 : : {
806 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
807 : : size_t request_len, response_len;
808 : : int rc = 0;
809 : :
810 : : request_len = sizeof(struct inline_ipsec_msg) +
811 : : sizeof(struct virtchnl_ipsec_sa_update);
812 : 0 : request = rte_malloc("iavf-sa-update-request", request_len, 0);
813 [ # # ]: 0 : if (request == NULL) {
814 : : rc = -ENOMEM;
815 : 0 : goto update_cleanup;
816 : : }
817 : :
818 : : response_len = sizeof(struct inline_ipsec_msg) +
819 : : sizeof(struct virtchnl_ipsec_resp);
820 : 0 : response = rte_malloc("iavf-sa-update-response", response_len, 0);
821 [ # # ]: 0 : if (response == NULL) {
822 : : rc = -ENOMEM;
823 : 0 : goto update_cleanup;
824 : : }
825 : :
826 : : /* set msg header params */
827 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SA_UPDATE;
828 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
829 : :
830 : : /* set request params */
831 : 0 : request->ipsec_data.sa_update->sa_index = sess->sa.hw_idx;
832 : 0 : request->ipsec_data.sa_update->esn_hi = sess->esn.hi;
833 : 0 : request->ipsec_data.sa_update->esn_low = sess->esn.low;
834 : :
835 : : /* send virtual channel request to add SA to hardware database */
836 : 0 : rc = iavf_ipsec_crypto_request(adapter,
837 : : (uint8_t *)request, request_len,
838 : : (uint8_t *)response, response_len);
839 [ # # ]: 0 : if (rc)
840 : 0 : goto update_cleanup;
841 : :
842 : : /* verify response */
843 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
844 [ # # ]: 0 : response->req_id != request->req_id)
845 : : rc = -EFAULT;
846 : : else
847 : 0 : rc = response->ipsec_data.ipsec_resp->resp;
848 : :
849 : 0 : update_cleanup:
850 : 0 : rte_free(request);
851 : 0 : rte_free(response);
852 : :
853 : 0 : return rc;
854 : : }
855 : :
856 : : static int
857 : 0 : iavf_ipsec_crypto_session_update(void *device,
858 : : struct rte_security_session *session,
859 : : struct rte_security_session_conf *conf)
860 : : {
861 : : struct iavf_adapter *adapter = NULL;
862 : : struct iavf_security_session *iavf_sess = NULL;
863 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
864 : : int rc = 0;
865 : :
866 : 0 : adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
867 : 0 : iavf_sess = SECURITY_GET_SESS_PRIV(session);
868 : :
869 : : /* verify we have a valid session and that it belong to this adapter */
870 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
871 : : return -EINVAL;
872 : :
873 : : /* update esn hi 32-bits */
874 [ # # # # ]: 0 : if (iavf_sess->esn.enabled && conf->ipsec.options.esn) {
875 : : /**
876 : : * Update ESN in hardware for inbound SA. Store in
877 : : * iavf_security_session for outbound SA for use
878 : : * in *iavf_ipsec_crypto_pkt_metadata_set* function.
879 : : */
880 : 0 : iavf_sess->esn.hi = conf->ipsec.esn.hi;
881 : 0 : iavf_sess->esn.low = conf->ipsec.esn.low;
882 [ # # ]: 0 : if (iavf_sess->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
883 : 0 : rc = iavf_ipsec_crypto_sa_update_esn(adapter,
884 : : iavf_sess);
885 : :
886 : : }
887 : :
888 : : return rc;
889 : : }
890 : :
891 : : static int
892 : 0 : iavf_ipsec_crypto_session_stats_get(void *device __rte_unused,
893 : : struct rte_security_session *session __rte_unused,
894 : : struct rte_security_stats *stats __rte_unused)
895 : : {
896 : 0 : return -EOPNOTSUPP;
897 : : }
898 : :
899 : : int
900 : 0 : iavf_ipsec_crypto_security_policy_delete(struct iavf_adapter *adapter,
901 : : uint8_t is_v4, uint32_t flow_id)
902 : : {
903 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
904 : : size_t request_len, response_len;
905 : : int rc = 0;
906 : :
907 : : request_len = sizeof(struct inline_ipsec_msg) +
908 : : sizeof(struct virtchnl_ipsec_sp_destroy);
909 : 0 : request = rte_malloc("iavf-sp-del-request", request_len, 0);
910 [ # # ]: 0 : if (request == NULL) {
911 : : rc = -ENOMEM;
912 : 0 : goto update_cleanup;
913 : : }
914 : :
915 : : response_len = sizeof(struct inline_ipsec_msg) +
916 : : sizeof(struct virtchnl_ipsec_resp);
917 : 0 : response = rte_malloc("iavf-sp-del-response", response_len, 0);
918 [ # # ]: 0 : if (response == NULL) {
919 : : rc = -ENOMEM;
920 : 0 : goto update_cleanup;
921 : : }
922 : :
923 : : /* set msg header params */
924 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SP_DESTROY;
925 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
926 : :
927 : : /* set security policy params */
928 : 0 : request->ipsec_data.sp_destroy->table_id = is_v4 ?
929 : 0 : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV4 :
930 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV6;
931 : 0 : request->ipsec_data.sp_destroy->rule_id = flow_id;
932 : :
933 : : /* send virtual channel request to add SA to hardware database */
934 : 0 : rc = iavf_ipsec_crypto_request(adapter,
935 : : (uint8_t *)request, request_len,
936 : : (uint8_t *)response, response_len);
937 [ # # ]: 0 : if (rc)
938 : 0 : goto update_cleanup;
939 : :
940 : : /* verify response */
941 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
942 [ # # ]: 0 : response->req_id != request->req_id)
943 : : rc = -EFAULT;
944 : : else
945 : 0 : return response->ipsec_data.ipsec_status->status;
946 : :
947 : 0 : update_cleanup:
948 : 0 : rte_free(request);
949 : 0 : rte_free(response);
950 : :
951 : 0 : return rc;
952 : : }
953 : :
954 : : static uint32_t
955 : 0 : iavf_ipsec_crypto_sa_del(struct iavf_adapter *adapter,
956 : : struct iavf_security_session *sess)
957 : : {
958 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
959 : : size_t request_len, response_len;
960 : :
961 : : int rc = 0;
962 : :
963 : : request_len = sizeof(struct inline_ipsec_msg) +
964 : : sizeof(struct virtchnl_ipsec_sa_destroy);
965 : :
966 : 0 : request = rte_malloc("iavf-sa-del-request", request_len, 0);
967 [ # # ]: 0 : if (request == NULL) {
968 : : rc = -ENOMEM;
969 : 0 : goto update_cleanup;
970 : : }
971 : :
972 : : response_len = sizeof(struct inline_ipsec_msg) +
973 : : sizeof(struct virtchnl_ipsec_resp);
974 : :
975 : 0 : response = rte_malloc("iavf-sa-del-response", response_len, 0);
976 [ # # ]: 0 : if (response == NULL) {
977 : : rc = -ENOMEM;
978 : 0 : goto update_cleanup;
979 : : }
980 : :
981 : : /* set msg header params */
982 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SA_DESTROY;
983 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
984 : :
985 : : /**
986 : : * SA delete supports deletion of 1-8 specified SA's or if the flag
987 : : * field is zero, all SA's associated with VF will be deleted.
988 : : */
989 [ # # ]: 0 : if (sess) {
990 : 0 : request->ipsec_data.sa_destroy->flag = 0x1;
991 : 0 : request->ipsec_data.sa_destroy->sa_index[0] = sess->sa.hw_idx;
992 : : } else {
993 : 0 : request->ipsec_data.sa_destroy->flag = 0x0;
994 : : }
995 : :
996 : : /* send virtual channel request to add SA to hardware database */
997 : 0 : rc = iavf_ipsec_crypto_request(adapter,
998 : : (uint8_t *)request, request_len,
999 : : (uint8_t *)response, response_len);
1000 [ # # ]: 0 : if (rc)
1001 : 0 : goto update_cleanup;
1002 : :
1003 : : /* verify response */
1004 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1005 [ # # ]: 0 : response->req_id != request->req_id)
1006 : : rc = -EFAULT;
1007 : :
1008 : : /**
1009 : : * Delete status will be the same bitmask as sa_destroy request flag if
1010 : : * deletes successful
1011 : : */
1012 : 0 : if (request->ipsec_data.sa_destroy->flag !=
1013 [ # # ]: 0 : response->ipsec_data.ipsec_status->status)
1014 : : rc = -EFAULT;
1015 : :
1016 : 0 : update_cleanup:
1017 : 0 : rte_free(response);
1018 : 0 : rte_free(request);
1019 : :
1020 : 0 : return rc;
1021 : : }
1022 : :
1023 : : static int
1024 : 0 : iavf_ipsec_crypto_session_destroy(void *device,
1025 : : struct rte_security_session *session)
1026 : : {
1027 : : struct iavf_adapter *adapter = NULL;
1028 : : struct iavf_security_session *iavf_sess = NULL;
1029 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1030 : : int ret;
1031 : :
1032 : 0 : adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
1033 : 0 : iavf_sess = SECURITY_GET_SESS_PRIV(session);
1034 : :
1035 : : /* verify we have a valid session and that it belong to this adapter */
1036 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
1037 : : return -EINVAL;
1038 : :
1039 : 0 : ret = iavf_ipsec_crypto_sa_del(adapter, iavf_sess);
1040 : : memset(iavf_sess, 0, sizeof(struct iavf_security_session));
1041 : 0 : return ret;
1042 : : }
1043 : :
1044 : : /**
1045 : : * Get ESP trailer from packet as well as calculate the total ESP trailer
1046 : : * length, which include padding, ESP trailer footer and the ICV
1047 : : */
1048 : : static inline struct rte_esp_tail *
1049 : 0 : iavf_ipsec_crypto_get_esp_trailer(struct rte_mbuf *m,
1050 : : struct iavf_security_session *s, uint16_t *esp_trailer_length)
1051 : : {
1052 : : struct rte_esp_tail *esp_trailer;
1053 : :
1054 : 0 : uint16_t length = sizeof(struct rte_esp_tail) + s->icv_sz;
1055 : : uint16_t offset = 0;
1056 : :
1057 : : /**
1058 : : * The ICV will not be present in TSO packets as this is appended by
1059 : : * hardware during segment generation
1060 : : */
1061 [ # # ]: 0 : if (m->ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
1062 : : length -= s->icv_sz;
1063 : :
1064 : 0 : *esp_trailer_length = length;
1065 : :
1066 : : /**
1067 : : * Calculate offset in packet to ESP trailer header, this should be
1068 : : * total packet length less the size of the ESP trailer plus the ICV
1069 : : * length if it is present
1070 : : */
1071 : 0 : offset = rte_pktmbuf_pkt_len(m) - length;
1072 : :
1073 [ # # ]: 0 : if (m->nb_segs > 1) {
1074 : : /* find segment which esp trailer is located */
1075 [ # # ]: 0 : while (m->data_len < offset) {
1076 : 0 : offset -= m->data_len;
1077 : 0 : m = m->next;
1078 : : }
1079 : : }
1080 : :
1081 : 0 : esp_trailer = rte_pktmbuf_mtod_offset(m, struct rte_esp_tail *, offset);
1082 : :
1083 : 0 : *esp_trailer_length += esp_trailer->pad_len;
1084 : :
1085 : 0 : return esp_trailer;
1086 : : }
1087 : :
1088 : : static inline uint16_t
1089 : : iavf_ipsec_crypto_compute_l4_payload_length(struct rte_mbuf *m,
1090 : : struct iavf_security_session *s, uint16_t esp_tlen)
1091 : : {
1092 : 0 : uint16_t ol2_len = m->l2_len; /* MAC + VLAN */
1093 : : uint16_t ol3_len = 0; /* ipv4/6 + ext hdrs */
1094 : : uint16_t ol4_len = 0; /* UDP NATT */
1095 : : uint16_t l3_len = 0; /* IPv4/6 + ext hdrs */
1096 : : uint16_t l4_len = 0; /* TCP/UDP/STCP hdrs */
1097 : 0 : uint16_t esp_hlen = sizeof(struct rte_esp_hdr) + s->iv_sz;
1098 : :
1099 : 0 : if (s->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1100 : 0 : ol3_len = m->outer_l3_len;
1101 : : /**<
1102 : : * application provided l3len assumed to include length of
1103 : : * ipv4/6 hdr + ext hdrs
1104 : : */
1105 : :
1106 [ # # ]: 0 : if (s->udp_encap.enabled) {
1107 : : ol4_len = sizeof(struct rte_udp_hdr);
1108 : 0 : l3_len = m->l3_len - ol4_len;
1109 : : l4_len = l3_len;
1110 : : } else {
1111 : 0 : l3_len = m->l3_len;
1112 : 0 : l4_len = m->l4_len;
1113 : : }
1114 : :
1115 : 0 : return rte_pktmbuf_pkt_len(m) - (ol2_len + ol3_len + ol4_len +
1116 : 0 : esp_hlen + l3_len + l4_len + esp_tlen);
1117 : : }
1118 : :
1119 : : static int
1120 : 0 : iavf_ipsec_crypto_pkt_metadata_set(void *device,
1121 : : struct rte_security_session *session,
1122 : : struct rte_mbuf *m, void *params)
1123 : : {
1124 : : struct rte_eth_dev *ethdev = device;
1125 : 0 : struct iavf_adapter *adapter =
1126 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
1127 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1128 : 0 : struct iavf_security_session *iavf_sess = SECURITY_GET_SESS_PRIV(session);
1129 : : struct iavf_ipsec_crypto_pkt_metadata *md;
1130 : : struct rte_esp_tail *esp_tail;
1131 : : uint64_t *sqn = params;
1132 : : uint16_t esp_trailer_length;
1133 : :
1134 : : /* Check we have valid session and is associated with this device */
1135 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
1136 : : return -EINVAL;
1137 : :
1138 : : /* Get dynamic metadata location from mbuf */
1139 : 0 : md = RTE_MBUF_DYNFIELD(m, iavf_sctx->pkt_md_offset,
1140 : : struct iavf_ipsec_crypto_pkt_metadata *);
1141 : :
1142 : : /* Set immutable metadata values from session template */
1143 : 0 : memcpy(md, &iavf_sess->pkt_metadata_template,
1144 : : sizeof(struct iavf_ipsec_crypto_pkt_metadata));
1145 : :
1146 : 0 : esp_tail = iavf_ipsec_crypto_get_esp_trailer(m, iavf_sess,
1147 : : &esp_trailer_length);
1148 : :
1149 : : /* Set per packet mutable metadata values */
1150 [ # # ]: 0 : md->esp_trailer_len = esp_trailer_length;
1151 : 0 : md->l4_payload_len = iavf_ipsec_crypto_compute_l4_payload_length(m,
1152 : : iavf_sess, esp_trailer_length);
1153 : 0 : md->next_proto = esp_tail->next_proto;
1154 : :
1155 : : /* If Extended SN in use set the upper 32-bits in metadata */
1156 [ # # # # ]: 0 : if (iavf_sess->esn.enabled && sqn != NULL)
1157 : 0 : md->esn = (uint32_t)(*sqn >> 32);
1158 : :
1159 : : return 0;
1160 : : }
1161 : :
1162 : : static int
1163 : 0 : iavf_ipsec_crypto_device_capabilities_get(struct iavf_adapter *adapter,
1164 : : struct virtchnl_ipsec_cap *capability)
1165 : : {
1166 : : /* Perform pf-vf comms */
1167 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
1168 : : size_t request_len, response_len;
1169 : : int rc;
1170 : :
1171 : : request_len = sizeof(struct inline_ipsec_msg);
1172 : :
1173 : 0 : request = rte_malloc("iavf-device-capability-request", request_len, 0);
1174 [ # # ]: 0 : if (request == NULL) {
1175 : : rc = -ENOMEM;
1176 : 0 : goto update_cleanup;
1177 : : }
1178 : :
1179 : : response_len = sizeof(struct inline_ipsec_msg) +
1180 : : sizeof(struct virtchnl_ipsec_cap);
1181 : 0 : response = rte_malloc("iavf-device-capability-response",
1182 : : response_len, 0);
1183 [ # # ]: 0 : if (response == NULL) {
1184 : : rc = -ENOMEM;
1185 : 0 : goto update_cleanup;
1186 : : }
1187 : :
1188 : : /* set msg header params */
1189 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_GET_CAP;
1190 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
1191 : :
1192 : : /* send virtual channel request to add SA to hardware database */
1193 : 0 : rc = iavf_ipsec_crypto_request(adapter,
1194 : : (uint8_t *)request, request_len,
1195 : : (uint8_t *)response, response_len);
1196 [ # # ]: 0 : if (rc)
1197 : 0 : goto update_cleanup;
1198 : :
1199 : : /* verify response id */
1200 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1201 [ # # ]: 0 : response->req_id != request->req_id){
1202 : : rc = -EFAULT;
1203 : 0 : goto update_cleanup;
1204 : : }
1205 : 0 : memcpy(capability, response->ipsec_data.ipsec_cap, sizeof(*capability));
1206 : :
1207 : 0 : update_cleanup:
1208 : 0 : rte_free(response);
1209 : 0 : rte_free(request);
1210 : :
1211 : 0 : return rc;
1212 : : }
1213 : :
1214 : : enum rte_crypto_auth_algorithm auth_maptbl[] = {
1215 : : /* Hash Algorithm */
1216 : : [VIRTCHNL_HASH_NO_ALG] = RTE_CRYPTO_AUTH_NULL,
1217 : : [VIRTCHNL_AES_CBC_MAC] = RTE_CRYPTO_AUTH_AES_CBC_MAC,
1218 : : [VIRTCHNL_AES_CMAC] = RTE_CRYPTO_AUTH_AES_CMAC,
1219 : : [VIRTCHNL_AES_GMAC] = RTE_CRYPTO_AUTH_AES_GMAC,
1220 : : [VIRTCHNL_AES_XCBC_MAC] = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
1221 : : [VIRTCHNL_MD5_HMAC] = RTE_CRYPTO_AUTH_MD5_HMAC,
1222 : : [VIRTCHNL_SHA1_HMAC] = RTE_CRYPTO_AUTH_SHA1_HMAC,
1223 : : [VIRTCHNL_SHA224_HMAC] = RTE_CRYPTO_AUTH_SHA224_HMAC,
1224 : : [VIRTCHNL_SHA256_HMAC] = RTE_CRYPTO_AUTH_SHA256_HMAC,
1225 : : [VIRTCHNL_SHA384_HMAC] = RTE_CRYPTO_AUTH_SHA384_HMAC,
1226 : : [VIRTCHNL_SHA512_HMAC] = RTE_CRYPTO_AUTH_SHA512_HMAC,
1227 : : [VIRTCHNL_SHA3_224_HMAC] = RTE_CRYPTO_AUTH_SHA3_224_HMAC,
1228 : : [VIRTCHNL_SHA3_256_HMAC] = RTE_CRYPTO_AUTH_SHA3_256_HMAC,
1229 : : [VIRTCHNL_SHA3_384_HMAC] = RTE_CRYPTO_AUTH_SHA3_384_HMAC,
1230 : : [VIRTCHNL_SHA3_512_HMAC] = RTE_CRYPTO_AUTH_SHA3_512_HMAC,
1231 : : };
1232 : :
1233 : : static void
1234 : : update_auth_capabilities(struct rte_cryptodev_capabilities *scap,
1235 : : struct virtchnl_algo_cap *acap,
1236 : : const struct rte_cryptodev_symmetric_capability *symcap)
1237 : : {
1238 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1239 : :
1240 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1241 : :
1242 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_AUTH;
1243 : :
1244 : 0 : capability->auth.algo = auth_maptbl[acap->algo_type];
1245 : 0 : capability->auth.block_size = acap->block_size;
1246 : :
1247 : 0 : capability->auth.key_size.min = acap->min_key_size;
1248 : 0 : capability->auth.key_size.max = acap->max_key_size;
1249 : 0 : capability->auth.key_size.increment = acap->inc_key_size;
1250 : :
1251 : 0 : capability->auth.digest_size.min = acap->min_digest_size;
1252 : 0 : capability->auth.digest_size.max = acap->max_digest_size;
1253 : 0 : capability->auth.digest_size.increment = acap->inc_digest_size;
1254 : :
1255 [ # # ]: 0 : if (symcap) {
1256 : 0 : capability->auth.iv_size.min = symcap->auth.iv_size.min;
1257 : 0 : capability->auth.iv_size.max = symcap->auth.iv_size.max;
1258 : 0 : capability->auth.iv_size.increment =
1259 : 0 : symcap->auth.iv_size.increment;
1260 : : } else {
1261 : 0 : capability->auth.iv_size.min = 0;
1262 : 0 : capability->auth.iv_size.max = 65535;
1263 : 0 : capability->auth.iv_size.increment = 1;
1264 : : }
1265 : : }
1266 : :
1267 : : enum rte_crypto_cipher_algorithm cipher_maptbl[] = {
1268 : : /* Cipher Algorithm */
1269 : : [VIRTCHNL_CIPHER_NO_ALG] = RTE_CRYPTO_CIPHER_NULL,
1270 : : [VIRTCHNL_3DES_CBC] = RTE_CRYPTO_CIPHER_3DES_CBC,
1271 : : [VIRTCHNL_AES_CBC] = RTE_CRYPTO_CIPHER_AES_CBC,
1272 : : [VIRTCHNL_AES_CTR] = RTE_CRYPTO_CIPHER_AES_CTR,
1273 : : };
1274 : :
1275 : : static void
1276 : : update_cipher_capabilities(struct rte_cryptodev_capabilities *scap,
1277 : : struct virtchnl_algo_cap *acap,
1278 : : const struct rte_cryptodev_symmetric_capability *symcap)
1279 : : {
1280 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1281 : :
1282 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1283 : :
1284 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1285 : :
1286 : 0 : capability->cipher.algo = cipher_maptbl[acap->algo_type];
1287 : :
1288 : 0 : capability->cipher.block_size = acap->block_size;
1289 : :
1290 : 0 : capability->cipher.key_size.min = acap->min_key_size;
1291 : 0 : capability->cipher.key_size.max = acap->max_key_size;
1292 : 0 : capability->cipher.key_size.increment = acap->inc_key_size;
1293 : :
1294 [ # # ]: 0 : if (symcap) {
1295 : 0 : capability->cipher.iv_size.min = symcap->cipher.iv_size.min;
1296 : 0 : capability->cipher.iv_size.max = symcap->cipher.iv_size.max;
1297 : 0 : capability->cipher.iv_size.increment =
1298 : 0 : symcap->cipher.iv_size.increment;
1299 : :
1300 : : } else {
1301 : 0 : capability->cipher.iv_size.min = 0;
1302 : 0 : capability->cipher.iv_size.max = 65535;
1303 : 0 : capability->cipher.iv_size.increment = 1;
1304 : : }
1305 : : }
1306 : :
1307 : : enum rte_crypto_aead_algorithm aead_maptbl[] = {
1308 : : /* AEAD Algorithm */
1309 : : [VIRTCHNL_AES_CCM] = RTE_CRYPTO_AEAD_AES_CCM,
1310 : : [VIRTCHNL_AES_GCM] = RTE_CRYPTO_AEAD_AES_GCM,
1311 : : [VIRTCHNL_CHACHA20_POLY1305] = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
1312 : : };
1313 : :
1314 : : static void
1315 : : update_aead_capabilities(struct rte_cryptodev_capabilities *scap,
1316 : : struct virtchnl_algo_cap *acap,
1317 : : const struct rte_cryptodev_symmetric_capability *symcap __rte_unused)
1318 : : {
1319 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1320 : :
1321 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1322 : :
1323 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_AEAD;
1324 : :
1325 : 0 : capability->aead.algo = aead_maptbl[acap->algo_type];
1326 : :
1327 : 0 : capability->aead.block_size = acap->block_size;
1328 : :
1329 : 0 : capability->aead.key_size.min = acap->min_key_size;
1330 : 0 : capability->aead.key_size.max = acap->max_key_size;
1331 : 0 : capability->aead.key_size.increment = acap->inc_key_size;
1332 : :
1333 : : /* remove constrains for aead and iv length */
1334 : 0 : capability->aead.aad_size.min = 0;
1335 : 0 : capability->aead.aad_size.max = 65535;
1336 : 0 : capability->aead.aad_size.increment = 1;
1337 : :
1338 : 0 : capability->aead.iv_size.min = 0;
1339 : 0 : capability->aead.iv_size.max = 65535;
1340 : 0 : capability->aead.iv_size.increment = 1;
1341 : :
1342 : 0 : capability->aead.digest_size.min = acap->min_digest_size;
1343 : 0 : capability->aead.digest_size.max = acap->max_digest_size;
1344 : 0 : capability->aead.digest_size.increment = acap->inc_digest_size;
1345 : 0 : }
1346 : :
1347 : : /**
1348 : : * Dynamically set crypto capabilities based on virtchannel IPsec
1349 : : * capabilities structure.
1350 : : */
1351 : : int
1352 : 0 : iavf_ipsec_crypto_set_security_capabililites(struct iavf_security_ctx
1353 : : *iavf_sctx, struct virtchnl_ipsec_cap *vch_cap)
1354 : : {
1355 : : struct rte_cryptodev_capabilities *capabilities;
1356 : : const struct rte_cryptodev_symmetric_capability *symcap;
1357 : : int i, j, number_of_capabilities = 0, ci = 0;
1358 : :
1359 : : /* Count the total number of crypto algorithms supported */
1360 [ # # ]: 0 : for (i = 0; i < VIRTCHNL_IPSEC_MAX_CRYPTO_CAP_NUM; i++)
1361 : 0 : number_of_capabilities += vch_cap->cap[i].algo_cap_num;
1362 : :
1363 : : /**
1364 : : * Allocate cryptodev capabilities structure for
1365 : : * *number_of_capabilities* items plus one item to null terminate the
1366 : : * array
1367 : : */
1368 : 0 : capabilities = rte_zmalloc("crypto_cap",
1369 : : sizeof(struct rte_cryptodev_capabilities) *
1370 : 0 : (number_of_capabilities + 1), 0);
1371 [ # # ]: 0 : if (!capabilities)
1372 : : return -ENOMEM;
1373 : 0 : capabilities[number_of_capabilities].op = RTE_CRYPTO_OP_TYPE_UNDEFINED;
1374 : :
1375 : : /**
1376 : : * Iterate over each virtchnl crypto capability by crypto type and
1377 : : * algorithm.
1378 : : */
1379 [ # # ]: 0 : for (i = 0; i < VIRTCHNL_IPSEC_MAX_CRYPTO_CAP_NUM; i++) {
1380 [ # # ]: 0 : for (j = 0; j < vch_cap->cap[i].algo_cap_num; j++, ci++) {
1381 [ # # # # ]: 0 : switch (vch_cap->cap[i].crypto_type) {
1382 : 0 : case VIRTCHNL_AUTH:
1383 : 0 : symcap = get_auth_capability(iavf_sctx,
1384 : 0 : capabilities[ci].sym.auth.algo);
1385 : : update_auth_capabilities(&capabilities[ci],
1386 : : &vch_cap->cap[i].algo_cap_list[j],
1387 : : symcap);
1388 : : break;
1389 : 0 : case VIRTCHNL_CIPHER:
1390 : 0 : symcap = get_cipher_capability(iavf_sctx,
1391 : 0 : capabilities[ci].sym.cipher.algo);
1392 : : update_cipher_capabilities(&capabilities[ci],
1393 : : &vch_cap->cap[i].algo_cap_list[j],
1394 : : symcap);
1395 : : break;
1396 : 0 : case VIRTCHNL_AEAD:
1397 : : symcap = get_aead_capability(iavf_sctx,
1398 : 0 : capabilities[ci].sym.aead.algo);
1399 : : update_aead_capabilities(&capabilities[ci],
1400 : : &vch_cap->cap[i].algo_cap_list[j],
1401 : : symcap);
1402 : : break;
1403 : 0 : default:
1404 : 0 : capabilities[ci].op =
1405 : : RTE_CRYPTO_OP_TYPE_UNDEFINED;
1406 : 0 : break;
1407 : : }
1408 : : }
1409 : : }
1410 : :
1411 : 0 : iavf_sctx->crypto_capabilities = capabilities;
1412 : 0 : return 0;
1413 : : }
1414 : :
1415 : : /**
1416 : : * Get security capabilities for device
1417 : : */
1418 : : static const struct rte_security_capability *
1419 : 0 : iavf_ipsec_crypto_capabilities_get(void *device)
1420 : : {
1421 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1422 : 0 : struct iavf_adapter *adapter =
1423 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
1424 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1425 : : unsigned int i;
1426 : :
1427 : : static struct rte_security_capability iavf_security_capabilities[] = {
1428 : : { /* IPsec Inline Crypto ESP Tunnel Egress */
1429 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1430 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1431 : : .ipsec = {
1432 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1433 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
1434 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
1435 : : .options = { .udp_encap = 1,
1436 : : .stats = 1, .esn = 1 },
1437 : : },
1438 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
1439 : : },
1440 : : { /* IPsec Inline Crypto ESP Tunnel Ingress */
1441 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1442 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1443 : : .ipsec = {
1444 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1445 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
1446 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1447 : : .options = { .udp_encap = 1,
1448 : : .stats = 1, .esn = 1 },
1449 : : },
1450 : : .ol_flags = 0
1451 : : },
1452 : : { /* IPsec Inline Crypto ESP Transport Egress */
1453 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1454 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1455 : : .ipsec = {
1456 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1457 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
1458 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
1459 : : .options = { .udp_encap = 1, .stats = 1,
1460 : : .esn = 1 },
1461 : : },
1462 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
1463 : : },
1464 : : { /* IPsec Inline Crypto ESP Transport Ingress */
1465 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1466 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1467 : : .ipsec = {
1468 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1469 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
1470 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1471 : : .options = { .udp_encap = 1, .stats = 1,
1472 : : .esn = 1 }
1473 : : },
1474 : : .ol_flags = 0
1475 : : },
1476 : : {
1477 : : .action = RTE_SECURITY_ACTION_TYPE_NONE
1478 : : }
1479 : : };
1480 : :
1481 : : /**
1482 : : * Update the security capabilities struct with the runtime discovered
1483 : : * crypto capabilities, except for last element of the array which is
1484 : : * the null termination
1485 : : */
1486 [ # # ]: 0 : for (i = 0; i < ((sizeof(iavf_security_capabilities) /
1487 : 0 : sizeof(iavf_security_capabilities[0])) - 1); i++) {
1488 : 0 : iavf_security_capabilities[i].crypto_capabilities =
1489 : 0 : iavf_sctx->crypto_capabilities;
1490 : : }
1491 : :
1492 : 0 : return iavf_security_capabilities;
1493 : : }
1494 : :
1495 : : static struct rte_security_ops iavf_ipsec_crypto_ops = {
1496 : : .session_get_size = iavf_ipsec_crypto_session_size_get,
1497 : : .session_create = iavf_ipsec_crypto_session_create,
1498 : : .session_update = iavf_ipsec_crypto_session_update,
1499 : : .session_stats_get = iavf_ipsec_crypto_session_stats_get,
1500 : : .session_destroy = iavf_ipsec_crypto_session_destroy,
1501 : : .set_pkt_metadata = iavf_ipsec_crypto_pkt_metadata_set,
1502 : : .capabilities_get = iavf_ipsec_crypto_capabilities_get,
1503 : : };
1504 : :
1505 : : int
1506 : 0 : iavf_security_ctx_create(struct iavf_adapter *adapter)
1507 : : {
1508 : : struct rte_security_ctx *sctx;
1509 : :
1510 : 0 : sctx = rte_malloc("security_ctx", sizeof(struct rte_security_ctx), 0);
1511 [ # # ]: 0 : if (sctx == NULL)
1512 : : return -ENOMEM;
1513 : :
1514 : 0 : sctx->device = adapter->vf.eth_dev;
1515 : 0 : sctx->ops = &iavf_ipsec_crypto_ops;
1516 : 0 : sctx->sess_cnt = 0;
1517 : :
1518 : 0 : adapter->vf.eth_dev->security_ctx = sctx;
1519 : :
1520 [ # # ]: 0 : if (adapter->security_ctx == NULL) {
1521 : 0 : adapter->security_ctx = rte_malloc("iavf_security_ctx",
1522 : : sizeof(struct iavf_security_ctx), 0);
1523 [ # # ]: 0 : if (adapter->security_ctx == NULL) {
1524 : 0 : rte_free(adapter->vf.eth_dev->security_ctx);
1525 : 0 : adapter->vf.eth_dev->security_ctx = NULL;
1526 : 0 : return -ENOMEM;
1527 : : }
1528 : : }
1529 : :
1530 : : return 0;
1531 : : }
1532 : :
1533 : : int
1534 : 0 : iavf_security_init(struct iavf_adapter *adapter)
1535 : : {
1536 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1537 : 0 : struct rte_mbuf_dynfield pkt_md_dynfield = {
1538 : : .name = "iavf_ipsec_crypto_pkt_metadata",
1539 : : .size = sizeof(struct iavf_ipsec_crypto_pkt_metadata),
1540 : : .align = alignof(struct iavf_ipsec_crypto_pkt_metadata)
1541 : : };
1542 : : struct virtchnl_ipsec_cap capabilities;
1543 : : int rc;
1544 : :
1545 : 0 : iavf_sctx->adapter = adapter;
1546 : :
1547 : 0 : iavf_sctx->pkt_md_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
1548 [ # # ]: 0 : if (iavf_sctx->pkt_md_offset < 0)
1549 : : return iavf_sctx->pkt_md_offset;
1550 : :
1551 : : /* Get device capabilities from Inline IPsec driver over PF-VF comms */
1552 : 0 : rc = iavf_ipsec_crypto_device_capabilities_get(adapter, &capabilities);
1553 [ # # ]: 0 : if (rc)
1554 : : return rc;
1555 : :
1556 : 0 : return iavf_ipsec_crypto_set_security_capabililites(iavf_sctx,
1557 : : &capabilities);
1558 : : }
1559 : :
1560 : : int
1561 : 0 : iavf_security_get_pkt_md_offset(struct iavf_adapter *adapter)
1562 : : {
1563 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1564 : :
1565 : 0 : return iavf_sctx->pkt_md_offset;
1566 : : }
1567 : :
1568 : : int
1569 : 0 : iavf_security_ctx_destroy(struct iavf_adapter *adapter)
1570 : : {
1571 : 0 : struct rte_security_ctx *sctx = adapter->vf.eth_dev->security_ctx;
1572 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1573 : :
1574 [ # # ]: 0 : if (iavf_sctx == NULL)
1575 : : return -ENODEV;
1576 : :
1577 : : /* free and reset security data structures */
1578 : 0 : rte_free(iavf_sctx);
1579 : 0 : rte_free(sctx);
1580 : :
1581 : 0 : adapter->security_ctx = NULL;
1582 : 0 : adapter->vf.eth_dev->security_ctx = NULL;
1583 : :
1584 : 0 : return 0;
1585 : : }
1586 : :
1587 : : static int
1588 : 0 : iavf_ipsec_crypto_status_get(struct iavf_adapter *adapter,
1589 : : struct virtchnl_ipsec_status *status)
1590 : : {
1591 : : /* Perform pf-vf comms */
1592 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
1593 : : size_t request_len, response_len;
1594 : : int rc;
1595 : :
1596 : : request_len = sizeof(struct inline_ipsec_msg);
1597 : :
1598 : 0 : request = rte_malloc("iavf-device-status-request", request_len, 0);
1599 [ # # ]: 0 : if (request == NULL) {
1600 : : rc = -ENOMEM;
1601 : 0 : goto update_cleanup;
1602 : : }
1603 : :
1604 : : response_len = sizeof(struct inline_ipsec_msg) +
1605 : : sizeof(struct virtchnl_ipsec_cap);
1606 : 0 : response = rte_malloc("iavf-device-status-response",
1607 : : response_len, 0);
1608 [ # # ]: 0 : if (response == NULL) {
1609 : : rc = -ENOMEM;
1610 : 0 : goto update_cleanup;
1611 : : }
1612 : :
1613 : : /* set msg header params */
1614 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_GET_STATUS;
1615 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
1616 : :
1617 : : /* send virtual channel request to add SA to hardware database */
1618 : 0 : rc = iavf_ipsec_crypto_request(adapter,
1619 : : (uint8_t *)request, request_len,
1620 : : (uint8_t *)response, response_len);
1621 [ # # ]: 0 : if (rc)
1622 : 0 : goto update_cleanup;
1623 : :
1624 : : /* verify response id */
1625 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1626 [ # # ]: 0 : response->req_id != request->req_id){
1627 : : rc = -EFAULT;
1628 : 0 : goto update_cleanup;
1629 : : }
1630 : 0 : memcpy(status, response->ipsec_data.ipsec_status, sizeof(*status));
1631 : :
1632 : 0 : update_cleanup:
1633 : 0 : rte_free(response);
1634 : 0 : rte_free(request);
1635 : :
1636 : 0 : return rc;
1637 : : }
1638 : :
1639 : :
1640 : : int
1641 : 0 : iavf_ipsec_crypto_supported(struct iavf_adapter *adapter)
1642 : : {
1643 : 0 : struct virtchnl_vf_resource *resources = adapter->vf.vf_res;
1644 : : int crypto_supported = false;
1645 : :
1646 : : /** Capability check for IPsec Crypto */
1647 [ # # # # ]: 0 : if (resources && (resources->vf_cap_flags &
1648 : : VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO)) {
1649 : : struct virtchnl_ipsec_status status;
1650 : 0 : int rc = iavf_ipsec_crypto_status_get(adapter, &status);
1651 [ # # # # ]: 0 : if (rc == 0 && status.status == INLINE_IPSEC_STATUS_AVAILABLE)
1652 : : crypto_supported = true;
1653 : : }
1654 : :
1655 : : /* Clear the VF flag to return faster next call */
1656 [ # # ]: 0 : if (resources && !crypto_supported)
1657 : 0 : resources->vf_cap_flags &=
1658 : : ~(VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO);
1659 : :
1660 : 0 : return crypto_supported;
1661 : : }
1662 : :
1663 : : #define IAVF_IPSEC_INSET_ESP (\
1664 : : IAVF_INSET_ESP_SPI)
1665 : :
1666 : : #define IAVF_IPSEC_INSET_AH (\
1667 : : IAVF_INSET_AH_SPI)
1668 : :
1669 : : #define IAVF_IPSEC_INSET_IPV4_NATT_ESP (\
1670 : : IAVF_INSET_IPV4_SRC | IAVF_INSET_IPV4_DST | \
1671 : : IAVF_INSET_ESP_SPI)
1672 : :
1673 : : #define IAVF_IPSEC_INSET_IPV6_NATT_ESP (\
1674 : : IAVF_INSET_IPV6_SRC | IAVF_INSET_IPV6_DST | \
1675 : : IAVF_INSET_ESP_SPI)
1676 : :
1677 : : enum iavf_ipsec_flow_pt_type {
1678 : : IAVF_PATTERN_ESP = 1,
1679 : : IAVF_PATTERN_AH,
1680 : : IAVF_PATTERN_UDP_ESP,
1681 : : };
1682 : : enum iavf_ipsec_flow_pt_ip_ver {
1683 : : IAVF_PATTERN_IPV4 = 1,
1684 : : IAVF_PATTERN_IPV6,
1685 : : };
1686 : :
1687 : : #define IAVF_PATTERN(t, ipt) ((void *)((t) | ((ipt) << 4)))
1688 : : #define IAVF_PATTERN_TYPE(pt) ((pt) & 0x0F)
1689 : : #define IAVF_PATTERN_IP_V(pt) ((pt) >> 4)
1690 : :
1691 : : static struct iavf_pattern_match_item iavf_ipsec_flow_pattern[] = {
1692 : : {iavf_pattern_eth_ipv4_esp, IAVF_IPSEC_INSET_ESP,
1693 : : IAVF_PATTERN(IAVF_PATTERN_ESP, IAVF_PATTERN_IPV4)},
1694 : : {iavf_pattern_eth_ipv6_esp, IAVF_IPSEC_INSET_ESP,
1695 : : IAVF_PATTERN(IAVF_PATTERN_ESP, IAVF_PATTERN_IPV6)},
1696 : : {iavf_pattern_eth_ipv4_ah, IAVF_IPSEC_INSET_AH,
1697 : : IAVF_PATTERN(IAVF_PATTERN_AH, IAVF_PATTERN_IPV4)},
1698 : : {iavf_pattern_eth_ipv6_ah, IAVF_IPSEC_INSET_AH,
1699 : : IAVF_PATTERN(IAVF_PATTERN_AH, IAVF_PATTERN_IPV6)},
1700 : : {iavf_pattern_eth_ipv4_udp_esp, IAVF_IPSEC_INSET_IPV4_NATT_ESP,
1701 : : IAVF_PATTERN(IAVF_PATTERN_UDP_ESP, IAVF_PATTERN_IPV4)},
1702 : : {iavf_pattern_eth_ipv6_udp_esp, IAVF_IPSEC_INSET_IPV6_NATT_ESP,
1703 : : IAVF_PATTERN(IAVF_PATTERN_UDP_ESP, IAVF_PATTERN_IPV6)},
1704 : : };
1705 : :
1706 : : struct iavf_ipsec_flow_item {
1707 : : uint64_t id;
1708 : : uint8_t is_ipv4;
1709 : : uint32_t spi;
1710 : : struct rte_ether_hdr eth_hdr;
1711 : : union {
1712 : : struct rte_ipv4_hdr ipv4_hdr;
1713 : : struct rte_ipv6_hdr ipv6_hdr;
1714 : : };
1715 : : struct rte_udp_hdr udp_hdr;
1716 : : uint8_t is_udp;
1717 : : };
1718 : :
1719 : : static void
1720 : 0 : parse_eth_item(const struct rte_flow_item_eth *item,
1721 : : struct rte_ether_hdr *eth)
1722 : : {
1723 : 0 : memcpy(eth->src_addr.addr_bytes,
1724 : 0 : item->hdr.src_addr.addr_bytes, sizeof(eth->src_addr));
1725 : 0 : memcpy(eth->dst_addr.addr_bytes,
1726 : 0 : item->hdr.dst_addr.addr_bytes, sizeof(eth->dst_addr));
1727 : 0 : }
1728 : :
1729 : : static void
1730 : : parse_ipv4_item(const struct rte_flow_item_ipv4 *item,
1731 : : struct rte_ipv4_hdr *ipv4)
1732 : : {
1733 : 0 : ipv4->src_addr = item->hdr.src_addr;
1734 : 0 : ipv4->dst_addr = item->hdr.dst_addr;
1735 : 0 : }
1736 : :
1737 : : static void
1738 : 0 : parse_ipv6_item(const struct rte_flow_item_ipv6 *item,
1739 : : struct rte_ipv6_hdr *ipv6)
1740 : : {
1741 : 0 : memcpy(ipv6->src_addr, item->hdr.src_addr, 16);
1742 : 0 : memcpy(ipv6->dst_addr, item->hdr.dst_addr, 16);
1743 : 0 : }
1744 : :
1745 : : static void
1746 : : parse_udp_item(const struct rte_flow_item_udp *item, struct rte_udp_hdr *udp)
1747 : : {
1748 : 0 : udp->dst_port = item->hdr.dst_port;
1749 : 0 : udp->src_port = item->hdr.src_port;
1750 : : }
1751 : :
1752 : : static int
1753 : : has_security_action(const struct rte_flow_action actions[],
1754 : : const void **session)
1755 : : {
1756 : : /* only {SECURITY; END} supported */
1757 [ # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
1758 [ # # ]: 0 : actions[1].type == RTE_FLOW_ACTION_TYPE_END) {
1759 : 0 : *session = actions[0].conf;
1760 : : return true;
1761 : : }
1762 : : return false;
1763 : : }
1764 : :
1765 : : static struct iavf_ipsec_flow_item *
1766 : 0 : iavf_ipsec_flow_item_parse(struct rte_eth_dev *ethdev,
1767 : : const struct rte_flow_item pattern[],
1768 : : const struct rte_flow_action actions[],
1769 : : uint32_t type)
1770 : : {
1771 : : const void *session;
1772 : : struct iavf_ipsec_flow_item
1773 : 0 : *ipsec_flow = rte_malloc("security-flow-rule",
1774 : : sizeof(struct iavf_ipsec_flow_item), 0);
1775 : 0 : enum iavf_ipsec_flow_pt_type p_type = IAVF_PATTERN_TYPE(type);
1776 : 0 : enum iavf_ipsec_flow_pt_ip_ver p_ip_type = IAVF_PATTERN_IP_V(type);
1777 : :
1778 [ # # ]: 0 : if (ipsec_flow == NULL)
1779 : : return NULL;
1780 : :
1781 : 0 : ipsec_flow->is_ipv4 = (p_ip_type == IAVF_PATTERN_IPV4);
1782 : :
1783 [ # # ]: 0 : if (pattern[0].spec)
1784 : 0 : parse_eth_item((const struct rte_flow_item_eth *)
1785 : : pattern[0].spec, &ipsec_flow->eth_hdr);
1786 : :
1787 [ # # # # ]: 0 : switch (p_type) {
1788 : 0 : case IAVF_PATTERN_ESP:
1789 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1790 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1791 : 0 : pattern[1].spec,
1792 : : &ipsec_flow->ipv4_hdr);
1793 : : } else {
1794 : 0 : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1795 : 0 : pattern[1].spec,
1796 : : &ipsec_flow->ipv6_hdr);
1797 : : }
1798 : 0 : ipsec_flow->spi =
1799 : : ((const struct rte_flow_item_esp *)
1800 : 0 : pattern[2].spec)->hdr.spi;
1801 : 0 : break;
1802 : 0 : case IAVF_PATTERN_AH:
1803 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1804 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1805 : 0 : pattern[1].spec,
1806 : : &ipsec_flow->ipv4_hdr);
1807 : : } else {
1808 : 0 : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1809 : 0 : pattern[1].spec,
1810 : : &ipsec_flow->ipv6_hdr);
1811 : : }
1812 : 0 : ipsec_flow->spi =
1813 : : ((const struct rte_flow_item_ah *)
1814 : 0 : pattern[2].spec)->spi;
1815 : 0 : break;
1816 : 0 : case IAVF_PATTERN_UDP_ESP:
1817 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1818 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1819 : 0 : pattern[1].spec,
1820 : : &ipsec_flow->ipv4_hdr);
1821 : : } else {
1822 : 0 : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1823 : 0 : pattern[1].spec,
1824 : : &ipsec_flow->ipv6_hdr);
1825 : : }
1826 : : parse_udp_item((const struct rte_flow_item_udp *)
1827 : 0 : pattern[2].spec,
1828 : : &ipsec_flow->udp_hdr);
1829 : 0 : ipsec_flow->is_udp = true;
1830 : 0 : ipsec_flow->spi =
1831 : : ((const struct rte_flow_item_esp *)
1832 : 0 : pattern[3].spec)->hdr.spi;
1833 : 0 : break;
1834 : 0 : default:
1835 : 0 : goto flow_cleanup;
1836 : : }
1837 : :
1838 : : if (!has_security_action(actions, &session))
1839 : 0 : goto flow_cleanup;
1840 : :
1841 [ # # ]: 0 : if (!iavf_ipsec_crypto_action_valid(ethdev, session,
1842 : : ipsec_flow->spi))
1843 : 0 : goto flow_cleanup;
1844 : :
1845 : : return ipsec_flow;
1846 : :
1847 : 0 : flow_cleanup:
1848 : 0 : rte_free(ipsec_flow);
1849 : 0 : return NULL;
1850 : : }
1851 : :
1852 : :
1853 : : static struct iavf_flow_parser iavf_ipsec_flow_parser;
1854 : :
1855 : : static int
1856 : 0 : iavf_ipsec_flow_init(struct iavf_adapter *ad)
1857 : : {
1858 : : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
1859 : : struct iavf_flow_parser *parser;
1860 : :
1861 [ # # ]: 0 : if (!vf->vf_res)
1862 : : return -EINVAL;
1863 : :
1864 [ # # ]: 0 : if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO)
1865 : : parser = &iavf_ipsec_flow_parser;
1866 : : else
1867 : : return -ENOTSUP;
1868 : :
1869 : 0 : return iavf_register_parser(parser, ad);
1870 : : }
1871 : :
1872 : : static void
1873 : 0 : iavf_ipsec_flow_uninit(struct iavf_adapter *ad)
1874 : : {
1875 : 0 : iavf_unregister_parser(&iavf_ipsec_flow_parser, ad);
1876 : 0 : }
1877 : :
1878 : : static int
1879 : 0 : iavf_ipsec_flow_create(struct iavf_adapter *ad,
1880 : : struct rte_flow *flow,
1881 : : void *meta,
1882 : : struct rte_flow_error *error)
1883 : : {
1884 : : struct iavf_ipsec_flow_item *ipsec_flow = meta;
1885 : : int flow_id = -1;
1886 [ # # ]: 0 : if (!ipsec_flow) {
1887 : 0 : rte_flow_error_set(error, EINVAL,
1888 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1889 : : "NULL rule.");
1890 : 0 : return -rte_errno;
1891 : : }
1892 : :
1893 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1894 : 0 : flow_id = iavf_ipsec_crypto_inbound_security_policy_add(ad,
1895 : : ipsec_flow->spi,
1896 : : 1,
1897 : : ipsec_flow->ipv4_hdr.dst_addr,
1898 : : NULL,
1899 : : 0,
1900 : 0 : ipsec_flow->is_udp,
1901 : 0 : ipsec_flow->udp_hdr.dst_port);
1902 : : } else {
1903 : 0 : flow_id = iavf_ipsec_crypto_inbound_security_policy_add(ad,
1904 : : ipsec_flow->spi,
1905 : : 0,
1906 : : 0,
1907 : 0 : ipsec_flow->ipv6_hdr.dst_addr,
1908 : : 0,
1909 : 0 : ipsec_flow->is_udp,
1910 : 0 : ipsec_flow->udp_hdr.dst_port);
1911 : : }
1912 : :
1913 [ # # ]: 0 : if (flow_id < 1) {
1914 : 0 : rte_flow_error_set(error, EINVAL,
1915 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1916 : : "Failed to add SA.");
1917 : 0 : return -rte_errno;
1918 : : }
1919 : :
1920 : 0 : ipsec_flow->id = flow_id;
1921 : 0 : flow->rule = ipsec_flow;
1922 : :
1923 : 0 : return 0;
1924 : : }
1925 : :
1926 : : static int
1927 : 0 : iavf_ipsec_flow_destroy(struct iavf_adapter *ad,
1928 : : struct rte_flow *flow,
1929 : : struct rte_flow_error *error)
1930 : : {
1931 : 0 : struct iavf_ipsec_flow_item *ipsec_flow = flow->rule;
1932 [ # # ]: 0 : if (!ipsec_flow) {
1933 : 0 : rte_flow_error_set(error, EINVAL,
1934 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1935 : : "NULL rule.");
1936 : 0 : return -rte_errno;
1937 : : }
1938 : :
1939 : 0 : iavf_ipsec_crypto_security_policy_delete(ad,
1940 : 0 : ipsec_flow->is_ipv4, ipsec_flow->id);
1941 : 0 : rte_free(ipsec_flow);
1942 : 0 : return 0;
1943 : : }
1944 : :
1945 : : static struct iavf_flow_engine iavf_ipsec_flow_engine = {
1946 : : .init = iavf_ipsec_flow_init,
1947 : : .uninit = iavf_ipsec_flow_uninit,
1948 : : .create = iavf_ipsec_flow_create,
1949 : : .destroy = iavf_ipsec_flow_destroy,
1950 : : .type = IAVF_FLOW_ENGINE_IPSEC_CRYPTO,
1951 : : };
1952 : :
1953 : : static int
1954 : 0 : iavf_ipsec_flow_parse(struct iavf_adapter *ad,
1955 : : struct iavf_pattern_match_item *array,
1956 : : uint32_t array_len,
1957 : : const struct rte_flow_item pattern[],
1958 : : const struct rte_flow_action actions[],
1959 : : uint32_t priority,
1960 : : void **meta,
1961 : : struct rte_flow_error *error)
1962 : : {
1963 : : struct iavf_pattern_match_item *item = NULL;
1964 : : int ret = -1;
1965 : :
1966 [ # # ]: 0 : if (priority >= 1)
1967 : 0 : return -rte_errno;
1968 : :
1969 : 0 : item = iavf_search_pattern_match_item(pattern, array, array_len, error);
1970 [ # # # # ]: 0 : if (item && item->meta) {
1971 : 0 : uint32_t type = (uint64_t)(item->meta);
1972 : : struct iavf_ipsec_flow_item *fi =
1973 : 0 : iavf_ipsec_flow_item_parse(ad->vf.eth_dev,
1974 : : pattern, actions, type);
1975 [ # # ]: 0 : if (fi && meta) {
1976 : 0 : *meta = fi;
1977 : : ret = 0;
1978 : : }
1979 : : }
1980 : : return ret;
1981 : : }
1982 : :
1983 : : static struct iavf_flow_parser iavf_ipsec_flow_parser = {
1984 : : .engine = &iavf_ipsec_flow_engine,
1985 : : .array = iavf_ipsec_flow_pattern,
1986 : : .array_len = RTE_DIM(iavf_ipsec_flow_pattern),
1987 : : .parse_pattern_action = iavf_ipsec_flow_parse,
1988 : : .stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,
1989 : : };
1990 : :
1991 : 238 : RTE_INIT(iavf_ipsec_flow_engine_register)
1992 : : {
1993 : 238 : iavf_register_flow_engine(&iavf_ipsec_flow_engine);
1994 : 238 : }
|