From bab6c52f4544ebe352a1a9f832137d9b4069ae6c Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 13 May 2021 08:36:56 -0700 Subject: tls: switch dtls to vc and track half-opens Also adds support for half-open support transport migration. Type: improvement Signed-off-by: Florin Coras Change-Id: Id04c194138956336f93246bbed0332a7030c67e2 --- src/vnet/session/application_worker.c | 2 +- src/vnet/session/session.c | 79 +++++++++++++++++++++++++++++++---- src/vnet/session/session.h | 2 + src/vnet/tls/tls.c | 63 ++++++++++++++++++++++++++-- 4 files changed, 132 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c index fad70c06de3..0b2f1459d9a 100644 --- a/src/vnet/session/application_worker.c +++ b/src/vnet/session/application_worker.c @@ -396,7 +396,7 @@ int app_worker_del_half_open (app_worker_t *app_wrk, session_t *s) { application_t *app = application_get (app_wrk->app_index); - ASSERT (vlib_get_thread_index () == 0); + ASSERT (vlib_get_thread_index () <= 1); pool_put_index (app_wrk->half_open_table, s->ho_index); if (app->cb_fns.half_open_cleanup_callback) app->cb_fns.half_open_cleanup_callback (s); diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 0d2301c5f83..7aadb2188b4 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -303,21 +303,82 @@ session_delete (session_t * s) void session_cleanup_half_open (session_handle_t ho_handle) { - session_t *s = session_get_from_handle (ho_handle); - transport_cleanup_half_open (session_get_transport_proto (s), - s->connection_index); + session_t *ho = session_get_from_handle (ho_handle); + + /* App transports can migrate their half-opens */ + if (ho->flags & SESSION_F_IS_MIGRATING) + { + /* Session still migrating, move to closed state to signal that the + * session should be removed. */ + if (ho->connection_index == ~0) + { + ho->session_state = SESSION_STATE_CLOSED; + return; + } + /* Migrated transports are no longer half-opens */ + transport_cleanup (session_get_transport_proto (ho), + ho->connection_index, ho->app_index /* overloaded */); + return; + } + transport_cleanup_half_open (session_get_transport_proto (ho), + ho->connection_index); +} + +static void +session_half_open_free (u32 ho_index) +{ + app_worker_t *app_wrk; + session_t *ho; + + ASSERT (vlib_get_thread_index () <= 1); + ho = ho_session_get (ho_index); + app_wrk = app_worker_get (ho->app_wrk_index); + app_worker_del_half_open (app_wrk, ho); + session_free (ho); +} + +static void +session_half_open_free_rpc (void *args) +{ + session_half_open_free (pointer_to_uword (args)); } void session_half_open_delete_notify (transport_connection_t *tc) { - app_worker_t *app_wrk; - session_t *s; + void *args = uword_to_pointer ((uword) tc->s_index, void *); + u32 ctrl_thread = vlib_num_workers () ? 1 : 0; + session_send_rpc_evt_to_thread (ctrl_thread, session_half_open_free_rpc, + args); +} - s = ho_session_get (tc->s_index); - app_wrk = app_worker_get (s->app_wrk_index); - app_worker_del_half_open (app_wrk, s); - session_free (s); +void +session_half_open_migrate_notify (transport_connection_t *tc) +{ + session_t *ho; + + ho = ho_session_get (tc->s_index); + ho->flags |= SESSION_F_IS_MIGRATING; + ho->connection_index = ~0; +} + +int +session_half_open_migrated_notify (transport_connection_t *tc) +{ + session_t *ho; + + ho = ho_session_get (tc->s_index); + + /* App probably detached so the half-open must be cleaned up */ + if (ho->session_state == SESSION_STATE_CLOSED) + { + session_half_open_delete_notify (tc); + return -1; + } + ho->connection_index = tc->c_index; + /* Overload app index for half-open with new thread */ + ho->app_index = tc->thread_index; + return 0; } session_t * diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index d14c68971de..bf326811b24 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -506,6 +506,8 @@ int session_stream_accept_notify (transport_connection_t * tc); void session_transport_closing_notify (transport_connection_t * tc); void session_transport_delete_notify (transport_connection_t * tc); void session_half_open_delete_notify (transport_connection_t *tc); +void session_half_open_migrate_notify (transport_connection_t *tc); +int session_half_open_migrated_notify (transport_connection_t *tc); void session_transport_closed_notify (transport_connection_t * tc); void session_transport_reset_notify (transport_connection_t * tc); int session_stream_accept (transport_connection_t * tc, u32 listener_index, diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c index 09fc8c62325..acaeb02f73c 100644 --- a/src/vnet/tls/tls.c +++ b/src/vnet/tls/tls.c @@ -234,6 +234,8 @@ tls_notify_app_connected (tls_ctx_t * ctx, session_error_t err) if (ctx->tls_type == TRANSPORT_PROTO_DTLS) { session_type_t st; + /* Cleanup half-open session as we don't get notification from udp */ + session_half_open_delete_notify (&ctx->connection); app_session = session_alloc (ctx->c_thread_index); app_session->session_state = SESSION_STATE_CREATED; ctx->c_s_index = app_session->session_index; @@ -647,6 +649,15 @@ dtls_migrate_ctx (void *arg) us = session_get_from_handle (ctx->tls_session_handle); us->opaque = ctx_handle; us->flags &= ~SESSION_F_IS_MIGRATING; + + /* Probably the app detached while the session was migrating. Cleanup */ + if (session_half_open_migrated_notify (&ctx->connection)) + { + ctx->no_app_session = 1; + tls_disconnect (ctx->tls_ctx_handle, vlib_get_thread_index ()); + return; + } + if (svm_fifo_max_dequeue (us->tx_fifo)) session_send_io_evt_to_thread (us->tx_fifo, SESSION_IO_EVT_TX); } @@ -662,6 +673,7 @@ dtls_session_migrate_callback (session_t *us, session_handle_t new_sh) ctx->tls_session_handle = new_sh; cloned_ctx = tls_ctx_detach (ctx); ctx->is_migrated = 1; + session_half_open_migrate_notify (&ctx->connection); session_send_rpc_evt_to_thread (new_thread, dtls_migrate_ctx, (void *) cloned_ctx); @@ -905,10 +917,14 @@ static void tls_cleanup_ho (u32 ho_index) { tls_main_t *tm = &tls_main; + session_handle_t tcp_sh; tls_ctx_t *ctx; + ctx = tls_ctx_half_open_get (ho_index); + tcp_sh = ctx->tls_session_handle; clib_rwlock_reader_unlock (&tm->half_open_rwlock); - session_cleanup_half_open (ctx->tls_session_handle); + session_cleanup_half_open (tcp_sh); + tls_ctx_half_open_free (ho_index); } int @@ -1182,6 +1198,8 @@ dtls_connect (transport_endpoint_cfg_t *tep) ctx->ckpair_index = ccfg->ckpair_index; ctx->tls_type = sep->transport_proto; ctx->tls_ctx_handle = ctx_handle; + ctx->c_proto = TRANSPORT_PROTO_DTLS; + ctx->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP; if (ccfg->hostname[0]) { ctx->srv_hostname = format (0, "%s", ccfg->hostname); @@ -1201,7 +1219,15 @@ dtls_connect (transport_endpoint_cfg_t *tep) TLS_DBG (1, "New DTLS connect request %x engine %d", ctx_handle, engine_type); - return 0; + return ctx_handle; +} + +static transport_connection_t * +dtls_half_open_get (u32 ho_index) +{ + tls_ctx_t *ho_ctx; + ho_ctx = tls_ctx_get_w_thread (ho_index, 1 /* udp connects */); + return &ho_ctx->connection; } static void @@ -1210,6 +1236,33 @@ dtls_cleanup_callback (u32 ctx_index, u32 thread_index) /* No op */ } +static void +dtls_cleanup_ho (u32 ho_index) +{ + tls_ctx_t *ctx; + ctx = tls_ctx_get_w_thread (ho_index, 1 /* udp connects */); + tls_ctx_free (ctx); +} + +u8 * +format_dtls_half_open (u8 *s, va_list *args) +{ + u32 ho_index = va_arg (*args, u32); + u32 __clib_unused thread_index = va_arg (*args, u32); + tls_ctx_t *ho_ctx; + session_t *us; + + ho_ctx = tls_ctx_get_w_thread (ho_index, 1 /* udp connects */); + + us = session_get_from_handle (ho_ctx->tls_session_handle); + s = format (s, "[%d:%d][%s] half-open app_wrk %u engine %u us %d:%d", + ho_ctx->c_thread_index, ho_ctx->c_s_index, "DTLS", + ho_ctx->parent_app_wrk_index, ho_ctx->tls_ctx_engine, + us->thread_index, us->session_index); + + return s; +} + static const transport_proto_vft_t dtls_proto = { .enable = 0, .connect = dtls_connect, @@ -1218,10 +1271,12 @@ static const transport_proto_vft_t dtls_proto = { .stop_listen = tls_stop_listen, .get_connection = tls_connection_get, .get_listener = tls_listener_get, + .get_half_open = dtls_half_open_get, .custom_tx = tls_custom_tx_callback, .cleanup = dtls_cleanup_callback, + .cleanup_ho = dtls_cleanup_ho, .format_connection = format_tls_connection, - .format_half_open = format_tls_half_open, + .format_half_open = format_dtls_half_open, .format_listener = format_tls_listener, .get_transport_endpoint = tls_transport_endpoint_get, .get_transport_listener_endpoint = tls_transport_listener_endpoint_get, @@ -1229,7 +1284,7 @@ static const transport_proto_vft_t dtls_proto = { .name = "dtls", .short_name = "D", .tx_type = TRANSPORT_TX_INTERNAL, - .service_type = TRANSPORT_SERVICE_APP, + .service_type = TRANSPORT_SERVICE_VC, }, }; -- cgit 1.2.3-korg