From: Dave Wallace Date: Wed, 18 Jun 2025 20:20:51 +0000 (-0400) Subject: quic: don't crash when no quic engine is available X-Git-Tag: v26.02-rc0~180 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F27%2F43227%2F18;p=vpp.git quic: don't crash when no quic engine is available - When there is no quic engine available, vpp crashes with an assert on startup which is not production friendly. Instead, emit warning message to stderr. - Fix crash in session_transport_closing_notify if a remote closed notification happens on an invalid session in the quicly engine. - Fix compilation errors when QUIC_DEBUG is set to 2 - Fix crash in 'show quic crypto context' command when quic engine is not present. - Add quic engine type to 'show quic' output. Type: fix Change-Id: I83b9e69873fa3cd61d1d852b78ed1ccd2112825c Signed-off-by: Dave Wallace --- diff --git a/src/plugins/quic/quic.c b/src/plugins/quic/quic.c index 1daf78b58f3..3a6ae06bafb 100644 --- a/src/plugins/quic/quic.c +++ b/src/plugins/quic/quic.c @@ -74,6 +74,21 @@ quic_list_crypto_context_command_fn (vlib_main_t *vm, unformat_input_t *input, crypto_context_t *crctx; vlib_thread_main_t *vtm = vlib_get_thread_main (); int i, num_threads = 1 /* main thread */ + vtm->n_threads; + quic_main_t *qm = &quic_main; + + session_cli_return_if_not_enabled (); + if (qm->engine_type == QUIC_ENGINE_NONE) + { + vlib_cli_output (vm, "No QUIC engine plugin enabled"); + return 0; + } + if (qm->engine_is_initialized[qm->engine_type] == 0) + { + vlib_cli_output (vm, "quic engine %s not initialized", + quic_engine_type_str (qm->engine_type)); + return 0; + } + for (i = 0; i < num_threads; i++) { pool_foreach (crctx, quic_wrk_ctx_get (&quic_main, i)->crypto_ctx_pool) @@ -805,7 +820,10 @@ static session_cb_vft_t quic_app_cb_vft = { .app_cert_key_pair_delete_callback = quic_app_cert_key_pair_delete_callback, }; -static const transport_proto_vft_t quic_proto = { +static clib_error_t *quic_enable (vlib_main_t *vm, u8 is_en); + +static transport_proto_vft_t quic_proto = { + .enable = quic_enable, .connect = quic_connect, .close = quic_proto_on_close, .start_listen = quic_start_listen, @@ -828,6 +846,58 @@ static const transport_proto_vft_t quic_proto = { }, }; +static clib_error_t * +quic_enable (vlib_main_t *vm, u8 is_en) +{ + quic_main_t *qm = &quic_main; + quic_worker_ctx_t *wrk_ctx; + quic_ctx_t *ctx; + crypto_context_t *crctx; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + int i; + + qm->engine_type = + quic_get_engine_type (QUIC_ENGINE_QUICLY, QUIC_ENGINE_OPENSSL); + if (qm->engine_type == QUIC_ENGINE_NONE) + { + /* Prevent crash in transport layer callbacks with no quic engine */ + quic_proto.connect = 0; + quic_proto.start_listen = 0; + clib_warning ( + "ERROR: NO QUIC ENGINE PLUGIN ENABLED!" + "\nEnable a quic engine plugin in the startup configuration."); + return clib_error_return (0, "No QUIC engine plugin enabled"); + } + + QUIC_DBG (1, "QUIC engine %s init", quic_engine_type_str (qm->engine_type)); + if (!is_en || qm->engine_is_initialized[qm->engine_type]) + return 0; + + qm->quic_input_node = &quic_input_node; + qm->num_threads = 1 /* main thread */ + vtm->n_threads; + vec_validate (quic_main.wrk_ctx, qm->num_threads - 1); + + for (i = 0; i < qm->num_threads; i++) + { + wrk_ctx = quic_wrk_ctx_get (qm, i); + pool_get_aligned_safe (wrk_ctx->crypto_ctx_pool, crctx, + CLIB_CACHE_LINE_BYTES); + pool_program_safe_realloc ((void **) &wrk_ctx->crypto_ctx_pool, + QUIC_CRYPTO_CTX_POOL_PER_THREAD_SIZE, + CLIB_CACHE_LINE_BYTES); + pool_get_aligned_safe (wrk_ctx->ctx_pool, ctx, CLIB_CACHE_LINE_BYTES); + pool_program_safe_realloc ((void **) &wrk_ctx->ctx_pool, + QUIC_CTX_POOL_PER_THREAD_SIZE, + CLIB_CACHE_LINE_BYTES); + } + + QUIC_DBG (1, "Initializing quic engine to %s", + quic_engine_type_str (qm->engine_type)); + quic_eng_engine_init (qm); + qm->engine_is_initialized[qm->engine_type] = 1; + return 0; +} + static void quic_update_fifo_size () { @@ -849,22 +919,19 @@ quic_update_fifo_size () static clib_error_t * quic_init (vlib_main_t * vm) { - u32 segment_size = 256 << 20; - vlib_thread_main_t *vtm = vlib_get_thread_main (); + quic_main_t *qm = &quic_main; vnet_app_attach_args_t _a, *a = &_a; u64 options[APP_OPTIONS_N_OPTIONS]; - quic_main_t *qm = &quic_main; + // TODO: Don't use hard-coded values for segment_size and seed[] + u32 segment_size = 256 << 20; u8 seed[32]; QUIC_DBG (1, "QUIC plugin init"); - qm->quic_input_node = &quic_input_node; if (syscall (SYS_getrandom, &seed, sizeof (seed), 0) != sizeof (seed)) return clib_error_return_unix (0, "getrandom() failed"); RAND_seed (seed, sizeof (seed)); - qm->num_threads = 1 /* main thread */ + vtm->n_threads; - clib_memset (a, 0, sizeof (*a)); clib_memset (options, 0, sizeof (options)); @@ -886,7 +953,6 @@ quic_init (vlib_main_t * vm) clib_warning ("failed to attach quic app"); return clib_error_return (0, "failed to attach quic app"); } - qm->app_index = a->app_index; transport_register_protocol (TRANSPORT_PROTO_QUIC, &quic_proto, @@ -898,53 +964,7 @@ quic_init (vlib_main_t * vm) return 0; } -static void -quic_engine_init () -{ - quic_main_t *qm = &quic_main; - quic_worker_ctx_t *wrk_ctx; - quic_ctx_t *ctx; - crypto_context_t *crctx; - int i; - - vec_validate (quic_main.wrk_ctx, qm->num_threads - 1); - - QUIC_DBG (1, "Initializing quic engine to %s", - quic_engine_type_str (qm->engine_type)); - - for (i = 0; i < qm->num_threads; i++) - { - wrk_ctx = quic_wrk_ctx_get (qm, i); - pool_get_aligned_safe (wrk_ctx->crypto_ctx_pool, crctx, - CLIB_CACHE_LINE_BYTES); - pool_program_safe_realloc ((void **) &wrk_ctx->crypto_ctx_pool, - QUIC_CRYPTO_CTX_POOL_PER_THREAD_SIZE, - CLIB_CACHE_LINE_BYTES); - pool_get_aligned_safe (wrk_ctx->ctx_pool, ctx, CLIB_CACHE_LINE_BYTES); - pool_program_safe_realloc ((void **) &wrk_ctx->ctx_pool, - QUIC_CTX_POOL_PER_THREAD_SIZE, - CLIB_CACHE_LINE_BYTES); - } - - quic_eng_engine_init (qm); - qm->engine_is_initialized[qm->engine_type] = 1; -} - -static clib_error_t * -quic_main_loop_init (vlib_main_t *vm) -{ - quic_main_t *qm = &quic_main; - - qm->engine_type = - quic_get_engine_type (QUIC_ENGINE_QUICLY, QUIC_ENGINE_OPENSSL); - QUIC_ASSERT (qm->engine_type != QUIC_ENGINE_NONE); - - quic_engine_init (); - return 0; -} - VLIB_INIT_FUNCTION (quic_init); -VLIB_MAIN_LOOP_ENTER_FUNCTION (quic_main_loop_init); static clib_error_t * quic_plugin_crypto_command_fn (vlib_main_t *vm, unformat_input_t *input, @@ -1159,9 +1179,22 @@ quic_show_connections_command_fn (vlib_main_t *vm, unformat_input_t *input, u32 num_workers = vlib_num_workers (); clib_error_t *error = 0; quic_ctx_t *ctx = NULL; + quic_main_t *qm = &quic_main; session_cli_return_if_not_enabled (); + if (qm->engine_type == QUIC_ENGINE_NONE) + { + vlib_cli_output (vm, "No QUIC engine plugin enabled"); + return 0; + } + if (qm->engine_is_initialized[qm->engine_type] == 0) + { + vlib_cli_output (vm, "quic engine %s not initialized", + quic_engine_type_str (qm->engine_type)); + return 0; + } + vlib_cli_output (vm, "engine: %s", quic_engine_type_str (qm->engine_type)); if (!unformat_user (input, unformat_line_input, line_input)) { quic_show_aggregated_stats (vm); diff --git a/src/plugins/quic_quicly/quic_quicly.c b/src/plugins/quic_quicly/quic_quicly.c index e621b0445e0..3c076ae2e70 100644 --- a/src/plugins/quic_quicly/quic_quicly.c +++ b/src/plugins/quic_quicly/quic_quicly.c @@ -327,8 +327,9 @@ static void quic_quicly_expired_timers_dispatch (u32 *expired_timers) { int i; -#if QUIC_DEBUG >= 4 - int64_t time_now = quic_wrk_ctx_get(quic_quicly_main.qm, vlib_get_thread_index ())->time_now); +#if QUIC_DEBUG >= 1 + int64_t time_now = + quic_wrk_ctx_get (quic_quicly_main.qm, vlib_get_thread_index ())->time_now; #endif for (i = 0; i < vec_len (expired_timers); i++) { @@ -1213,6 +1214,7 @@ quic_quicly_engine_init (quic_main_t *qm) tw_timer_wheel_1t_3w_1024sl_ov_t *tw; u32 i; + QUIC_DBG (2, "quic_quicly_engine_init -- start"); qm->default_crypto_engine = CRYPTO_ENGINE_PICOTLS; qm->default_quic_cc = QUIC_CC_RENO; qm->max_packets_per_key = DEFAULT_MAX_PACKETS_PER_KEY; diff --git a/src/plugins/quic_quicly/quic_quicly_crypto.c b/src/plugins/quic_quicly/quic_quicly_crypto.c index 13c7e6d2087..cc2780fc295 100644 --- a/src/plugins/quic_quicly/quic_quicly_crypto.c +++ b/src/plugins/quic_quicly/quic_quicly_crypto.c @@ -203,13 +203,25 @@ quic_quicly_on_closed_by_remote (quicly_closed_by_remote_t *self, { quic_ctx_t *ctx = quic_quicly_get_conn_ctx (conn); #if QUIC_DEBUG >= 2 - session_t *quic_session = session_get (ctx->c_s_index, ctx->c_thread_index); - clib_warning ("Session 0x%lx closed by peer (%U) %.*s ", - session_handle (quic_session), quic_quicly_format_err, code, - reason_len, reason); + if (ctx->c_s_index == QUIC_SESSION_INVALID) + { + clib_warning ("Unopened Session closed by peer (%U) %.*S ", + quic_quicly_format_err, code, reason_len, reason); + } + else + { + session_t *quic_session = + session_get (ctx->c_s_index, ctx->c_thread_index); + clib_warning ("Session 0x%lx closed by peer (%U) %.*s ", + session_handle (quic_session), quic_quicly_format_err, + code, reason_len, reason); + } #endif ctx->conn_state = QUIC_CONN_STATE_PASSIVE_CLOSING; - session_transport_closing_notify (&ctx->connection); + if (ctx->c_s_index != QUIC_SESSION_INVALID) + { + session_transport_closing_notify (&ctx->connection); + } } static int64_t diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index edec182541e..fa3106a2c57 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -1015,7 +1015,8 @@ transport_enable_disable (vlib_main_t * vm, u8 is_en) vec_foreach (vft, tp_vfts) { if (vft->enable) - (vft->enable) (vm, is_en); + if ((vft->enable) (vm, is_en) != 0) + continue; if (vft->update_time) session_register_update_time_fn (vft->update_time, is_en);