LCOV - code coverage report
Current view: top level - vnet/ipsec - ipsec.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 360 429 83.9 %
Date: 2023-07-05 22:20:52 Functions: 20 22 90.9 %

          Line data    Source code
       1             : /*
       2             :  * ipsec.c : IPSEC module functions
       3             :  *
       4             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vnet/vnet.h>
      19             : #include <vnet/api_errno.h>
      20             : #include <vnet/ip/ip.h>
      21             : #include <vnet/interface.h>
      22             : #include <vnet/udp/udp_local.h>
      23             : 
      24             : #include <vnet/ipsec/ipsec.h>
      25             : #include <vnet/ipsec/esp.h>
      26             : #include <vnet/ipsec/ah.h>
      27             : #include <vnet/ipsec/ipsec_tun.h>
      28             : #include <vnet/ipsec/ipsec_itf.h>
      29             : #include <vnet/ipsec/ipsec_spd_fp_lookup.h>
      30             : 
      31             : /* Flow cache is sized for 1 million flows with a load factor of .25.
      32             :  */
      33             : #define IPSEC4_OUT_SPD_DEFAULT_HASH_NUM_BUCKETS (1 << 22)
      34             : 
      35             : /* Flow cache is sized for 1 million flows with a load factor of .25.
      36             :  */
      37             : #define IPSEC4_SPD_DEFAULT_HASH_NUM_BUCKETS (1 << 22)
      38             : 
      39             : ipsec_main_t ipsec_main;
      40             : 
      41             : esp_async_post_next_t esp_encrypt_async_next;
      42             : esp_async_post_next_t esp_decrypt_async_next;
      43             : 
      44             : clib_error_t *
      45           0 : ipsec_register_next_header (vlib_main_t *vm, u8 next_header,
      46             :                             const char *next_node)
      47             : {
      48           0 :   ipsec_main_t *im = &ipsec_main;
      49           0 :   const vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) next_node);
      50             :   /* -post nodes (eg. esp4-decrypt-post) are siblings of non-post nodes (eg.
      51             :    * esp4-decrypt) and will therefore have the same next index */
      52           0 :   const vlib_node_t *esp_decrypt_nodes[] = {
      53           0 :     vlib_get_node (vm, im->esp4_decrypt_node_index),
      54           0 :     vlib_get_node (vm, im->esp6_decrypt_node_index),
      55           0 :     vlib_get_node (vm, im->esp4_decrypt_tun_node_index),
      56           0 :     vlib_get_node (vm, im->esp6_decrypt_tun_node_index),
      57             :   };
      58             :   uword slot, max;
      59             :   int i;
      60             : 
      61             :   /* looks for a next_index value that we can use for all esp decrypt nodes to
      62             :    * avoid maintaining different next index arrays... */
      63             : 
      64           0 :   slot = vlib_node_get_next (vm, esp_decrypt_nodes[0]->index, node->index);
      65           0 :   max = vec_len (esp_decrypt_nodes[0]->next_nodes);
      66           0 :   for (i = 1; i < ARRAY_LEN (esp_decrypt_nodes); i++)
      67             :     {
      68             :       /* if next node already exists, check it shares the same next_index */
      69           0 :       if (slot !=
      70           0 :           vlib_node_get_next (vm, esp_decrypt_nodes[i]->index, node->index))
      71           0 :         return clib_error_return (
      72             :           0, "next node already exists with different next index");
      73             :       /* compute a suitable slot from the max of all nodes next index */
      74           0 :       max = clib_max (max, vec_len (esp_decrypt_nodes[i]->next_nodes));
      75             :     }
      76             : 
      77           0 :   if (~0 == slot)
      78             :     {
      79             :       /* next node not there yet, add it using the computed max */
      80           0 :       slot = max;
      81           0 :       for (i = 0; i < ARRAY_LEN (esp_decrypt_nodes); i++)
      82           0 :         vlib_node_add_next_with_slot (vm, esp_decrypt_nodes[i]->index,
      83           0 :                                       node->index, slot);
      84             :     }
      85             : 
      86           0 :   im->next_header_registrations[next_header] = slot;
      87           0 :   return 0;
      88             : }
      89             : 
      90             : static clib_error_t *
      91         409 : ipsec_check_ah_support (ipsec_sa_t * sa)
      92             : {
      93         409 :   ipsec_main_t *im = &ipsec_main;
      94             : 
      95         409 :   if (sa->integ_alg == IPSEC_INTEG_ALG_NONE)
      96           0 :     return clib_error_return (0, "unsupported none integ-alg");
      97             : 
      98         409 :   if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
      99           0 :     return clib_error_return (0, "No crypto engine support for %U",
     100             :                               format_ipsec_integ_alg, sa->integ_alg);
     101             : 
     102         409 :   return 0;
     103             : }
     104             : 
     105             : static clib_error_t *
     106        6187 : ipsec_check_esp_support (ipsec_sa_t * sa)
     107             : {
     108        6187 :   ipsec_main_t *im = &ipsec_main;
     109             : 
     110        6187 :   if (IPSEC_INTEG_ALG_NONE != sa->integ_alg)
     111             :     {
     112        4433 :       if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
     113           0 :         return clib_error_return (0, "No crypto engine support for %U",
     114             :                                   format_ipsec_integ_alg, sa->integ_alg);
     115             :     }
     116        6187 :   if (IPSEC_CRYPTO_ALG_NONE != sa->crypto_alg)
     117             :     {
     118        5745 :       if (!vnet_crypto_is_set_handler (im->crypto_algs[sa->crypto_alg].alg))
     119           0 :         return clib_error_return (0, "No crypto engine support for %U",
     120             :                                   format_ipsec_crypto_alg, sa->crypto_alg);
     121             :     }
     122             : 
     123        6187 :   return (0);
     124             : }
     125             : 
     126             : clib_error_t *
     127           0 : ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
     128             : {
     129           0 :   ipsec_ah_backend_t *ah =
     130           0 :     pool_elt_at_index (im->ah_backends, im->ah_current_backend);
     131           0 :   if (ah->add_del_sa_sess_cb)
     132             :     {
     133           0 :       clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
     134           0 :       if (err)
     135           0 :         return err;
     136             :     }
     137           0 :   ipsec_esp_backend_t *esp =
     138           0 :     pool_elt_at_index (im->esp_backends, im->esp_current_backend);
     139           0 :   if (esp->add_del_sa_sess_cb)
     140             :     {
     141           0 :       clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
     142           0 :       if (err)
     143           0 :         return err;
     144             :     }
     145           0 :   return 0;
     146             : }
     147             : 
     148             : clib_error_t *
     149        6596 : ipsec_check_support_cb (ipsec_main_t * im, ipsec_sa_t * sa)
     150             : {
     151        6596 :   clib_error_t *error = 0;
     152             : 
     153        6596 :   if (PREDICT_FALSE (sa->protocol == IPSEC_PROTOCOL_AH))
     154             :     {
     155         409 :       ipsec_ah_backend_t *ah =
     156         409 :         pool_elt_at_index (im->ah_backends, im->ah_current_backend);
     157         409 :       ASSERT (ah->check_support_cb);
     158         409 :       error = ah->check_support_cb (sa);
     159             :     }
     160             :   else
     161             :     {
     162        6187 :       ipsec_esp_backend_t *esp =
     163        6187 :         pool_elt_at_index (im->esp_backends, im->esp_current_backend);
     164        6187 :       ASSERT (esp->check_support_cb);
     165        6187 :       error = esp->check_support_cb (sa);
     166             :     }
     167        6596 :   return error;
     168             : }
     169             : 
     170             : 
     171             : static void
     172        5590 : ipsec_add_node (vlib_main_t * vm, const char *node_name,
     173             :                 const char *prev_node_name, u32 * out_node_index,
     174             :                 u32 * out_next_index)
     175             : {
     176             :   vlib_node_t *prev_node, *node;
     177        5590 :   prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
     178        5590 :   ASSERT (prev_node);
     179        5590 :   node = vlib_get_node_by_name (vm, (u8 *) node_name);
     180        5590 :   ASSERT (node);
     181        5590 :   *out_node_index = node->index;
     182        5590 :   *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
     183        5590 : }
     184             : 
     185             : static inline uword
     186         387 : ipsec_udp_registration_key (u16 port, u8 is_ip4)
     187             : {
     188         387 :   uword key = (is_ip4) ? AF_IP4 : AF_IP6;
     189             : 
     190         387 :   key |= (uword) (port << 16);
     191         387 :   return key;
     192             : }
     193             : 
     194             : void
     195         188 : ipsec_unregister_udp_port (u16 port, u8 is_ip4)
     196             : {
     197         188 :   ipsec_main_t *im = &ipsec_main;
     198             :   u32 n_regs;
     199             :   uword *p, key;
     200             : 
     201         188 :   key = ipsec_udp_registration_key (port, is_ip4);
     202         188 :   p = hash_get (im->udp_port_registrations, key);
     203             : 
     204         188 :   ASSERT (p);
     205             : 
     206         188 :   n_regs = p[0];
     207             : 
     208         188 :   if (0 == --n_regs)
     209             :     {
     210         174 :       udp_unregister_dst_port (vlib_get_main (), port, is_ip4);
     211         174 :       hash_unset (im->udp_port_registrations, key);
     212             :     }
     213             :   else
     214             :     {
     215          14 :       hash_unset (im->udp_port_registrations, key);
     216          14 :       hash_set (im->udp_port_registrations, key, n_regs);
     217             :     }
     218         188 : }
     219             : 
     220             : void
     221         199 : ipsec_register_udp_port (u16 port, u8 is_ip4)
     222             : {
     223         199 :   ipsec_main_t *im = &ipsec_main;
     224             :   u32 n_regs, node_index;
     225             :   uword *p, key;
     226             : 
     227         199 :   key = ipsec_udp_registration_key (port, is_ip4);
     228         199 :   node_index =
     229         199 :     (is_ip4) ? ipsec4_tun_input_node.index : ipsec6_tun_input_node.index;
     230         199 :   p = hash_get (im->udp_port_registrations, key);
     231             : 
     232         199 :   n_regs = (p ? p[0] : 0);
     233             : 
     234         199 :   if (0 == n_regs++)
     235         185 :     udp_register_dst_port (vlib_get_main (), port, node_index, is_ip4);
     236             : 
     237         199 :   hash_unset (im->udp_port_registrations, key);
     238         199 :   hash_set (im->udp_port_registrations, key, n_regs);
     239         199 : }
     240             : 
     241             : u32
     242         559 : ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
     243             :                            const char *name,
     244             :                            const char *ah4_encrypt_node_name,
     245             :                            const char *ah4_decrypt_node_name,
     246             :                            const char *ah6_encrypt_node_name,
     247             :                            const char *ah6_decrypt_node_name,
     248             :                            check_support_cb_t ah_check_support_cb,
     249             :                            add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
     250             : {
     251             :   ipsec_ah_backend_t *b;
     252         559 :   pool_get (im->ah_backends, b);
     253         559 :   b->name = format (0, "%s%c", name, 0);
     254             : 
     255         559 :   ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output-feature",
     256         559 :                   &b->ah4_encrypt_node_index, &b->ah4_encrypt_next_index);
     257         559 :   ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input-feature",
     258         559 :                   &b->ah4_decrypt_node_index, &b->ah4_decrypt_next_index);
     259         559 :   ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output-feature",
     260         559 :                   &b->ah6_encrypt_node_index, &b->ah6_encrypt_next_index);
     261         559 :   ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input-feature",
     262         559 :                   &b->ah6_decrypt_node_index, &b->ah6_decrypt_next_index);
     263             : 
     264         559 :   b->check_support_cb = ah_check_support_cb;
     265         559 :   b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
     266         559 :   return b - im->ah_backends;
     267             : }
     268             : 
     269             : u32
     270         559 : ipsec_register_esp_backend (
     271             :   vlib_main_t *vm, ipsec_main_t *im, const char *name,
     272             :   const char *esp4_encrypt_node_name, const char *esp4_encrypt_node_tun_name,
     273             :   const char *esp4_decrypt_node_name, const char *esp4_decrypt_tun_node_name,
     274             :   const char *esp6_encrypt_node_name, const char *esp6_encrypt_node_tun_name,
     275             :   const char *esp6_decrypt_node_name, const char *esp6_decrypt_tun_node_name,
     276             :   const char *esp_mpls_encrypt_node_tun_name,
     277             :   check_support_cb_t esp_check_support_cb,
     278             :   add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
     279             : {
     280             :   ipsec_esp_backend_t *b;
     281             : 
     282         559 :   pool_get (im->esp_backends, b);
     283         559 :   b->name = format (0, "%s%c", name, 0);
     284             : 
     285         559 :   ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output-feature",
     286         559 :                   &b->esp4_encrypt_node_index, &b->esp4_encrypt_next_index);
     287         559 :   ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input-feature",
     288         559 :                   &b->esp4_decrypt_node_index, &b->esp4_decrypt_next_index);
     289         559 :   ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output-feature",
     290         559 :                   &b->esp6_encrypt_node_index, &b->esp6_encrypt_next_index);
     291         559 :   ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
     292         559 :                   &b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
     293         559 :   ipsec_add_node (vm, esp4_decrypt_tun_node_name, "ipsec4-tun-input",
     294         559 :                   &b->esp4_decrypt_tun_node_index,
     295         559 :                   &b->esp4_decrypt_tun_next_index);
     296         559 :   ipsec_add_node (vm, esp6_decrypt_tun_node_name, "ipsec6-tun-input",
     297         559 :                   &b->esp6_decrypt_tun_node_index,
     298         559 :                   &b->esp6_decrypt_tun_next_index);
     299             : 
     300         559 :   b->esp6_encrypt_tun_node_index =
     301         559 :     vlib_get_node_by_name (vm, (u8 *) esp6_encrypt_node_tun_name)->index;
     302         559 :   b->esp_mpls_encrypt_tun_node_index =
     303         559 :     vlib_get_node_by_name (vm, (u8 *) esp_mpls_encrypt_node_tun_name)->index;
     304         559 :   b->esp4_encrypt_tun_node_index =
     305         559 :     vlib_get_node_by_name (vm, (u8 *) esp4_encrypt_node_tun_name)->index;
     306             : 
     307         559 :   b->check_support_cb = esp_check_support_cb;
     308         559 :   b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
     309             : 
     310         559 :   return b - im->esp_backends;
     311             : }
     312             : 
     313             : clib_error_t *
     314        1123 : ipsec_rsc_in_use (ipsec_main_t * im)
     315             : {
     316             :   /* return an error is crypto resource are in use */
     317        1123 :   if (pool_elts (ipsec_sa_pool) > 0)
     318           0 :     return clib_error_return (0, "%d SA entries configured",
     319             :                               pool_elts (ipsec_sa_pool));
     320        1123 :   if (ipsec_itf_count () > 0)
     321           0 :     return clib_error_return (0, "%d IPSec interface configured",
     322             :                               ipsec_itf_count ());
     323             : 
     324        1123 :   return (NULL);
     325             : }
     326             : 
     327             : int
     328         562 : ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
     329             : {
     330         562 :   if (ipsec_rsc_in_use (im))
     331           0 :     return VNET_API_ERROR_RSRC_IN_USE;
     332             : 
     333         562 :   if (pool_is_free_index (im->ah_backends, backend_idx))
     334           1 :     return VNET_API_ERROR_INVALID_VALUE;
     335             : 
     336         561 :   ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
     337         561 :   im->ah_current_backend = backend_idx;
     338         561 :   im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
     339         561 :   im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
     340         561 :   im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
     341         561 :   im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
     342         561 :   im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
     343         561 :   im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
     344         561 :   im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
     345         561 :   im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
     346             : 
     347         561 :   return 0;
     348             : }
     349             : 
     350             : int
     351         561 : ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
     352             : {
     353         561 :   if (ipsec_rsc_in_use (im))
     354           0 :     return VNET_API_ERROR_RSRC_IN_USE;
     355             : 
     356         561 :   if (pool_is_free_index (im->esp_backends, backend_idx))
     357           1 :     return VNET_API_ERROR_INVALID_VALUE;
     358             : 
     359         560 :   ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
     360         560 :   im->esp_current_backend = backend_idx;
     361         560 :   im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
     362         560 :   im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
     363         560 :   im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
     364         560 :   im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
     365         560 :   im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
     366         560 :   im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
     367         560 :   im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
     368         560 :   im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
     369         560 :   im->esp4_decrypt_tun_node_index = b->esp4_decrypt_tun_node_index;
     370         560 :   im->esp4_decrypt_tun_next_index = b->esp4_decrypt_tun_next_index;
     371         560 :   im->esp6_decrypt_tun_node_index = b->esp6_decrypt_tun_node_index;
     372         560 :   im->esp6_decrypt_tun_next_index = b->esp6_decrypt_tun_next_index;
     373         560 :   im->esp4_encrypt_tun_node_index = b->esp4_encrypt_tun_node_index;
     374         560 :   im->esp6_encrypt_tun_node_index = b->esp6_encrypt_tun_node_index;
     375         560 :   im->esp_mpls_encrypt_tun_node_index = b->esp_mpls_encrypt_tun_node_index;
     376             : 
     377         560 :   return 0;
     378             : }
     379             : 
     380             : void
     381          22 : ipsec_set_async_mode (u32 is_enabled)
     382             : {
     383          22 :   ipsec_main_t *im = &ipsec_main;
     384             :   ipsec_sa_t *sa;
     385             : 
     386          22 :   im->async_mode = is_enabled;
     387             : 
     388             :   /* change SA crypto op data */
     389          40 :   pool_foreach (sa, ipsec_sa_pool)
     390          18 :     ipsec_sa_set_async_mode (sa, is_enabled);
     391          22 : }
     392             : 
     393             : static void
     394         559 : crypto_engine_backend_register_post_node (vlib_main_t * vm)
     395             : {
     396             :   esp_async_post_next_t *eit;
     397             :   esp_async_post_next_t *dit;
     398             : 
     399         559 :   eit = &esp_encrypt_async_next;
     400         559 :   eit->esp4_post_next =
     401         559 :     vnet_crypto_register_post_node (vm, "esp4-encrypt-post");
     402         559 :   eit->esp6_post_next =
     403         559 :     vnet_crypto_register_post_node (vm, "esp6-encrypt-post");
     404         559 :   eit->esp4_tun_post_next =
     405         559 :     vnet_crypto_register_post_node (vm, "esp4-encrypt-tun-post");
     406         559 :   eit->esp6_tun_post_next =
     407         559 :     vnet_crypto_register_post_node (vm, "esp6-encrypt-tun-post");
     408         559 :   eit->esp_mpls_tun_post_next =
     409         559 :     vnet_crypto_register_post_node (vm, "esp-mpls-encrypt-tun-post");
     410             : 
     411         559 :   dit = &esp_decrypt_async_next;
     412         559 :   dit->esp4_post_next =
     413         559 :     vnet_crypto_register_post_node (vm, "esp4-decrypt-post");
     414         559 :   dit->esp6_post_next =
     415         559 :     vnet_crypto_register_post_node (vm, "esp6-decrypt-post");
     416         559 :   dit->esp4_tun_post_next =
     417         559 :     vnet_crypto_register_post_node (vm, "esp4-decrypt-tun-post");
     418         559 :   dit->esp6_tun_post_next =
     419         559 :     vnet_crypto_register_post_node (vm, "esp6-decrypt-tun-post");
     420         559 : }
     421             : 
     422             : static clib_error_t *
     423         559 : ipsec_init (vlib_main_t * vm)
     424             : {
     425             :   clib_error_t *error;
     426         559 :   ipsec_main_t *im = &ipsec_main;
     427             :   ipsec_main_crypto_alg_t *a;
     428             : 
     429             :   /* Backend registration requires the feature arcs to be set up */
     430         559 :   if ((error = vlib_call_init_function (vm, vnet_feature_init)))
     431           0 :     return (error);
     432             : 
     433         559 :   im->vnet_main = vnet_get_main ();
     434         559 :   im->vlib_main = vm;
     435             : 
     436         559 :   im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
     437         559 :   im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
     438         559 :   im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
     439             : 
     440         559 :   vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
     441         559 :   ASSERT (node);
     442         559 :   im->error_drop_node_index = node->index;
     443             : 
     444         559 :   im->ah_current_backend = ~0;
     445         559 :   im->esp_current_backend = ~0;
     446             : 
     447         559 :   u32 idx = ipsec_register_ah_backend (vm, im, "crypto engine backend",
     448             :                                        "ah4-encrypt",
     449             :                                        "ah4-decrypt",
     450             :                                        "ah6-encrypt",
     451             :                                        "ah6-decrypt",
     452             :                                        ipsec_check_ah_support,
     453             :                                        NULL);
     454             : 
     455         559 :   im->ah_default_backend = idx;
     456         559 :   int rv = ipsec_select_ah_backend (im, idx);
     457         559 :   ASSERT (0 == rv);
     458             :   (void) (rv);                  // avoid warning
     459             : 
     460         559 :   idx = ipsec_register_esp_backend (
     461             :     vm, im, "crypto engine backend", "esp4-encrypt", "esp4-encrypt-tun",
     462             :     "esp4-decrypt", "esp4-decrypt-tun", "esp6-encrypt", "esp6-encrypt-tun",
     463             :     "esp6-decrypt", "esp6-decrypt-tun", "esp-mpls-encrypt-tun",
     464             :     ipsec_check_esp_support, NULL);
     465         559 :   im->esp_default_backend = idx;
     466             : 
     467         559 :   rv = ipsec_select_esp_backend (im, idx);
     468         559 :   ASSERT (0 == rv);
     469             :   (void) (rv);                  // avoid warning
     470             : 
     471         559 :   if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
     472           0 :     return error;
     473             : 
     474         559 :   vec_validate (im->crypto_algs, IPSEC_CRYPTO_N_ALG - 1);
     475             : 
     476         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_NONE;
     477         559 :   a->enc_op_id = VNET_CRYPTO_OP_NONE;
     478         559 :   a->dec_op_id = VNET_CRYPTO_OP_NONE;
     479         559 :   a->alg = VNET_CRYPTO_ALG_NONE;
     480         559 :   a->iv_size = 0;
     481         559 :   a->block_align = 1;
     482             : 
     483         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
     484         559 :   a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
     485         559 :   a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
     486         559 :   a->alg = VNET_CRYPTO_ALG_DES_CBC;
     487         559 :   a->iv_size = a->block_align = 8;
     488             : 
     489         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
     490         559 :   a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
     491         559 :   a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
     492         559 :   a->alg = VNET_CRYPTO_ALG_3DES_CBC;
     493         559 :   a->iv_size = a->block_align = 8;
     494             : 
     495         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
     496         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
     497         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
     498         559 :   a->alg = VNET_CRYPTO_ALG_AES_128_CBC;
     499         559 :   a->iv_size = a->block_align = 16;
     500             : 
     501         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
     502         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
     503         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
     504         559 :   a->alg = VNET_CRYPTO_ALG_AES_192_CBC;
     505         559 :   a->iv_size = a->block_align = 16;
     506             : 
     507         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
     508         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
     509         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
     510         559 :   a->alg = VNET_CRYPTO_ALG_AES_256_CBC;
     511         559 :   a->iv_size = a->block_align = 16;
     512             : 
     513         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CTR_128;
     514         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_128_CTR_ENC;
     515         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_128_CTR_DEC;
     516         559 :   a->alg = VNET_CRYPTO_ALG_AES_128_CTR;
     517         559 :   a->iv_size = 8;
     518         559 :   a->block_align = 1;
     519             : 
     520         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CTR_192;
     521         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_192_CTR_ENC;
     522         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_192_CTR_DEC;
     523         559 :   a->alg = VNET_CRYPTO_ALG_AES_192_CTR;
     524         559 :   a->iv_size = 8;
     525         559 :   a->block_align = 1;
     526             : 
     527         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CTR_256;
     528         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_256_CTR_ENC;
     529         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_256_CTR_DEC;
     530         559 :   a->alg = VNET_CRYPTO_ALG_AES_256_CTR;
     531         559 :   a->iv_size = 8;
     532         559 :   a->block_align = 1;
     533             : 
     534         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
     535         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
     536         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
     537         559 :   a->alg = VNET_CRYPTO_ALG_AES_128_GCM;
     538         559 :   a->iv_size = 8;
     539         559 :   a->block_align = 1;
     540         559 :   a->icv_size = 16;
     541             : 
     542         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_192;
     543         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
     544         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
     545         559 :   a->alg = VNET_CRYPTO_ALG_AES_192_GCM;
     546         559 :   a->iv_size = 8;
     547         559 :   a->block_align = 1;
     548         559 :   a->icv_size = 16;
     549             : 
     550         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
     551         559 :   a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
     552         559 :   a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
     553         559 :   a->alg = VNET_CRYPTO_ALG_AES_256_GCM;
     554         559 :   a->iv_size = 8;
     555         559 :   a->block_align = 1;
     556         559 :   a->icv_size = 16;
     557             : 
     558         559 :   a = im->crypto_algs + IPSEC_CRYPTO_ALG_CHACHA20_POLY1305;
     559         559 :   a->enc_op_id = VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC;
     560         559 :   a->dec_op_id = VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC;
     561         559 :   a->alg = VNET_CRYPTO_ALG_CHACHA20_POLY1305;
     562         559 :   a->iv_size = 8;
     563         559 :   a->icv_size = 16;
     564             : 
     565         559 :   vec_validate (im->integ_algs, IPSEC_INTEG_N_ALG - 1);
     566             :   ipsec_main_integ_alg_t *i;
     567             : 
     568         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_MD5_96];
     569         559 :   i->op_id = VNET_CRYPTO_OP_MD5_HMAC;
     570         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_MD5;
     571         559 :   i->icv_size = 12;
     572             : 
     573         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
     574         559 :   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
     575         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_SHA1;
     576         559 :   i->icv_size = 12;
     577             : 
     578         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
     579         559 :   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
     580         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
     581         559 :   i->icv_size = 12;
     582             : 
     583         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
     584         559 :   i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
     585         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
     586         559 :   i->icv_size = 16;
     587             : 
     588         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
     589         559 :   i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
     590         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_SHA384;
     591         559 :   i->icv_size = 24;
     592             : 
     593         559 :   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
     594         559 :   i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
     595         559 :   i->alg = VNET_CRYPTO_ALG_HMAC_SHA512;
     596         559 :   i->icv_size = 32;
     597             : 
     598         559 :   vec_validate_aligned (im->ptd, vlib_num_workers (), CLIB_CACHE_LINE_BYTES);
     599             : 
     600         559 :   im->async_mode = 0;
     601         559 :   crypto_engine_backend_register_post_node (vm);
     602             : 
     603         559 :   im->ipsec4_out_spd_hash_tbl = NULL;
     604         559 :   im->output_flow_cache_flag = 0;
     605         559 :   im->ipsec4_out_spd_flow_cache_entries = 0;
     606         559 :   im->epoch_count = 0;
     607         559 :   im->ipsec4_out_spd_hash_num_buckets =
     608             :     IPSEC4_OUT_SPD_DEFAULT_HASH_NUM_BUCKETS;
     609             : 
     610         559 :   im->ipsec4_in_spd_hash_tbl = NULL;
     611         559 :   im->input_flow_cache_flag = 0;
     612         559 :   im->ipsec4_in_spd_flow_cache_entries = 0;
     613         559 :   im->input_epoch_count = 0;
     614         559 :   im->ipsec4_in_spd_hash_num_buckets = IPSEC4_SPD_DEFAULT_HASH_NUM_BUCKETS;
     615             : 
     616      143663 :   vec_validate_init_empty_aligned (im->next_header_registrations, 255, ~0,
     617             :                                    CLIB_CACHE_LINE_BYTES);
     618             : 
     619         559 :   im->fp_spd_ipv4_out_is_enabled = 0;
     620         559 :   im->fp_spd_ipv6_out_is_enabled = 0;
     621         559 :   im->fp_spd_ipv4_in_is_enabled = 0;
     622         559 :   im->fp_spd_ipv6_in_is_enabled = 0;
     623             : 
     624         559 :   im->fp_lookup_hash_buckets = IPSEC_FP_HASH_LOOKUP_HASH_BUCKETS;
     625             : 
     626         559 :   return 0;
     627             : }
     628             : 
     629       50959 : VLIB_INIT_FUNCTION (ipsec_init);
     630             : 
     631             : static clib_error_t *
     632         559 : ipsec_config (vlib_main_t *vm, unformat_input_t *input)
     633             : {
     634         559 :   ipsec_main_t *im = &ipsec_main;
     635             :   unformat_input_t sub_input;
     636             : 
     637             :   u32 ipsec4_out_spd_hash_num_buckets;
     638             :   u32 ipsec4_in_spd_hash_num_buckets;
     639             :   u32 ipsec_spd_fp_num_buckets;
     640         559 :   bool fp_spd_ip4_enabled = false;
     641         559 :   bool fp_spd_ip6_enabled = false;
     642             : 
     643         598 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     644             :     {
     645          39 :       if (unformat (input, "ipv6-outbound-spd-fast-path on"))
     646             :         {
     647           7 :           im->fp_spd_ipv6_out_is_enabled = 1;
     648           7 :           fp_spd_ip6_enabled = true;
     649             :         }
     650          32 :       else if (unformat (input, "ipv6-outbound-spd-fast-path off"))
     651           0 :         im->fp_spd_ipv6_out_is_enabled = 0;
     652          32 :       else if (unformat (input, "ipv4-outbound-spd-fast-path on"))
     653             :         {
     654           8 :           im->fp_spd_ipv4_out_is_enabled = 1;
     655           8 :           im->output_flow_cache_flag = 0;
     656           8 :           fp_spd_ip4_enabled = true;
     657             :         }
     658          24 :       else if (unformat (input, "ipv4-outbound-spd-fast-path off"))
     659           0 :         im->fp_spd_ipv4_out_is_enabled = 0;
     660          24 :       else if (unformat (input, "ipv6-inbound-spd-fast-path on"))
     661             :         {
     662           1 :           im->fp_spd_ipv6_in_is_enabled = 1;
     663           1 :           fp_spd_ip6_enabled = true;
     664             :         }
     665          23 :       else if (unformat (input, "ipv6-inbound-spd-fast-path off"))
     666           0 :         im->fp_spd_ipv6_in_is_enabled = 0;
     667          23 :       else if (unformat (input, "ipv4-inbound-spd-fast-path on"))
     668             :         {
     669           8 :           im->fp_spd_ipv4_in_is_enabled = 1;
     670           8 :           im->input_flow_cache_flag = 0;
     671           8 :           fp_spd_ip4_enabled = true;
     672             :         }
     673          15 :       else if (unformat (input, "ipv4-inbound-spd-fast-path off"))
     674           0 :         im->fp_spd_ipv4_in_is_enabled = 0;
     675          15 :       else if (unformat (input, "spd-fast-path-num-buckets %d",
     676             :                          &ipsec_spd_fp_num_buckets))
     677             :         {
     678             :           /* Number of bihash buckets is power of 2 >= input */
     679           0 :           im->fp_lookup_hash_buckets = 1ULL
     680           0 :                                        << max_log2 (ipsec_spd_fp_num_buckets);
     681             :         }
     682          15 :       else if (unformat (input, "ipv4-outbound-spd-flow-cache on"))
     683           6 :         im->output_flow_cache_flag = im->fp_spd_ipv4_out_is_enabled ? 0 : 1;
     684           9 :       else if (unformat (input, "ipv4-outbound-spd-flow-cache off"))
     685           0 :         im->output_flow_cache_flag = 0;
     686           9 :       else if (unformat (input, "ipv4-outbound-spd-hash-buckets %d",
     687             :                          &ipsec4_out_spd_hash_num_buckets))
     688             :         {
     689             :           /* Size of hash is power of 2 >= number of buckets */
     690           1 :           im->ipsec4_out_spd_hash_num_buckets =
     691           1 :             1ULL << max_log2 (ipsec4_out_spd_hash_num_buckets);
     692             :         }
     693           8 :       else if (unformat (input, "ipv4-inbound-spd-flow-cache on"))
     694           7 :         im->input_flow_cache_flag = im->fp_spd_ipv4_in_is_enabled ? 0 : 1;
     695           1 :       else if (unformat (input, "ipv4-inbound-spd-flow-cache off"))
     696           0 :         im->input_flow_cache_flag = 0;
     697           1 :       else if (unformat (input, "ipv4-inbound-spd-hash-buckets %d",
     698             :                          &ipsec4_in_spd_hash_num_buckets))
     699             :         {
     700           1 :           im->ipsec4_in_spd_hash_num_buckets =
     701           1 :             1ULL << max_log2 (ipsec4_in_spd_hash_num_buckets);
     702             :         }
     703           0 :       else if (unformat (input, "ip4 %U", unformat_vlib_cli_sub_input,
     704             :                          &sub_input))
     705             :         {
     706           0 :           uword table_size = ~0;
     707           0 :           u32 n_buckets = ~0;
     708             : 
     709           0 :           while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT)
     710             :             {
     711           0 :               if (unformat (&sub_input, "num-buckets %u", &n_buckets))
     712             :                 ;
     713             :               else
     714           0 :                 return clib_error_return (0, "unknown input `%U'",
     715             :                                           format_unformat_error, &sub_input);
     716             :             }
     717             : 
     718           0 :           ipsec_tun_table_init (AF_IP4, table_size, n_buckets);
     719             :         }
     720           0 :       else if (unformat (input, "ip6 %U", unformat_vlib_cli_sub_input,
     721             :                          &sub_input))
     722             :         {
     723           0 :           uword table_size = ~0;
     724           0 :           u32 n_buckets = ~0;
     725             : 
     726           0 :           while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT)
     727             :             {
     728           0 :               if (unformat (&sub_input, "num-buckets %u", &n_buckets))
     729             :                 ;
     730             :               else
     731           0 :                 return clib_error_return (0, "unknown input `%U'",
     732             :                                           format_unformat_error, &sub_input);
     733             :             }
     734             : 
     735           0 :           ipsec_tun_table_init (AF_IP6, table_size, n_buckets);
     736             :         }
     737             :       else
     738           0 :         return clib_error_return (0, "unknown input `%U'",
     739             :                                   format_unformat_error, input);
     740             :     }
     741         559 :   if (im->output_flow_cache_flag)
     742             :     {
     743           6 :       vec_add2 (im->ipsec4_out_spd_hash_tbl, im->ipsec4_out_spd_hash_tbl,
     744             :                 im->ipsec4_out_spd_hash_num_buckets);
     745             :     }
     746         559 :   if (im->input_flow_cache_flag)
     747             :     {
     748           7 :       vec_add2 (im->ipsec4_in_spd_hash_tbl, im->ipsec4_in_spd_hash_tbl,
     749             :                 im->ipsec4_in_spd_hash_num_buckets);
     750             :     }
     751             : 
     752         559 :   if (fp_spd_ip4_enabled)
     753          16 :     pool_alloc_aligned (im->fp_ip4_lookup_hashes_pool,
     754             :                         IPSEC_FP_IP4_HASHES_POOL_SIZE, CLIB_CACHE_LINE_BYTES);
     755             : 
     756         559 :   if (fp_spd_ip6_enabled)
     757           8 :     pool_alloc_aligned (im->fp_ip6_lookup_hashes_pool,
     758             :                         IPSEC_FP_IP6_HASHES_POOL_SIZE, CLIB_CACHE_LINE_BYTES);
     759             : 
     760         559 :   return 0;
     761             : }
     762             : 
     763        7306 : VLIB_CONFIG_FUNCTION (ipsec_config, "ipsec");
     764             : 
     765             : /*
     766             :  * fd.io coding-style-patch-verification: ON
     767             :  *
     768             :  * Local Variables:
     769             :  * eval: (c-set-style "gnu")
     770             :  * End:
     771             :  */

Generated by: LCOV version 1.14