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 = (uint32_t *)&conf->ipsec.tunnel.ipv6.dst_addr;
514 : :
515 : 0 : sa_cfg->virtchnl_ip_type = VIRTCHNL_IPV6;
516 : :
517 : 0 : ((uint32_t *)sa_cfg->dst_addr)[0] = htonl(v6_dst_addr[0]);
518 : 0 : ((uint32_t *)sa_cfg->dst_addr)[1] = htonl(v6_dst_addr[1]);
519 : 0 : ((uint32_t *)sa_cfg->dst_addr)[2] = htonl(v6_dst_addr[2]);
520 : 0 : ((uint32_t *)sa_cfg->dst_addr)[3] = htonl(v6_dst_addr[3]);
521 : : }
522 : :
523 : : /* set crypto params */
524 [ # # ]: 0 : if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
525 : 0 : sa_add_set_aead_params(&sa_cfg->crypto_cfg.items[0],
526 : : &conf->crypto_xform->aead, conf->ipsec.salt);
527 : :
528 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
529 : 0 : sa_add_set_cipher_params(&sa_cfg->crypto_cfg.items[0],
530 : : &conf->crypto_xform->cipher, conf->ipsec.salt);
531 : 0 : sa_add_set_auth_params(&sa_cfg->crypto_cfg.items[1],
532 : 0 : &conf->crypto_xform->next->auth, conf->ipsec.salt);
533 : :
534 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
535 : 0 : sa_add_set_auth_params(&sa_cfg->crypto_cfg.items[0],
536 : : &conf->crypto_xform->auth, conf->ipsec.salt);
537 [ # # ]: 0 : if (conf->crypto_xform->auth.algo != RTE_CRYPTO_AUTH_AES_GMAC)
538 : 0 : sa_add_set_cipher_params(&sa_cfg->crypto_cfg.items[1],
539 : 0 : &conf->crypto_xform->next->cipher, conf->ipsec.salt);
540 : : }
541 : :
542 : : /* send virtual channel request to add SA to hardware database */
543 : 0 : rc = iavf_ipsec_crypto_request(adapter,
544 : : (uint8_t *)request, request_len,
545 : : (uint8_t *)response, response_len);
546 [ # # ]: 0 : if (rc)
547 : 0 : goto update_cleanup;
548 : :
549 : : /* verify response id */
550 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
551 [ # # ]: 0 : response->req_id != request->req_id)
552 : : rc = -EFAULT;
553 : : else
554 : 0 : rc = response->ipsec_data.sa_cfg_resp->sa_handle;
555 : 0 : update_cleanup:
556 : 0 : rte_free(response);
557 : 0 : rte_free(request);
558 : :
559 : 0 : return rc;
560 : : }
561 : :
562 : : static void
563 : 0 : set_pkt_metadata_template(struct iavf_ipsec_crypto_pkt_metadata *template,
564 : : struct iavf_security_session *sess)
565 : : {
566 : 0 : template->sa_idx = sess->sa.hw_idx;
567 : :
568 [ # # ]: 0 : if (sess->udp_encap.enabled)
569 : 0 : template->ol_flags = IAVF_IPSEC_CRYPTO_OL_FLAGS_NATT;
570 : :
571 [ # # ]: 0 : if (sess->esn.enabled)
572 : 0 : template->ol_flags = IAVF_IPSEC_CRYPTO_OL_FLAGS_ESN;
573 : :
574 [ # # ]: 0 : template->len_iv = calc_ipsec_desc_iv_len_field(sess->iv_sz);
575 : 0 : template->ctx_desc_ipsec_params =
576 [ # # # ]: 0 : calc_context_desc_cipherblock_sz(sess->block_sz) |
577 : 0 : ((uint8_t)(sess->icv_sz >> 2) << 3);
578 : 0 : }
579 : :
580 : : static void
581 : 0 : set_session_parameter(struct iavf_security_ctx *iavf_sctx,
582 : : struct iavf_security_session *sess,
583 : : struct rte_security_session_conf *conf, uint32_t sa_idx)
584 : : {
585 : 0 : sess->adapter = iavf_sctx->adapter;
586 : :
587 : 0 : sess->mode = conf->ipsec.mode;
588 : 0 : sess->direction = conf->ipsec.direction;
589 : :
590 [ # # ]: 0 : if (sess->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
591 : 0 : sess->type = conf->ipsec.tunnel.type;
592 : :
593 : 0 : sess->sa.spi = conf->ipsec.spi;
594 : 0 : sess->sa.hw_idx = sa_idx;
595 : :
596 [ # # ]: 0 : if (conf->ipsec.options.esn) {
597 : 0 : sess->esn.enabled = 1;
598 : 0 : sess->esn.value = conf->ipsec.esn.value;
599 : : }
600 : :
601 [ # # ]: 0 : if (conf->ipsec.options.udp_encap)
602 : 0 : sess->udp_encap.enabled = 1;
603 : :
604 [ # # ]: 0 : if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
605 : 0 : sess->block_sz = get_aead_blocksize(iavf_sctx,
606 : : conf->crypto_xform->aead.algo);
607 : 0 : sess->iv_sz = sizeof(uint64_t); /* iv.length includes salt */
608 : 0 : sess->icv_sz = conf->crypto_xform->aead.digest_length;
609 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
610 : 0 : sess->block_sz = get_cipher_blocksize(iavf_sctx,
611 : : conf->crypto_xform->cipher.algo);
612 : 0 : sess->iv_sz = conf->crypto_xform->cipher.iv.length;
613 : 0 : sess->icv_sz = conf->crypto_xform->next->auth.digest_length;
614 [ # # ]: 0 : } else if (conf->crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
615 [ # # ]: 0 : if (conf->crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
616 : 0 : sess->block_sz = get_auth_blocksize(iavf_sctx,
617 : : conf->crypto_xform->auth.algo);
618 : 0 : sess->iv_sz = sizeof(uint64_t); /* iv len inc. salt */
619 : 0 : sess->icv_sz = conf->crypto_xform->auth.digest_length;
620 : : } else {
621 : 0 : sess->block_sz = get_cipher_blocksize(iavf_sctx,
622 : 0 : conf->crypto_xform->next->cipher.algo);
623 : 0 : sess->iv_sz =
624 : 0 : conf->crypto_xform->next->cipher.iv.length;
625 : 0 : sess->icv_sz = conf->crypto_xform->auth.digest_length;
626 : : }
627 : : }
628 : :
629 : 0 : set_pkt_metadata_template(&sess->pkt_metadata_template, sess);
630 : 0 : }
631 : :
632 : : /**
633 : : * Create IPsec Security Association for inline IPsec Crypto offload.
634 : : *
635 : : * 1. validate session configuration parameters
636 : : * 2. allocate session memory from mempool
637 : : * 3. add SA to hardware database
638 : : * 4. set session parameters
639 : : * 5. create packet metadata template for datapath
640 : : */
641 : : static int
642 : 0 : iavf_ipsec_crypto_session_create(void *device,
643 : : struct rte_security_session_conf *conf,
644 : : struct rte_security_session *session)
645 : : {
646 : : struct rte_eth_dev *ethdev = device;
647 : 0 : struct iavf_adapter *adapter =
648 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
649 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
650 : 0 : struct iavf_security_session *iavf_session = SECURITY_GET_SESS_PRIV(session);
651 : : int sa_idx;
652 : : int ret = 0;
653 : :
654 : : /* validate that all SA parameters are valid for device */
655 : 0 : ret = iavf_ipsec_crypto_session_validate_conf(iavf_sctx, conf);
656 [ # # ]: 0 : if (ret)
657 : : return ret;
658 : :
659 : : /* add SA to hardware database */
660 : 0 : sa_idx = iavf_ipsec_crypto_security_association_add(adapter, conf);
661 [ # # ]: 0 : if (sa_idx < 0) {
662 [ # # # # ]: 0 : PMD_DRV_LOG(ERR,
663 : : "Failed to add SA (spi: %d, mode: %s, direction: %s)",
664 : : conf->ipsec.spi,
665 : : conf->ipsec.mode ==
666 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT ?
667 : : "transport" : "tunnel",
668 : : conf->ipsec.direction ==
669 : : RTE_SECURITY_IPSEC_SA_DIR_INGRESS ?
670 : : "inbound" : "outbound");
671 : :
672 : 0 : return -EFAULT;
673 : : }
674 : :
675 : : /* save data plane required session parameters */
676 : 0 : set_session_parameter(iavf_sctx, iavf_session, conf, sa_idx);
677 : :
678 : 0 : return 0;
679 : : }
680 : :
681 : : /**
682 : : * Check if valid ipsec crypto action.
683 : : * SPI must be non-zero and SPI in session must match SPI value
684 : : * passed into function.
685 : : *
686 : : * returns: 0 if invalid session or SPI value equal zero
687 : : * returns: 1 if valid
688 : : */
689 : : uint32_t
690 : 0 : iavf_ipsec_crypto_action_valid(struct rte_eth_dev *ethdev,
691 : : const struct rte_security_session *session, uint32_t spi)
692 : : {
693 : 0 : struct iavf_adapter *adapter =
694 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
695 : : const struct iavf_security_session *sess = (const void *)session->driver_priv_data;
696 : :
697 : : /* verify we have a valid session and that it belong to this adapter */
698 [ # # ]: 0 : if (unlikely(sess == NULL || sess->adapter != adapter))
699 : : return false;
700 : :
701 : : /* SPI value must be non-zero and must match flow SPI*/
702 [ # # # # ]: 0 : if (spi == 0 || (htonl(sess->sa.spi) != spi))
703 : 0 : return false;
704 : :
705 : : return true;
706 : : }
707 : :
708 : : /**
709 : : * Send virtual channel security policy add request to IES driver.
710 : : *
711 : : * IES driver expects SPI and destination IP address to be in host
712 : : * order, but DPDK APIs are network order, therefore we need to do a htonl
713 : : * conversion of these parameters.
714 : : */
715 : : int
716 : 0 : iavf_ipsec_crypto_inbound_security_policy_add(struct iavf_adapter *adapter,
717 : : uint32_t esp_spi,
718 : : uint8_t is_v4,
719 : : rte_be32_t v4_dst_addr,
720 : : uint8_t *v6_dst_addr,
721 : : uint8_t drop,
722 : : bool is_udp,
723 : : uint16_t udp_port)
724 : : {
725 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
726 : : size_t request_len, response_len;
727 : : int rc = 0;
728 : :
729 : : request_len = sizeof(struct inline_ipsec_msg) +
730 : : sizeof(struct virtchnl_ipsec_sp_cfg);
731 : 0 : request = rte_malloc("iavf-inbound-security-policy-add-request",
732 : : request_len, 0);
733 [ # # ]: 0 : if (request == NULL) {
734 : : rc = -ENOMEM;
735 : 0 : goto update_cleanup;
736 : : }
737 : :
738 : : /* set msg header params */
739 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SP_CREATE;
740 [ # # ]: 0 : request->req_id = (uint16_t)0xDEADBEEF;
741 : :
742 : : /* ESP SPI */
743 : 0 : request->ipsec_data.sp_cfg->spi = htonl(esp_spi);
744 : :
745 : : /* Destination IP */
746 [ # # ]: 0 : if (is_v4) {
747 : 0 : request->ipsec_data.sp_cfg->table_id =
748 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV4;
749 : 0 : request->ipsec_data.sp_cfg->dip[0] = htonl(v4_dst_addr);
750 : : } else {
751 : 0 : request->ipsec_data.sp_cfg->table_id =
752 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV6;
753 : 0 : request->ipsec_data.sp_cfg->dip[0] =
754 : 0 : htonl(((uint32_t *)v6_dst_addr)[0]);
755 : 0 : request->ipsec_data.sp_cfg->dip[1] =
756 : 0 : htonl(((uint32_t *)v6_dst_addr)[1]);
757 : 0 : request->ipsec_data.sp_cfg->dip[2] =
758 : 0 : htonl(((uint32_t *)v6_dst_addr)[2]);
759 : 0 : request->ipsec_data.sp_cfg->dip[3] =
760 : 0 : htonl(((uint32_t *)v6_dst_addr)[3]);
761 : : }
762 : :
763 : 0 : request->ipsec_data.sp_cfg->drop = drop;
764 : :
765 : : /** Traffic Class/Congestion Domain currently not support */
766 : 0 : request->ipsec_data.sp_cfg->set_tc = 0;
767 : 0 : request->ipsec_data.sp_cfg->cgd = 0;
768 : 0 : request->ipsec_data.sp_cfg->is_udp = is_udp;
769 : 0 : request->ipsec_data.sp_cfg->udp_port = htons(udp_port);
770 : :
771 : : response_len = sizeof(struct inline_ipsec_msg) +
772 : : sizeof(struct virtchnl_ipsec_sp_cfg_resp);
773 : 0 : response = rte_malloc("iavf-inbound-security-policy-add-response",
774 : : response_len, 0);
775 [ # # ]: 0 : if (response == NULL) {
776 : : rc = -ENOMEM;
777 : 0 : goto update_cleanup;
778 : : }
779 : :
780 : : /* send virtual channel request to add SA to hardware database */
781 : 0 : rc = iavf_ipsec_crypto_request(adapter,
782 : : (uint8_t *)request, request_len,
783 : : (uint8_t *)response, response_len);
784 [ # # ]: 0 : if (rc)
785 : 0 : goto update_cleanup;
786 : :
787 : : /* verify response */
788 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
789 [ # # ]: 0 : response->req_id != request->req_id)
790 : : rc = -EFAULT;
791 : : else
792 : 0 : rc = response->ipsec_data.sp_cfg_resp->rule_id;
793 : :
794 : 0 : update_cleanup:
795 : 0 : rte_free(request);
796 : 0 : rte_free(response);
797 : :
798 : 0 : return rc;
799 : : }
800 : :
801 : : static uint32_t
802 : 0 : iavf_ipsec_crypto_sa_update_esn(struct iavf_adapter *adapter,
803 : : struct iavf_security_session *sess)
804 : : {
805 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
806 : : size_t request_len, response_len;
807 : : int rc = 0;
808 : :
809 : : request_len = sizeof(struct inline_ipsec_msg) +
810 : : sizeof(struct virtchnl_ipsec_sa_update);
811 : 0 : request = rte_malloc("iavf-sa-update-request", request_len, 0);
812 [ # # ]: 0 : if (request == NULL) {
813 : : rc = -ENOMEM;
814 : 0 : goto update_cleanup;
815 : : }
816 : :
817 : : response_len = sizeof(struct inline_ipsec_msg) +
818 : : sizeof(struct virtchnl_ipsec_resp);
819 : 0 : response = rte_malloc("iavf-sa-update-response", response_len, 0);
820 [ # # ]: 0 : if (response == NULL) {
821 : : rc = -ENOMEM;
822 : 0 : goto update_cleanup;
823 : : }
824 : :
825 : : /* set msg header params */
826 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SA_UPDATE;
827 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
828 : :
829 : : /* set request params */
830 : 0 : request->ipsec_data.sa_update->sa_index = sess->sa.hw_idx;
831 : 0 : request->ipsec_data.sa_update->esn_hi = sess->esn.hi;
832 : 0 : request->ipsec_data.sa_update->esn_low = sess->esn.low;
833 : :
834 : : /* send virtual channel request to add SA to hardware database */
835 : 0 : rc = iavf_ipsec_crypto_request(adapter,
836 : : (uint8_t *)request, request_len,
837 : : (uint8_t *)response, response_len);
838 [ # # ]: 0 : if (rc)
839 : 0 : goto update_cleanup;
840 : :
841 : : /* verify response */
842 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
843 [ # # ]: 0 : response->req_id != request->req_id)
844 : : rc = -EFAULT;
845 : : else
846 : 0 : rc = response->ipsec_data.ipsec_resp->resp;
847 : :
848 : 0 : update_cleanup:
849 : 0 : rte_free(request);
850 : 0 : rte_free(response);
851 : :
852 : 0 : return rc;
853 : : }
854 : :
855 : : static int
856 : 0 : iavf_ipsec_crypto_session_update(void *device,
857 : : struct rte_security_session *session,
858 : : struct rte_security_session_conf *conf)
859 : : {
860 : : struct iavf_adapter *adapter = NULL;
861 : : struct iavf_security_session *iavf_sess = NULL;
862 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
863 : : int rc = 0;
864 : :
865 : 0 : adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
866 : 0 : iavf_sess = SECURITY_GET_SESS_PRIV(session);
867 : :
868 : : /* verify we have a valid session and that it belong to this adapter */
869 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
870 : : return -EINVAL;
871 : :
872 : : /* update esn hi 32-bits */
873 [ # # # # ]: 0 : if (iavf_sess->esn.enabled && conf->ipsec.options.esn) {
874 : : /**
875 : : * Update ESN in hardware for inbound SA. Store in
876 : : * iavf_security_session for outbound SA for use
877 : : * in *iavf_ipsec_crypto_pkt_metadata_set* function.
878 : : */
879 : 0 : iavf_sess->esn.hi = conf->ipsec.esn.hi;
880 : 0 : iavf_sess->esn.low = conf->ipsec.esn.low;
881 [ # # ]: 0 : if (iavf_sess->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
882 : 0 : rc = iavf_ipsec_crypto_sa_update_esn(adapter,
883 : : iavf_sess);
884 : :
885 : : }
886 : :
887 : : return rc;
888 : : }
889 : :
890 : : static int
891 : 0 : iavf_ipsec_crypto_session_stats_get(void *device __rte_unused,
892 : : struct rte_security_session *session __rte_unused,
893 : : struct rte_security_stats *stats __rte_unused)
894 : : {
895 : 0 : return -EOPNOTSUPP;
896 : : }
897 : :
898 : : int
899 : 0 : iavf_ipsec_crypto_security_policy_delete(struct iavf_adapter *adapter,
900 : : uint8_t is_v4, uint32_t flow_id)
901 : : {
902 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
903 : : size_t request_len, response_len;
904 : : int rc = 0;
905 : :
906 : : request_len = sizeof(struct inline_ipsec_msg) +
907 : : sizeof(struct virtchnl_ipsec_sp_destroy);
908 : 0 : request = rte_malloc("iavf-sp-del-request", request_len, 0);
909 [ # # ]: 0 : if (request == NULL) {
910 : : rc = -ENOMEM;
911 : 0 : goto update_cleanup;
912 : : }
913 : :
914 : : response_len = sizeof(struct inline_ipsec_msg) +
915 : : sizeof(struct virtchnl_ipsec_resp);
916 : 0 : response = rte_malloc("iavf-sp-del-response", response_len, 0);
917 [ # # ]: 0 : if (response == NULL) {
918 : : rc = -ENOMEM;
919 : 0 : goto update_cleanup;
920 : : }
921 : :
922 : : /* set msg header params */
923 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SP_DESTROY;
924 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
925 : :
926 : : /* set security policy params */
927 : 0 : request->ipsec_data.sp_destroy->table_id = is_v4 ?
928 : 0 : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV4 :
929 : : VIRTCHNL_IPSEC_INBOUND_SPD_TBL_IPV6;
930 : 0 : request->ipsec_data.sp_destroy->rule_id = flow_id;
931 : :
932 : : /* send virtual channel request to add SA to hardware database */
933 : 0 : rc = iavf_ipsec_crypto_request(adapter,
934 : : (uint8_t *)request, request_len,
935 : : (uint8_t *)response, response_len);
936 [ # # ]: 0 : if (rc)
937 : 0 : goto update_cleanup;
938 : :
939 : : /* verify response */
940 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
941 [ # # ]: 0 : response->req_id != request->req_id)
942 : : rc = -EFAULT;
943 : : else
944 : 0 : return response->ipsec_data.ipsec_status->status;
945 : :
946 : 0 : update_cleanup:
947 : 0 : rte_free(request);
948 : 0 : rte_free(response);
949 : :
950 : 0 : return rc;
951 : : }
952 : :
953 : : static uint32_t
954 : 0 : iavf_ipsec_crypto_sa_del(struct iavf_adapter *adapter,
955 : : struct iavf_security_session *sess)
956 : : {
957 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
958 : : size_t request_len, response_len;
959 : :
960 : : int rc = 0;
961 : :
962 : : request_len = sizeof(struct inline_ipsec_msg) +
963 : : sizeof(struct virtchnl_ipsec_sa_destroy);
964 : :
965 : 0 : request = rte_malloc("iavf-sa-del-request", request_len, 0);
966 [ # # ]: 0 : if (request == NULL) {
967 : : rc = -ENOMEM;
968 : 0 : goto update_cleanup;
969 : : }
970 : :
971 : : response_len = sizeof(struct inline_ipsec_msg) +
972 : : sizeof(struct virtchnl_ipsec_resp);
973 : :
974 : 0 : response = rte_malloc("iavf-sa-del-response", response_len, 0);
975 [ # # ]: 0 : if (response == NULL) {
976 : : rc = -ENOMEM;
977 : 0 : goto update_cleanup;
978 : : }
979 : :
980 : : /* set msg header params */
981 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_SA_DESTROY;
982 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
983 : :
984 : : /**
985 : : * SA delete supports deletion of 1-8 specified SA's or if the flag
986 : : * field is zero, all SA's associated with VF will be deleted.
987 : : */
988 [ # # ]: 0 : if (sess) {
989 : 0 : request->ipsec_data.sa_destroy->flag = 0x1;
990 : 0 : request->ipsec_data.sa_destroy->sa_index[0] = sess->sa.hw_idx;
991 : : } else {
992 : 0 : request->ipsec_data.sa_destroy->flag = 0x0;
993 : : }
994 : :
995 : : /* send virtual channel request to add SA to hardware database */
996 : 0 : rc = iavf_ipsec_crypto_request(adapter,
997 : : (uint8_t *)request, request_len,
998 : : (uint8_t *)response, response_len);
999 [ # # ]: 0 : if (rc)
1000 : 0 : goto update_cleanup;
1001 : :
1002 : : /* verify response */
1003 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1004 [ # # ]: 0 : response->req_id != request->req_id)
1005 : : rc = -EFAULT;
1006 : :
1007 : : /**
1008 : : * Delete status will be the same bitmask as sa_destroy request flag if
1009 : : * deletes successful
1010 : : */
1011 : 0 : if (request->ipsec_data.sa_destroy->flag !=
1012 [ # # ]: 0 : response->ipsec_data.ipsec_status->status)
1013 : : rc = -EFAULT;
1014 : :
1015 : 0 : update_cleanup:
1016 : 0 : rte_free(response);
1017 : 0 : rte_free(request);
1018 : :
1019 : 0 : return rc;
1020 : : }
1021 : :
1022 : : static int
1023 : 0 : iavf_ipsec_crypto_session_destroy(void *device,
1024 : : struct rte_security_session *session)
1025 : : {
1026 : : struct iavf_adapter *adapter = NULL;
1027 : : struct iavf_security_session *iavf_sess = NULL;
1028 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1029 : : int ret;
1030 : :
1031 : 0 : adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
1032 : 0 : iavf_sess = SECURITY_GET_SESS_PRIV(session);
1033 : :
1034 : : /* verify we have a valid session and that it belong to this adapter */
1035 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
1036 : : return -EINVAL;
1037 : :
1038 : 0 : ret = iavf_ipsec_crypto_sa_del(adapter, iavf_sess);
1039 : : memset(iavf_sess, 0, sizeof(struct iavf_security_session));
1040 : 0 : return ret;
1041 : : }
1042 : :
1043 : : /**
1044 : : * Get ESP trailer from packet as well as calculate the total ESP trailer
1045 : : * length, which include padding, ESP trailer footer and the ICV
1046 : : */
1047 : : static inline struct rte_esp_tail *
1048 : 0 : iavf_ipsec_crypto_get_esp_trailer(struct rte_mbuf *m,
1049 : : struct iavf_security_session *s, uint16_t *esp_trailer_length)
1050 : : {
1051 : : struct rte_esp_tail *esp_trailer;
1052 : :
1053 : 0 : uint16_t length = sizeof(struct rte_esp_tail) + s->icv_sz;
1054 : : uint16_t offset = 0;
1055 : :
1056 : : /**
1057 : : * The ICV will not be present in TSO packets as this is appended by
1058 : : * hardware during segment generation
1059 : : */
1060 [ # # ]: 0 : if (m->ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
1061 : : length -= s->icv_sz;
1062 : :
1063 : 0 : *esp_trailer_length = length;
1064 : :
1065 : : /**
1066 : : * Calculate offset in packet to ESP trailer header, this should be
1067 : : * total packet length less the size of the ESP trailer plus the ICV
1068 : : * length if it is present
1069 : : */
1070 : 0 : offset = rte_pktmbuf_pkt_len(m) - length;
1071 : :
1072 [ # # ]: 0 : if (m->nb_segs > 1) {
1073 : : /* find segment which esp trailer is located */
1074 [ # # ]: 0 : while (m->data_len < offset) {
1075 : 0 : offset -= m->data_len;
1076 : 0 : m = m->next;
1077 : : }
1078 : : }
1079 : :
1080 : 0 : esp_trailer = rte_pktmbuf_mtod_offset(m, struct rte_esp_tail *, offset);
1081 : :
1082 : 0 : *esp_trailer_length += esp_trailer->pad_len;
1083 : :
1084 : 0 : return esp_trailer;
1085 : : }
1086 : :
1087 : : static inline uint16_t
1088 : : iavf_ipsec_crypto_compute_l4_payload_length(struct rte_mbuf *m,
1089 : : struct iavf_security_session *s, uint16_t esp_tlen)
1090 : : {
1091 : 0 : uint16_t ol2_len = m->l2_len; /* MAC + VLAN */
1092 : : uint16_t ol3_len = 0; /* ipv4/6 + ext hdrs */
1093 : : uint16_t ol4_len = 0; /* UDP NATT */
1094 : : uint16_t l3_len = 0; /* IPv4/6 + ext hdrs */
1095 : : uint16_t l4_len = 0; /* TCP/UDP/STCP hdrs */
1096 : 0 : uint16_t esp_hlen = sizeof(struct rte_esp_hdr) + s->iv_sz;
1097 : :
1098 : 0 : if (s->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1099 : 0 : ol3_len = m->outer_l3_len;
1100 : : /**<
1101 : : * application provided l3len assumed to include length of
1102 : : * ipv4/6 hdr + ext hdrs
1103 : : */
1104 : :
1105 [ # # ]: 0 : if (s->udp_encap.enabled) {
1106 : : ol4_len = sizeof(struct rte_udp_hdr);
1107 : 0 : l3_len = m->l3_len - ol4_len;
1108 : : l4_len = l3_len;
1109 : : } else {
1110 : 0 : l3_len = m->l3_len;
1111 : 0 : l4_len = m->l4_len;
1112 : : }
1113 : :
1114 : 0 : return rte_pktmbuf_pkt_len(m) - (ol2_len + ol3_len + ol4_len +
1115 : 0 : esp_hlen + l3_len + l4_len + esp_tlen);
1116 : : }
1117 : :
1118 : : static int
1119 : 0 : iavf_ipsec_crypto_pkt_metadata_set(void *device,
1120 : : struct rte_security_session *session,
1121 : : struct rte_mbuf *m, void *params)
1122 : : {
1123 : : struct rte_eth_dev *ethdev = device;
1124 : 0 : struct iavf_adapter *adapter =
1125 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(ethdev->data->dev_private);
1126 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1127 : 0 : struct iavf_security_session *iavf_sess = SECURITY_GET_SESS_PRIV(session);
1128 : : struct iavf_ipsec_crypto_pkt_metadata *md;
1129 : : struct rte_esp_tail *esp_tail;
1130 : : uint64_t *sqn = params;
1131 : : uint16_t esp_trailer_length;
1132 : :
1133 : : /* Check we have valid session and is associated with this device */
1134 [ # # ]: 0 : if (unlikely(iavf_sess == NULL || iavf_sess->adapter != adapter))
1135 : : return -EINVAL;
1136 : :
1137 : : /* Get dynamic metadata location from mbuf */
1138 : 0 : md = RTE_MBUF_DYNFIELD(m, iavf_sctx->pkt_md_offset,
1139 : : struct iavf_ipsec_crypto_pkt_metadata *);
1140 : :
1141 : : /* Set immutable metadata values from session template */
1142 : 0 : memcpy(md, &iavf_sess->pkt_metadata_template,
1143 : : sizeof(struct iavf_ipsec_crypto_pkt_metadata));
1144 : :
1145 : 0 : esp_tail = iavf_ipsec_crypto_get_esp_trailer(m, iavf_sess,
1146 : : &esp_trailer_length);
1147 : :
1148 : : /* Set per packet mutable metadata values */
1149 [ # # ]: 0 : md->esp_trailer_len = esp_trailer_length;
1150 : 0 : md->l4_payload_len = iavf_ipsec_crypto_compute_l4_payload_length(m,
1151 : : iavf_sess, esp_trailer_length);
1152 : 0 : md->next_proto = esp_tail->next_proto;
1153 : :
1154 : : /* If Extended SN in use set the upper 32-bits in metadata */
1155 [ # # # # ]: 0 : if (iavf_sess->esn.enabled && sqn != NULL)
1156 : 0 : md->esn = (uint32_t)(*sqn >> 32);
1157 : :
1158 : : return 0;
1159 : : }
1160 : :
1161 : : static int
1162 : 0 : iavf_ipsec_crypto_device_capabilities_get(struct iavf_adapter *adapter,
1163 : : struct virtchnl_ipsec_cap *capability)
1164 : : {
1165 : : /* Perform pf-vf comms */
1166 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
1167 : : size_t request_len, response_len;
1168 : : int rc;
1169 : :
1170 : : request_len = sizeof(struct inline_ipsec_msg);
1171 : :
1172 : 0 : request = rte_malloc("iavf-device-capability-request", request_len, 0);
1173 [ # # ]: 0 : if (request == NULL) {
1174 : : rc = -ENOMEM;
1175 : 0 : goto update_cleanup;
1176 : : }
1177 : :
1178 : : response_len = sizeof(struct inline_ipsec_msg) +
1179 : : sizeof(struct virtchnl_ipsec_cap);
1180 : 0 : response = rte_malloc("iavf-device-capability-response",
1181 : : response_len, 0);
1182 [ # # ]: 0 : if (response == NULL) {
1183 : : rc = -ENOMEM;
1184 : 0 : goto update_cleanup;
1185 : : }
1186 : :
1187 : : /* set msg header params */
1188 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_GET_CAP;
1189 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
1190 : :
1191 : : /* send virtual channel request to add SA to hardware database */
1192 : 0 : rc = iavf_ipsec_crypto_request(adapter,
1193 : : (uint8_t *)request, request_len,
1194 : : (uint8_t *)response, response_len);
1195 [ # # ]: 0 : if (rc)
1196 : 0 : goto update_cleanup;
1197 : :
1198 : : /* verify response id */
1199 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1200 [ # # ]: 0 : response->req_id != request->req_id){
1201 : : rc = -EFAULT;
1202 : 0 : goto update_cleanup;
1203 : : }
1204 : 0 : memcpy(capability, response->ipsec_data.ipsec_cap, sizeof(*capability));
1205 : :
1206 : 0 : update_cleanup:
1207 : 0 : rte_free(response);
1208 : 0 : rte_free(request);
1209 : :
1210 : 0 : return rc;
1211 : : }
1212 : :
1213 : : enum rte_crypto_auth_algorithm auth_maptbl[] = {
1214 : : /* Hash Algorithm */
1215 : : [VIRTCHNL_HASH_NO_ALG] = RTE_CRYPTO_AUTH_NULL,
1216 : : [VIRTCHNL_AES_CBC_MAC] = RTE_CRYPTO_AUTH_AES_CBC_MAC,
1217 : : [VIRTCHNL_AES_CMAC] = RTE_CRYPTO_AUTH_AES_CMAC,
1218 : : [VIRTCHNL_AES_GMAC] = RTE_CRYPTO_AUTH_AES_GMAC,
1219 : : [VIRTCHNL_AES_XCBC_MAC] = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
1220 : : [VIRTCHNL_MD5_HMAC] = RTE_CRYPTO_AUTH_MD5_HMAC,
1221 : : [VIRTCHNL_SHA1_HMAC] = RTE_CRYPTO_AUTH_SHA1_HMAC,
1222 : : [VIRTCHNL_SHA224_HMAC] = RTE_CRYPTO_AUTH_SHA224_HMAC,
1223 : : [VIRTCHNL_SHA256_HMAC] = RTE_CRYPTO_AUTH_SHA256_HMAC,
1224 : : [VIRTCHNL_SHA384_HMAC] = RTE_CRYPTO_AUTH_SHA384_HMAC,
1225 : : [VIRTCHNL_SHA512_HMAC] = RTE_CRYPTO_AUTH_SHA512_HMAC,
1226 : : [VIRTCHNL_SHA3_224_HMAC] = RTE_CRYPTO_AUTH_SHA3_224_HMAC,
1227 : : [VIRTCHNL_SHA3_256_HMAC] = RTE_CRYPTO_AUTH_SHA3_256_HMAC,
1228 : : [VIRTCHNL_SHA3_384_HMAC] = RTE_CRYPTO_AUTH_SHA3_384_HMAC,
1229 : : [VIRTCHNL_SHA3_512_HMAC] = RTE_CRYPTO_AUTH_SHA3_512_HMAC,
1230 : : };
1231 : :
1232 : : static void
1233 : : update_auth_capabilities(struct rte_cryptodev_capabilities *scap,
1234 : : struct virtchnl_algo_cap *acap,
1235 : : const struct rte_cryptodev_symmetric_capability *symcap)
1236 : : {
1237 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1238 : :
1239 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1240 : :
1241 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_AUTH;
1242 : :
1243 : 0 : capability->auth.algo = auth_maptbl[acap->algo_type];
1244 : 0 : capability->auth.block_size = acap->block_size;
1245 : :
1246 : 0 : capability->auth.key_size.min = acap->min_key_size;
1247 : 0 : capability->auth.key_size.max = acap->max_key_size;
1248 : 0 : capability->auth.key_size.increment = acap->inc_key_size;
1249 : :
1250 : 0 : capability->auth.digest_size.min = acap->min_digest_size;
1251 : 0 : capability->auth.digest_size.max = acap->max_digest_size;
1252 : 0 : capability->auth.digest_size.increment = acap->inc_digest_size;
1253 : :
1254 [ # # ]: 0 : if (symcap) {
1255 : 0 : capability->auth.iv_size.min = symcap->auth.iv_size.min;
1256 : 0 : capability->auth.iv_size.max = symcap->auth.iv_size.max;
1257 : 0 : capability->auth.iv_size.increment =
1258 : 0 : symcap->auth.iv_size.increment;
1259 : : } else {
1260 : 0 : capability->auth.iv_size.min = 0;
1261 : 0 : capability->auth.iv_size.max = 65535;
1262 : 0 : capability->auth.iv_size.increment = 1;
1263 : : }
1264 : : }
1265 : :
1266 : : enum rte_crypto_cipher_algorithm cipher_maptbl[] = {
1267 : : /* Cipher Algorithm */
1268 : : [VIRTCHNL_CIPHER_NO_ALG] = RTE_CRYPTO_CIPHER_NULL,
1269 : : [VIRTCHNL_3DES_CBC] = RTE_CRYPTO_CIPHER_3DES_CBC,
1270 : : [VIRTCHNL_AES_CBC] = RTE_CRYPTO_CIPHER_AES_CBC,
1271 : : [VIRTCHNL_AES_CTR] = RTE_CRYPTO_CIPHER_AES_CTR,
1272 : : };
1273 : :
1274 : : static void
1275 : : update_cipher_capabilities(struct rte_cryptodev_capabilities *scap,
1276 : : struct virtchnl_algo_cap *acap,
1277 : : const struct rte_cryptodev_symmetric_capability *symcap)
1278 : : {
1279 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1280 : :
1281 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1282 : :
1283 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1284 : :
1285 : 0 : capability->cipher.algo = cipher_maptbl[acap->algo_type];
1286 : :
1287 : 0 : capability->cipher.block_size = acap->block_size;
1288 : :
1289 : 0 : capability->cipher.key_size.min = acap->min_key_size;
1290 : 0 : capability->cipher.key_size.max = acap->max_key_size;
1291 : 0 : capability->cipher.key_size.increment = acap->inc_key_size;
1292 : :
1293 [ # # ]: 0 : if (symcap) {
1294 : 0 : capability->cipher.iv_size.min = symcap->cipher.iv_size.min;
1295 : 0 : capability->cipher.iv_size.max = symcap->cipher.iv_size.max;
1296 : 0 : capability->cipher.iv_size.increment =
1297 : 0 : symcap->cipher.iv_size.increment;
1298 : :
1299 : : } else {
1300 : 0 : capability->cipher.iv_size.min = 0;
1301 : 0 : capability->cipher.iv_size.max = 65535;
1302 : 0 : capability->cipher.iv_size.increment = 1;
1303 : : }
1304 : : }
1305 : :
1306 : : enum rte_crypto_aead_algorithm aead_maptbl[] = {
1307 : : /* AEAD Algorithm */
1308 : : [VIRTCHNL_AES_CCM] = RTE_CRYPTO_AEAD_AES_CCM,
1309 : : [VIRTCHNL_AES_GCM] = RTE_CRYPTO_AEAD_AES_GCM,
1310 : : [VIRTCHNL_CHACHA20_POLY1305] = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
1311 : : };
1312 : :
1313 : : static void
1314 : : update_aead_capabilities(struct rte_cryptodev_capabilities *scap,
1315 : : struct virtchnl_algo_cap *acap,
1316 : : const struct rte_cryptodev_symmetric_capability *symcap __rte_unused)
1317 : : {
1318 : : struct rte_cryptodev_symmetric_capability *capability = &scap->sym;
1319 : :
1320 : 0 : scap->op = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1321 : :
1322 : 0 : capability->xform_type = RTE_CRYPTO_SYM_XFORM_AEAD;
1323 : :
1324 : 0 : capability->aead.algo = aead_maptbl[acap->algo_type];
1325 : :
1326 : 0 : capability->aead.block_size = acap->block_size;
1327 : :
1328 : 0 : capability->aead.key_size.min = acap->min_key_size;
1329 : 0 : capability->aead.key_size.max = acap->max_key_size;
1330 : 0 : capability->aead.key_size.increment = acap->inc_key_size;
1331 : :
1332 : : /* remove constrains for aead and iv length */
1333 : 0 : capability->aead.aad_size.min = 0;
1334 : 0 : capability->aead.aad_size.max = 65535;
1335 : 0 : capability->aead.aad_size.increment = 1;
1336 : :
1337 : 0 : capability->aead.iv_size.min = 0;
1338 : 0 : capability->aead.iv_size.max = 65535;
1339 : 0 : capability->aead.iv_size.increment = 1;
1340 : :
1341 : 0 : capability->aead.digest_size.min = acap->min_digest_size;
1342 : 0 : capability->aead.digest_size.max = acap->max_digest_size;
1343 : 0 : capability->aead.digest_size.increment = acap->inc_digest_size;
1344 : 0 : }
1345 : :
1346 : : /**
1347 : : * Dynamically set crypto capabilities based on virtchannel IPsec
1348 : : * capabilities structure.
1349 : : */
1350 : : int
1351 : 0 : iavf_ipsec_crypto_set_security_capabililites(struct iavf_security_ctx
1352 : : *iavf_sctx, struct virtchnl_ipsec_cap *vch_cap)
1353 : : {
1354 : : struct rte_cryptodev_capabilities *capabilities;
1355 : : const struct rte_cryptodev_symmetric_capability *symcap;
1356 : : int i, j, number_of_capabilities = 0, ci = 0;
1357 : :
1358 : : /* Count the total number of crypto algorithms supported */
1359 [ # # ]: 0 : for (i = 0; i < VIRTCHNL_IPSEC_MAX_CRYPTO_CAP_NUM; i++)
1360 : 0 : number_of_capabilities += vch_cap->cap[i].algo_cap_num;
1361 : :
1362 : : /**
1363 : : * Allocate cryptodev capabilities structure for
1364 : : * *number_of_capabilities* items plus one item to null terminate the
1365 : : * array
1366 : : */
1367 : 0 : capabilities = rte_zmalloc("crypto_cap",
1368 : : sizeof(struct rte_cryptodev_capabilities) *
1369 : 0 : (number_of_capabilities + 1), 0);
1370 [ # # ]: 0 : if (!capabilities)
1371 : : return -ENOMEM;
1372 : 0 : capabilities[number_of_capabilities].op = RTE_CRYPTO_OP_TYPE_UNDEFINED;
1373 : :
1374 : : /**
1375 : : * Iterate over each virtchnl crypto capability by crypto type and
1376 : : * algorithm.
1377 : : */
1378 [ # # ]: 0 : for (i = 0; i < VIRTCHNL_IPSEC_MAX_CRYPTO_CAP_NUM; i++) {
1379 [ # # ]: 0 : for (j = 0; j < vch_cap->cap[i].algo_cap_num; j++, ci++) {
1380 [ # # # # ]: 0 : switch (vch_cap->cap[i].crypto_type) {
1381 : 0 : case VIRTCHNL_AUTH:
1382 : 0 : symcap = get_auth_capability(iavf_sctx,
1383 : 0 : capabilities[ci].sym.auth.algo);
1384 : : update_auth_capabilities(&capabilities[ci],
1385 : : &vch_cap->cap[i].algo_cap_list[j],
1386 : : symcap);
1387 : : break;
1388 : 0 : case VIRTCHNL_CIPHER:
1389 : 0 : symcap = get_cipher_capability(iavf_sctx,
1390 : 0 : capabilities[ci].sym.cipher.algo);
1391 : : update_cipher_capabilities(&capabilities[ci],
1392 : : &vch_cap->cap[i].algo_cap_list[j],
1393 : : symcap);
1394 : : break;
1395 : 0 : case VIRTCHNL_AEAD:
1396 : : symcap = get_aead_capability(iavf_sctx,
1397 : 0 : capabilities[ci].sym.aead.algo);
1398 : : update_aead_capabilities(&capabilities[ci],
1399 : : &vch_cap->cap[i].algo_cap_list[j],
1400 : : symcap);
1401 : : break;
1402 : 0 : default:
1403 : 0 : capabilities[ci].op =
1404 : : RTE_CRYPTO_OP_TYPE_UNDEFINED;
1405 : 0 : break;
1406 : : }
1407 : : }
1408 : : }
1409 : :
1410 : 0 : iavf_sctx->crypto_capabilities = capabilities;
1411 : 0 : return 0;
1412 : : }
1413 : :
1414 : : /**
1415 : : * Get security capabilities for device
1416 : : */
1417 : : static const struct rte_security_capability *
1418 : 0 : iavf_ipsec_crypto_capabilities_get(void *device)
1419 : : {
1420 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
1421 : 0 : struct iavf_adapter *adapter =
1422 : 0 : IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
1423 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1424 : : unsigned int i;
1425 : :
1426 : : static struct rte_security_capability iavf_security_capabilities[] = {
1427 : : { /* IPsec Inline Crypto ESP Tunnel Egress */
1428 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1429 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1430 : : .ipsec = {
1431 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1432 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
1433 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
1434 : : .options = { .udp_encap = 1,
1435 : : .stats = 1, .esn = 1 },
1436 : : },
1437 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
1438 : : },
1439 : : { /* IPsec Inline Crypto ESP Tunnel Ingress */
1440 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1441 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1442 : : .ipsec = {
1443 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1444 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
1445 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1446 : : .options = { .udp_encap = 1,
1447 : : .stats = 1, .esn = 1 },
1448 : : },
1449 : : .ol_flags = 0
1450 : : },
1451 : : { /* IPsec Inline Crypto ESP Transport Egress */
1452 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1453 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1454 : : .ipsec = {
1455 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1456 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
1457 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
1458 : : .options = { .udp_encap = 1, .stats = 1,
1459 : : .esn = 1 },
1460 : : },
1461 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
1462 : : },
1463 : : { /* IPsec Inline Crypto ESP Transport Ingress */
1464 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
1465 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
1466 : : .ipsec = {
1467 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
1468 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
1469 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
1470 : : .options = { .udp_encap = 1, .stats = 1,
1471 : : .esn = 1 }
1472 : : },
1473 : : .ol_flags = 0
1474 : : },
1475 : : {
1476 : : .action = RTE_SECURITY_ACTION_TYPE_NONE
1477 : : }
1478 : : };
1479 : :
1480 : : /**
1481 : : * Update the security capabilities struct with the runtime discovered
1482 : : * crypto capabilities, except for last element of the array which is
1483 : : * the null termination
1484 : : */
1485 [ # # ]: 0 : for (i = 0; i < ((sizeof(iavf_security_capabilities) /
1486 : 0 : sizeof(iavf_security_capabilities[0])) - 1); i++) {
1487 : 0 : iavf_security_capabilities[i].crypto_capabilities =
1488 : 0 : iavf_sctx->crypto_capabilities;
1489 : : }
1490 : :
1491 : 0 : return iavf_security_capabilities;
1492 : : }
1493 : :
1494 : : static struct rte_security_ops iavf_ipsec_crypto_ops = {
1495 : : .session_get_size = iavf_ipsec_crypto_session_size_get,
1496 : : .session_create = iavf_ipsec_crypto_session_create,
1497 : : .session_update = iavf_ipsec_crypto_session_update,
1498 : : .session_stats_get = iavf_ipsec_crypto_session_stats_get,
1499 : : .session_destroy = iavf_ipsec_crypto_session_destroy,
1500 : : .set_pkt_metadata = iavf_ipsec_crypto_pkt_metadata_set,
1501 : : .capabilities_get = iavf_ipsec_crypto_capabilities_get,
1502 : : };
1503 : :
1504 : : int
1505 : 0 : iavf_security_ctx_create(struct iavf_adapter *adapter)
1506 : : {
1507 : : struct rte_security_ctx *sctx;
1508 : :
1509 : 0 : sctx = rte_malloc("security_ctx", sizeof(struct rte_security_ctx), 0);
1510 [ # # ]: 0 : if (sctx == NULL)
1511 : : return -ENOMEM;
1512 : :
1513 : 0 : sctx->device = adapter->vf.eth_dev;
1514 : 0 : sctx->ops = &iavf_ipsec_crypto_ops;
1515 : 0 : sctx->sess_cnt = 0;
1516 : :
1517 : 0 : adapter->vf.eth_dev->security_ctx = sctx;
1518 : :
1519 [ # # ]: 0 : if (adapter->security_ctx == NULL) {
1520 : 0 : adapter->security_ctx = rte_malloc("iavf_security_ctx",
1521 : : sizeof(struct iavf_security_ctx), 0);
1522 [ # # ]: 0 : if (adapter->security_ctx == NULL) {
1523 : 0 : rte_free(adapter->vf.eth_dev->security_ctx);
1524 : 0 : adapter->vf.eth_dev->security_ctx = NULL;
1525 : 0 : return -ENOMEM;
1526 : : }
1527 : : }
1528 : :
1529 : : return 0;
1530 : : }
1531 : :
1532 : : int
1533 : 0 : iavf_security_init(struct iavf_adapter *adapter)
1534 : : {
1535 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1536 : 0 : struct rte_mbuf_dynfield pkt_md_dynfield = {
1537 : : .name = "iavf_ipsec_crypto_pkt_metadata",
1538 : : .size = sizeof(struct iavf_ipsec_crypto_pkt_metadata),
1539 : : .align = alignof(struct iavf_ipsec_crypto_pkt_metadata)
1540 : : };
1541 : : struct virtchnl_ipsec_cap capabilities;
1542 : : int rc;
1543 : :
1544 : 0 : iavf_sctx->adapter = adapter;
1545 : :
1546 : 0 : iavf_sctx->pkt_md_offset = rte_mbuf_dynfield_register(&pkt_md_dynfield);
1547 [ # # ]: 0 : if (iavf_sctx->pkt_md_offset < 0)
1548 : : return iavf_sctx->pkt_md_offset;
1549 : :
1550 : : /* Get device capabilities from Inline IPsec driver over PF-VF comms */
1551 : 0 : rc = iavf_ipsec_crypto_device_capabilities_get(adapter, &capabilities);
1552 [ # # ]: 0 : if (rc)
1553 : : return rc;
1554 : :
1555 : 0 : return iavf_ipsec_crypto_set_security_capabililites(iavf_sctx,
1556 : : &capabilities);
1557 : : }
1558 : :
1559 : : int
1560 : 0 : iavf_security_get_pkt_md_offset(struct iavf_adapter *adapter)
1561 : : {
1562 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1563 : :
1564 : 0 : return iavf_sctx->pkt_md_offset;
1565 : : }
1566 : :
1567 : : int
1568 : 0 : iavf_security_ctx_destroy(struct iavf_adapter *adapter)
1569 : : {
1570 : 0 : struct rte_security_ctx *sctx = adapter->vf.eth_dev->security_ctx;
1571 : 0 : struct iavf_security_ctx *iavf_sctx = adapter->security_ctx;
1572 : :
1573 [ # # ]: 0 : if (iavf_sctx == NULL)
1574 : : return -ENODEV;
1575 : :
1576 : : /* free and reset security data structures */
1577 : 0 : rte_free(iavf_sctx);
1578 : 0 : rte_free(sctx);
1579 : :
1580 : 0 : adapter->security_ctx = NULL;
1581 : 0 : adapter->vf.eth_dev->security_ctx = NULL;
1582 : :
1583 : 0 : return 0;
1584 : : }
1585 : :
1586 : : static int
1587 : 0 : iavf_ipsec_crypto_status_get(struct iavf_adapter *adapter,
1588 : : struct virtchnl_ipsec_status *status)
1589 : : {
1590 : : /* Perform pf-vf comms */
1591 : : struct inline_ipsec_msg *request = NULL, *response = NULL;
1592 : : size_t request_len, response_len;
1593 : : int rc;
1594 : :
1595 : : request_len = sizeof(struct inline_ipsec_msg);
1596 : :
1597 : 0 : request = rte_malloc("iavf-device-status-request", request_len, 0);
1598 [ # # ]: 0 : if (request == NULL) {
1599 : : rc = -ENOMEM;
1600 : 0 : goto update_cleanup;
1601 : : }
1602 : :
1603 : : response_len = sizeof(struct inline_ipsec_msg) +
1604 : : sizeof(struct virtchnl_ipsec_cap);
1605 : 0 : response = rte_malloc("iavf-device-status-response",
1606 : : response_len, 0);
1607 [ # # ]: 0 : if (response == NULL) {
1608 : : rc = -ENOMEM;
1609 : 0 : goto update_cleanup;
1610 : : }
1611 : :
1612 : : /* set msg header params */
1613 : 0 : request->ipsec_opcode = INLINE_IPSEC_OP_GET_STATUS;
1614 : 0 : request->req_id = (uint16_t)0xDEADBEEF;
1615 : :
1616 : : /* send virtual channel request to add SA to hardware database */
1617 : 0 : rc = iavf_ipsec_crypto_request(adapter,
1618 : : (uint8_t *)request, request_len,
1619 : : (uint8_t *)response, response_len);
1620 [ # # ]: 0 : if (rc)
1621 : 0 : goto update_cleanup;
1622 : :
1623 : : /* verify response id */
1624 [ # # ]: 0 : if (response->ipsec_opcode != request->ipsec_opcode ||
1625 [ # # ]: 0 : response->req_id != request->req_id){
1626 : : rc = -EFAULT;
1627 : 0 : goto update_cleanup;
1628 : : }
1629 : 0 : memcpy(status, response->ipsec_data.ipsec_status, sizeof(*status));
1630 : :
1631 : 0 : update_cleanup:
1632 : 0 : rte_free(response);
1633 : 0 : rte_free(request);
1634 : :
1635 : 0 : return rc;
1636 : : }
1637 : :
1638 : :
1639 : : int
1640 : 0 : iavf_ipsec_crypto_supported(struct iavf_adapter *adapter)
1641 : : {
1642 : 0 : struct virtchnl_vf_resource *resources = adapter->vf.vf_res;
1643 : : int crypto_supported = false;
1644 : :
1645 : : /** Capability check for IPsec Crypto */
1646 [ # # # # ]: 0 : if (resources && (resources->vf_cap_flags &
1647 : : VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO)) {
1648 : : struct virtchnl_ipsec_status status;
1649 : 0 : int rc = iavf_ipsec_crypto_status_get(adapter, &status);
1650 [ # # # # ]: 0 : if (rc == 0 && status.status == INLINE_IPSEC_STATUS_AVAILABLE)
1651 : : crypto_supported = true;
1652 : : }
1653 : :
1654 : : /* Clear the VF flag to return faster next call */
1655 [ # # ]: 0 : if (resources && !crypto_supported)
1656 : 0 : resources->vf_cap_flags &=
1657 : : ~(VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO);
1658 : :
1659 : 0 : return crypto_supported;
1660 : : }
1661 : :
1662 : : #define IAVF_IPSEC_INSET_ESP (\
1663 : : IAVF_INSET_ESP_SPI)
1664 : :
1665 : : #define IAVF_IPSEC_INSET_AH (\
1666 : : IAVF_INSET_AH_SPI)
1667 : :
1668 : : #define IAVF_IPSEC_INSET_IPV4_NATT_ESP (\
1669 : : IAVF_INSET_IPV4_SRC | IAVF_INSET_IPV4_DST | \
1670 : : IAVF_INSET_ESP_SPI)
1671 : :
1672 : : #define IAVF_IPSEC_INSET_IPV6_NATT_ESP (\
1673 : : IAVF_INSET_IPV6_SRC | IAVF_INSET_IPV6_DST | \
1674 : : IAVF_INSET_ESP_SPI)
1675 : :
1676 : : enum iavf_ipsec_flow_pt_type {
1677 : : IAVF_PATTERN_ESP = 1,
1678 : : IAVF_PATTERN_AH,
1679 : : IAVF_PATTERN_UDP_ESP,
1680 : : };
1681 : : enum iavf_ipsec_flow_pt_ip_ver {
1682 : : IAVF_PATTERN_IPV4 = 1,
1683 : : IAVF_PATTERN_IPV6,
1684 : : };
1685 : :
1686 : : #define IAVF_PATTERN(t, ipt) ((void *)((t) | ((ipt) << 4)))
1687 : : #define IAVF_PATTERN_TYPE(pt) ((pt) & 0x0F)
1688 : : #define IAVF_PATTERN_IP_V(pt) ((pt) >> 4)
1689 : :
1690 : : static struct iavf_pattern_match_item iavf_ipsec_flow_pattern[] = {
1691 : : {iavf_pattern_eth_ipv4_esp, IAVF_IPSEC_INSET_ESP,
1692 : : IAVF_PATTERN(IAVF_PATTERN_ESP, IAVF_PATTERN_IPV4)},
1693 : : {iavf_pattern_eth_ipv6_esp, IAVF_IPSEC_INSET_ESP,
1694 : : IAVF_PATTERN(IAVF_PATTERN_ESP, IAVF_PATTERN_IPV6)},
1695 : : {iavf_pattern_eth_ipv4_ah, IAVF_IPSEC_INSET_AH,
1696 : : IAVF_PATTERN(IAVF_PATTERN_AH, IAVF_PATTERN_IPV4)},
1697 : : {iavf_pattern_eth_ipv6_ah, IAVF_IPSEC_INSET_AH,
1698 : : IAVF_PATTERN(IAVF_PATTERN_AH, IAVF_PATTERN_IPV6)},
1699 : : {iavf_pattern_eth_ipv4_udp_esp, IAVF_IPSEC_INSET_IPV4_NATT_ESP,
1700 : : IAVF_PATTERN(IAVF_PATTERN_UDP_ESP, IAVF_PATTERN_IPV4)},
1701 : : {iavf_pattern_eth_ipv6_udp_esp, IAVF_IPSEC_INSET_IPV6_NATT_ESP,
1702 : : IAVF_PATTERN(IAVF_PATTERN_UDP_ESP, IAVF_PATTERN_IPV6)},
1703 : : };
1704 : :
1705 : : struct iavf_ipsec_flow_item {
1706 : : uint64_t id;
1707 : : uint8_t is_ipv4;
1708 : : uint32_t spi;
1709 : : struct rte_ether_hdr eth_hdr;
1710 : : union {
1711 : : struct rte_ipv4_hdr ipv4_hdr;
1712 : : struct rte_ipv6_hdr ipv6_hdr;
1713 : : };
1714 : : struct rte_udp_hdr udp_hdr;
1715 : : uint8_t is_udp;
1716 : : };
1717 : :
1718 : : static void
1719 : 0 : parse_eth_item(const struct rte_flow_item_eth *item,
1720 : : struct rte_ether_hdr *eth)
1721 : : {
1722 : 0 : memcpy(eth->src_addr.addr_bytes,
1723 : 0 : item->hdr.src_addr.addr_bytes, sizeof(eth->src_addr));
1724 : 0 : memcpy(eth->dst_addr.addr_bytes,
1725 : 0 : item->hdr.dst_addr.addr_bytes, sizeof(eth->dst_addr));
1726 : 0 : }
1727 : :
1728 : : static void
1729 : : parse_ipv4_item(const struct rte_flow_item_ipv4 *item,
1730 : : struct rte_ipv4_hdr *ipv4)
1731 : : {
1732 : 0 : ipv4->src_addr = item->hdr.src_addr;
1733 : 0 : ipv4->dst_addr = item->hdr.dst_addr;
1734 : 0 : }
1735 : :
1736 : : static void
1737 : : parse_ipv6_item(const struct rte_flow_item_ipv6 *item,
1738 : : struct rte_ipv6_hdr *ipv6)
1739 : : {
1740 : 0 : ipv6->src_addr = item->hdr.src_addr;
1741 : 0 : ipv6->dst_addr = item->hdr.dst_addr;
1742 : 0 : }
1743 : :
1744 : : static void
1745 : : parse_udp_item(const struct rte_flow_item_udp *item, struct rte_udp_hdr *udp)
1746 : : {
1747 : 0 : udp->dst_port = item->hdr.dst_port;
1748 : 0 : udp->src_port = item->hdr.src_port;
1749 : : }
1750 : :
1751 : : static int
1752 : : has_security_action(const struct rte_flow_action actions[],
1753 : : const void **session)
1754 : : {
1755 : : /* only {SECURITY; END} supported */
1756 [ # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
1757 [ # # ]: 0 : actions[1].type == RTE_FLOW_ACTION_TYPE_END) {
1758 : 0 : *session = actions[0].conf;
1759 : : return true;
1760 : : }
1761 : : return false;
1762 : : }
1763 : :
1764 : : static struct iavf_ipsec_flow_item *
1765 : 0 : iavf_ipsec_flow_item_parse(struct rte_eth_dev *ethdev,
1766 : : const struct rte_flow_item pattern[],
1767 : : const struct rte_flow_action actions[],
1768 : : uint32_t type)
1769 : : {
1770 : : const void *session;
1771 : : struct iavf_ipsec_flow_item
1772 : 0 : *ipsec_flow = rte_malloc("security-flow-rule",
1773 : : sizeof(struct iavf_ipsec_flow_item), 0);
1774 : 0 : enum iavf_ipsec_flow_pt_type p_type = IAVF_PATTERN_TYPE(type);
1775 : 0 : enum iavf_ipsec_flow_pt_ip_ver p_ip_type = IAVF_PATTERN_IP_V(type);
1776 : :
1777 [ # # ]: 0 : if (ipsec_flow == NULL)
1778 : : return NULL;
1779 : :
1780 : 0 : ipsec_flow->is_ipv4 = (p_ip_type == IAVF_PATTERN_IPV4);
1781 : :
1782 [ # # ]: 0 : if (pattern[0].spec)
1783 : 0 : parse_eth_item((const struct rte_flow_item_eth *)
1784 : : pattern[0].spec, &ipsec_flow->eth_hdr);
1785 : :
1786 [ # # # # ]: 0 : switch (p_type) {
1787 : 0 : case IAVF_PATTERN_ESP:
1788 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1789 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1790 : 0 : pattern[1].spec,
1791 : : &ipsec_flow->ipv4_hdr);
1792 : : } else {
1793 : : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1794 : 0 : pattern[1].spec,
1795 : : &ipsec_flow->ipv6_hdr);
1796 : : }
1797 : 0 : ipsec_flow->spi =
1798 : : ((const struct rte_flow_item_esp *)
1799 : 0 : pattern[2].spec)->hdr.spi;
1800 : 0 : break;
1801 : 0 : case IAVF_PATTERN_AH:
1802 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1803 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1804 : 0 : pattern[1].spec,
1805 : : &ipsec_flow->ipv4_hdr);
1806 : : } else {
1807 : : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1808 : 0 : pattern[1].spec,
1809 : : &ipsec_flow->ipv6_hdr);
1810 : : }
1811 : 0 : ipsec_flow->spi =
1812 : : ((const struct rte_flow_item_ah *)
1813 : 0 : pattern[2].spec)->spi;
1814 : 0 : break;
1815 : 0 : case IAVF_PATTERN_UDP_ESP:
1816 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1817 : : parse_ipv4_item((const struct rte_flow_item_ipv4 *)
1818 : 0 : pattern[1].spec,
1819 : : &ipsec_flow->ipv4_hdr);
1820 : : } else {
1821 : : parse_ipv6_item((const struct rte_flow_item_ipv6 *)
1822 : 0 : pattern[1].spec,
1823 : : &ipsec_flow->ipv6_hdr);
1824 : : }
1825 : : parse_udp_item((const struct rte_flow_item_udp *)
1826 : 0 : pattern[2].spec,
1827 : : &ipsec_flow->udp_hdr);
1828 : 0 : ipsec_flow->is_udp = true;
1829 : 0 : ipsec_flow->spi =
1830 : : ((const struct rte_flow_item_esp *)
1831 : 0 : pattern[3].spec)->hdr.spi;
1832 : 0 : break;
1833 : 0 : default:
1834 : 0 : goto flow_cleanup;
1835 : : }
1836 : :
1837 : : if (!has_security_action(actions, &session))
1838 : 0 : goto flow_cleanup;
1839 : :
1840 [ # # ]: 0 : if (!iavf_ipsec_crypto_action_valid(ethdev, session,
1841 : : ipsec_flow->spi))
1842 : 0 : goto flow_cleanup;
1843 : :
1844 : : return ipsec_flow;
1845 : :
1846 : 0 : flow_cleanup:
1847 : 0 : rte_free(ipsec_flow);
1848 : 0 : return NULL;
1849 : : }
1850 : :
1851 : :
1852 : : static struct iavf_flow_parser iavf_ipsec_flow_parser;
1853 : :
1854 : : static int
1855 : 0 : iavf_ipsec_flow_init(struct iavf_adapter *ad)
1856 : : {
1857 : : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
1858 : : struct iavf_flow_parser *parser;
1859 : :
1860 [ # # ]: 0 : if (!vf->vf_res)
1861 : : return -EINVAL;
1862 : :
1863 [ # # ]: 0 : if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO)
1864 : : parser = &iavf_ipsec_flow_parser;
1865 : : else
1866 : : return -ENOTSUP;
1867 : :
1868 : 0 : return iavf_register_parser(parser, ad);
1869 : : }
1870 : :
1871 : : static void
1872 : 0 : iavf_ipsec_flow_uninit(struct iavf_adapter *ad)
1873 : : {
1874 : 0 : iavf_unregister_parser(&iavf_ipsec_flow_parser, ad);
1875 : 0 : }
1876 : :
1877 : : static int
1878 : 0 : iavf_ipsec_flow_create(struct iavf_adapter *ad,
1879 : : struct rte_flow *flow,
1880 : : void *meta,
1881 : : struct rte_flow_error *error)
1882 : : {
1883 : : struct iavf_ipsec_flow_item *ipsec_flow = meta;
1884 : : int flow_id = -1;
1885 [ # # ]: 0 : if (!ipsec_flow) {
1886 : 0 : rte_flow_error_set(error, EINVAL,
1887 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1888 : : "NULL rule.");
1889 : 0 : return -rte_errno;
1890 : : }
1891 : :
1892 [ # # ]: 0 : if (ipsec_flow->is_ipv4) {
1893 : 0 : flow_id = iavf_ipsec_crypto_inbound_security_policy_add(ad,
1894 : : ipsec_flow->spi,
1895 : : 1,
1896 : : ipsec_flow->ipv4_hdr.dst_addr,
1897 : : NULL,
1898 : : 0,
1899 : 0 : ipsec_flow->is_udp,
1900 : 0 : ipsec_flow->udp_hdr.dst_port);
1901 : : } else {
1902 : 0 : flow_id = iavf_ipsec_crypto_inbound_security_policy_add(ad,
1903 : : ipsec_flow->spi,
1904 : : 0,
1905 : : 0,
1906 : 0 : ipsec_flow->ipv6_hdr.dst_addr.a,
1907 : : 0,
1908 : 0 : ipsec_flow->is_udp,
1909 : 0 : ipsec_flow->udp_hdr.dst_port);
1910 : : }
1911 : :
1912 [ # # ]: 0 : if (flow_id < 1) {
1913 : 0 : rte_flow_error_set(error, EINVAL,
1914 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1915 : : "Failed to add SA.");
1916 : 0 : return -rte_errno;
1917 : : }
1918 : :
1919 : 0 : ipsec_flow->id = flow_id;
1920 : 0 : flow->rule = ipsec_flow;
1921 : :
1922 : 0 : return 0;
1923 : : }
1924 : :
1925 : : static int
1926 : 0 : iavf_ipsec_flow_destroy(struct iavf_adapter *ad,
1927 : : struct rte_flow *flow,
1928 : : struct rte_flow_error *error)
1929 : : {
1930 : 0 : struct iavf_ipsec_flow_item *ipsec_flow = flow->rule;
1931 [ # # ]: 0 : if (!ipsec_flow) {
1932 : 0 : rte_flow_error_set(error, EINVAL,
1933 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1934 : : "NULL rule.");
1935 : 0 : return -rte_errno;
1936 : : }
1937 : :
1938 : 0 : iavf_ipsec_crypto_security_policy_delete(ad,
1939 : 0 : ipsec_flow->is_ipv4, ipsec_flow->id);
1940 : 0 : rte_free(ipsec_flow);
1941 : 0 : return 0;
1942 : : }
1943 : :
1944 : : static struct iavf_flow_engine iavf_ipsec_flow_engine = {
1945 : : .init = iavf_ipsec_flow_init,
1946 : : .uninit = iavf_ipsec_flow_uninit,
1947 : : .create = iavf_ipsec_flow_create,
1948 : : .destroy = iavf_ipsec_flow_destroy,
1949 : : .type = IAVF_FLOW_ENGINE_IPSEC_CRYPTO,
1950 : : };
1951 : :
1952 : : static int
1953 : 0 : iavf_ipsec_flow_parse(struct iavf_adapter *ad,
1954 : : struct iavf_pattern_match_item *array,
1955 : : uint32_t array_len,
1956 : : const struct rte_flow_item pattern[],
1957 : : const struct rte_flow_action actions[],
1958 : : uint32_t priority,
1959 : : void **meta,
1960 : : struct rte_flow_error *error)
1961 : : {
1962 : : struct iavf_pattern_match_item *item = NULL;
1963 : : int ret = -1;
1964 : :
1965 [ # # ]: 0 : if (priority >= 1)
1966 : 0 : return -rte_errno;
1967 : :
1968 : 0 : item = iavf_search_pattern_match_item(pattern, array, array_len, error);
1969 [ # # # # ]: 0 : if (item && item->meta) {
1970 : 0 : uint32_t type = (uint64_t)(item->meta);
1971 : : struct iavf_ipsec_flow_item *fi =
1972 : 0 : iavf_ipsec_flow_item_parse(ad->vf.eth_dev,
1973 : : pattern, actions, type);
1974 [ # # ]: 0 : if (fi && meta) {
1975 : 0 : *meta = fi;
1976 : : ret = 0;
1977 : : }
1978 : : }
1979 : : return ret;
1980 : : }
1981 : :
1982 : : static struct iavf_flow_parser iavf_ipsec_flow_parser = {
1983 : : .engine = &iavf_ipsec_flow_engine,
1984 : : .array = iavf_ipsec_flow_pattern,
1985 : : .array_len = RTE_DIM(iavf_ipsec_flow_pattern),
1986 : : .parse_pattern_action = iavf_ipsec_flow_parse,
1987 : : .stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,
1988 : : };
1989 : :
1990 : 251 : RTE_INIT(iavf_ipsec_flow_engine_register)
1991 : : {
1992 : 251 : iavf_register_flow_engine(&iavf_ipsec_flow_engine);
1993 : 251 : }
|