diff options
author | Florin Coras <fcoras@cisco.com> | 2017-10-02 00:18:51 -0700 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2017-10-10 20:42:50 +0000 |
commit | cea194d8f973a2f2b5ef72d212533057174cc70a (patch) | |
tree | 6fdd2e8a929c62625d1ad35bfbec342129989aef /src/vnet/session/application_namespace.c | |
parent | 1f36a93d3d68f5ba6dcda08809394ce757cefd72 (diff) |
session: add support for application namespacing
Applications are now provided the option to select the namespace they
are to be attached to and the scope of their attachement. Application
namespaces are meant to:
1) constrain the scope of communication through the network by
association with source interfaces and/or fib tables that provide the
source ips to be used and limit the scope of routing
2) provide a namespace local scope to session layer communication, as
opposed to the global scope provided by 1). That is, sessions can be
established without assistance from transport and network layers.
Albeit, zero/local-host ip addresses must still be provided in session
establishment messages due to existing application idiosyncrasies. This
mode of communication uses shared-memory fifos (cut-through sessions)
exclusively.
If applications request no namespace, they are assigned to the default
one, which at its turn uses the default fib. Applications can request
access to both local and global scopes for a namespace. If no scope is
specified, session layer defaults to the global one.
When a sw_if_index is provided for a namespace, zero-ip (INADDR_ANY)
binds are converted to binds to the requested interface.
Change-Id: Ia0f660bbf7eec7f89673f75b4821fc7c3d58e3d1
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/session/application_namespace.c')
-rw-r--r-- | src/vnet/session/application_namespace.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c new file mode 100644 index 00000000000..7f90943f9cd --- /dev/null +++ b/src/vnet/session/application_namespace.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <vnet/session/application_namespace.h> +#include <vnet/session/session_table.h> +#include <vnet/session/session.h> +#include <vnet/fib/fib_table.h> + +/** + * Hash table of application namespaces by app ns ids + */ +uword *app_namespace_lookup_table; + +/** + * Pool of application namespaces + */ +static app_namespace_t *app_namespace_pool; + +app_namespace_t * +app_namespace_get (u32 index) +{ + return pool_elt_at_index (app_namespace_pool, index); +} + +app_namespace_t * +app_namespace_get_from_id (const u8 * ns_id) +{ + u32 index = app_namespace_index_from_id (ns_id); + if (index == APP_NAMESPACE_INVALID_INDEX) + return 0; + return app_namespace_get (index); +} + +u32 +app_namespace_index (app_namespace_t * app_ns) +{ + return (app_ns - app_namespace_pool); +} + +app_namespace_t * +app_namespace_alloc (u8 * ns_id) +{ + app_namespace_t *app_ns; + pool_get (app_namespace_pool, app_ns); + memset (app_ns, 0, sizeof (*app_ns)); + app_ns->ns_id = vec_dup (ns_id); + hash_set_mem (app_namespace_lookup_table, app_ns->ns_id, + app_ns - app_namespace_pool); + return app_ns; +} + +clib_error_t * +vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t * a) +{ + app_namespace_t *app_ns; + session_table_t *st; + + if (a->is_add) + { + if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX + && !vnet_get_sw_interface_safe (vnet_get_main (), a->sw_if_index)) + return clib_error_return_code (0, VNET_API_ERROR_INVALID_SW_IF_INDEX, + 0, "sw_if_index %u doesn't exist", + a->sw_if_index); + + if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX) + { + a->ip4_fib_id = + fib_table_get_table_id_for_sw_if_index (FIB_PROTOCOL_IP4, + a->sw_if_index); + a->ip6_fib_id = + fib_table_get_table_id_for_sw_if_index (FIB_PROTOCOL_IP4, + a->sw_if_index); + } + if (a->sw_if_index == APP_NAMESPACE_INVALID_INDEX + && a->ip4_fib_id == APP_NAMESPACE_INVALID_INDEX) + return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0, + "sw_if_index or fib_id must be " + "configured"); + st = session_table_alloc (); + session_table_init (st); + + app_ns = app_namespace_get_from_id (a->ns_id); + if (!app_ns) + app_ns = app_namespace_alloc (a->ns_id); + app_ns->ns_secret = a->secret; + app_ns->sw_if_index = a->sw_if_index; + app_ns->local_table_index = session_table_index (st); + app_ns->ip4_fib_index = + fib_table_find (FIB_PROTOCOL_IP4, a->ip4_fib_id); + app_ns->ip6_fib_index = + fib_table_find (FIB_PROTOCOL_IP6, a->ip6_fib_id); + } + else + { + return clib_error_return_code (0, VNET_API_ERROR_UNIMPLEMENTED, 0, + "namespace deletion not supported"); + } + return 0; +} + +const u8 * +app_namespace_id (app_namespace_t * app_ns) +{ + return app_ns->ns_id; +} + +u32 +app_namespace_index_from_id (const u8 * ns_id) +{ + uword *indexp; + indexp = hash_get_mem (app_namespace_lookup_table, ns_id); + if (!indexp) + return APP_NAMESPACE_INVALID_INDEX; + return *indexp; +} + +const u8 * +app_namespace_id_from_index (u32 index) +{ + app_namespace_t *app_ns; + + app_ns = app_namespace_get (index); + return app_namespace_id (app_ns); +} + +void +app_namespaces_init (void) +{ + u8 *ns_id = format (0, "default"); + app_namespace_lookup_table = + hash_create_vec (0, sizeof (u8), sizeof (uword)); + + /* + * Allocate default namespace + */ + vnet_app_namespace_add_del_args_t a = { + .ns_id = ns_id, + .secret = 0, + .sw_if_index = APP_NAMESPACE_INVALID_INDEX, + .is_add = 1 + }; + vnet_app_namespace_add_del (&a); + vec_free (ns_id); +} + +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; + u32 sw_if_index, fib_id = APP_NAMESPACE_INVALID_INDEX; + u64 secret; + clib_error_t *error = 0; + + session_cli_return_if_not_enabled (); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "add")) + is_add = 1; + else if (unformat (input, "id %_%v%_", &ns_id)) + ; + else if (unformat (input, "secret %lu", &secret)) + secret_set = 1; + else if (unformat (input, "sw_if_index %u", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (input, "fib_id", &fib_id)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, 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; + } + + if (is_add) + { + vnet_app_namespace_add_del_args_t args = { + .ns_id = ns_id, + .secret = secret, + .sw_if_index = sw_if_index, + .ip4_fib_id = fib_id, + .is_add = 1 + }; + error = vnet_app_namespace_add_del (&args); + } + + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (app_ns_command, static) = +{ + .path = "app ns", + .short_help = "app ns [add] id <namespace-id> secret <secret> " + "sw_if_index <sw_if_index>", + .function = app_ns_fn, +}; +/* *INDENT-ON* */ + +u8 * +format_app_namespace (u8 * s, va_list * args) +{ + app_namespace_t *app_ns = va_arg (*args, app_namespace_t *); + s = format (s, "%-20v%-20lu%-20u", app_ns->ns_id, app_ns->ns_secret, + app_ns->sw_if_index); + return s; +} + +static clib_error_t * +show_app_ns_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + app_namespace_t *app_ns; + session_table_t *st; + u8 *ns_id, do_table = 0; + + session_cli_return_if_not_enabled (); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table %_%v%_", &ns_id)) + do_table = 1; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + if (do_table) + { + app_ns = app_namespace_get_from_id (ns_id); + if (!app_ns) + { + vlib_cli_output (vm, "ns %v not found", ns_id); + return 0; + } + st = session_table_get (app_ns->local_table_index); + if (!st) + { + vlib_cli_output (vm, "table for ns %v could not be found", ns_id); + return 0; + } + session_lookup_show_table_entries (vm, st, 0, 1); + vec_free (ns_id); + return 0; + } + + vlib_cli_output (vm, "%-20s%-20s%-20s", "Namespace", "Secret", + "sw_if_index"); + + /* *INDENT-OFF* */ + pool_foreach (app_ns, app_namespace_pool, ({ + vlib_cli_output (vm, "%U", format_app_namespace, app_ns); + })); + /* *INDENT-ON* */ + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_app_ns_command, static) = +{ + .path = "show app ns", + .short_help = "show app ns", + .function = show_app_ns_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |