ikev2: lazy initialization 77/33877/4
authorBenoît Ganne <bganne@cisco.com>
Tue, 28 Sep 2021 16:59:53 +0000 (18:59 +0200)
committerDamjan Marion <dmarion@me.com>
Fri, 8 Oct 2021 11:18:23 +0000 (11:18 +0000)
 - do not initialize resources if ikev2 is not used.
 - process IKE packets only if we have profile(s) configured

Type: improvement

Change-Id: I57c95a888532eafd70989096c0555ebb1d7bef25
Signed-off-by: Benoît Ganne <bganne@cisco.com>
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2.h
src/plugins/ikev2/ikev2_cli.c
src/plugins/ikev2/ikev2_priv.h

index c184a46..b521104 100644 (file)
@@ -3926,12 +3926,51 @@ ikev2_profile_free (ikev2_profile_t * p)
   vec_free (p->rem_id.data);
 }
 
+static void
+ikev2_bind (vlib_main_t *vm, ikev2_main_t *km)
+{
+  if (0 == km->bind_refcount)
+    {
+      udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip4.index, 1);
+      udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip6.index, 0);
+      udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip4.index, 1);
+      udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip6.index, 0);
+
+      vlib_punt_register (km->punt_hdl,
+                         ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
+                         "ikev2-ip4-natt");
+    }
+
+  km->bind_refcount++;
+}
+
+static void
+ikev2_unbind (vlib_main_t *vm, ikev2_main_t *km)
+{
+  km->bind_refcount--;
+  if (0 == km->bind_refcount)
+    {
+      vlib_punt_unregister (km->punt_hdl,
+                           ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
+                           "ikev2-ip4-natt");
+
+      udp_unregister_dst_port (vm, IKEV2_PORT_NATT, 0);
+      udp_unregister_dst_port (vm, IKEV2_PORT_NATT, 1);
+      udp_unregister_dst_port (vm, IKEV2_PORT, 0);
+      udp_unregister_dst_port (vm, IKEV2_PORT, 1);
+    }
+}
+
+static void ikev2_lazy_init (ikev2_main_t *km);
+
 clib_error_t *
 ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
 {
   ikev2_main_t *km = &ikev2_main;
   ikev2_profile_t *p;
 
+  ikev2_lazy_init (km);
+
   if (is_add)
     {
       if (ikev2_profile_index_by_name (name))
@@ -3945,6 +3984,8 @@ ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
       p->tun_itf = ~0;
       uword index = p - km->profiles;
       mhash_set_mem (&km->profile_index_by_name, name, &index, 0);
+
+      ikev2_bind (vm, km);
     }
   else
     {
@@ -3952,6 +3993,8 @@ ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
       if (!p)
        return clib_error_return (0, "policy %v does not exists", name);
 
+      ikev2_unbind (vm, km);
+
       ikev2_unregister_udp_port (p);
       ikev2_cleanup_profile_sessions (km, p);
 
@@ -4798,65 +4841,24 @@ clib_error_t *
 ikev2_init (vlib_main_t * vm)
 {
   ikev2_main_t *km = &ikev2_main;
-  vlib_thread_main_t *tm = vlib_get_thread_main ();
-  int thread_id;
 
   clib_memset (km, 0, sizeof (ikev2_main_t));
+
+  km->log_level = IKEV2_LOG_ERROR;
+  km->log_class = vlib_log_register_class ("ikev2", 0);
+
   km->vnet_main = vnet_get_main ();
   km->vlib_main = vm;
 
   km->liveness_period = IKEV2_LIVENESS_PERIOD_CHECK;
   km->liveness_max_retries = IKEV2_LIVENESS_RETRIES;
-  ikev2_crypto_init (km);
-
-  mhash_init_vec_string (&km->profile_index_by_name, sizeof (uword));
-
-  vec_validate_aligned (km->per_thread_data, tm->n_vlib_mains - 1,
-                       CLIB_CACHE_LINE_BYTES);
-  for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++)
-    {
-      ikev2_main_per_thread_data_t *ptd =
-       vec_elt_at_index (km->per_thread_data, thread_id);
-
-      ptd->sa_by_rspi = hash_create (0, sizeof (uword));
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-      ptd->evp_ctx = EVP_CIPHER_CTX_new ();
-      ptd->hmac_ctx = HMAC_CTX_new ();
-#else
-      EVP_CIPHER_CTX_init (&ptd->_evp_ctx);
-      ptd->evp_ctx = &ptd->_evp_ctx;
-      HMAC_CTX_init (&(ptd->_hmac_ctx));
-      ptd->hmac_ctx = &ptd->_hmac_ctx;
-#endif
-    }
-
-  km->sa_by_ispi = hash_create (0, sizeof (uword));
-  km->sw_if_indices = hash_create (0, 0);
-
-  udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip4.index, 1);
-  udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip6.index, 0);
-  udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip4.index, 1);
-  udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip6.index, 0);
 
-  vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("ikev2-ip4-natt");
-  vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
-                     "ikev2-ip4-natt");
-  ikev2_cli_reference ();
-
-  km->dns_resolve_name =
-    vlib_get_plugin_symbol ("dns_plugin.so", "dns_resolve_name");
-  if (!km->dns_resolve_name)
-    ikev2_log_error ("cannot load symbols from dns plugin");
-
-  km->log_level = IKEV2_LOG_ERROR;
-  km->log_class = vlib_log_register_class ("ikev2", 0);
   return 0;
 }
 
 /* *INDENT-OFF* */
 VLIB_INIT_FUNCTION (ikev2_init) = {
-  .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init", "dns_init"),
+  .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init"),
 };
 /* *INDENT-ON* */
 
@@ -5223,6 +5225,9 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
   ikev2_child_sa_t *c;
   u32 *sai;
 
+  /* lazy init will wake it up */
+  vlib_process_wait_for_event (vm);
+
   while (1)
     {
       vlib_process_wait_for_event_or_clock (vm, 2);
@@ -5312,6 +5317,56 @@ VLIB_REGISTER_NODE (ikev2_mngr_process_node, static) = {
     "ikev2-manager-process",
 };
 
+static void
+ikev2_lazy_init (ikev2_main_t *km)
+{
+  vlib_thread_main_t *tm = vlib_get_thread_main ();
+  int thread_id;
+
+  if (km->lazy_init_done)
+    return;
+
+  ikev2_crypto_init (km);
+
+  mhash_init_vec_string (&km->profile_index_by_name, sizeof (uword));
+
+  vec_validate_aligned (km->per_thread_data, tm->n_vlib_mains - 1,
+                       CLIB_CACHE_LINE_BYTES);
+  for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++)
+    {
+      ikev2_main_per_thread_data_t *ptd =
+       vec_elt_at_index (km->per_thread_data, thread_id);
+
+      ptd->sa_by_rspi = hash_create (0, sizeof (uword));
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+      ptd->evp_ctx = EVP_CIPHER_CTX_new ();
+      ptd->hmac_ctx = HMAC_CTX_new ();
+#else
+      EVP_CIPHER_CTX_init (&ptd->_evp_ctx);
+      ptd->evp_ctx = &ptd->_evp_ctx;
+      HMAC_CTX_init (&(ptd->_hmac_ctx));
+      ptd->hmac_ctx = &ptd->_hmac_ctx;
+#endif
+    }
+
+  km->sa_by_ispi = hash_create (0, sizeof (uword));
+  km->sw_if_indices = hash_create (0, 0);
+
+  km->punt_hdl = vlib_punt_client_register ("ikev2");
+
+  km->dns_resolve_name =
+    vlib_get_plugin_symbol ("dns_plugin.so", "dns_resolve_name");
+  if (!km->dns_resolve_name)
+    ikev2_log_error ("cannot load symbols from dns plugin");
+
+  /* wake up ikev2 process */
+  vlib_process_signal_event (vlib_get_first_main (),
+                            ikev2_mngr_process_node.index, 0, 0);
+
+  km->lazy_init_done = 1;
+}
+
 VLIB_PLUGIN_REGISTER () = {
     .version = VPP_BUILD_VER,
     .description = "Internet Key Exchange (IKEv2) Protocol",
index 308ffe5..020a3f0 100644 (file)
@@ -451,7 +451,6 @@ uword unformat_ikev2_transform_dh_type (unformat_input_t * input,
                                        va_list * args);
 uword unformat_ikev2_transform_esn_type (unformat_input_t * input,
                                         va_list * args);
-void ikev2_cli_reference (void);
 
 clib_error_t *ikev2_set_liveness_params (u32 period, u32 max_retries);
 
index 3523ce0..382f1e1 100644 (file)
@@ -805,11 +805,6 @@ VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
 };
 /* *INDENT-ON* */
 
-void
-ikev2_cli_reference (void)
-{
-}
-
 static clib_error_t *
 ikev2_set_log_level_command_fn (vlib_main_t * vm,
                                unformat_input_t * input,
index 4c56b98..0a60368 100644 (file)
@@ -531,6 +531,16 @@ typedef struct
 
   /* pointer to name resolver function in dns plugin */
   int (*dns_resolve_name) ();
+
+  /* flag indicating whether lazy init is done or not */
+  int lazy_init_done;
+
+  /* refcount for IKEv2 udp ports and IPsec NATT punt registration */
+  int bind_refcount;
+
+  /* punt handle for IPsec NATT IPSEC_PUNT_IP4_SPI_UDP_0 reason */
+  vlib_punt_hdl_t punt_hdl;
+
 } ikev2_main_t;
 
 extern ikev2_main_t ikev2_main;