crypto: use fixed crypto frame pool 26/38926/5
authorgaoginskx <gabrielx.oginski@intel.com>
Mon, 7 Jun 2021 11:07:01 +0000 (12:07 +0100)
committerFan Zhang <fanzhang.oss@gmail.com>
Thu, 8 Jun 2023 09:18:58 +0000 (09:18 +0000)
The async frames pool may be resized once drained. This will cause 2 problems: original pool pointer is invalidated and pool size changed, both problems will confuse the crypto infra user graph nodes (like IPsec and Wireguard) and crypto engines if they expect the pool pointers always valid and the pool size never changed (for performance reason).

This patch introduces fixed size of the async frames pool. This helps zeroing surprise to the components shown above and avoiding segmentation fault when pool resizing happened. In addition, the crypto engine may take advantage of the feature to sync its own pool/vector with crypto infra.

Type: improvement

Signed-off-by: Gabriel Oginski <gabrielx.oginski@intel.com>
Signed-off-by: Piotr Bronowski <piotrx.bronowski@intel.com>
Change-Id: I2a71783b90149fa376848b9c4f84ce8c6c034bef

src/plugins/wireguard/wireguard_input.c
src/plugins/wireguard/wireguard_output_tun.c
src/vnet/crypto/crypto.c
src/vnet/crypto/crypto.h
src/vnet/ipsec/esp_decrypt.c
src/vnet/ipsec/esp_encrypt.c
src/vnet/ipsec/ipsec.api

index db37fa5..cf8a597 100644 (file)
@@ -611,6 +611,8 @@ wg_input_process (vlib_main_t *vm, wg_per_thread_data_t *ptd,
        {
          *async_frame = vnet_crypto_async_get_frame (
            vm, VNET_CRYPTO_OP_CHACHA20_POLY1305_TAG16_AAD0_DEC);
+         if (PREDICT_FALSE (NULL == *async_frame))
+           goto error;
          /* Save the frame to the list we'll submit at the end */
          vec_add1 (ptd->async_frames, *async_frame);
        }
index 4ff1621..a563081 100644 (file)
@@ -368,6 +368,8 @@ wg_add_to_async_frame (vlib_main_t *vm, wg_per_thread_data_t *ptd,
     {
       *async_frame = vnet_crypto_async_get_frame (
        vm, VNET_CRYPTO_OP_CHACHA20_POLY1305_TAG16_AAD0_ENC);
+      if (PREDICT_FALSE (NULL == *async_frame))
+       goto error;
       /* Save the frame to the list we'll submit at the end */
       vec_add1 (ptd->async_frames, *async_frame);
     }
index 5d951a1..81cbda8 100644 (file)
@@ -706,8 +706,7 @@ vnet_crypto_init (vlib_main_t * vm)
   cm->async_alg_index_by_name = hash_create_string (0, sizeof (uword));
   vec_validate_aligned (cm->threads, tm->n_vlib_mains, CLIB_CACHE_LINE_BYTES);
   vec_foreach (ct, cm->threads)
-    pool_alloc_aligned (ct->frame_pool, VNET_CRYPTO_FRAME_POOL_SIZE,
-                       CLIB_CACHE_LINE_BYTES);
+    pool_init_fixed (ct->frame_pool, VNET_CRYPTO_FRAME_POOL_SIZE);
   vec_validate (cm->algs, VNET_CRYPTO_N_ALGS);
   vec_validate (cm->async_algs, VNET_CRYPTO_N_ASYNC_ALGS);
 
index 36fde2a..c16839d 100644 (file)
@@ -556,12 +556,16 @@ vnet_crypto_async_get_frame (vlib_main_t * vm, vnet_crypto_async_op_id_t opt)
   vnet_crypto_thread_t *ct = cm->threads + vm->thread_index;
   vnet_crypto_async_frame_t *f = NULL;
 
-  pool_get_aligned (ct->frame_pool, f, CLIB_CACHE_LINE_BYTES);
-  if (CLIB_DEBUG > 0)
-    clib_memset (f, 0xfe, sizeof (*f));
-  f->state = VNET_CRYPTO_FRAME_STATE_NOT_PROCESSED;
-  f->op = opt;
-  f->n_elts = 0;
+  if (PREDICT_TRUE (pool_free_elts (ct->frame_pool)))
+    {
+      pool_get_aligned (ct->frame_pool, f, CLIB_CACHE_LINE_BYTES);
+#if CLIB_DEBUG > 0
+      clib_memset (f, 0xfe, sizeof (*f));
+#endif
+      f->state = VNET_CRYPTO_FRAME_STATE_NOT_PROCESSED;
+      f->op = opt;
+      f->n_elts = 0;
+    }
 
   return f;
 }
index 6db1fe3..43d292d 100644 (file)
@@ -1183,6 +1183,15 @@ esp_decrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
            {
              async_frames[async_op] =
                vnet_crypto_async_get_frame (vm, async_op);
+             if (PREDICT_FALSE (!async_frames[async_op]))
+               {
+                 err = ESP_DECRYPT_ERROR_NO_AVAIL_FRAME;
+                 esp_decrypt_set_next_index (
+                   b[0], node, thread_index, err, n_noop, noop_nexts,
+                   ESP_DECRYPT_NEXT_DROP, current_sa_index);
+                 goto next;
+               }
+
              /* Save the frame to the list we'll submit at the end */
              vec_add1 (ptd->async_frames, async_frames[async_op]);
            }
index ea0bf34..7f9b5ed 100644 (file)
@@ -999,6 +999,16 @@ esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
            {
              async_frames[async_op] =
                vnet_crypto_async_get_frame (vm, async_op);
+
+             if (PREDICT_FALSE (!async_frames[async_op]))
+               {
+                 err = ESP_ENCRYPT_ERROR_NO_AVAIL_FRAME;
+                 esp_encrypt_set_next_index (b[0], node, thread_index, err,
+                                             n_noop, noop_nexts, drop_next,
+                                             current_sa_index);
+                 goto trace;
+               }
+
              /* Save the frame to the list we'll submit at the end */
              vec_add1 (ptd->async_frames, async_frames[async_op]);
            }
index 6cbad6e..2e69e62 100644 (file)
@@ -607,6 +607,12 @@ counters esp_decrypt {
     units "packets";
     description "unsupported payload";
   };
+  no_avail_frame {
+  severity error;
+  type counter64;
+  units "packets";
+  description "no available frame (packet dropped)";
+  };
 };
 
 counters esp_encrypt {
@@ -664,6 +670,12 @@ counters esp_encrypt {
     units "packets";
     description "no Encrypting SA (packet dropped)";
   };
+  no_avail_frame {
+  severity error;
+  type counter64;
+  units "packets";
+  description "no available frame (packet dropped)";
+  };
 };
 
 counters ah_encrypt {