From f83d6668b083ca9ce502240557d8f6abd8645922 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 16 Feb 2022 17:59:55 -0800 Subject: http hsa: support multiple listeners for http tps Type: improvement Signed-off-by: Florin Coras Change-Id: Ie89326ed4e599231fc20de67c5dadbb428568bec --- src/plugins/hs_apps/http_tps.c | 179 +++++++++++++++++++++++++++----- src/plugins/http/http.c | 45 ++++++-- src/plugins/http/http.h | 2 +- src/plugins/http_static/static_server.c | 1 + 4 files changed, 195 insertions(+), 32 deletions(-) diff --git a/src/plugins/hs_apps/http_tps.c b/src/plugins/hs_apps/http_tps.c index e149335903a..4407427e652 100644 --- a/src/plugins/hs_apps/http_tps.c +++ b/src/plugins/hs_apps/http_tps.c @@ -26,6 +26,7 @@ typedef struct u64 data_len; u64 data_offset; u32 vpp_session_index; + u8 *uri; } hts_session_t; typedef struct hs_main_ @@ -36,6 +37,9 @@ typedef struct hs_main_ u32 ckpair_index; u8 *test_data; + /** Hash table of listener uris to handles */ + uword *uri_to_handle; + /* * Configs */ @@ -44,6 +48,7 @@ typedef struct hs_main_ u64 segment_size; u8 debug_level; u8 no_zc; + u8 *default_uri; } hts_main_t; static hts_main_t hts_main; @@ -418,23 +423,53 @@ hts_transport_needs_crypto (transport_proto_t proto) proto == TRANSPORT_PROTO_QUIC; } -static int -hts_listen (hts_main_t *htm) +static clib_error_t * +hts_listen (hts_main_t *htm, u8 *listen_uri, u8 is_del) { session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL; vnet_listen_args_t _a, *a = &_a; - char *uri = "tcp://0.0.0.0/80"; - u8 need_crypto; + u8 need_crypto, *uri; + hts_session_t *hls; + session_t *ls; + uword *p; int rv; - clib_memset (a, 0, sizeof (*a)); - a->app_index = htm->app_index; + uri = listen_uri ? listen_uri : htm->default_uri; + p = hash_get_mem (htm->uri_to_handle, uri); - if (htm->uri) - uri = (char *) htm->uri; + if (is_del) + { + if (!p) + return clib_error_return (0, "not listening on %v", uri); - if (parse_uri (uri, &sep)) - return -1; + hls = hts_session_get (0, *p); + ls = listen_session_get (hls->vpp_session_index); + + vnet_unlisten_args_t ua = { + .handle = listen_session_get_handle (ls), + .app_index = htm->app_index, + .wrk_map_index = 0 /* default wrk */ + }; + + hash_unset_mem (htm->uri_to_handle, uri); + + if (vnet_unlisten (&ua)) + return clib_error_return (0, "failed to unlisten"); + + vec_free (hls->uri); + hts_session_free (hls); + + return 0; + } + + if (p) + return clib_error_return (0, "already listening %v", uri); + + if (parse_uri ((char *) uri, &sep)) + return clib_error_return (0, "failed to parse uri %v", uri); + + clib_memset (a, 0, sizeof (*a)); + a->app_index = htm->app_index; need_crypto = hts_transport_needs_crypto (sep.transport_proto); @@ -453,7 +488,16 @@ hts_listen (hts_main_t *htm) if (need_crypto) clib_mem_free (a->sep_ext.ext_cfg); - return rv; + if (rv) + return clib_error_return (0, "failed to listen on %v", uri); + + hls = hts_session_alloc (0); + hls->uri = vec_dup (uri); + ls = listen_session_get_from_handle (a->handle); + hls->vpp_session_index = ls->session_index; + hash_set_mem (htm->uri_to_handle, hls->uri, hls->session_index); + + return 0; } static int @@ -474,11 +518,9 @@ hts_create (vlib_main_t *vm) clib_warning ("failed to attach server"); return -1; } - if (hts_listen (htm)) - { - clib_warning ("failed to start listening"); - return -1; - } + + htm->default_uri = format (0, "tcp://0.0.0.0/80%c", 0); + htm->uri_to_handle = hash_create_vec (0, sizeof (u8), sizeof (uword)); return 0; } @@ -490,7 +532,9 @@ hts_create_command_fn (vlib_main_t *vm, unformat_input_t *input, unformat_input_t _line_input, *line_input = &_line_input; hts_main_t *htm = &hts_main; clib_error_t *error = 0; + u8 is_del = 0; u64 mem_size; + u8 *uri = 0; /* Get a line of input. */ if (!unformat_user (input, unformat_line_input, line_input)) @@ -504,12 +548,14 @@ hts_create_command_fn (vlib_main_t *vm, unformat_input_t *input, else if (unformat (line_input, "fifo-size %U", unformat_memory_size, &mem_size)) htm->fifo_size = mem_size; - else if (unformat (line_input, "uri %s", &htm->uri)) + else if (unformat (line_input, "uri %s", &uri)) ; else if (unformat (line_input, "no-zc")) htm->no_zc = 1; else if (unformat (line_input, "debug")) htm->debug_level = 1; + else if (unformat (line_input, "del")) + is_del = 1; else { error = clib_error_return (0, "unknown input `%U'", @@ -521,28 +567,111 @@ hts_create_command_fn (vlib_main_t *vm, unformat_input_t *input, unformat_free (line_input); if (error) - return error; + goto done; start_server: - if (htm->app_index != (u32) ~0) - return clib_error_return (0, "http tps is already running"); + if (htm->app_index == (u32) ~0) + { + vnet_session_enable_disable (vm, 1 /* is_enable */); - vnet_session_enable_disable (vm, 1 /* is_enable */); + if (hts_create (vm)) + { + error = clib_error_return (0, "http tps create failed"); + goto done; + } + } - if (hts_create (vm)) - return clib_error_return (0, "http tps create failed"); + error = hts_listen (htm, uri, is_del); - return 0; +done: + + vec_free (uri); + return error; } VLIB_CLI_COMMAND (http_tps_command, static) = { .path = "http tps", .short_help = "http tps [uri ] [fifo-size ] " - "[segment-size ] [prealloc-fifos ] [debug] [no-zc]", + "[segment-size ] [prealloc-fifos ] [debug] [no-zc] " + "[del]", .function = hts_create_command_fn, }; +static clib_error_t * +hts_show_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + hts_main_t *htm = &hts_main; + clib_error_t *error = 0; + u8 do_listeners = 0; + hts_session_t **sessions; + u32 n_listeners = 0, n_sessions = 0; + + if (!unformat_user (input, unformat_line_input, line_input)) + goto no_input; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "listeners")) + do_listeners = 1; + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + break; + } + } + + if (error) + return error; + +no_input: + + if (htm->app_index == ~0) + { + vlib_cli_output (vm, "http tps not enabled"); + goto done; + } + + if (do_listeners) + { + uword handle; + u8 *s = 0, *uri; + + /* clang-format off */ + hash_foreach (uri, handle, htm->uri_to_handle, ({ + s = format (s, "%-30v%lx\n", uri, handle); + })); + /* clang-format on */ + + if (s) + { + vlib_cli_output (vm, "%-29s%s", "URI", "Index"); + vlib_cli_output (vm, "%v", s); + vec_free (s); + } + goto done; + } + + n_listeners = hash_elts (htm->uri_to_handle); + vec_foreach (sessions, htm->sessions) + n_sessions += pool_elts (*sessions); + + vlib_cli_output (vm, " app index: %u\n listeners: %u\n sesions: %u", + htm->app_index, n_listeners, n_sessions - n_listeners); + +done: + return 0; +} + +VLIB_CLI_COMMAND (show_http_tps_command, static) = { + .path = "show http tps", + .short_help = "http tps [listeners]", + .function = hts_show_command_fn, +}; + static clib_error_t * hs_main_init (vlib_main_t *vm) { diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index 868d0ddf42d..f1a304829ac 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -76,17 +76,27 @@ static u32 http_listener_alloc (void) { http_main_t *hm = &http_main; - http_conn_t *ctx; + http_conn_t *lhc; - pool_get_zero (hm->listener_ctx_pool, ctx); - ctx->c_c_index = ctx - hm->listener_ctx_pool; - return ctx->c_c_index; + pool_get_zero (hm->listener_pool, lhc); + lhc->c_c_index = lhc - hm->listener_pool; + return lhc->c_c_index; } http_conn_t * -http_listener_get (u32 ctx_index) +http_listener_get (u32 lhc_index) { - return pool_elt_at_index (http_main.listener_ctx_pool, ctx_index); + return pool_elt_at_index (http_main.listener_pool, lhc_index); +} + +void +http_listener_free (http_conn_t *lhc) +{ + http_main_t *hm = &http_main; + + if (CLIB_DEBUG) + memset (lhc, 0xfc, sizeof (*lhc)); + pool_put (hm->listener_pool, lhc); } void @@ -776,6 +786,28 @@ http_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep) return lhc_index; } +static u32 +http_stop_listen (u32 listener_index) +{ + http_conn_t *lhc; + int rv; + + lhc = http_listener_get (listener_index); + + vnet_unlisten_args_t a = { + .handle = lhc->h_tc_session_handle, + .app_index = http_main.app_index, + .wrk_map_index = 0 /* default wrk */ + }; + + if ((rv = vnet_unlisten (&a))) + clib_warning ("unlisten returned %d", rv); + + http_listener_free (lhc); + + return 0; +} + static void http_transport_close (u32 hc_index, u32 thread_index) { @@ -956,6 +988,7 @@ static const transport_proto_vft_t http_proto = { .enable = http_transport_enable, .connect = http_transport_connect, .start_listen = http_start_listen, + .stop_listen = http_stop_listen, .close = http_transport_close, .custom_tx = http_app_tx_callback, .get_connection = http_transport_get_connection, diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h index 8a5731ea592..da74459794c 100644 --- a/src/plugins/http/http.h +++ b/src/plugins/http/http.h @@ -165,7 +165,7 @@ typedef struct http_worker_ typedef struct http_main_ { http_worker_t *wrk; - http_conn_t *listener_ctx_pool; + http_conn_t *listener_pool; u32 app_index; clib_timebase_t timebase; diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index cd54670884a..4eafb1f0111 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -719,6 +719,7 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, { error = clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); + break; } } -- cgit 1.2.3-korg