From b3ea73e766013bed70340688ce361d9096045b44 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Thu, 5 Aug 2021 10:22:52 +0200 Subject: [PATCH] session: implement app_ns deletion Type: feature Change-Id: If0edbb21a0283d66c648a9e190d238c8cfa56353 Signed-off-by: Nathan Skrzypczak --- src/plugins/unittest/session_test.c | 12 ++++ src/vnet/session/application.c | 41 ++++++++---- src/vnet/session/application.h | 1 + src/vnet/session/application_namespace.c | 107 ++++++++++++++++++++++--------- src/vnet/session/application_namespace.h | 1 + src/vnet/session/mma_template.c | 5 ++ src/vnet/session/session_api.c | 21 +++++- src/vnet/session/session_rules_table.c | 7 ++ src/vnet/session/session_rules_table.h | 1 + src/vnet/session/session_table.c | 25 ++++++++ src/vnet/session/session_table.h | 1 + src/vnet/session/transport.h | 10 ++- 12 files changed, 182 insertions(+), 50 deletions(-) diff --git a/src/plugins/unittest/session_test.c b/src/plugins/unittest/session_test.c index b54712c3885..292f7253a67 100644 --- a/src/plugins/unittest/session_test.c +++ b/src/plugins/unittest/session_test.c @@ -420,6 +420,10 @@ session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input) detach_args.app_index = client_index; vnet_application_detach (&detach_args); + ns_args.is_add = 0; + error = vnet_app_namespace_add_del (&ns_args); + SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error); + /* Allow the disconnects to finish before removing the routes. */ vlib_process_suspend (vm, 10e-3); @@ -766,6 +770,10 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) detach_args.app_index = server_index; vnet_application_detach (&detach_args); + ns_args.is_add = 0; + error = vnet_app_namespace_add_del (&ns_args); + SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error); + /* * Cleanup */ @@ -1601,6 +1609,10 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) detach_args.app_index = server_index2; vnet_application_detach (&detach_args); + ns_args.is_add = 0; + error = vnet_app_namespace_add_del (&ns_args); + SESSION_TEST ((error == 0), "app ns delete should succeed: %d", error); + vec_free (ns_id); vec_free (attach_args.name); return 0; diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c index d3e598ca271..d8b2b3edcf0 100644 --- a/src/vnet/session/application.c +++ b/src/vnet/session/application.c @@ -947,6 +947,31 @@ application_detach_process (application_t * app, u32 api_client_index) vec_free (wrks); } +void +application_namespace_cleanup (app_namespace_t *app_ns) +{ + u32 *app_indices = 0, *app_index; + application_t *app; + u32 ns_index; + + ns_index = app_namespace_index (app_ns); + pool_foreach (app, app_main.app_pool) + if (app->ns_index == ns_index) + vec_add1 (app_indices, app->ns_index); + + vec_foreach (app_index, app_indices) + { + app = application_get (*app_index); + + if (application_is_proxy (app)) + application_remove_proxy (app); + app->flags &= ~APP_OPTIONS_FLAGS_IS_PROXY; + + application_free (app); + } + vec_free (app_indices); +} + app_worker_t * application_get_worker (application_t * app, u32 wrk_map_index) { @@ -1611,12 +1636,8 @@ application_setup_proxy (application_t * app) ASSERT (application_is_proxy (app)); - /* *INDENT-OFF* */ - transport_proto_foreach (tp, ({ - if (transports & (1 << tp)) - application_start_stop_proxy (app, tp, 1); - })); - /* *INDENT-ON* */ + transport_proto_foreach (tp, transports) + application_start_stop_proxy (app, tp, 1); } void @@ -1627,12 +1648,8 @@ application_remove_proxy (application_t * app) ASSERT (application_is_proxy (app)); - /* *INDENT-OFF* */ - transport_proto_foreach (tp, ({ - if (transports & (1 << tp)) - application_start_stop_proxy (app, tp, 0); - })); - /* *INDENT-ON* */ + transport_proto_foreach (tp, transports) + application_start_stop_proxy (app, tp, 0); } segment_manager_props_t * diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h index 6afbaa3eef0..b3201b9833e 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -280,6 +280,7 @@ u8 application_has_local_scope (application_t * app); u8 application_has_global_scope (application_t * app); void application_setup_proxy (application_t * app); void application_remove_proxy (application_t * app); +void application_namespace_cleanup (app_namespace_t *app_ns); segment_manager_props_t *application_get_segment_manager_properties (u32 app_index); diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c index 349e79bbff4..bece746a757 100644 --- a/src/vnet/session/application_namespace.c +++ b/src/vnet/session/application_namespace.c @@ -55,6 +55,15 @@ app_namespace_index (app_namespace_t * app_ns) return (app_ns - app_namespace_pool); } +void +app_namespace_free (app_namespace_t *app_ns) +{ + hash_unset_mem (app_namespace_lookup_table, app_ns->ns_id); + vec_free (app_ns->ns_id); + + pool_put (app_namespace_pool, app_ns); +} + app_namespace_t * app_namespace_alloc (const u8 *ns_id) { @@ -77,6 +86,7 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a) { app_namespace_t *app_ns; session_table_t *st; + u32 ns_index; int rv; if (a->is_add) @@ -109,10 +119,28 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a) st->is_local = 1; st->appns_index = app_namespace_index (app_ns); app_ns->local_table_index = session_table_index (st); + if (a->netns) + { + app_ns->netns = vec_dup (a->netns); + vec_terminate_c_string (app_ns->netns); + } + if (a->sock_name) + { + app_ns->sock_name = vec_dup (a->sock_name); + vec_terminate_c_string (app_ns->sock_name); + } + + /* Add socket for namespace, + * only at creation time */ + if (app_sapi_enabled) + { + rv = appns_sapi_add_ns_socket (app_ns); + if (rv) + return rv; + } } + app_ns->ns_secret = a->secret; - app_ns->netns = a->netns ? vec_dup (a->netns) : 0; - app_ns->sock_name = a->sock_name ? vec_dup (a->sock_name) : 0; app_ns->sw_if_index = a->sw_if_index; app_ns->ip4_fib_index = fib_table_find (FIB_PROTOCOL_IP4, a->ip4_fib_id); @@ -120,18 +148,33 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a) fib_table_find (FIB_PROTOCOL_IP6, a->ip6_fib_id); session_lookup_set_tables_appns (app_ns); - /* Add socket for namespace */ - if (app_sapi_enabled) - { - rv = appns_sapi_add_ns_socket (app_ns); - if (rv) - return rv; - } } else { - return VNET_API_ERROR_UNIMPLEMENTED; + ns_index = app_namespace_index_from_id (a->ns_id); + if (ns_index == APP_NAMESPACE_INVALID_INDEX) + return VNET_API_ERROR_INVALID_VALUE; + + app_ns = app_namespace_get (ns_index); + if (!app_ns) + return VNET_API_ERROR_INVALID_VALUE; + + application_namespace_cleanup (app_ns); + + if (app_sapi_enabled) + appns_sapi_del_ns_socket (app_ns); + + st = session_table_get (app_ns->local_table_index); + + session_table_free (st, FIB_PROTOCOL_MAX); + if (app_ns->netns) + vec_free (app_ns->netns); + if (app_ns->sock_name) + vec_free (app_ns->sock_name); + + app_namespace_free (app_ns); } + return 0; } @@ -241,6 +284,8 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input, { if (unformat (line_input, "add")) is_add = 1; + else if (unformat (line_input, "del")) + is_add = 0; else if (unformat (line_input, "id %_%v%_", &ns_id)) ; else if (unformat (line_input, "secret %lu", &secret)) @@ -264,31 +309,33 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input, } } - if (!ns_id || !secret_set || !sw_if_index_set) + if (!ns_id) { - vlib_cli_output (vm, "namespace-id, secret and interface must be " - "provided"); + vlib_cli_output (vm, "namespace-id must be provided"); goto done; } - if (is_add) + if (is_add && (!secret_set || !sw_if_index_set)) { - /* clang-format off */ - vnet_app_namespace_add_del_args_t args = { - .ns_id = ns_id, - .netns = netns, - .sock_name = sock_name, - .secret = secret, - .sw_if_index = sw_if_index, - .ip4_fib_id = fib_id, - .is_add = 1 - }; - /* clang-format on */ - - if ((rv = vnet_app_namespace_add_del (&args))) - error = clib_error_return (0, "app namespace add del returned %d", rv); + vlib_cli_output (vm, "secret and interface must be provided"); + goto done; } + /* clang-format off */ + vnet_app_namespace_add_del_args_t args = { + .ns_id = ns_id, + .netns = netns, + .secret = secret, + .sw_if_index = sw_if_index, + .sock_name = sock_name, + .ip4_fib_id = fib_id, + .is_add = is_add, + }; + /* clang-format on */ + + if ((rv = vnet_app_namespace_add_del (&args))) + error = clib_error_return (0, "app namespace add del returned %d", rv); + done: vec_free (ns_id); @@ -302,8 +349,8 @@ done: /* *INDENT-OFF* */ VLIB_CLI_COMMAND (app_ns_command, static) = { .path = "app ns", - .short_help = "app ns [add] id secret " - "if [netns ]", + .short_help = "app ns [add|del] id secret " + "sw_if_index if [netns ]", .function = app_ns_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/session/application_namespace.h b/src/vnet/session/application_namespace.h index 5449d4755c3..14e6a650e56 100644 --- a/src/vnet/session/application_namespace.h +++ b/src/vnet/session/application_namespace.h @@ -160,6 +160,7 @@ appns_sapi_handle_sock_index (u32 sapi_sock_handle) } int appns_sapi_add_ns_socket (app_namespace_t * app_ns); +void appns_sapi_del_ns_socket (app_namespace_t *app_ns); u8 appns_sapi_enabled (void); void appns_sapi_enable (void); diff --git a/src/vnet/session/mma_template.c b/src/vnet/session/mma_template.c index ae730e5dbea..4b2770bb756 100644 --- a/src/vnet/session/mma_template.c +++ b/src/vnet/session/mma_template.c @@ -65,6 +65,11 @@ RT (mma_rule_free) (RTT (mma_rules_table) * srt, RTT (mma_rule) * rule) return rule; } +void RT (mma_rules_table_free) (RTT (mma_rules_table) * srt) +{ + pool_free (srt->rules); +} + RTT (mma_rule) * RT (mma_rules_table_get_rule) (RTT (mma_rules_table) * srt, u32 srt_index) { diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index c0ed1250dab..c031545323e 100644 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -930,7 +930,7 @@ vl_api_app_namespace_add_del_v3_t_handler ( mp->netns[sizeof (mp->netns) - 1] = 0; ns_id = format (0, "%s", &mp->namespace_id); netns = format (0, "%s", &mp->netns); - sock_name = format (0, "%s", &mp->sock_name); + sock_name = vl_api_from_api_to_new_vec (mp, &mp->sock_name); vnet_app_namespace_add_del_args_t args = { .ns_id = ns_id, .netns = netns, @@ -1762,6 +1762,23 @@ error: return err; } +void +appns_sapi_del_ns_socket (app_namespace_t *app_ns) +{ + app_ns_api_handle_t *handle; + clib_socket_t *cs; + + pool_foreach (cs, app_ns->app_sockets) + { + handle = (app_ns_api_handle_t *) &cs->private_data; + clib_file_del_by_index (&file_main, handle->aah_file_index); + + clib_socket_close (cs); + clib_socket_free (cs); + } + pool_free (app_ns->app_sockets); +} + int appns_sapi_add_ns_socket (app_namespace_t * app_ns) { @@ -1799,7 +1816,7 @@ appns_sapi_add_ns_socket (app_namespace_t * app_ns) * Create and initialize socket to listen on */ cs = appns_sapi_alloc_socket (app_ns); - cs->config = (char *) app_ns->sock_name; + cs->config = (char *) vec_dup (app_ns->sock_name); cs->flags = CLIB_SOCKET_F_IS_SERVER | CLIB_SOCKET_F_ALLOW_GROUP_WRITE | CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED; diff --git a/src/vnet/session/session_rules_table.c b/src/vnet/session/session_rules_table.c index 34bd6a38676..5108c00d728 100644 --- a/src/vnet/session/session_rules_table.c +++ b/src/vnet/session/session_rules_table.c @@ -513,6 +513,13 @@ session_rules_table_add_del (session_rules_table_t * srt, return 0; } +void +session_rules_table_free (session_rules_table_t *srt) +{ + mma_rules_table_free_16 (&srt->session_rules_tables_16); + mma_rules_table_free_40 (&srt->session_rules_tables_40); +} + void session_rules_table_init (session_rules_table_t * srt) { diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h index 8679cb8a0c7..206ef2f380f 100644 --- a/src/vnet/session/session_rules_table.h +++ b/src/vnet/session/session_rules_table.h @@ -116,6 +116,7 @@ int session_rules_table_add_del (session_rules_table_t * srt, u8 *session_rules_table_rule_tag (session_rules_table_t * srt, u32 ri, u8 is_ip4); void session_rules_table_init (session_rules_table_t * srt); +void session_rules_table_free (session_rules_table_t *srt); #endif /* SRC_VNET_SESSION_SESSION_RULES_TABLE_H_ */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/session/session_table.c b/src/vnet/session/session_table.c index d0b576fda7b..9af8ae6a584 100644 --- a/src/vnet/session/session_table.c +++ b/src/vnet/session/session_table.c @@ -60,6 +60,31 @@ session_table_get (u32 table_index) _(v6,halfopen,buckets,20000) \ _(v6,halfopen,memory,(64<<20)) +void +session_table_free (session_table_t *slt, u8 fib_proto) +{ + u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; + int i; + + for (i = 0; i < TRANSPORT_N_PROTOS; i++) + session_rules_table_free (&slt->session_rules[i]); + + vec_free (slt->session_rules); + + if (fib_proto == FIB_PROTOCOL_IP4 || all) + { + clib_bihash_free_16_8 (&slt->v4_session_hash); + clib_bihash_free_16_8 (&slt->v4_half_open_hash); + } + if (fib_proto == FIB_PROTOCOL_IP6 || all) + { + clib_bihash_free_48_8 (&slt->v6_session_hash); + clib_bihash_free_48_8 (&slt->v6_half_open_hash); + } + + pool_put (lookup_tables, slt); +} + /** * Initialize session table hash tables * diff --git a/src/vnet/session/session_table.h b/src/vnet/session/session_table.h index ead3c302681..2127ea45d01 100644 --- a/src/vnet/session/session_table.h +++ b/src/vnet/session/session_table.h @@ -67,6 +67,7 @@ session_table_t *session_table_alloc (void); session_table_t *session_table_get (u32 table_index); u32 session_table_index (session_table_t * slt); void session_table_init (session_table_t * slt, u8 fib_proto); +void session_table_free (session_table_t *slt, u8 fib_proto); /* Internal, try not to use it! */ session_table_t *_get_session_tables (); diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index 447552c539e..2cfec06ec94 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -127,12 +127,10 @@ typedef struct _transport_proto_vft extern transport_proto_vft_t *tp_vfts; -#define transport_proto_foreach(VAR, BODY) \ -do { \ - for (VAR = 0; VAR < vec_len (tp_vfts); VAR++) \ - if (tp_vfts[VAR].push_header != 0) \ - do { BODY; } while (0); \ -} while (0) +#define transport_proto_foreach(VAR, VAR_ALLOW_BM) \ + for (VAR = 0; VAR < vec_len (tp_vfts); VAR++) \ + if (tp_vfts[VAR].push_header != 0) \ + if (VAR_ALLOW_BM & (1 << VAR)) int transport_connect (transport_proto_t tp, transport_endpoint_cfg_t * tep); void transport_half_close (transport_proto_t tp, u32 conn_index, -- 2.16.6