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