LCOV - code coverage report
Current view: top level - vnet/ipsec - ipsec_spd.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 108 113 95.6 %
Date: 2023-07-05 22:20:52 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/ipsec/ipsec.h>
      17             : #include <vnet/ipsec/ipsec_io.h>
      18             : 
      19             : int
      20        3168 : ipsec_add_del_spd (vlib_main_t * vm, u32 spd_id, int is_add)
      21             : {
      22        3168 :   ipsec_main_t *im = &ipsec_main;
      23        3168 :   ipsec_spd_t *spd = 0;
      24        3168 :   ipsec_spd_fp_t *fp_spd = 0;
      25             :   uword *p;
      26             :   u32 spd_index, k, v;
      27             : 
      28        3168 :   p = hash_get (im->spd_index_by_spd_id, spd_id);
      29        3168 :   if (p && is_add)
      30           0 :     return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
      31        3168 :   if (!p && !is_add)
      32           0 :     return VNET_API_ERROR_NO_SUCH_ENTRY;
      33             : 
      34        3168 :   if (!is_add)                  /* delete */
      35             :     {
      36        1584 :       spd_index = p[0];
      37        1584 :       spd = pool_elt_at_index (im->spds, spd_index);
      38        1584 :       if (!spd)
      39           0 :         return VNET_API_ERROR_INVALID_VALUE;
      40             : 
      41             :       /* *INDENT-OFF* */
      42      102964 :       hash_foreach (k, v, im->spd_index_by_sw_if_index, ({
      43             :         if (v == spd_index)
      44             :           ipsec_set_interface_spd(vm, k, spd_id, 0);
      45             :       }));
      46             :       /* *INDENT-ON* */
      47        1584 :       hash_unset (im->spd_index_by_spd_id, spd_id);
      48             : #define _(s,v) vec_free(spd->policies[IPSEC_SPD_POLICY_##s]);
      49        1584 :       foreach_ipsec_spd_policy_type
      50             : #undef _
      51             : 
      52        1584 :         fp_spd = &spd->fp_spd;
      53             : 
      54        1584 :       if (im->fp_spd_ipv4_out_is_enabled)
      55             :         {
      56           8 :           if (fp_spd->ip4_out_lookup_hash_idx != INDEX_INVALID)
      57             :             {
      58           8 :               clib_bihash_16_8_t *bihash_table =
      59           8 :                 pool_elt_at_index (im->fp_ip4_lookup_hashes_pool,
      60             :                                    fp_spd->ip4_out_lookup_hash_idx);
      61             : 
      62           8 :               clib_bihash_free_16_8 (bihash_table);
      63           8 :               vec_free (fp_spd->name4_out);
      64           8 :               pool_put_index (im->fp_ip4_lookup_hashes_pool,
      65             :                               fp_spd->ip4_out_lookup_hash_idx);
      66             :             }
      67             :         }
      68             : 
      69        1584 :       if (im->fp_spd_ipv4_in_is_enabled)
      70             :         {
      71           9 :           if (fp_spd->ip4_in_lookup_hash_idx != INDEX_INVALID)
      72             :             {
      73           9 :               clib_bihash_16_8_t *bihash_table = pool_elt_at_index (
      74             :                 im->fp_ip4_lookup_hashes_pool, fp_spd->ip4_in_lookup_hash_idx);
      75             : 
      76           9 :               clib_bihash_free_16_8 (bihash_table);
      77           9 :               vec_free (fp_spd->name4_in);
      78           9 :               pool_put_index (im->fp_ip4_lookup_hashes_pool,
      79             :                               fp_spd->ip4_in_lookup_hash_idx);
      80             :             }
      81             :         }
      82             : 
      83        1584 :       if (im->fp_spd_ipv6_out_is_enabled)
      84             :         {
      85           7 :           if (fp_spd->ip6_out_lookup_hash_idx != INDEX_INVALID)
      86             :             {
      87           7 :               clib_bihash_40_8_t *bihash_table =
      88           7 :                 pool_elt_at_index (im->fp_ip6_lookup_hashes_pool,
      89             :                                    fp_spd->ip6_out_lookup_hash_idx);
      90             : 
      91           7 :               clib_bihash_free_40_8 (bihash_table);
      92           7 :               vec_free (fp_spd->name6_out);
      93           7 :               pool_put_index (im->fp_ip6_lookup_hashes_pool,
      94             :                               fp_spd->ip6_out_lookup_hash_idx);
      95             :             }
      96             :         }
      97        1584 :       if (im->fp_spd_ipv6_in_is_enabled)
      98             :         {
      99           2 :           if (fp_spd->ip6_in_lookup_hash_idx != INDEX_INVALID)
     100             :             {
     101           2 :               clib_bihash_40_8_t *bihash_table = pool_elt_at_index (
     102             :                 im->fp_ip6_lookup_hashes_pool, fp_spd->ip6_in_lookup_hash_idx);
     103             : 
     104           2 :               clib_bihash_free_40_8 (bihash_table);
     105           2 :               vec_free (fp_spd->name6_in);
     106           2 :               pool_put_index (im->fp_ip6_lookup_hashes_pool,
     107             :                               fp_spd->ip6_in_lookup_hash_idx);
     108             :             }
     109             :         }
     110             : 
     111        1584 :       pool_put (im->spds, spd);
     112             :     }
     113             :   else /* create new SPD */
     114             :     {
     115        1584 :       pool_get (im->spds, spd);
     116        1584 :       clib_memset (spd, 0, sizeof (*spd));
     117        1584 :       spd_index = spd - im->spds;
     118        1584 :       spd->id = spd_id;
     119        1584 :       hash_set (im->spd_index_by_spd_id, spd_id, spd_index);
     120             : 
     121        1584 :       fp_spd = &spd->fp_spd;
     122        1584 :       fp_spd->ip4_out_lookup_hash_idx = INDEX_INVALID;
     123        1584 :       fp_spd->ip4_in_lookup_hash_idx = INDEX_INVALID;
     124        1584 :       fp_spd->ip6_out_lookup_hash_idx = INDEX_INVALID;
     125        1584 :       fp_spd->ip6_in_lookup_hash_idx = INDEX_INVALID;
     126             : 
     127        1584 :       if (im->fp_spd_ipv4_out_is_enabled)
     128             :         {
     129          16 :           if (pool_elts (im->fp_ip4_lookup_hashes_pool) <
     130           8 :               pool_max_len (im->fp_ip4_lookup_hashes_pool))
     131             :             {
     132             :               clib_bihash_16_8_t *bihash_table;
     133           8 :               fp_spd->name4_out = format (0, "spd_%u_fp_ip4_out", spd_id);
     134             : 
     135           8 :               pool_get (im->fp_ip4_lookup_hashes_pool, bihash_table);
     136           8 :               fp_spd->ip4_out_lookup_hash_idx =
     137           8 :                 bihash_table - im->fp_ip4_lookup_hashes_pool;
     138           8 :               clib_bihash_init_16_8 (bihash_table, (char *) fp_spd->name4_out,
     139             :                                      im->fp_lookup_hash_buckets,
     140           8 :                                      im->fp_lookup_hash_buckets *
     141             :                                        IPSEC_FP_IP4_HASH_MEM_PER_BUCKET);
     142             :             }
     143             :         }
     144             : 
     145        1584 :       if (im->fp_spd_ipv4_in_is_enabled)
     146             :         {
     147          18 :           if (pool_elts (im->fp_ip4_lookup_hashes_pool) <
     148           9 :               pool_max_len (im->fp_ip4_lookup_hashes_pool))
     149             :             {
     150             :               clib_bihash_16_8_t *bihash_table;
     151           9 :               fp_spd->name4_in = format (0, "spd_%u_fp_ip4_in", spd_id);
     152             : 
     153           9 :               pool_get (im->fp_ip4_lookup_hashes_pool, bihash_table);
     154           9 :               fp_spd->ip4_in_lookup_hash_idx =
     155           9 :                 bihash_table - im->fp_ip4_lookup_hashes_pool;
     156           9 :               clib_bihash_init_16_8 (bihash_table, (char *) fp_spd->name4_in,
     157             :                                      im->fp_lookup_hash_buckets,
     158           9 :                                      im->fp_lookup_hash_buckets *
     159             :                                        IPSEC_FP_IP4_HASH_MEM_PER_BUCKET);
     160             :             }
     161             :         }
     162        1584 :       if (im->fp_spd_ipv6_out_is_enabled)
     163             :         {
     164          14 :           if (pool_elts (im->fp_ip6_lookup_hashes_pool) <
     165           7 :               pool_max_len (im->fp_ip6_lookup_hashes_pool))
     166             :             {
     167             :               clib_bihash_40_8_t *bihash_table;
     168           7 :               ipsec_spd_fp_t *fp_spd = &spd->fp_spd;
     169             : 
     170           7 :               fp_spd->name6_out = format (0, "spd_%u_fp_ip6_out", spd_id);
     171             : 
     172           7 :               fp_spd->name6_out = format (0, "spd_%u_fp_ip6_out", spd_id);
     173           7 :               pool_get (im->fp_ip6_lookup_hashes_pool, bihash_table);
     174           7 :               fp_spd->ip6_out_lookup_hash_idx =
     175           7 :                 bihash_table - im->fp_ip6_lookup_hashes_pool;
     176           7 :               clib_bihash_init_40_8 (bihash_table, (char *) fp_spd->name6_out,
     177             :                                      im->fp_lookup_hash_buckets,
     178           7 :                                      im->fp_lookup_hash_buckets *
     179             :                                        IPSEC_FP_IP6_HASH_MEM_PER_BUCKET);
     180             :             }
     181             :         }
     182        1584 :       if (im->fp_spd_ipv6_in_is_enabled)
     183             :         {
     184           4 :           if (pool_elts (im->fp_ip6_lookup_hashes_pool) <
     185           2 :               pool_max_len (im->fp_ip6_lookup_hashes_pool))
     186             :             {
     187             :               clib_bihash_40_8_t *bihash_table;
     188           2 :               ipsec_spd_fp_t *fp_spd = &spd->fp_spd;
     189             : 
     190           2 :               fp_spd->name6_in = format (0, "spd_%u_fp_ip6_in", spd_id);
     191           2 :               pool_get (im->fp_ip6_lookup_hashes_pool, bihash_table);
     192           2 :               fp_spd->ip6_in_lookup_hash_idx =
     193           2 :                 bihash_table - im->fp_ip6_lookup_hashes_pool;
     194           2 :               clib_bihash_init_40_8 (bihash_table, (char *) fp_spd->name6_in,
     195             :                                      im->fp_lookup_hash_buckets,
     196           2 :                                      im->fp_lookup_hash_buckets *
     197             :                                        IPSEC_FP_IP6_HASH_MEM_PER_BUCKET);
     198             :             }
     199             :         }
     200             :     }
     201        3168 :   return 0;
     202             : }
     203             : 
     204             : int
     205        3230 : ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id,
     206             :                          int is_add)
     207             : {
     208        3230 :   ipsec_main_t *im = &ipsec_main;
     209             :   ip4_ipsec_config_t config;
     210             : 
     211             :   u32 spd_index;
     212             :   uword *p;
     213             : 
     214        3230 :   p = hash_get (im->spd_index_by_spd_id, spd_id);
     215        3230 :   if (!p)
     216           0 :     return VNET_API_ERROR_SYSCALL_ERROR_1;      /* no such spd-id */
     217             : 
     218        3230 :   spd_index = p[0];
     219             : 
     220        3230 :   p = hash_get (im->spd_index_by_sw_if_index, sw_if_index);
     221        3230 :   if (p && is_add)
     222           0 :     return VNET_API_ERROR_SYSCALL_ERROR_2;      /* spd already assigned */
     223             : 
     224        3230 :   if (is_add)
     225             :     {
     226        1615 :       hash_set (im->spd_index_by_sw_if_index, sw_if_index, spd_index);
     227             :     }
     228             :   else
     229             :     {
     230        1615 :       hash_unset (im->spd_index_by_sw_if_index, sw_if_index);
     231             :     }
     232             : 
     233             :   /* enable IPsec on TX */
     234        3230 :   vnet_feature_enable_disable ("ip4-output", "ipsec4-output-feature",
     235             :                                sw_if_index, is_add, 0, 0);
     236        3230 :   vnet_feature_enable_disable ("ip6-output", "ipsec6-output-feature",
     237             :                                sw_if_index, is_add, 0, 0);
     238             : 
     239        3230 :   config.spd_index = spd_index;
     240             : 
     241             :   /* enable IPsec on RX */
     242        3230 :   vnet_feature_enable_disable ("ip4-unicast", "ipsec4-input-feature",
     243             :                                sw_if_index, is_add, &config, sizeof (config));
     244        3230 :   vnet_feature_enable_disable ("ip6-unicast", "ipsec6-input-feature",
     245             :                                sw_if_index, is_add, &config, sizeof (config));
     246             : 
     247        3230 :   return 0;
     248             : }
     249             : 
     250             : /*
     251             :  * fd.io coding-style-patch-verification: ON
     252             :  *
     253             :  * Local Variables:
     254             :  * eval: (c-set-style "gnu")
     255             :  * End:
     256             :  */

Generated by: LCOV version 1.14