LCOV - code coverage report
Current view: top level - lib/pipeline - rte_swx_ipsec.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 597 0.2 %
Date: 2024-02-14 00:53:57 Functions: 1 25 4.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 429 0.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2022 Intel Corporation
       3                 :            :  */
       4                 :            : #include <stdlib.h>
       5                 :            : #include <stdio.h>
       6                 :            : #include <errno.h>
       7                 :            : #include <arpa/inet.h>
       8                 :            : 
       9                 :            : #include <rte_common.h>
      10                 :            : #include <rte_ip.h>
      11                 :            : #include <rte_tailq.h>
      12                 :            : #include <rte_eal_memconfig.h>
      13                 :            : #include <rte_ring.h>
      14                 :            : #include <rte_mbuf.h>
      15                 :            : #include <rte_cryptodev.h>
      16                 :            : #include <rte_ipsec.h>
      17                 :            : 
      18                 :            : #include "rte_swx_ipsec.h"
      19                 :            : 
      20                 :            : #ifndef RTE_SWX_IPSEC_HUGE_PAGES_DISABLE
      21                 :            : 
      22                 :            : #include <rte_malloc.h>
      23                 :            : 
      24                 :            : static void *
      25                 :            : env_calloc(size_t size, size_t alignment, int numa_node)
      26                 :            : {
      27                 :          0 :         return rte_zmalloc_socket(NULL, size, alignment, numa_node);
      28                 :            : }
      29                 :            : 
      30                 :            : static void
      31                 :            : env_free(void *start, size_t size __rte_unused)
      32                 :            : {
      33                 :          0 :         rte_free(start);
      34                 :          0 : }
      35                 :            : 
      36                 :            : #else
      37                 :            : 
      38                 :            : #include <numa.h>
      39                 :            : 
      40                 :            : static void *
      41                 :            : env_calloc(size_t size, size_t alignment __rte_unused, int numa_node)
      42                 :            : {
      43                 :            :         void *start;
      44                 :            : 
      45                 :            :         if (numa_available() == -1)
      46                 :            :                 return NULL;
      47                 :            : 
      48                 :            :         start = numa_alloc_onnode(size, numa_node);
      49                 :            :         if (!start)
      50                 :            :                 return NULL;
      51                 :            : 
      52                 :            :         memset(start, 0, size);
      53                 :            :         return start;
      54                 :            : }
      55                 :            : 
      56                 :            : static void
      57                 :            : env_free(void *start, size_t size)
      58                 :            : {
      59                 :            :         if ((numa_available() == -1) || !start)
      60                 :            :                 return;
      61                 :            : 
      62                 :            :         numa_free(start, size);
      63                 :            : }
      64                 :            : 
      65                 :            : #endif
      66                 :            : 
      67                 :            : #ifndef RTE_SWX_IPSEC_POOL_CACHE_SIZE
      68                 :            : #define RTE_SWX_IPSEC_POOL_CACHE_SIZE 256
      69                 :            : #endif
      70                 :            : 
      71                 :            : /* The two crypto device mempools have their size set to the number of SAs. The mempool API requires
      72                 :            :  * the mempool size to be at least 1.5 times the size of the mempool cache.
      73                 :            :  */
      74                 :            : #define N_SA_MIN (RTE_SWX_IPSEC_POOL_CACHE_SIZE * 1.5)
      75                 :            : 
      76                 :            : struct ipsec_sa {
      77                 :            :         struct rte_ipsec_session s;
      78                 :            :         int valid;
      79                 :            : };
      80                 :            : 
      81                 :            : struct ipsec_pkts_in {
      82                 :            :         struct rte_mbuf *pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      83                 :            :         struct ipsec_sa *sa[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      84                 :            :         struct rte_ipsec_group groups[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      85                 :            :         struct rte_crypto_op *group_cops[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      86                 :            :         struct rte_crypto_op *cops[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      87                 :            :         uint32_t n_cops;
      88                 :            : };
      89                 :            : 
      90                 :            : struct ipsec_pkts_out {
      91                 :            :         struct rte_crypto_op *cops[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      92                 :            :         struct rte_mbuf *group_pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      93                 :            :         struct rte_ipsec_group groups[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      94                 :            :         struct rte_mbuf *pkts[RTE_SWX_IPSEC_BURST_SIZE_MAX];
      95                 :            :         uint32_t n_pkts;
      96                 :            : };
      97                 :            : 
      98                 :            : struct rte_swx_ipsec {
      99                 :            :         /*
     100                 :            :          * Parameters.
     101                 :            :          */
     102                 :            : 
     103                 :            :         /* IPsec instance name. */
     104                 :            :         char name[RTE_SWX_IPSEC_NAME_SIZE];
     105                 :            : 
     106                 :            :         /* Input packet queue. */
     107                 :            :         struct rte_ring *ring_in;
     108                 :            : 
     109                 :            :         /* Output packet queue. */
     110                 :            :         struct rte_ring *ring_out;
     111                 :            : 
     112                 :            :         /* Crypto device ID. */
     113                 :            :         uint8_t dev_id;
     114                 :            : 
     115                 :            :         /* Crypto device queue pair ID. */
     116                 :            :         uint16_t qp_id;
     117                 :            : 
     118                 :            :         /* Burst sizes. */
     119                 :            :         struct rte_swx_ipsec_burst_size bsz;
     120                 :            : 
     121                 :            :         /* SA table size. */
     122                 :            :         size_t n_sa_max;
     123                 :            : 
     124                 :            :         /*
     125                 :            :          * Internals.
     126                 :            :          */
     127                 :            :         /* Crypto device buffer pool for sessions. */
     128                 :            :         struct rte_mempool *mp_session;
     129                 :            : 
     130                 :            :         /* Pre-crypto packets. */
     131                 :            :         struct ipsec_pkts_in in;
     132                 :            : 
     133                 :            :         /* Post-crypto packets. */
     134                 :            :         struct ipsec_pkts_out out;
     135                 :            : 
     136                 :            :         /* Crypto device enqueue threshold. */
     137                 :            :         uint32_t crypto_wr_threshold;
     138                 :            : 
     139                 :            :         /* Packets currently under crypto device processing. */
     140                 :            :         uint32_t n_pkts_crypto;
     141                 :            : 
     142                 :            :         /* List of free SADB positions. */
     143                 :            :         uint32_t *sa_free_id;
     144                 :            : 
     145                 :            :         /* Number of elements in the SADB list of free positions. */
     146                 :            :         size_t n_sa_free_id;
     147                 :            : 
     148                 :            :         /* Allocated memory total size in bytes. */
     149                 :            :         size_t total_size;
     150                 :            : 
     151                 :            :         /* Flag for registration to the global list of instances. */
     152                 :            :         int registered;
     153                 :            : 
     154                 :            :         /*
     155                 :            :          * Table memory.
     156                 :            :          */
     157                 :            :         uint8_t memory[] __rte_cache_aligned;
     158                 :            : };
     159                 :            : 
     160                 :            : static inline struct ipsec_sa *
     161                 :            : ipsec_sa_get(struct rte_swx_ipsec *ipsec, uint32_t sa_id)
     162                 :            : {
     163                 :          0 :         struct ipsec_sa *sadb = (struct ipsec_sa *)ipsec->memory;
     164                 :            : 
     165                 :          0 :         return &sadb[sa_id & (ipsec->n_sa_max - 1)];
     166                 :            : }
     167                 :            : 
     168                 :            : /* Global list of instances. */
     169                 :            : TAILQ_HEAD(rte_swx_ipsec_list, rte_tailq_entry);
     170                 :            : 
     171                 :            : static struct rte_tailq_elem rte_swx_ipsec_tailq = {
     172                 :            :         .name = "RTE_SWX_IPSEC",
     173                 :            : };
     174                 :            : 
     175         [ -  + ]:        235 : EAL_REGISTER_TAILQ(rte_swx_ipsec_tailq)
     176                 :            : 
     177                 :            : struct rte_swx_ipsec *
     178                 :          0 : rte_swx_ipsec_find(const char *name)
     179                 :            : {
     180                 :            :         struct rte_swx_ipsec_list *ipsec_list;
     181                 :            :         struct rte_tailq_entry *te = NULL;
     182                 :            : 
     183         [ #  # ]:          0 :         if (!name ||
     184         [ #  # ]:          0 :             !name[0] ||
     185         [ #  # ]:          0 :             (strnlen(name, RTE_SWX_IPSEC_NAME_SIZE) == RTE_SWX_IPSEC_NAME_SIZE))
     186                 :            :                 return NULL;
     187                 :            : 
     188                 :          0 :         ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list);
     189                 :            : 
     190                 :          0 :         rte_mcfg_tailq_read_lock();
     191                 :            : 
     192         [ #  # ]:          0 :         TAILQ_FOREACH(te, ipsec_list, next) {
     193                 :          0 :                 struct rte_swx_ipsec *ipsec = (struct rte_swx_ipsec *)te->data;
     194                 :            : 
     195         [ #  # ]:          0 :                 if (!strncmp(name, ipsec->name, sizeof(ipsec->name))) {
     196                 :          0 :                         rte_mcfg_tailq_read_unlock();
     197                 :          0 :                         return ipsec;
     198                 :            :                 }
     199                 :            :         }
     200                 :            : 
     201                 :          0 :         rte_mcfg_tailq_read_unlock();
     202                 :          0 :         return NULL;
     203                 :            : }
     204                 :            : 
     205                 :            : static int
     206                 :          0 : ipsec_register(struct rte_swx_ipsec *ipsec)
     207                 :            : {
     208                 :            :         struct rte_swx_ipsec_list *ipsec_list;
     209                 :            :         struct rte_tailq_entry *te = NULL;
     210                 :            : 
     211                 :          0 :         ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list);
     212                 :            : 
     213                 :          0 :         rte_mcfg_tailq_write_lock();
     214                 :            : 
     215         [ #  # ]:          0 :         TAILQ_FOREACH(te, ipsec_list, next) {
     216                 :          0 :                 struct rte_swx_ipsec *elem = (struct rte_swx_ipsec *)te->data;
     217                 :            : 
     218         [ #  # ]:          0 :                 if (!strncmp(ipsec->name, elem->name, sizeof(ipsec->name))) {
     219                 :          0 :                         rte_mcfg_tailq_write_unlock();
     220                 :          0 :                         return -EEXIST;
     221                 :            :                 }
     222                 :            :         }
     223                 :            : 
     224                 :          0 :         te = calloc(1, sizeof(struct rte_tailq_entry));
     225         [ #  # ]:          0 :         if (!te) {
     226                 :          0 :                 rte_mcfg_tailq_write_unlock();
     227                 :          0 :                 return -ENOMEM;
     228                 :            :         }
     229                 :            : 
     230                 :          0 :         te->data = (void *)ipsec;
     231                 :          0 :         TAILQ_INSERT_TAIL(ipsec_list, te, next);
     232                 :          0 :         rte_mcfg_tailq_write_unlock();
     233                 :          0 :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :            : static void
     237                 :          0 : ipsec_unregister(struct rte_swx_ipsec *ipsec)
     238                 :            : {
     239                 :            :         struct rte_swx_ipsec_list *ipsec_list;
     240                 :            :         struct rte_tailq_entry *te = NULL;
     241                 :            : 
     242                 :          0 :         ipsec_list = RTE_TAILQ_CAST(rte_swx_ipsec_tailq.head, rte_swx_ipsec_list);
     243                 :            : 
     244                 :          0 :         rte_mcfg_tailq_write_lock();
     245                 :            : 
     246         [ #  # ]:          0 :         TAILQ_FOREACH(te, ipsec_list, next) {
     247         [ #  # ]:          0 :                 if (te->data == (void *)ipsec) {
     248         [ #  # ]:          0 :                         TAILQ_REMOVE(ipsec_list, te, next);
     249                 :          0 :                         rte_mcfg_tailq_write_unlock();
     250                 :          0 :                         free(te);
     251                 :          0 :                         return;
     252                 :            :                 }
     253                 :            :         }
     254                 :            : 
     255                 :          0 :         rte_mcfg_tailq_write_unlock();
     256                 :            : }
     257                 :            : 
     258                 :            : static void
     259                 :            : ipsec_session_free(struct rte_swx_ipsec *ipsec, struct rte_ipsec_session *s);
     260                 :            : 
     261                 :            : void
     262                 :          0 : rte_swx_ipsec_free(struct rte_swx_ipsec *ipsec)
     263                 :            : {
     264                 :            :         size_t i;
     265                 :            : 
     266         [ #  # ]:          0 :         if (!ipsec)
     267                 :            :                 return;
     268                 :            : 
     269                 :            :         /* Remove the current instance from the global list. */
     270         [ #  # ]:          0 :         if (ipsec->registered)
     271                 :          0 :                 ipsec_unregister(ipsec);
     272                 :            : 
     273                 :            :         /* SADB. */
     274         [ #  # ]:          0 :         for (i = 0; i < ipsec->n_sa_max; i++) {
     275                 :            :                 struct ipsec_sa *sa = ipsec_sa_get(ipsec, i);
     276                 :            : 
     277         [ #  # ]:          0 :                 if (!sa->valid)
     278                 :          0 :                         continue;
     279                 :            : 
     280                 :            :                 /* SA session. */
     281                 :          0 :                 ipsec_session_free(ipsec, &sa->s);
     282                 :            :         }
     283                 :            : 
     284                 :            :         /* Crypto device buffer pools. */
     285                 :          0 :         rte_mempool_free(ipsec->mp_session);
     286                 :            : 
     287                 :            :         /* IPsec object memory. */
     288                 :            :         env_free(ipsec, ipsec->total_size);
     289                 :            : }
     290                 :            : 
     291                 :            : int
     292                 :          0 : rte_swx_ipsec_create(struct rte_swx_ipsec **ipsec_out,
     293                 :            :                      const char *name,
     294                 :            :                      struct rte_swx_ipsec_params *params,
     295                 :            :                      int numa_node)
     296                 :            : {
     297                 :            :         char resource_name[RTE_SWX_IPSEC_NAME_SIZE];
     298                 :            :         struct rte_swx_ipsec *ipsec = NULL;
     299                 :            :         struct rte_ring *ring_in, *ring_out;
     300                 :            :         struct rte_cryptodev_info dev_info;
     301                 :            :         size_t n_sa_max, sadb_offset, sadb_size, sa_free_id_offset, sa_free_id_size, total_size, i;
     302                 :            :         uint32_t dev_session_size;
     303                 :            :         int dev_id, status = 0;
     304                 :            : 
     305                 :            :         /* Check input parameters. */
     306                 :          0 :         if (!ipsec_out ||
     307         [ #  # ]:          0 :             !name ||
     308         [ #  # ]:          0 :             !name[0] ||
     309   [ #  #  #  # ]:          0 :             (strnlen((name), RTE_SWX_IPSEC_NAME_SIZE) == RTE_SWX_IPSEC_NAME_SIZE) ||
     310                 :          0 :             !params ||
     311         [ #  # ]:          0 :             (params->bsz.ring_rd > RTE_SWX_IPSEC_BURST_SIZE_MAX) ||
     312         [ #  # ]:          0 :             (params->bsz.ring_wr > RTE_SWX_IPSEC_BURST_SIZE_MAX) ||
     313         [ #  # ]:          0 :             (params->bsz.crypto_wr > RTE_SWX_IPSEC_BURST_SIZE_MAX) ||
     314         [ #  # ]:          0 :             (params->bsz.crypto_rd > RTE_SWX_IPSEC_BURST_SIZE_MAX) ||
     315         [ #  # ]:          0 :             !params->n_sa_max) {
     316                 :            :                 status = -EINVAL;
     317                 :          0 :                 goto error;
     318                 :            :         }
     319                 :            : 
     320                 :          0 :         ring_in = rte_ring_lookup(params->ring_in_name);
     321         [ #  # ]:          0 :         if (!ring_in) {
     322                 :            :                 status = -EINVAL;
     323                 :          0 :                 goto error;
     324                 :            :         }
     325                 :            : 
     326                 :          0 :         ring_out = rte_ring_lookup(params->ring_out_name);
     327         [ #  # ]:          0 :         if (!ring_out) {
     328                 :            :                 status = -EINVAL;
     329                 :          0 :                 goto error;
     330                 :            :         }
     331                 :            : 
     332                 :          0 :         dev_id = rte_cryptodev_get_dev_id(params->crypto_dev_name);
     333         [ #  # ]:          0 :         if (dev_id == -1) {
     334                 :            :                 status = -EINVAL;
     335                 :          0 :                 goto error;
     336                 :            :         }
     337                 :            : 
     338                 :          0 :         rte_cryptodev_info_get(dev_id, &dev_info);
     339         [ #  # ]:          0 :         if (params->crypto_dev_queue_pair_id >= dev_info.max_nb_queue_pairs) {
     340                 :            :                 status = -EINVAL;
     341                 :          0 :                 goto error;
     342                 :            :         }
     343                 :            : 
     344                 :            :         /* Memory allocation. */
     345         [ #  # ]:          0 :         n_sa_max = rte_align64pow2(RTE_MAX(params->n_sa_max, N_SA_MIN));
     346                 :            : 
     347                 :            :         sadb_offset = sizeof(struct rte_swx_ipsec);
     348                 :          0 :         sadb_size = RTE_CACHE_LINE_ROUNDUP(n_sa_max * sizeof(struct ipsec_sa));
     349                 :            : 
     350                 :          0 :         sa_free_id_offset = sadb_offset + sadb_size;
     351                 :          0 :         sa_free_id_size = RTE_CACHE_LINE_ROUNDUP(n_sa_max * sizeof(uint32_t));
     352                 :            : 
     353                 :          0 :         total_size = sa_free_id_offset + sa_free_id_size;
     354                 :            :         ipsec = env_calloc(total_size, RTE_CACHE_LINE_SIZE, numa_node);
     355         [ #  # ]:          0 :         if (!ipsec) {
     356                 :            :                 status = -ENOMEM;
     357                 :          0 :                 goto error;
     358                 :            :         }
     359                 :            : 
     360                 :            :         /* Initialization. */
     361                 :          0 :         strcpy(ipsec->name, name);
     362                 :          0 :         ipsec->ring_in = ring_in;
     363                 :          0 :         ipsec->ring_out = ring_out;
     364                 :          0 :         ipsec->dev_id = (uint8_t)dev_id;
     365                 :          0 :         ipsec->qp_id = params->crypto_dev_queue_pair_id;
     366                 :          0 :         memcpy(&ipsec->bsz, &params->bsz, sizeof(struct rte_swx_ipsec_burst_size));
     367                 :          0 :         ipsec->n_sa_max = n_sa_max;
     368                 :            : 
     369                 :          0 :         ipsec->crypto_wr_threshold = params->bsz.crypto_wr * 3 / 4;
     370                 :            : 
     371                 :          0 :         ipsec->sa_free_id = (uint32_t *)&ipsec->memory[sa_free_id_offset];
     372         [ #  # ]:          0 :         for (i = 0; i < n_sa_max; i++)
     373                 :          0 :                 ipsec->sa_free_id[i] = n_sa_max - 1 - i;
     374                 :          0 :         ipsec->n_sa_free_id = n_sa_max;
     375                 :            : 
     376                 :          0 :         ipsec->total_size = total_size;
     377                 :            : 
     378                 :            :         /* Crypto device memory pools. */
     379                 :          0 :         dev_session_size = rte_cryptodev_sym_get_private_session_size((uint8_t)dev_id);
     380                 :            : 
     381                 :            :         snprintf(resource_name, sizeof(resource_name), "%s_mp", name);
     382                 :          0 :         ipsec->mp_session = rte_cryptodev_sym_session_pool_create(resource_name,
     383                 :            :                 n_sa_max, /* number of pool elements */
     384                 :            :                 dev_session_size, /* pool element size */
     385                 :            :                 RTE_SWX_IPSEC_POOL_CACHE_SIZE, /* pool cache size */
     386                 :            :                 0, /* pool element private data size */
     387                 :            :                 numa_node);
     388         [ #  # ]:          0 :         if (!ipsec->mp_session) {
     389                 :            :                 status = -ENOMEM;
     390                 :          0 :                 goto error;
     391                 :            :         }
     392                 :            : 
     393                 :            :         /* Add the current instance to the global list. */
     394                 :          0 :         status = ipsec_register(ipsec);
     395         [ #  # ]:          0 :         if (status)
     396                 :          0 :                 goto error;
     397                 :            : 
     398                 :          0 :         ipsec->registered = 1;
     399                 :            : 
     400                 :          0 :         *ipsec_out = ipsec;
     401                 :          0 :         return 0;
     402                 :            : 
     403                 :          0 : error:
     404                 :          0 :         rte_swx_ipsec_free(ipsec);
     405                 :          0 :         return status;
     406                 :            : }
     407                 :            : 
     408                 :            : static inline int
     409                 :            : ipsec_sa_group(struct rte_swx_ipsec *ipsec, int n_pkts)
     410                 :            : {
     411                 :            :         struct ipsec_sa *sa;
     412                 :            :         struct rte_ipsec_group *g;
     413                 :            :         int n_groups, n_pkts_in_group, i;
     414                 :            : 
     415                 :          0 :         sa = ipsec->in.sa[0];
     416                 :            : 
     417                 :          0 :         g = &ipsec->in.groups[0];
     418                 :          0 :         g->id.ptr = sa;
     419                 :          0 :         g->m = &ipsec->in.pkts[0];
     420                 :            :         n_pkts_in_group = 1;
     421                 :            :         n_groups = 1;
     422                 :            : 
     423         [ #  # ]:          0 :         for (i = 1; i < n_pkts; i++) {
     424                 :          0 :                 struct ipsec_sa *sa_new = ipsec->in.sa[i];
     425                 :            : 
     426                 :            :                 /* Same SA => Add the current pkt to the same group. */
     427         [ #  # ]:          0 :                 if (sa_new == sa) {
     428                 :          0 :                         n_pkts_in_group++;
     429                 :          0 :                         continue;
     430                 :            :                 }
     431                 :            : 
     432                 :            :                 /* Different SA => Close the current group & add the current pkt to a new group. */
     433                 :          0 :                 g->cnt = n_pkts_in_group;
     434                 :            :                 sa = sa_new;
     435                 :            : 
     436                 :          0 :                 g++;
     437                 :          0 :                 g->id.ptr = sa;
     438                 :          0 :                 g->m = &ipsec->in.pkts[i];
     439                 :            :                 n_pkts_in_group = 1;
     440                 :          0 :                 n_groups++;
     441                 :            :         }
     442                 :            : 
     443                 :            :         /* Close the last group. */
     444                 :          0 :         g->cnt = n_pkts_in_group;
     445                 :            : 
     446                 :            :         return n_groups;
     447                 :            : }
     448                 :            : 
     449                 :            : static inline void
     450                 :          0 : ipsec_crypto_enqueue(struct rte_swx_ipsec *ipsec, uint16_t n_cops)
     451                 :            : {
     452                 :          0 :         struct rte_crypto_op **dst0 = ipsec->in.cops, **dst;
     453                 :          0 :         struct rte_crypto_op **src = ipsec->in.group_cops;
     454                 :            : 
     455                 :          0 :         uint32_t n_pkts_crypto = ipsec->n_pkts_crypto;
     456                 :          0 :         uint32_t n_dst = ipsec->in.n_cops;
     457                 :          0 :         uint32_t n_dst_max = ipsec->bsz.crypto_wr;
     458                 :          0 :         uint32_t n_dst_avail = n_dst_max - n_dst;
     459                 :          0 :         uint32_t n_src = n_cops;
     460                 :            :         uint32_t i;
     461                 :            : 
     462                 :          0 :         dst = &dst0[n_dst];
     463                 :            : 
     464                 :            :         /* Shortcut: If no elements in DST and enough elements in SRC, then simply use SRC directly
     465                 :            :          * instead of moving the SRC to DST first and then using DST.
     466                 :            :          */
     467   [ #  #  #  # ]:          0 :         if (!n_dst && n_src >= ipsec->crypto_wr_threshold) {
     468                 :            :                 uint16_t n_ok;
     469                 :            : 
     470                 :          0 :                 n_ok = rte_cryptodev_enqueue_burst(ipsec->dev_id, ipsec->qp_id, src, n_src);
     471                 :          0 :                 ipsec->n_pkts_crypto = n_pkts_crypto + n_ok;
     472                 :            : 
     473         [ #  # ]:          0 :                 for (i = n_ok; i < n_src; i++) {
     474                 :          0 :                         struct rte_crypto_op *cop = src[i];
     475                 :          0 :                         struct rte_mbuf *m = cop->sym->m_src;
     476                 :            : 
     477                 :          0 :                         rte_pktmbuf_free(m);
     478                 :            :                 }
     479                 :            : 
     480                 :            :                 return;
     481                 :            :         }
     482                 :            : 
     483                 :            :         /* Move from SRC to DST. Every time DST gets full, send burst from DST. */
     484         [ #  # ]:          0 :         for ( ; n_src >= n_dst_avail; ) {
     485                 :            :                 uint32_t n_ok;
     486                 :            : 
     487                 :            :                 /* Move from SRC to DST. */
     488         [ #  # ]:          0 :                 for (i = 0; i < n_dst_avail; i++)
     489                 :          0 :                         *dst++ = *src++;
     490                 :            : 
     491                 :          0 :                 n_src -= n_dst_avail;
     492                 :            : 
     493                 :            :                 /* DST full: send burst from DST. */
     494                 :          0 :                 n_ok = rte_cryptodev_enqueue_burst(ipsec->dev_id, ipsec->qp_id, dst0, n_dst_max);
     495                 :          0 :                 n_pkts_crypto += n_ok;
     496                 :            : 
     497         [ #  # ]:          0 :                 for (i = n_ok ; i < n_dst_max; i++) {
     498                 :          0 :                         struct rte_crypto_op *cop = dst0[i];
     499                 :          0 :                         struct rte_mbuf *m = cop->sym->m_src;
     500                 :            : 
     501                 :          0 :                         rte_pktmbuf_free(m);
     502                 :            :                 }
     503                 :            : 
     504                 :            :                 /* Next iteration. */
     505                 :            :                 dst = dst0;
     506                 :            :                 n_dst = 0;
     507                 :            :                 n_dst_avail = n_dst_max;
     508                 :            :         }
     509                 :            : 
     510                 :          0 :         ipsec->n_pkts_crypto = n_pkts_crypto;
     511                 :            : 
     512                 :            :         /* Move from SRC to DST. Not enough elements in SRC to get DST full. */
     513         [ #  # ]:          0 :         for (i = 0; i < n_src; i++)
     514                 :          0 :                 *dst++ = *src++;
     515                 :            : 
     516                 :          0 :         n_dst += n_src;
     517                 :            : 
     518                 :          0 :         ipsec->in.n_cops = n_dst;
     519                 :            : }
     520                 :            : 
     521                 :            : /**
     522                 :            :  * Packet buffer anatomy:
     523                 :            :  *
     524                 :            :  * +----------+---------+--------------------------------------------------------------------------+
     525                 :            :  * | Offset   | Size    | Description                                                              |
     526                 :            :  * | (Byte #) | (Bytes) |                                                                          |
     527                 :            :  * +==========+=========+==========================================================================+
     528                 :            :  * | 0        | 128     | Meta-data: struct rte_mbuf.                                              |
     529                 :            :  * |          |         | The buf_addr field points to the start of the packet section.            |
     530                 :            :  * +----------+---------+--------------------------------------------------------------------------+
     531                 :            :  * | 128      | 128     | Meta-data: struct ipsec_mbuf (see below).                                |
     532                 :            :  * +----------+---------+--------------------------------------------------------------------------+
     533                 :            :  * | 256      |         | Packet section.                                                          |
     534                 :            :  * |          |         | The first packet byte is placed at the offset indicated by the struct    |
     535                 :            :  * |          |         | rte_mbuf::data_off field relative to the start of the packet section.    |
     536                 :            :  * +----------+---------+--------------------------------------------------------------------------+
     537                 :            :  */
     538                 :            : struct ipsec_mbuf {
     539                 :            :         struct ipsec_sa *sa;
     540                 :            :         struct rte_crypto_op cop;
     541                 :            :         struct rte_crypto_sym_op sym_cop;
     542                 :            :         uint8_t buffer[32]; /* The crypto IV is placed here. */
     543                 :            : };
     544                 :            : 
     545                 :            : /* Offset from the start of the struct ipsec_mbuf::cop where the crypto IV will be placed. */
     546                 :            : #define IV_OFFSET (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
     547                 :            : 
     548                 :            : #define META_LENGTH sizeof(struct rte_swx_ipsec_input_packet_metadata)
     549                 :            : 
     550                 :            : static inline void
     551                 :          0 : rte_swx_ipsec_pre_crypto(struct rte_swx_ipsec *ipsec)
     552                 :            : {
     553                 :            :         int n_pkts, n_groups, i;
     554                 :            : 
     555                 :            :         /* Read packets from the input ring. */
     556                 :          0 :         n_pkts = rte_ring_sc_dequeue_burst(ipsec->ring_in,
     557                 :          0 :                                            (void **)ipsec->in.pkts,
     558                 :            :                                            ipsec->bsz.ring_rd,
     559                 :            :                                            NULL);
     560         [ #  # ]:          0 :         if (!n_pkts)
     561                 :            :                 return;
     562                 :            : 
     563                 :            :         /* Get the SA for each packet. */
     564         [ #  # ]:          0 :         for (i = 0; i < n_pkts; i++) {
     565                 :          0 :                 struct rte_mbuf *m = ipsec->in.pkts[i];
     566                 :            :                 struct rte_swx_ipsec_input_packet_metadata *meta;
     567                 :            :                 struct rte_ipv4_hdr *ipv4_hdr;
     568                 :            :                 uint32_t sa_id;
     569                 :            : 
     570                 :          0 :                 meta = rte_pktmbuf_mtod(m, struct rte_swx_ipsec_input_packet_metadata *);
     571                 :          0 :                 ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, META_LENGTH);
     572                 :            : 
     573                 :            :                 /* Read the SA ID from the IPsec meta-data placed at the front of the IP packet. */
     574         [ #  # ]:          0 :                 sa_id = ntohl(meta->sa_id);
     575                 :            : 
     576                 :            :                 /* Consume the IPsec meta-data. */
     577                 :          0 :                 m->data_off += META_LENGTH;
     578                 :          0 :                 m->data_len -= META_LENGTH;
     579                 :          0 :                 m->pkt_len -= META_LENGTH;
     580                 :            : 
     581                 :            :                 /* Set the fields required by the IPsec library. */
     582                 :          0 :                 m->l2_len = 0;
     583                 :          0 :                 m->l3_len = (ipv4_hdr->version_ihl >> 4 == 4) ?
     584         [ #  # ]:          0 :                         sizeof(struct rte_ipv4_hdr) :
     585                 :            :                         sizeof(struct rte_ipv6_hdr);
     586                 :            : 
     587                 :            :                 /* Get the SA. */
     588                 :          0 :                 ipsec->in.sa[i] = ipsec_sa_get(ipsec, sa_id);
     589                 :            :         }
     590                 :            : 
     591                 :            :         /* Group packets that share the same SA. */
     592                 :            :         n_groups = ipsec_sa_group(ipsec, n_pkts);
     593                 :            : 
     594                 :            :         /* Write each group of packets sharing the same SA to the crypto device. */
     595         [ #  # ]:          0 :         for (i = 0; i < n_groups; i++) {
     596                 :            :                 struct rte_ipsec_group *g = &ipsec->in.groups[i];
     597                 :          0 :                 struct ipsec_sa *sa = g->id.ptr;
     598                 :          0 :                 struct rte_ipsec_session *s = &sa->s;
     599                 :            :                 uint32_t j;
     600                 :            :                 uint16_t n_pkts_ok;
     601                 :            : 
     602                 :            :                 /* Prepare the crypto ops for the current group. */
     603         [ #  # ]:          0 :                 for (j = 0; j < g->cnt; j++) {
     604                 :          0 :                         struct rte_mbuf *m = g->m[j];
     605                 :            :                         struct ipsec_mbuf *priv = rte_mbuf_to_priv(m);
     606                 :            : 
     607                 :          0 :                         priv->sa = sa;
     608                 :          0 :                         ipsec->in.group_cops[j] = &priv->cop;
     609                 :            :                 }
     610                 :            : 
     611                 :          0 :                 n_pkts_ok = rte_ipsec_pkt_crypto_prepare(s, g->m, ipsec->in.group_cops, g->cnt);
     612                 :            : 
     613         [ #  # ]:          0 :                 for (j = n_pkts_ok; j < g->cnt; j++) {
     614                 :          0 :                         struct rte_mbuf *m = g->m[j];
     615                 :            : 
     616                 :          0 :                         rte_pktmbuf_free(m);
     617                 :            :                 }
     618                 :            : 
     619                 :            :                 /* Write the crypto ops of the current group to the crypto device. */
     620                 :          0 :                 ipsec_crypto_enqueue(ipsec, n_pkts_ok);
     621                 :            :         }
     622                 :            : }
     623                 :            : 
     624                 :            : static inline void
     625                 :          0 : ipsec_ring_enqueue(struct rte_swx_ipsec *ipsec, struct rte_ipsec_group *g, uint32_t n_pkts)
     626                 :            : {
     627                 :          0 :         struct rte_mbuf **dst0 = ipsec->out.pkts, **dst;
     628                 :          0 :         struct rte_mbuf **src = g->m;
     629                 :            : 
     630                 :          0 :         uint32_t n_dst = ipsec->out.n_pkts;
     631                 :          0 :         uint32_t n_dst_max = ipsec->bsz.ring_wr;
     632                 :          0 :         uint32_t n_dst_avail = n_dst_max - n_dst;
     633                 :            :         uint32_t n_src = n_pkts;
     634                 :            :         uint32_t i;
     635                 :            : 
     636                 :          0 :         dst = &dst0[n_dst];
     637                 :            : 
     638                 :            :         /* Move from SRC to DST. Every time DST gets full, send burst from DST. */
     639         [ #  # ]:          0 :         for ( ; n_src >= n_dst_avail; ) {
     640                 :            :                 uint32_t n_ok;
     641                 :            : 
     642                 :            :                 /* Move from SRC to DST. */
     643         [ #  # ]:          0 :                 for (i = 0; i < n_dst_avail; i++)
     644                 :          0 :                         *dst++ = *src++;
     645                 :            : 
     646                 :          0 :                 n_src -= n_dst_avail;
     647                 :            : 
     648                 :            :                 /* DST full: send burst from DST. */
     649                 :          0 :                 n_ok = rte_ring_sp_enqueue_burst(ipsec->ring_out, (void **)dst0, n_dst_max, NULL);
     650                 :            : 
     651         [ #  # ]:          0 :                 for (i = n_ok ; i < n_dst_max; i++) {
     652                 :          0 :                         struct rte_mbuf *m = dst[i];
     653                 :            : 
     654                 :          0 :                         rte_pktmbuf_free(m);
     655                 :            :                 }
     656                 :            : 
     657                 :            :                 /* Next iteration. */
     658                 :            :                 dst = dst0;
     659                 :            :                 n_dst = 0;
     660                 :            :                 n_dst_avail = n_dst_max;
     661                 :            :         }
     662                 :            : 
     663                 :            :         /* Move from SRC to DST. Not enough elements in SRC to get DST full. */
     664         [ #  # ]:          0 :         for (i = 0; i < n_src; i++)
     665                 :          0 :                 *dst++ = *src++;
     666                 :            : 
     667                 :          0 :         n_dst += n_src;
     668                 :            : 
     669                 :          0 :         ipsec->out.n_pkts = n_dst;
     670                 :          0 : }
     671                 :            : 
     672                 :            : static inline void
     673                 :          0 : rte_swx_ipsec_post_crypto(struct rte_swx_ipsec *ipsec)
     674                 :            : {
     675                 :          0 :         uint32_t n_pkts_crypto = ipsec->n_pkts_crypto, n_pkts, ng, i;
     676                 :            : 
     677                 :            :         /* Read the crypto ops from the crypto device. */
     678         [ #  # ]:          0 :         if (!n_pkts_crypto)
     679                 :            :                 return;
     680                 :            : 
     681                 :          0 :         n_pkts = rte_cryptodev_dequeue_burst(ipsec->dev_id,
     682                 :          0 :                                              ipsec->qp_id,
     683                 :          0 :                                              ipsec->out.cops,
     684                 :          0 :                                              ipsec->bsz.crypto_rd);
     685         [ #  # ]:          0 :         if (!n_pkts)
     686                 :            :                 return;
     687                 :            : 
     688                 :          0 :         ipsec->n_pkts_crypto = n_pkts_crypto - n_pkts;
     689                 :            : 
     690                 :            :         /* Group packets that share the same SA. */
     691                 :          0 :         ng = rte_ipsec_pkt_crypto_group((const struct rte_crypto_op **)(uintptr_t)ipsec->out.cops,
     692                 :          0 :                                               ipsec->out.group_pkts,
     693                 :          0 :                                               ipsec->out.groups,
     694                 :            :                                               n_pkts);
     695                 :            : 
     696                 :            :         /* Perform post-crypto IPsec processing for each group of packets that share the same SA.
     697                 :            :          * Write each group of packets to the output ring.
     698                 :            :          */
     699         [ #  # ]:          0 :         for (i = 0, n_pkts = 0; i < ng; i++) {
     700                 :          0 :                 struct rte_ipsec_group *g = &ipsec->out.groups[i];
     701                 :          0 :                 struct rte_ipsec_session *s = g->id.ptr;
     702                 :            :                 uint32_t n_pkts_ok, j;
     703                 :            : 
     704                 :            :                 /* Perform post-crypto IPsec processing for the current group. */
     705                 :          0 :                 n_pkts_ok = rte_ipsec_pkt_process(s, g->m, g->cnt);
     706                 :            : 
     707         [ #  # ]:          0 :                 for (j = n_pkts_ok; j < g->cnt; j++) {
     708                 :          0 :                         struct rte_mbuf *m = g->m[j];
     709                 :            : 
     710                 :          0 :                         rte_pktmbuf_free(m);
     711                 :            :                 }
     712                 :            : 
     713                 :            :                 /* Write the packets of the current group to the output ring. */
     714                 :          0 :                 ipsec_ring_enqueue(ipsec, g, n_pkts_ok);
     715                 :            :         }
     716                 :            : }
     717                 :            : 
     718                 :            : void
     719                 :          0 : rte_swx_ipsec_run(struct rte_swx_ipsec *ipsec)
     720                 :            : {
     721                 :          0 :         rte_swx_ipsec_pre_crypto(ipsec);
     722                 :          0 :         rte_swx_ipsec_post_crypto(ipsec);
     723                 :          0 : }
     724                 :            : 
     725                 :            : /**
     726                 :            :  * IPsec Control Plane API
     727                 :            :  */
     728                 :            : struct cipher_alg {
     729                 :            :         const char *name;
     730                 :            :         enum rte_crypto_cipher_algorithm alg;
     731                 :            :         uint32_t iv_size;
     732                 :            :         uint32_t block_size;
     733                 :            :         uint32_t key_size;
     734                 :            : };
     735                 :            : 
     736                 :            : struct auth_alg {
     737                 :            :         const char *name;
     738                 :            :         enum rte_crypto_auth_algorithm alg;
     739                 :            :         uint32_t iv_size;
     740                 :            :         uint32_t digest_size;
     741                 :            :         uint32_t key_size;
     742                 :            : };
     743                 :            : 
     744                 :            : struct aead_alg {
     745                 :            :         const char *name;
     746                 :            :         enum rte_crypto_aead_algorithm alg;
     747                 :            :         uint32_t iv_size;
     748                 :            :         uint32_t block_size;
     749                 :            :         uint32_t digest_size;
     750                 :            :         uint32_t key_size;
     751                 :            :         uint32_t aad_size;
     752                 :            : };
     753                 :            : 
     754                 :            : static struct cipher_alg cipher_algs[] = {
     755                 :            :         [0] = {
     756                 :            :                 .name = "null",
     757                 :            :                 .alg = RTE_CRYPTO_CIPHER_NULL,
     758                 :            :                 .iv_size = 0,
     759                 :            :                 .block_size = 4,
     760                 :            :                 .key_size = 0,
     761                 :            :         },
     762                 :            : 
     763                 :            :         [1] = {
     764                 :            :                 .name = "aes-cbc-128",
     765                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CBC,
     766                 :            :                 .iv_size = 16,
     767                 :            :                 .block_size = 16,
     768                 :            :                 .key_size = 16,
     769                 :            :         },
     770                 :            : 
     771                 :            :         [2] = {
     772                 :            :                 .name = "aes-cbc-192",
     773                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CBC,
     774                 :            :                 .iv_size = 16,
     775                 :            :                 .block_size = 16,
     776                 :            :                 .key_size = 24,
     777                 :            :         },
     778                 :            : 
     779                 :            :         [3] = {
     780                 :            :                 .name = "aes-cbc-256",
     781                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CBC,
     782                 :            :                 .iv_size = 16,
     783                 :            :                 .block_size = 16,
     784                 :            :                 .key_size = 32,
     785                 :            :         },
     786                 :            : 
     787                 :            :         [4] = {
     788                 :            :                 .name = "aes-ctr-128",
     789                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CTR,
     790                 :            :                 .iv_size = 8,
     791                 :            :                 .block_size = 4,
     792                 :            :                 .key_size = 20,
     793                 :            :         },
     794                 :            : 
     795                 :            :         [5] = {
     796                 :            :                 .name = "aes-ctr-192",
     797                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CTR,
     798                 :            :                 .iv_size = 16,
     799                 :            :                 .block_size = 16,
     800                 :            :                 .key_size = 28,
     801                 :            :         },
     802                 :            : 
     803                 :            :         [6] = {
     804                 :            :                 .name = "aes-ctr-256",
     805                 :            :                 .alg = RTE_CRYPTO_CIPHER_AES_CTR,
     806                 :            :                 .iv_size = 16,
     807                 :            :                 .block_size = 16,
     808                 :            :                 .key_size = 36,
     809                 :            :         },
     810                 :            : 
     811                 :            :         [7] = {
     812                 :            :                 .name = "3des-cbc",
     813                 :            :                 .alg = RTE_CRYPTO_CIPHER_3DES_CBC,
     814                 :            :                 .iv_size = 8,
     815                 :            :                 .block_size = 8,
     816                 :            :                 .key_size = 24,
     817                 :            :         },
     818                 :            : 
     819                 :            :         [8] = {
     820                 :            :                 .name = "des-cbc",
     821                 :            :                 .alg = RTE_CRYPTO_CIPHER_DES_CBC,
     822                 :            :                 .iv_size = 8,
     823                 :            :                 .block_size = 8,
     824                 :            :                 .key_size = 8,
     825                 :            :         },
     826                 :            : };
     827                 :            : 
     828                 :            : static struct auth_alg auth_algs[] = {
     829                 :            :         [0] = {
     830                 :            :                 .name = "null",
     831                 :            :                 .alg = RTE_CRYPTO_AUTH_NULL,
     832                 :            :                 .iv_size = 0,
     833                 :            :                 .digest_size = 0,
     834                 :            :                 .key_size = 0,
     835                 :            :         },
     836                 :            : 
     837                 :            :         [1] = {
     838                 :            :                 .name = "sha1-hmac",
     839                 :            :                 .alg = RTE_CRYPTO_AUTH_SHA1_HMAC,
     840                 :            :                 .iv_size = 0,
     841                 :            :                 .digest_size = 12,
     842                 :            :                 .key_size = 20,
     843                 :            :         },
     844                 :            : 
     845                 :            :         [2] = {
     846                 :            :                 .name = "sha256-hmac",
     847                 :            :                 .alg = RTE_CRYPTO_AUTH_SHA256_HMAC,
     848                 :            :                 .iv_size = 0,
     849                 :            :                 .digest_size = 16,
     850                 :            :                 .key_size = 32,
     851                 :            :         },
     852                 :            : 
     853                 :            :         [3] = {
     854                 :            :                 .name = "sha384-hmac",
     855                 :            :                 .alg = RTE_CRYPTO_AUTH_SHA384_HMAC,
     856                 :            :                 .iv_size = 0,
     857                 :            :                 .digest_size = 24,
     858                 :            :                 .key_size = 48,
     859                 :            :         },
     860                 :            : 
     861                 :            :         [4] = {
     862                 :            :                 .name = "sha512-hmac",
     863                 :            :                 .alg = RTE_CRYPTO_AUTH_SHA512_HMAC,
     864                 :            :                 .iv_size = 0,
     865                 :            :                 .digest_size = 32,
     866                 :            :                 .key_size = 64,
     867                 :            :         },
     868                 :            : 
     869                 :            :         [5] = {
     870                 :            :                 .name = "aes-gmac",
     871                 :            :                 .alg = RTE_CRYPTO_AUTH_AES_GMAC,
     872                 :            :                 .iv_size = 8,
     873                 :            :                 .digest_size = 16,
     874                 :            :                 .key_size = 20,
     875                 :            :         },
     876                 :            : 
     877                 :            :         [6] = {
     878                 :            :                 .name = "aes-xcbc-mac-96",
     879                 :            :                 .alg = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
     880                 :            :                 .iv_size = 0,
     881                 :            :                 .digest_size = 12,
     882                 :            :                 .key_size = 16,
     883                 :            :         },
     884                 :            : };
     885                 :            : 
     886                 :            : static struct aead_alg aead_algs[] = {
     887                 :            :         [0] = {
     888                 :            :                 .name = "aes-gcm-128",
     889                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_GCM,
     890                 :            :                 .iv_size = 8,
     891                 :            :                 .block_size = 4,
     892                 :            :                 .key_size = 20,
     893                 :            :                 .digest_size = 16,
     894                 :            :                 .aad_size = 8,
     895                 :            :         },
     896                 :            : 
     897                 :            :         [1] = {
     898                 :            :                 .name = "aes-gcm-192",
     899                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_GCM,
     900                 :            :                 .iv_size = 8,
     901                 :            :                 .block_size = 4,
     902                 :            :                 .key_size = 28,
     903                 :            :                 .digest_size = 16,
     904                 :            :                 .aad_size = 8,
     905                 :            :         },
     906                 :            : 
     907                 :            :         [2] = {
     908                 :            :                 .name = "aes-gcm-256",
     909                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_GCM,
     910                 :            :                 .iv_size = 8,
     911                 :            :                 .block_size = 4,
     912                 :            :                 .key_size = 36,
     913                 :            :                 .digest_size = 16,
     914                 :            :                 .aad_size = 8,
     915                 :            :         },
     916                 :            : 
     917                 :            :         [3] = {
     918                 :            :                 .name = "aes-ccm-128",
     919                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_CCM,
     920                 :            :                 .iv_size = 8,
     921                 :            :                 .block_size = 4,
     922                 :            :                 .key_size = 20,
     923                 :            :                 .digest_size = 16,
     924                 :            :                 .aad_size = 8,
     925                 :            :         },
     926                 :            : 
     927                 :            :         [4] = {
     928                 :            :                 .name = "aes-ccm-192",
     929                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_CCM,
     930                 :            :                 .iv_size = 8,
     931                 :            :                 .block_size = 4,
     932                 :            :                 .key_size = 28,
     933                 :            :                 .digest_size = 16,
     934                 :            :                 .aad_size = 8,
     935                 :            :         },
     936                 :            : 
     937                 :            :         [5] = {
     938                 :            :                 .name = "aes-ccm-256",
     939                 :            :                 .alg = RTE_CRYPTO_AEAD_AES_CCM,
     940                 :            :                 .iv_size = 8,
     941                 :            :                 .block_size = 4,
     942                 :            :                 .key_size = 36,
     943                 :            :                 .digest_size = 16,
     944                 :            :                 .aad_size = 8,
     945                 :            :         },
     946                 :            : 
     947                 :            :         [6] = {
     948                 :            :                 .name = "chacha20-poly1305",
     949                 :            :                 .alg = RTE_CRYPTO_AEAD_CHACHA20_POLY1305,
     950                 :            :                 .iv_size = 12,
     951                 :            :                 .block_size = 64,
     952                 :            :                 .key_size = 36,
     953                 :            :                 .digest_size = 16,
     954                 :            :                 .aad_size = 8,
     955                 :            :         },
     956                 :            : };
     957                 :            : 
     958                 :            : static struct cipher_alg *
     959                 :          0 : cipher_alg_find(const char *name)
     960                 :            : {
     961                 :            :         size_t i;
     962                 :            : 
     963         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(cipher_algs); i++) {
     964                 :          0 :                 struct cipher_alg *alg = &cipher_algs[i];
     965                 :            : 
     966         [ #  # ]:          0 :                 if (!strcmp(name, alg->name))
     967                 :          0 :                         return alg;
     968                 :            :         }
     969                 :            : 
     970                 :            :         return NULL;
     971                 :            : }
     972                 :            : 
     973                 :            : static struct cipher_alg *
     974                 :            : cipher_alg_find_by_id(enum rte_crypto_cipher_algorithm alg_id, uint32_t key_size)
     975                 :            : {
     976                 :            :         size_t i;
     977                 :            : 
     978         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(cipher_algs); i++) {
     979                 :          0 :                 struct cipher_alg *alg = &cipher_algs[i];
     980                 :            : 
     981   [ #  #  #  # ]:          0 :                 if (alg->alg == alg_id && alg->key_size == key_size)
     982                 :            :                         return alg;
     983                 :            :         }
     984                 :            : 
     985                 :            :         return NULL;
     986                 :            : }
     987                 :            : 
     988                 :            : static struct auth_alg *
     989                 :          0 : auth_alg_find(const char *name)
     990                 :            : {
     991                 :            :         size_t i;
     992                 :            : 
     993         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(auth_algs); i++) {
     994                 :          0 :                 struct auth_alg *alg = &auth_algs[i];
     995                 :            : 
     996         [ #  # ]:          0 :                 if (!strcmp(name, alg->name))
     997                 :          0 :                         return alg;
     998                 :            :         }
     999                 :            : 
    1000                 :            :         return NULL;
    1001                 :            : }
    1002                 :            : 
    1003                 :            : static struct auth_alg *
    1004                 :            : auth_alg_find_by_id(enum rte_crypto_auth_algorithm alg_id, uint32_t key_size)
    1005                 :            : {
    1006                 :            :         size_t i;
    1007                 :            : 
    1008         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(auth_algs); i++) {
    1009                 :          0 :                 struct auth_alg *alg = &auth_algs[i];
    1010                 :            : 
    1011   [ #  #  #  # ]:          0 :                 if (alg->alg == alg_id && alg->key_size == key_size)
    1012                 :            :                         return alg;
    1013                 :            :         }
    1014                 :            : 
    1015                 :            :         return NULL;
    1016                 :            : }
    1017                 :            : 
    1018                 :            : static struct aead_alg *
    1019                 :          0 : aead_alg_find(const char *name)
    1020                 :            : {
    1021                 :            :         size_t i;
    1022                 :            : 
    1023         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(aead_algs); i++) {
    1024                 :          0 :                 struct aead_alg *alg = &aead_algs[i];
    1025                 :            : 
    1026         [ #  # ]:          0 :                 if (!strcmp(name, alg->name))
    1027                 :          0 :                         return alg;
    1028                 :            :         }
    1029                 :            : 
    1030                 :            :         return NULL;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : static struct aead_alg *
    1034                 :            : aead_alg_find_by_id(enum rte_crypto_aead_algorithm alg_id, uint32_t key_size)
    1035                 :            : {
    1036                 :            :         size_t i;
    1037                 :            : 
    1038         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(aead_algs); i++) {
    1039                 :          0 :                 struct aead_alg *alg = &aead_algs[i];
    1040                 :            : 
    1041   [ #  #  #  # ]:          0 :                 if (alg->alg == alg_id && alg->key_size == key_size)
    1042                 :            :                         return alg;
    1043                 :            :         }
    1044                 :            : 
    1045                 :            :         return NULL;
    1046                 :            : }
    1047                 :            : 
    1048                 :            : static int
    1049                 :            : char_to_hex(char c, uint8_t *val)
    1050                 :            : {
    1051                 :          0 :         if (c >= '0' && c <= '9') {
    1052                 :            :                 *val = c - '0';
    1053                 :            :                 return 0;
    1054                 :            :         }
    1055                 :            : 
    1056   [ #  #  #  # ]:          0 :         if (c >= 'A' && c <= 'F') {
    1057                 :          0 :                 *val = c - 'A' + 10;
    1058                 :            :                 return 0;
    1059                 :            :         }
    1060                 :            : 
    1061   [ #  #  #  # ]:          0 :         if (c >= 'a' && c <= 'f') {
    1062                 :          0 :                 *val = c - 'a' + 10;
    1063                 :            :                 return 0;
    1064                 :            :         }
    1065                 :            : 
    1066                 :            :         return -EINVAL;
    1067                 :            : }
    1068                 :            : 
    1069                 :            : static int
    1070                 :          0 : hex_string_parse(char *src, uint8_t *dst, uint32_t n_dst_bytes)
    1071                 :            : {
    1072                 :            :         uint32_t i;
    1073                 :            : 
    1074                 :            :         /* Check input arguments. */
    1075   [ #  #  #  #  :          0 :         if (!src || !src[0] || !dst || !n_dst_bytes)
                   #  # ]
    1076                 :            :                 return -EINVAL;
    1077                 :            : 
    1078                 :            :         /* Skip any leading "0x" or "0X" in the src string. */
    1079   [ #  #  #  # ]:          0 :         if ((src[0] == '0') && (src[1] == 'x' || src[1] == 'X'))
    1080                 :          0 :                 src += 2;
    1081                 :            : 
    1082                 :            :         /* Convert each group of two hex characters in the src string to one byte in dst array. */
    1083         [ #  # ]:          0 :         for (i = 0; i < n_dst_bytes; i++) {
    1084                 :            :                 uint8_t a, b;
    1085                 :            :                 int status;
    1086                 :            : 
    1087         [ #  # ]:          0 :                 status = char_to_hex(*src, &a);
    1088                 :            :                 if (status)
    1089                 :            :                         return status;
    1090                 :            :                 src++;
    1091                 :            : 
    1092         [ #  # ]:          0 :                 status = char_to_hex(*src, &b);
    1093                 :            :                 if (status)
    1094                 :            :                         return status;
    1095                 :          0 :                 src++;
    1096                 :            : 
    1097                 :          0 :                 dst[i] = a * 16 + b;
    1098                 :            :         }
    1099                 :            : 
    1100                 :            :         /* Check for the end of the src string. */
    1101         [ #  # ]:          0 :         if (*src)
    1102                 :          0 :                 return -EINVAL;
    1103                 :            : 
    1104                 :            :         return 0;
    1105                 :            : }
    1106                 :            : 
    1107                 :            : static int
    1108                 :            : token_is_comment(const char *token)
    1109                 :            : {
    1110         [ #  # ]:          0 :         if ((token[0] == '#') ||
    1111         [ #  # ]:          0 :             (token[0] == ';') ||
    1112         [ #  # ]:          0 :             ((token[0] == '/') && (token[1] == '/')))
    1113                 :            :                 return 1; /* TRUE. */
    1114                 :            : 
    1115                 :            :         return 0; /* FALSE. */
    1116                 :            : }
    1117                 :            : 
    1118                 :            : #define MAX_TOKENS 64
    1119                 :            : 
    1120                 :            : #define CHECK(condition, msg)          \
    1121                 :            : do {                                   \
    1122                 :            :         if (!(condition)) {            \
    1123                 :            :                 if (errmsg)            \
    1124                 :            :                         *errmsg = msg; \
    1125                 :            :                 goto error;            \
    1126                 :            :         }                              \
    1127                 :            : } while (0)
    1128                 :            : 
    1129                 :            : struct rte_swx_ipsec_sa_params *
    1130                 :          0 : rte_swx_ipsec_sa_read(struct rte_swx_ipsec *ipsec __rte_unused,
    1131                 :            :                       const char *string,
    1132                 :            :                       int *is_blank_or_comment,
    1133                 :            :                       const char **errmsg)
    1134                 :            : {
    1135                 :            :         char *token_array[MAX_TOKENS], **t;
    1136                 :            :         struct rte_swx_ipsec_sa_params *p = NULL;
    1137                 :            :         char *s0 = NULL, *s;
    1138                 :            :         uint32_t n_tokens = 0;
    1139                 :            :         int blank_or_comment = 0;
    1140                 :            : 
    1141                 :            :         /* Check input arguments. */
    1142   [ #  #  #  #  :          0 :         CHECK(string && string[0], "NULL input");
                   #  # ]
    1143                 :            : 
    1144                 :            :         /* Memory allocation. */
    1145                 :          0 :         s0 = strdup(string);
    1146                 :          0 :         p = calloc(1, sizeof(struct rte_swx_ipsec_sa_params));
    1147   [ #  #  #  # ]:          0 :         CHECK(s0 && p, "Not enough memory");
    1148                 :            : 
    1149                 :            :         /* Parse the string into tokens. */
    1150                 :          0 :         for (s = s0; ; ) {
    1151                 :            :                 char *token;
    1152                 :            : 
    1153                 :          0 :                 token = strtok_r(s, " \f\n\r\t\v", &s);
    1154         [ #  # ]:          0 :                 if (!token || token_is_comment(token))
    1155                 :            :                         break;
    1156                 :            : 
    1157   [ #  #  #  # ]:          0 :                 CHECK(n_tokens < RTE_DIM(token_array), "Too many tokens");
    1158                 :            : 
    1159                 :          0 :                 token_array[n_tokens] = token;
    1160                 :          0 :                 n_tokens++;
    1161                 :            :         }
    1162                 :            : 
    1163                 :            :         t = token_array;
    1164         [ #  # ]:          0 :         if (!n_tokens) {
    1165                 :            :                 blank_or_comment = 1;
    1166                 :          0 :                 goto error;
    1167                 :            :         }
    1168                 :            : 
    1169                 :            :         /*
    1170                 :            :          * Crypto operation.
    1171                 :            :          */
    1172         [ #  # ]:          0 :         if (!strcmp(t[0], "encrypt"))
    1173                 :          0 :                 p->encrypt = 1;
    1174         [ #  # ]:          0 :         else if (!strcmp(t[0], "decrypt"))
    1175                 :          0 :                 p->encrypt = 0;
    1176                 :            :         else
    1177         [ #  # ]:          0 :                 CHECK(0, "Missing \"encrypt\"/\"decrypt\" keyword");
    1178                 :            : 
    1179                 :            :         t++;
    1180                 :          0 :         n_tokens--;
    1181                 :            : 
    1182                 :            :         /*
    1183                 :            :          * Crypto parameters.
    1184                 :            :          */
    1185   [ #  #  #  # ]:          0 :         CHECK(n_tokens >= 2, "Not enough tokens");
    1186                 :            : 
    1187         [ #  # ]:          0 :         if (!strcmp(t[0], "cipher")) {
    1188                 :            :                 struct cipher_alg *cipher_alg;
    1189                 :            :                 struct auth_alg *auth_alg;
    1190                 :            :                 uint32_t key_size;
    1191                 :            : 
    1192                 :          0 :                 p->crypto.is_aead = 0;
    1193                 :            : 
    1194                 :            :                 /* cipher. */
    1195                 :          0 :                 cipher_alg = cipher_alg_find(t[1]);
    1196   [ #  #  #  # ]:          0 :                 CHECK(cipher_alg, "Unsupported cipher algorithm");
    1197                 :            : 
    1198                 :          0 :                 key_size = cipher_alg->key_size;
    1199                 :          0 :                 p->crypto.cipher_auth.cipher.alg = cipher_alg->alg;
    1200                 :          0 :                 p->crypto.cipher_auth.cipher.key_size = key_size;
    1201                 :            : 
    1202                 :            :                 t += 2;
    1203                 :          0 :                 n_tokens -= 2;
    1204                 :            : 
    1205         [ #  # ]:          0 :                 if (key_size) {
    1206                 :            :                         int status;
    1207                 :            : 
    1208   [ #  #  #  # ]:          0 :                         CHECK(n_tokens >= 2, "Not enough tokens");
    1209   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[0], "key"), "Missing cipher \"key\" keyword");
    1210   [ #  #  #  # ]:          0 :                         CHECK(key_size <= RTE_DIM(p->crypto.cipher_auth.cipher.key),
    1211                 :            :                                 "Cipher algorithm key too big");
    1212                 :            : 
    1213                 :          0 :                         status = hex_string_parse(t[1], p->crypto.cipher_auth.cipher.key, key_size);
    1214   [ #  #  #  # ]:          0 :                         CHECK(!status, "Cipher key invalid format");
    1215                 :            : 
    1216                 :            :                         t += 2;
    1217                 :          0 :                         n_tokens -= 2;
    1218                 :            :                 }
    1219                 :            : 
    1220                 :            :                 /* authentication. */
    1221   [ #  #  #  # ]:          0 :                 CHECK(n_tokens >= 2, "Not enough tokens");
    1222   [ #  #  #  # ]:          0 :                 CHECK(!strcmp(t[0], "auth"), "Missing \"auth\" keyword");
    1223                 :            : 
    1224                 :          0 :                 auth_alg = auth_alg_find(t[1]);
    1225   [ #  #  #  # ]:          0 :                 CHECK(auth_alg, "Unsupported authentication algorithm");
    1226                 :            : 
    1227                 :          0 :                 key_size = auth_alg->key_size;
    1228                 :          0 :                 p->crypto.cipher_auth.auth.alg = auth_alg->alg;
    1229                 :          0 :                 p->crypto.cipher_auth.auth.key_size = key_size;
    1230                 :            : 
    1231                 :          0 :                 t += 2;
    1232                 :          0 :                 n_tokens -= 2;
    1233                 :            : 
    1234         [ #  # ]:          0 :                 if (key_size) {
    1235                 :            :                         int status;
    1236                 :            : 
    1237   [ #  #  #  # ]:          0 :                         CHECK(n_tokens >= 2, "Not enough tokens");
    1238   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[0], "key"), "Missing authentication \"key\" keyword");
    1239   [ #  #  #  # ]:          0 :                         CHECK(key_size <= RTE_DIM(p->crypto.cipher_auth.auth.key),
    1240                 :            :                                 "Authentication algorithm key too big");
    1241                 :            : 
    1242                 :          0 :                         status = hex_string_parse(t[1], p->crypto.cipher_auth.auth.key, key_size);
    1243   [ #  #  #  # ]:          0 :                         CHECK(!status, "Authentication key invalid format");
    1244                 :            : 
    1245                 :          0 :                         t += 2;
    1246                 :          0 :                         n_tokens -= 2;
    1247                 :            :                 }
    1248         [ #  # ]:          0 :         } else if (!strcmp(t[0], "aead")) {
    1249                 :            :                 struct aead_alg *alg;
    1250                 :            :                 uint32_t key_size;
    1251                 :            :                 int status;
    1252                 :            : 
    1253                 :          0 :                 p->crypto.is_aead = 1;
    1254                 :            : 
    1255   [ #  #  #  # ]:          0 :                 CHECK(n_tokens >= 4, "Not enough tokens");
    1256                 :          0 :                 alg = aead_alg_find(t[1]);
    1257   [ #  #  #  # ]:          0 :                 CHECK(alg, "Unsupported AEAD algorithm");
    1258                 :            : 
    1259                 :          0 :                 key_size = alg->key_size;
    1260                 :          0 :                 p->crypto.aead.alg = alg->alg;
    1261                 :          0 :                 p->crypto.aead.key_size = key_size;
    1262                 :            : 
    1263   [ #  #  #  # ]:          0 :                 CHECK(!strcmp(t[2], "key"), "Missing AEAD \"key\" keyword");
    1264   [ #  #  #  # ]:          0 :                 CHECK(key_size <= RTE_DIM(p->crypto.aead.key),
    1265                 :            :                         "AEAD algorithm key too big");
    1266                 :            : 
    1267                 :          0 :                 status = hex_string_parse(t[3], p->crypto.aead.key, key_size);
    1268   [ #  #  #  # ]:          0 :                 CHECK(!status, "AEAD key invalid format");
    1269                 :            : 
    1270                 :            :                 t += 4;
    1271                 :          0 :                 n_tokens -= 4;
    1272                 :            :         } else
    1273         [ #  # ]:          0 :                 CHECK(0, "Missing \"cipher\"/\"aead\" keyword");
    1274                 :            : 
    1275                 :            :         /*
    1276                 :            :          * Packet ecapsulation parameters.
    1277                 :            :          */
    1278   [ #  #  #  # ]:          0 :         CHECK(n_tokens >= 4, "Not enough tokens");
    1279   [ #  #  #  # ]:          0 :         CHECK(!strcmp(t[0], "esp"), "Missing \"esp\" keyword");
    1280   [ #  #  #  # ]:          0 :         CHECK(!strcmp(t[1], "spi"), "Missing \"spi\" keyword");
    1281                 :            : 
    1282                 :          0 :         p->encap.esp.spi = strtoul(t[2], &t[2], 0);
    1283   [ #  #  #  # ]:          0 :         CHECK(!t[2][0], "ESP SPI field invalid format");
    1284                 :            : 
    1285                 :            :         t += 3;
    1286                 :          0 :         n_tokens -= 3;
    1287                 :            : 
    1288         [ #  # ]:          0 :         if (!strcmp(t[0], "tunnel")) {
    1289                 :          0 :                 p->encap.tunnel_mode = 1;
    1290                 :            : 
    1291   [ #  #  #  # ]:          0 :                 CHECK(n_tokens >= 6, "Not enough tokens");
    1292                 :            : 
    1293         [ #  # ]:          0 :                 if (!strcmp(t[1], "ipv4")) {
    1294                 :            :                         uint32_t addr;
    1295                 :            : 
    1296                 :          0 :                         p->encap.tunnel_ipv4 = 1;
    1297                 :            : 
    1298   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[2], "srcaddr"), "Missing \"srcaddr\" keyword");
    1299                 :            : 
    1300                 :          0 :                         addr = strtoul(t[3], &t[3], 0);
    1301   [ #  #  #  # ]:          0 :                         CHECK(!t[3][0], "Tunnel IPv4 source address invalid format");
    1302                 :          0 :                         p->encap.tunnel.ipv4.src_addr.s_addr = htonl(addr);
    1303                 :            : 
    1304   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[4], "dstaddr"), "Missing \"dstaddr\" keyword");
    1305                 :            : 
    1306                 :          0 :                         addr = strtoul(t[5], &t[5], 0);
    1307   [ #  #  #  # ]:          0 :                         CHECK(!t[5][0], "Tunnel IPv4 destination address invalid format");
    1308                 :          0 :                         p->encap.tunnel.ipv4.dst_addr.s_addr = htonl(addr);
    1309                 :            : 
    1310                 :            :                         t += 6;
    1311                 :          0 :                         n_tokens -= 6;
    1312         [ #  # ]:          0 :                 } else if (!strcmp(t[1], "ipv6")) {
    1313                 :            :                         int status;
    1314                 :            : 
    1315                 :          0 :                         p->encap.tunnel_ipv4 = 0;
    1316                 :            : 
    1317   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[2], "srcaddr"), "Missing \"srcaddr\" keyword");
    1318                 :            : 
    1319                 :          0 :                         status = hex_string_parse(t[3],
    1320                 :          0 :                                                   p->encap.tunnel.ipv6.src_addr.s6_addr,
    1321                 :            :                                                   16);
    1322   [ #  #  #  # ]:          0 :                         CHECK(!status, "Tunnel IPv6 source address invalid format");
    1323                 :            : 
    1324   [ #  #  #  # ]:          0 :                         CHECK(!strcmp(t[4], "dstaddr"), "Missing \"dstaddr\" keyword");
    1325                 :            : 
    1326                 :          0 :                         status = hex_string_parse(t[5],
    1327                 :          0 :                                                   p->encap.tunnel.ipv6.dst_addr.s6_addr,
    1328                 :            :                                                   16);
    1329   [ #  #  #  # ]:          0 :                         CHECK(!status, "Tunnel IPv6 destination address invalid format");
    1330                 :            : 
    1331                 :            :                         t += 6;
    1332                 :          0 :                         n_tokens -= 6;
    1333                 :            :                 } else
    1334         [ #  # ]:          0 :                         CHECK(0, "Missing \"ipv4\"/\"ipv6\" keyword");
    1335         [ #  # ]:          0 :         } else if (!strcmp(t[0], "transport")) {
    1336                 :          0 :                 p->encap.tunnel_mode = 0;
    1337                 :            : 
    1338                 :            :                 t++;
    1339                 :          0 :                 n_tokens--;
    1340                 :            :         } else
    1341         [ #  # ]:          0 :                 CHECK(0, "Missing \"tunnel\"/\"transport\" keyword");
    1342                 :            : 
    1343                 :            :         /*
    1344                 :            :          * Any other parameters.
    1345                 :            :          */
    1346   [ #  #  #  # ]:          0 :         CHECK(!n_tokens, "Unexpected trailing tokens");
    1347                 :            : 
    1348                 :          0 :         free(s0);
    1349                 :          0 :         return p;
    1350                 :            : 
    1351                 :          0 : error:
    1352                 :          0 :         free(p);
    1353                 :          0 :         free(s0);
    1354         [ #  # ]:          0 :         if (is_blank_or_comment)
    1355                 :          0 :                 *is_blank_or_comment = blank_or_comment;
    1356                 :            :         return NULL;
    1357                 :            : }
    1358                 :            : 
    1359                 :            : static void
    1360                 :          0 : tunnel_ipv4_header_set(struct rte_ipv4_hdr *h, struct rte_swx_ipsec_sa_params *p)
    1361                 :            : {
    1362                 :          0 :         struct rte_ipv4_hdr ipv4_hdr = {
    1363                 :            :                 .version_ihl = 0x45,
    1364                 :            :                 .type_of_service = 0,
    1365                 :            :                 .total_length = 0, /* Cannot be pre-computed. */
    1366                 :            :                 .packet_id = 0,
    1367                 :            :                 .fragment_offset = 0,
    1368                 :            :                 .time_to_live = 64,
    1369                 :            :                 .next_proto_id = IPPROTO_ESP,
    1370                 :            :                 .hdr_checksum = 0, /* Cannot be pre-computed. */
    1371                 :          0 :                 .src_addr = p->encap.tunnel.ipv4.src_addr.s_addr,
    1372                 :          0 :                 .dst_addr = p->encap.tunnel.ipv4.dst_addr.s_addr,
    1373                 :            :         };
    1374                 :            : 
    1375                 :            :         memcpy(h, &ipv4_hdr, sizeof(ipv4_hdr));
    1376                 :          0 : }
    1377                 :            : 
    1378                 :            : static void
    1379                 :          0 : tunnel_ipv6_header_set(struct rte_ipv6_hdr *h, struct rte_swx_ipsec_sa_params *p)
    1380                 :            : {
    1381                 :          0 :         struct rte_ipv6_hdr ipv6_hdr = {
    1382                 :            :                 .vtc_flow = 0x60000000,
    1383                 :            :                 .payload_len = 0, /* Cannot be pre-computed. */
    1384                 :            :                 .proto = IPPROTO_ESP,
    1385                 :            :                 .hop_limits = 64,
    1386                 :            :                 .src_addr = {0},
    1387                 :            :                 .dst_addr = {0},
    1388                 :            :         };
    1389                 :            : 
    1390                 :            :         memcpy(h, &ipv6_hdr, sizeof(ipv6_hdr));
    1391                 :          0 :         memcpy(h->src_addr, p->encap.tunnel.ipv6.src_addr.s6_addr, 16);
    1392                 :          0 :         memcpy(h->dst_addr, p->encap.tunnel.ipv6.dst_addr.s6_addr, 16);
    1393                 :          0 : }
    1394                 :            : 
    1395                 :            : /* IPsec library SA parameters. */
    1396                 :            : static struct rte_crypto_sym_xform *
    1397                 :          0 : crypto_xform_get(struct rte_swx_ipsec_sa_params *p,
    1398                 :            :                 struct rte_crypto_sym_xform *xform,
    1399                 :            :                 uint32_t *salt_out)
    1400                 :            : {
    1401         [ #  # ]:          0 :         if (p->crypto.is_aead) {
    1402                 :            :                 struct aead_alg *alg;
    1403                 :            :                 uint32_t key_size, salt, iv_length;
    1404                 :            : 
    1405                 :          0 :                 alg = aead_alg_find_by_id(p->crypto.aead.alg, p->crypto.aead.key_size);
    1406         [ #  # ]:          0 :                 if (!alg)
    1407                 :            :                         return NULL;
    1408                 :            : 
    1409                 :            :                 /* salt and salt-related key size adjustment. */
    1410                 :          0 :                 key_size = p->crypto.aead.key_size - 4;
    1411                 :          0 :                 memcpy(&salt, &p->crypto.aead.key[key_size], 4);
    1412                 :            : 
    1413                 :            :                 /* IV length. */
    1414                 :            :                 iv_length = 12;
    1415         [ #  # ]:          0 :                 if (p->crypto.aead.alg == RTE_CRYPTO_AEAD_AES_CCM)
    1416                 :            :                         iv_length = 11;
    1417                 :            : 
    1418                 :            :                 /* xform. */
    1419                 :          0 :                 xform[0].type = RTE_CRYPTO_SYM_XFORM_AEAD;
    1420                 :          0 :                 xform[0].aead.op = p->encrypt ?
    1421                 :          0 :                         RTE_CRYPTO_AEAD_OP_ENCRYPT :
    1422                 :            :                         RTE_CRYPTO_AEAD_OP_DECRYPT;
    1423                 :          0 :                 xform[0].aead.algo = p->crypto.aead.alg;
    1424                 :          0 :                 xform[0].aead.key.data = p->crypto.aead.key;
    1425                 :          0 :                 xform[0].aead.key.length = key_size;
    1426                 :          0 :                 xform[0].aead.iv.offset = IV_OFFSET;
    1427                 :          0 :                 xform[0].aead.iv.length = iv_length;
    1428                 :          0 :                 xform[0].aead.digest_length = alg->digest_size;
    1429                 :          0 :                 xform[0].aead.aad_length = alg->aad_size;
    1430                 :          0 :                 xform[0].next = NULL;
    1431                 :            : 
    1432                 :          0 :                 *salt_out = salt;
    1433                 :          0 :                 return &xform[0];
    1434                 :            :         } else {
    1435                 :            :                 struct cipher_alg *cipher_alg;
    1436                 :            :                 struct auth_alg *auth_alg;
    1437                 :            :                 uint32_t cipher_key_size, auth_key_size, salt, auth_iv_length;
    1438                 :            : 
    1439                 :          0 :                 cipher_alg = cipher_alg_find_by_id(p->crypto.cipher_auth.cipher.alg,
    1440                 :            :                                                    p->crypto.cipher_auth.cipher.key_size);
    1441         [ #  # ]:          0 :                 if (!cipher_alg)
    1442                 :            :                         return NULL;
    1443                 :            : 
    1444                 :          0 :                 auth_alg = auth_alg_find_by_id(p->crypto.cipher_auth.auth.alg,
    1445                 :            :                                                p->crypto.cipher_auth.auth.key_size);
    1446         [ #  # ]:          0 :                 if (!auth_alg)
    1447                 :            :                         return NULL;
    1448                 :            : 
    1449                 :            :                 /* salt and salt-related key size adjustment. */
    1450                 :            :                 cipher_key_size = p->crypto.cipher_auth.cipher.key_size;
    1451                 :            :                 auth_key_size = p->crypto.cipher_auth.auth.key_size;
    1452                 :            : 
    1453      [ #  #  # ]:          0 :                 switch (p->crypto.cipher_auth.cipher.alg) {
    1454                 :          0 :                 case RTE_CRYPTO_CIPHER_AES_CBC:
    1455                 :            :                 case RTE_CRYPTO_CIPHER_3DES_CBC:
    1456                 :          0 :                         salt = (uint32_t)rand();
    1457                 :          0 :                         break;
    1458                 :            : 
    1459                 :          0 :                 case RTE_CRYPTO_CIPHER_AES_CTR:
    1460                 :          0 :                         cipher_key_size -= 4;
    1461                 :          0 :                         memcpy(&salt, &p->crypto.cipher_auth.cipher.key[cipher_key_size], 4);
    1462                 :            :                         break;
    1463                 :            : 
    1464                 :          0 :                 default:
    1465                 :          0 :                         salt = 0;
    1466                 :            :                 }
    1467                 :            : 
    1468         [ #  # ]:          0 :                 if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC) {
    1469                 :          0 :                         auth_key_size -= 4;
    1470                 :          0 :                         memcpy(&salt, &p->crypto.cipher_auth.auth.key[auth_key_size], 4);
    1471                 :            :                 }
    1472                 :            : 
    1473                 :            :                 /* IV length. */
    1474                 :          0 :                 auth_iv_length = cipher_alg->iv_size;
    1475         [ #  # ]:          0 :                 if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC)
    1476                 :            :                         auth_iv_length = 12;
    1477                 :            : 
    1478                 :            :                 /* xform. */
    1479         [ #  # ]:          0 :                 if (p->encrypt) {
    1480                 :          0 :                         xform[0].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
    1481                 :          0 :                         xform[0].cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
    1482                 :          0 :                         xform[0].cipher.algo = p->crypto.cipher_auth.cipher.alg;
    1483                 :          0 :                         xform[0].cipher.key.data = p->crypto.cipher_auth.cipher.key;
    1484                 :          0 :                         xform[0].cipher.key.length = cipher_key_size;
    1485                 :          0 :                         xform[0].cipher.iv.offset = IV_OFFSET;
    1486                 :          0 :                         xform[0].cipher.iv.length = cipher_alg->iv_size;
    1487                 :          0 :                         xform[0].cipher.dataunit_len = 0;
    1488                 :          0 :                         xform[0].next = &xform[1];
    1489                 :            : 
    1490                 :          0 :                         xform[1].type = RTE_CRYPTO_SYM_XFORM_AUTH;
    1491                 :          0 :                         xform[1].auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
    1492                 :          0 :                         xform[1].auth.algo = p->crypto.cipher_auth.auth.alg;
    1493                 :          0 :                         xform[1].auth.key.data = p->crypto.cipher_auth.auth.key;
    1494                 :          0 :                         xform[1].auth.key.length = auth_key_size;
    1495                 :          0 :                         xform[1].auth.iv.offset = IV_OFFSET;
    1496                 :          0 :                         xform[1].auth.iv.length = auth_iv_length;
    1497                 :          0 :                         xform[1].auth.digest_length = auth_alg->digest_size;
    1498                 :          0 :                         xform[1].next = NULL;
    1499                 :            :                 } else {
    1500                 :          0 :                         xform[0].type = RTE_CRYPTO_SYM_XFORM_AUTH;
    1501                 :          0 :                         xform[0].auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
    1502                 :          0 :                         xform[0].auth.algo = p->crypto.cipher_auth.auth.alg;
    1503                 :          0 :                         xform[0].auth.key.data = p->crypto.cipher_auth.auth.key;
    1504                 :          0 :                         xform[0].auth.key.length = auth_key_size;
    1505                 :          0 :                         xform[0].auth.iv.offset = IV_OFFSET;
    1506                 :          0 :                         xform[0].auth.iv.length = auth_iv_length;
    1507                 :          0 :                         xform[0].auth.digest_length = auth_alg->digest_size;
    1508                 :          0 :                         xform[0].next = &xform[1];
    1509                 :            : 
    1510                 :          0 :                         xform[1].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
    1511                 :          0 :                         xform[1].cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
    1512                 :          0 :                         xform[1].cipher.algo = p->crypto.cipher_auth.cipher.alg;
    1513                 :          0 :                         xform[1].cipher.key.data = p->crypto.cipher_auth.cipher.key;
    1514                 :          0 :                         xform[1].cipher.key.length = cipher_key_size;
    1515                 :          0 :                         xform[1].cipher.iv.offset = IV_OFFSET;
    1516                 :          0 :                         xform[1].cipher.iv.length = cipher_alg->iv_size;
    1517                 :          0 :                         xform[1].cipher.dataunit_len = 0;
    1518                 :          0 :                         xform[1].next = NULL;
    1519                 :            :                 }
    1520                 :            : 
    1521                 :          0 :                 *salt_out = salt;
    1522                 :            : 
    1523         [ #  # ]:          0 :                 if (p->crypto.cipher_auth.auth.alg == RTE_CRYPTO_AUTH_AES_GMAC) {
    1524         [ #  # ]:          0 :                         if (p->encrypt)
    1525                 :          0 :                                 return &xform[1];
    1526                 :            : 
    1527                 :          0 :                         xform[0].next = NULL;
    1528                 :          0 :                         return &xform[0];
    1529                 :            :                 }
    1530                 :            : 
    1531                 :            :                 return &xform[0];
    1532                 :            :         }
    1533                 :            : }
    1534                 :            : 
    1535                 :            : static void
    1536                 :          0 : ipsec_xform_get(struct rte_swx_ipsec_sa_params *p,
    1537                 :            :                 struct rte_security_ipsec_xform *ipsec_xform,
    1538                 :            :                 uint32_t salt)
    1539                 :            : {
    1540                 :          0 :         ipsec_xform->spi = p->encap.esp.spi;
    1541                 :            : 
    1542                 :          0 :         ipsec_xform->salt = salt;
    1543                 :            : 
    1544                 :          0 :         ipsec_xform->options.esn = 0;
    1545                 :          0 :         ipsec_xform->options.udp_encap = 0;
    1546                 :          0 :         ipsec_xform->options.copy_dscp = 1;
    1547                 :          0 :         ipsec_xform->options.copy_flabel = 0;
    1548                 :          0 :         ipsec_xform->options.copy_df = 0;
    1549                 :          0 :         ipsec_xform->options.dec_ttl = 0;
    1550                 :          0 :         ipsec_xform->options.ecn = 1;
    1551                 :          0 :         ipsec_xform->options.stats = 0;
    1552                 :          0 :         ipsec_xform->options.iv_gen_disable = 0;
    1553                 :          0 :         ipsec_xform->options.tunnel_hdr_verify = 0;
    1554                 :          0 :         ipsec_xform->options.udp_ports_verify = 0;
    1555                 :          0 :         ipsec_xform->options.ip_csum_enable = 0;
    1556                 :          0 :         ipsec_xform->options.l4_csum_enable = 0;
    1557                 :          0 :         ipsec_xform->options.ip_reassembly_en = 0;
    1558                 :            : 
    1559                 :          0 :         ipsec_xform->direction = p->encrypt ?
    1560                 :          0 :                 RTE_SECURITY_IPSEC_SA_DIR_EGRESS :
    1561                 :            :                 RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
    1562                 :            : 
    1563                 :          0 :         ipsec_xform->proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
    1564                 :            : 
    1565                 :          0 :         ipsec_xform->mode = p->encap.tunnel_mode ?
    1566         [ #  # ]:          0 :                 RTE_SECURITY_IPSEC_SA_MODE_TUNNEL :
    1567                 :            :                 RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
    1568                 :            : 
    1569                 :          0 :         ipsec_xform->tunnel.type = p->encap.tunnel_ipv4 ?
    1570         [ #  # ]:          0 :                 RTE_SECURITY_IPSEC_TUNNEL_IPV4 :
    1571                 :            :                 RTE_SECURITY_IPSEC_TUNNEL_IPV6;
    1572                 :            : 
    1573         [ #  # ]:          0 :         if (p->encap.tunnel_mode) {
    1574         [ #  # ]:          0 :                 if (p->encap.tunnel_ipv4) {
    1575                 :          0 :                         ipsec_xform->tunnel.ipv4.src_ip = p->encap.tunnel.ipv4.src_addr;
    1576                 :          0 :                         ipsec_xform->tunnel.ipv4.dst_ip = p->encap.tunnel.ipv4.dst_addr;
    1577                 :          0 :                         ipsec_xform->tunnel.ipv4.dscp = 0;
    1578                 :          0 :                         ipsec_xform->tunnel.ipv4.df = 0;
    1579                 :          0 :                         ipsec_xform->tunnel.ipv4.ttl = 64;
    1580                 :            :                 } else {
    1581                 :          0 :                         ipsec_xform->tunnel.ipv6.src_addr = p->encap.tunnel.ipv6.src_addr;
    1582                 :          0 :                         ipsec_xform->tunnel.ipv6.dst_addr = p->encap.tunnel.ipv6.dst_addr;
    1583                 :          0 :                         ipsec_xform->tunnel.ipv6.dscp = 0;
    1584                 :          0 :                         ipsec_xform->tunnel.ipv6.flabel = 0;
    1585                 :          0 :                         ipsec_xform->tunnel.ipv6.hlimit = 64;
    1586                 :            :                 }
    1587                 :            :         }
    1588                 :            : 
    1589                 :          0 :         ipsec_xform->life.packets_soft_limit = 0;
    1590                 :          0 :         ipsec_xform->life.bytes_soft_limit = 0;
    1591                 :          0 :         ipsec_xform->life.packets_hard_limit = 0;
    1592                 :          0 :         ipsec_xform->life.bytes_hard_limit = 0;
    1593                 :            : 
    1594                 :          0 :         ipsec_xform->replay_win_sz = 0;
    1595                 :            : 
    1596                 :          0 :         ipsec_xform->esn.value = 0;
    1597                 :            : 
    1598                 :          0 :         ipsec_xform->udp.dport = 0;
    1599                 :          0 :         ipsec_xform->udp.sport = 0;
    1600                 :          0 : }
    1601                 :            : 
    1602                 :            : static int
    1603                 :          0 : ipsec_sa_prm_get(struct rte_swx_ipsec_sa_params *p,
    1604                 :            :                  struct rte_ipsec_sa_prm *sa_prm,
    1605                 :            :                  struct rte_ipv4_hdr *ipv4_hdr,
    1606                 :            :                  struct rte_ipv6_hdr *ipv6_hdr,
    1607                 :            :                  struct rte_crypto_sym_xform *crypto_xform)
    1608                 :            : {
    1609                 :            :         uint32_t salt;
    1610                 :            : 
    1611                 :            :         memset(sa_prm, 0, sizeof(*sa_prm)); /* Better to be safe than sorry. */
    1612                 :            : 
    1613                 :            :         sa_prm->userdata = 0; /* Not used. */
    1614                 :            : 
    1615                 :            :         sa_prm->flags = 0; /* Flag RTE_IPSEC_SAFLAG_SQN_ATOM not enabled. */
    1616                 :            : 
    1617                 :            :         /*
    1618                 :            :          * crypto_xform.
    1619                 :            :          */
    1620                 :          0 :         sa_prm->crypto_xform = crypto_xform_get(p, crypto_xform, &salt);
    1621         [ #  # ]:          0 :         if (!sa_prm->crypto_xform)
    1622                 :            :                 return -EINVAL;
    1623                 :            : 
    1624                 :            :         /*
    1625                 :            :          * ipsec_xform.
    1626                 :            :          */
    1627                 :          0 :         ipsec_xform_get(p, &sa_prm->ipsec_xform, salt);
    1628                 :            : 
    1629                 :            :         /*
    1630                 :            :          * tunnel / transport.
    1631                 :            :          *
    1632                 :            :          * Currently, the input IP packet type is assumed to be IPv4. To support both IPv4 and IPv6,
    1633                 :            :          * the input packet type should be added to the SA configuration parameters.
    1634                 :            :          */
    1635         [ #  # ]:          0 :         if (p->encap.tunnel_mode) {
    1636         [ #  # ]:          0 :                 if (p->encap.tunnel_ipv4) {
    1637                 :          0 :                         sa_prm->tun.hdr_len = sizeof(struct rte_ipv4_hdr);
    1638                 :          0 :                         sa_prm->tun.hdr_l3_off = 0;
    1639                 :          0 :                         sa_prm->tun.next_proto = IPPROTO_IPIP; /* IPv4. */
    1640                 :          0 :                         sa_prm->tun.hdr = ipv4_hdr;
    1641                 :            :                 } else {
    1642                 :          0 :                         sa_prm->tun.hdr_len = sizeof(struct rte_ipv6_hdr);
    1643                 :          0 :                         sa_prm->tun.hdr_l3_off = 0;
    1644                 :          0 :                         sa_prm->tun.next_proto = IPPROTO_IPIP; /* IPv4. */
    1645                 :          0 :                         sa_prm->tun.hdr = ipv6_hdr;
    1646                 :            :                 }
    1647                 :            :         } else {
    1648                 :          0 :                 sa_prm->trs.proto = IPPROTO_IPIP; /* IPv4. */
    1649                 :            :         }
    1650                 :            : 
    1651                 :            :         return 0;
    1652                 :            : }
    1653                 :            : 
    1654                 :            : static int
    1655                 :          0 : ipsec_session_create(struct rte_swx_ipsec *ipsec,
    1656                 :            :                      struct rte_swx_ipsec_sa_params *p,
    1657                 :            :                      struct rte_ipsec_session *s)
    1658                 :            : {
    1659                 :            :         struct rte_ipv4_hdr ipv4_hdr;
    1660                 :            :         struct rte_ipv6_hdr ipv6_hdr;
    1661                 :            :         struct rte_crypto_sym_xform crypto_xform[2];
    1662                 :            :         struct rte_ipsec_sa_prm sa_prm;
    1663                 :            :         struct rte_ipsec_sa *sa = NULL;
    1664                 :            :         struct rte_cryptodev_sym_session *crypto_session = NULL;
    1665                 :            :         int sa_size;
    1666                 :            :         int sa_valid = 0, status = 0;
    1667                 :            : 
    1668                 :          0 :         tunnel_ipv4_header_set(&ipv4_hdr, p);
    1669                 :          0 :         tunnel_ipv6_header_set(&ipv6_hdr, p);
    1670                 :            : 
    1671                 :            :         /* IPsec library SA setup. */
    1672                 :          0 :         status = ipsec_sa_prm_get(p, &sa_prm, &ipv4_hdr, &ipv6_hdr, crypto_xform);
    1673         [ #  # ]:          0 :         if (status)
    1674                 :          0 :                 goto error;
    1675                 :            : 
    1676                 :          0 :         sa_size = rte_ipsec_sa_size(&sa_prm);
    1677         [ #  # ]:          0 :         if (sa_size < 0) {
    1678                 :            :                 status = sa_size;
    1679                 :          0 :                 goto error;
    1680                 :            :         }
    1681         [ #  # ]:          0 :         if (!sa_size) {
    1682                 :            :                 status = -EINVAL;
    1683                 :          0 :                 goto error;
    1684                 :            :         }
    1685                 :            : 
    1686                 :          0 :         sa = calloc(1, sa_size);
    1687         [ #  # ]:          0 :         if (!sa) {
    1688                 :            :                 status = -ENOMEM;
    1689                 :          0 :                 goto error;
    1690                 :            :         }
    1691                 :            : 
    1692                 :          0 :         sa_size = rte_ipsec_sa_init(sa, &sa_prm, sa_size);
    1693         [ #  # ]:          0 :         if (sa_size < 0) {
    1694                 :            :                 status = sa_size;
    1695                 :          0 :                 goto error;
    1696                 :            :         }
    1697         [ #  # ]:          0 :         if (!sa_size) {
    1698                 :            :                 status = -EINVAL;
    1699                 :          0 :                 goto error;
    1700                 :            :         }
    1701                 :            : 
    1702                 :            :         sa_valid = 1;
    1703                 :            : 
    1704                 :            :         /* Cryptodev library session setup. */
    1705                 :          0 :         crypto_session = rte_cryptodev_sym_session_create(ipsec->dev_id,
    1706                 :            :                                                           sa_prm.crypto_xform,
    1707                 :            :                                                           ipsec->mp_session);
    1708         [ #  # ]:          0 :         if (!crypto_session) {
    1709                 :            :                 status = -ENOMEM;
    1710                 :          0 :                 goto error;
    1711                 :            :         }
    1712                 :            : 
    1713                 :            :         /* IPsec library session setup. */
    1714                 :          0 :         s->sa = sa;
    1715                 :          0 :         s->type = RTE_SECURITY_ACTION_TYPE_NONE;
    1716                 :          0 :         s->crypto.ses = crypto_session;
    1717                 :          0 :         s->crypto.dev_id = ipsec->dev_id;
    1718                 :          0 :         s->pkt_func.prepare.async = NULL;
    1719                 :          0 :         s->pkt_func.process = NULL;
    1720                 :            : 
    1721                 :          0 :         status = rte_ipsec_session_prepare(s);
    1722         [ #  # ]:          0 :         if (status)
    1723                 :          0 :                 goto error;
    1724                 :            : 
    1725                 :            :         return 0;
    1726                 :            : 
    1727                 :          0 : error:
    1728                 :            :         /* sa. */
    1729         [ #  # ]:          0 :         if (sa_valid)
    1730                 :          0 :                 rte_ipsec_sa_fini(sa);
    1731                 :            : 
    1732                 :          0 :         free(sa);
    1733                 :            : 
    1734                 :            :         /* crypto_session. */
    1735         [ #  # ]:          0 :         if (crypto_session)
    1736                 :          0 :                 rte_cryptodev_sym_session_free(ipsec->dev_id, crypto_session);
    1737                 :            : 
    1738                 :            :         /* s. */
    1739                 :            :         memset(s, 0, sizeof(*s));
    1740                 :            : 
    1741                 :          0 :         return status;
    1742                 :            : }
    1743                 :            : 
    1744                 :            : static void
    1745                 :          0 : ipsec_session_free(struct rte_swx_ipsec *ipsec,
    1746                 :            :                    struct rte_ipsec_session *s)
    1747                 :            : {
    1748         [ #  # ]:          0 :         if (!s)
    1749                 :            :                 return;
    1750                 :            : 
    1751                 :            :         /* IPsec library SA. */
    1752         [ #  # ]:          0 :         if (s->sa)
    1753                 :          0 :                 rte_ipsec_sa_fini(s->sa);
    1754                 :          0 :         free(s->sa);
    1755                 :            : 
    1756                 :            :         /* Cryptodev library session. */
    1757         [ #  # ]:          0 :         if (s->crypto.ses)
    1758                 :          0 :                 rte_cryptodev_sym_session_free(ipsec->dev_id, s->crypto.ses);
    1759                 :            : 
    1760                 :            :         /* IPsec library session. */
    1761                 :            :         memset(s, 0, sizeof(*s));
    1762                 :            : }
    1763                 :            : 
    1764                 :            : int
    1765                 :          0 : rte_swx_ipsec_sa_add(struct rte_swx_ipsec *ipsec,
    1766                 :            :                      struct rte_swx_ipsec_sa_params *sa_params,
    1767                 :            :                      uint32_t *id)
    1768                 :            : {
    1769                 :            :         struct ipsec_sa *sa;
    1770                 :            :         uint32_t sa_id;
    1771                 :            :         int status;
    1772                 :            : 
    1773                 :            :         /* Check the input parameters. */
    1774   [ #  #  #  # ]:          0 :         if (!ipsec || !sa_params || !id)
    1775                 :            :                 return -EINVAL;
    1776                 :            : 
    1777                 :            :         /* Allocate a free SADB entry. */
    1778         [ #  # ]:          0 :         if (!ipsec->n_sa_free_id)
    1779                 :            :                 return -ENOSPC;
    1780                 :            : 
    1781                 :          0 :         sa_id = ipsec->sa_free_id[ipsec->n_sa_free_id - 1];
    1782                 :          0 :         ipsec->n_sa_free_id--;
    1783                 :            : 
    1784                 :            :         /* Acquire the SA resources. */
    1785                 :            :         sa = ipsec_sa_get(ipsec, sa_id);
    1786                 :            : 
    1787                 :          0 :         status = ipsec_session_create(ipsec, sa_params, &sa->s);
    1788         [ #  # ]:          0 :         if (status) {
    1789                 :            :                 /* Free the allocated SADB entry. */
    1790                 :          0 :                 ipsec->sa_free_id[ipsec->n_sa_free_id] = sa_id;
    1791                 :          0 :                 ipsec->n_sa_free_id++;
    1792                 :            : 
    1793                 :          0 :                 return status;
    1794                 :            :         }
    1795                 :            : 
    1796                 :            :         /* Validate the new SA. */
    1797                 :          0 :         sa->valid = 1;
    1798                 :          0 :         *id = sa_id;
    1799                 :            : 
    1800                 :          0 :         return 0;
    1801                 :            : }
    1802                 :            : 
    1803                 :            : void
    1804                 :          0 : rte_swx_ipsec_sa_delete(struct rte_swx_ipsec *ipsec,
    1805                 :            :                         uint32_t sa_id)
    1806                 :            : {
    1807                 :            :         struct ipsec_sa *sa;
    1808                 :            : 
    1809                 :            :         /* Check the input parameters. */
    1810   [ #  #  #  # ]:          0 :         if (!ipsec || (sa_id >= ipsec->n_sa_max))
    1811                 :            :                 return;
    1812                 :            : 
    1813                 :            :         /* Release the SA resources. */
    1814                 :            :         sa = ipsec_sa_get(ipsec, sa_id);
    1815                 :            : 
    1816                 :          0 :         ipsec_session_free(ipsec, &sa->s);
    1817                 :            : 
    1818                 :            :         /* Free the SADB entry. */
    1819                 :          0 :         ipsec->sa_free_id[ipsec->n_sa_free_id] = sa_id;
    1820                 :          0 :         ipsec->n_sa_free_id++;
    1821                 :            : 
    1822                 :            :         /* Invalidate the SA. */
    1823                 :          0 :         sa->valid = 0;
    1824                 :            : }

Generated by: LCOV version 1.14