From 7cb471a0279ab2a3740a49d6ce9cf7b24f0a3f4d Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Fri, 23 Jul 2021 08:39:26 -0700 Subject: [PATCH] session vcl: support abstract sockets for app ns App namespaces can now be associated to a linux ip netns, e.g.: app ns add id secret sw_if_index netns If session layer's app sock api is enabled, this triggers the creation of an abstract listening socket in the netns that has been configured. For the example above that would be @vpp/session/. Consequently, vcl, or other apps attaching to vpp, can connect to said abstract socket from an ip netns without the need to share unix domain socket files. In particular, for vcl it's enough to set app-socket-api to @vpp/session/ in the conf file. Type: feature Signed-off-by: Florin Coras Change-Id: I26fdc626a760a3f423c5b8be4251623f6e9cd73a --- src/vnet/session/application_namespace.c | 44 +++++++++++++++++------- src/vnet/session/application_namespace.h | 6 ++++ src/vnet/session/session.api | 39 +++++++++++++++++++++ src/vnet/session/session_api.c | 59 ++++++++++++++++++++++++++++++-- 4 files changed, 132 insertions(+), 16 deletions(-) diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c index b9674bed94a..6d91fc362b2 100644 --- a/src/vnet/session/application_namespace.c +++ b/src/vnet/session/application_namespace.c @@ -104,6 +104,7 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a) app_ns->local_table_index = session_table_index (st); } app_ns->ns_secret = a->secret; + app_ns->netns = a->netns ? vec_dup (a->netns) : 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); @@ -184,12 +185,17 @@ app_namespaces_init (void) /* * Allocate default namespace */ + + /* clang-format off */ vnet_app_namespace_add_del_args_t a = { .ns_id = ns_id, + .netns = 0, .secret = 0, .sw_if_index = APP_NAMESPACE_INVALID_INDEX, .is_add = 1 }; + /* clang-format on */ + vnet_app_namespace_add_del (&a); vec_free (ns_id); } @@ -198,8 +204,8 @@ static clib_error_t * app_ns_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + u8 is_add = 0, *ns_id = 0, secret_set = 0, sw_if_index_set = 0, *netns = 0; unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 0, *ns_id = 0, secret_set = 0, sw_if_index_set = 0; u32 sw_if_index, fib_id = APP_NAMESPACE_INVALID_INDEX; u64 secret; clib_error_t *error = 0; @@ -222,45 +228,54 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input, sw_if_index_set = 1; else if (unformat (line_input, "fib_id", &fib_id)) ; + else if (unformat (line_input, "netns %_%v%_", &netns)) + ; else { error = clib_error_return (0, "unknown input `%U'", format_unformat_error, line_input); - unformat_free (line_input); - return error; + goto done; } } - unformat_free (line_input); if (!ns_id || !secret_set || !sw_if_index_set) { vlib_cli_output (vm, "namespace-id, secret and sw_if_index must be " "provided"); - return 0; + goto done; } if (is_add) { + /* 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, .ip4_fib_id = fib_id, .is_add = 1 }; + /* clang-format on */ + if ((rv = vnet_app_namespace_add_del (&args))) - return clib_error_return (0, "app namespace add del returned %d", rv); + error = clib_error_return (0, "app namespace add del returned %d", rv); } +done: + + vec_free (ns_id); + vec_free (netns); + unformat_free (line_input); + return error; } /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (app_ns_command, static) = -{ +VLIB_CLI_COMMAND (app_ns_command, static) = { .path = "app ns", .short_help = "app ns [add] id secret " - "sw_if_index ", + "sw_if_index [netns ]", .function = app_ns_fn, }; /* *INDENT-ON* */ @@ -269,8 +284,11 @@ u8 * format_app_namespace (u8 * s, va_list * args) { app_namespace_t *app_ns = va_arg (*args, app_namespace_t *); - s = format (s, "%-10u%-20lu%-20u%-50v", app_namespace_index (app_ns), - app_ns->ns_secret, app_ns->sw_if_index, app_ns->ns_id); + + s = + format (s, "%-10u%-10lu%-15d%-15v%-15v%-40v", app_namespace_index (app_ns), + app_ns->ns_secret, app_ns->sw_if_index, app_ns->ns_id, + app_ns->netns, app_ns->sock_name); return s; } @@ -374,8 +392,8 @@ show_app_ns_fn (vlib_main_t * vm, unformat_input_t * main_input, } do_ns_list: - vlib_cli_output (vm, "%-10s%-20s%-20s%-50s", "Index", "Secret", - "sw_if_index", "Name"); + vlib_cli_output (vm, "%-10s%-10s%-15s%-15s%-15s%-40s", "Index", "Secret", + "sw_if_index", "Id", "netns", "Socket"); /* *INDENT-OFF* */ pool_foreach (app_ns, app_namespace_pool) { diff --git a/src/vnet/session/application_namespace.h b/src/vnet/session/application_namespace.h index ddc6d08c2fc..313b2d0e63d 100644 --- a/src/vnet/session/application_namespace.h +++ b/src/vnet/session/application_namespace.h @@ -50,6 +50,11 @@ typedef struct _app_namespace */ u8 *ns_id; + /** + * Linux netns if one was provided + */ + u8 *netns; + /** * Name of socket applications can use to attach to session layer */ @@ -64,6 +69,7 @@ typedef struct _app_namespace typedef struct _vnet_app_namespace_add_del_args { u8 *ns_id; + u8 *netns; u64 secret; u32 sw_if_index; u32 ip4_fib_id; diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api index 53e2834e839..43bde1afbbd 100644 --- a/src/vnet/session/session.api +++ b/src/vnet/session/session.api @@ -217,6 +217,7 @@ autoreply define session_enable_disable { @param namespace_id - namespace id */ define app_namespace_add_del { + option deprecated; u32 client_index; u32 context; u64 secret; @@ -226,12 +227,50 @@ define app_namespace_add_del { string namespace_id[]; }; +/** \brief add/del application namespace + @param client_index - opaque cookie to identify the sender + client to vpp direction only + @param context - sender context, to match reply w/ request + @param secret - secret shared between app and vpp + @param sw_if_index - local interface that "supports" namespace. Set to + ~0 if no preference + @param ip4_fib_id - id of ip4 fib that "supports" the namespace. Ignored + if sw_if_index set. + @param ip6_fib_id - id of ip6 fib that "supports" the namespace. Ignored + if sw_if_index set. + @param namespace_id - namespace id + @param netns - linux net namespace +*/ +define app_namespace_add_del_v2 { + u32 client_index; + u32 context; + u64 secret; + vl_api_interface_index_t sw_if_index [default=0xffffffff]; + u32 ip4_fib_id; + u32 ip6_fib_id; + string namespace_id[64]; + string netns[64]; +}; + /** \brief Reply for app namespace add/del @param context - returned sender context, to match reply w/ request @param retval - return code @param appns_index - app namespace index */ define app_namespace_add_del_reply +{ + option deprecated; + u32 context; + i32 retval; + u32 appns_index; +}; + +/** \brief Reply for app namespace add/del + @param context - returned sender context, to match reply w/ request + @param retval - return code + @param appns_index - app namespace index +*/ +define app_namespace_add_del_v2_reply { u32 context; i32 retval; diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index 75c4700361f..7e7cffbbdd4 100644 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -855,6 +855,55 @@ done: /* *INDENT-ON* */ } +static void +vl_api_app_namespace_add_del_v2_t_handler ( + vl_api_app_namespace_add_del_v2_t *mp) +{ + vl_api_app_namespace_add_del_v2_reply_t *rmp; + u8 *ns_id = 0, *netns = 0; + u32 appns_index = 0; + int rv = 0; + + if (session_main_is_enabled () == 0) + { + rv = VNET_API_ERROR_FEATURE_DISABLED; + goto done; + } + + mp->namespace_id[sizeof (mp->namespace_id) - 1] = 0; + mp->netns[sizeof (mp->netns) - 1] = 0; + ns_id = format (0, "%s", &mp->namespace_id); + netns = format (0, "%s", &mp->netns); + + vnet_app_namespace_add_del_args_t args = { + .ns_id = ns_id, + .netns = netns, + .secret = clib_net_to_host_u64 (mp->secret), + .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index), + .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id), + .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id), + .is_add = 1 + }; + rv = vnet_app_namespace_add_del (&args); + if (!rv) + { + appns_index = app_namespace_index_from_id (ns_id); + if (appns_index == APP_NAMESPACE_INVALID_INDEX) + { + clib_warning ("app ns lookup failed"); + rv = VNET_API_ERROR_UNSPECIFIED; + } + } + vec_free (ns_id); + vec_free (netns); + +done: + REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_V2_REPLY, ({ + if (!rv) + rmp->appns_index = clib_host_to_net_u32 (appns_index); + })); +} + static void vl_api_session_rule_add_del_t_handler (vl_api_session_rule_add_del_t * mp) { @@ -1604,7 +1653,11 @@ appns_sapi_add_ns_socket (app_namespace_t * app_ns) goto error; } - app_ns->sock_name = format (0, "%v%v%c", dir, app_ns->ns_id, 0); + /* Use abstract sockets if a netns was provided */ + if (app_ns->netns) + app_ns->sock_name = format (0, "@vpp/session/%v%c", app_ns->ns_id, 0); + else + app_ns->sock_name = format (0, "%v%v%c", dir, app_ns->ns_id, 0); /* * Create and initialize socket to listen on @@ -1615,14 +1668,14 @@ appns_sapi_add_ns_socket (app_namespace_t * app_ns) CLIB_SOCKET_F_ALLOW_GROUP_WRITE | CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED; - if ((err = clib_socket_init (cs))) + if ((err = clib_socket_init_netns (cs, app_ns->netns))) { clib_error_report (err); rv = -1; goto error; } - if (stat ((char *) app_ns->sock_name, &file_stat) == -1) + if (!app_ns->netns && stat ((char *) app_ns->sock_name, &file_stat) == -1) { rv = -1; goto error; -- 2.16.6