diff options
author | Dave Barach <dave@barachs.net> | 2020-07-14 18:30:05 -0400 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2020-07-16 21:39:23 +0000 |
commit | ac0326fc5ae7ac4a8126bbc2f496a92fcfe4755e (patch) | |
tree | 3bb8d7fac43b165ccd6dd106b597fd733e5b28b8 /src/plugins/adl/adl.c | |
parent | 9a0f2a5e7f678de58807fd49d47deec367656715 (diff) |
adl: move allow/deny list function to plugin
Provide binary API compatibility support for the "cop" APIs until vpp
21.01.
Change the deprecation date in map.api to vpp 21.01.
Type: refactor
Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I0e60d96de4ae9ae4448f134cf257934126f3b760
Diffstat (limited to 'src/plugins/adl/adl.c')
-rw-r--r-- | src/plugins/adl/adl.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/src/plugins/adl/adl.c b/src/plugins/adl/adl.c new file mode 100644 index 00000000000..832bfd4a982 --- /dev/null +++ b/src/plugins/adl/adl.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2016,2020 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/ethernet/ethernet.h> +#include <vnet/plugin/plugin.h> +#include <vpp/app/version.h> +#include <plugins/adl/adl.h> + +adl_main_t adl_main; + +static clib_error_t * +adl_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) +{ + adl_main_t *am = &adl_main; + adl_config_data_t _data, *data = &_data; + vlib_main_t *vm = am->vlib_main; + vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);; + adl_config_main_t *acm; + int address_family; + u32 ci, default_next; + + clib_memset (data, 0, sizeof (*data)); + + /* + * Ignore local interface, pg interfaces. $$$ need a #define for the + * first "real" interface. The answer is 5 at the moment. + */ + if (hi->dev_class_index == vnet_local_interface_device_class.index) + return 0; + + for (address_family = VNET_ADL_IP4; address_family < VNET_N_ADLS; + address_family++) + { + acm = &am->adl_config_mains[address_family]; + + /* + * Once-only code to initialize the per-address-family + * adl feature subgraphs. + * Since the (single) start-node, adl-input, must be able + * to push pkts into three separate subgraphs, we + * use a unified adl_feature_type_t enumeration. + */ + + if (!(acm->config_main.node_index_by_feature_index)) + { + switch (address_family) + { + case VNET_ADL_IP4: + { + static char *start_nodes[] = { "adl-input" }; + static char *feature_nodes[] = { + [IP4_RX_ADL_ALLOWLIST] = "ip4-adl-allowlist", + [IP4_RX_ADL_INPUT] = "ip4-input", + }; + + vnet_config_init (vm, &acm->config_main, + start_nodes, ARRAY_LEN (start_nodes), + feature_nodes, ARRAY_LEN (feature_nodes)); + } + break; + case VNET_ADL_IP6: + { + static char *start_nodes[] = { "adl-input" }; + static char *feature_nodes[] = { + [IP6_RX_ADL_ALLOWLIST] = "ip6-adl-allowlist", + [IP6_RX_ADL_INPUT] = "ip6-input", + }; + vnet_config_init (vm, &acm->config_main, + start_nodes, ARRAY_LEN (start_nodes), + feature_nodes, ARRAY_LEN (feature_nodes)); + } + break; + + case VNET_ADL_DEFAULT: + { + static char *start_nodes[] = { "adl-input" }; + static char *feature_nodes[] = { + [DEFAULT_RX_ADL_ALLOWLIST] = "default-adl-allowlist", + [DEFAULT_RX_ADL_INPUT] = "ethernet-input", + }; + vnet_config_init (vm, &acm->config_main, + start_nodes, ARRAY_LEN (start_nodes), + feature_nodes, ARRAY_LEN (feature_nodes)); + } + break; + + default: + clib_warning ("bug"); + break; + } + } + vec_validate_init_empty (acm->config_index_by_sw_if_index, sw_if_index, + ~0); + + ci = acm->config_index_by_sw_if_index[sw_if_index]; + + /* Create a sensible initial config: send pkts to xxx-input */ + if (address_family == VNET_ADL_IP4) + default_next = IP4_RX_ADL_INPUT; + else if (address_family == VNET_ADL_IP6) + default_next = IP6_RX_ADL_INPUT; + else + default_next = DEFAULT_RX_ADL_INPUT; + + if (is_add) + ci = vnet_config_add_feature (vm, &acm->config_main, + ci, default_next, data, sizeof (*data)); + else + { + /* If the feature was actually configured */ + if (ci != ~0) + { + ci = vnet_config_del_feature (vm, &acm->config_main, + ci, default_next, data, + sizeof (*data)); + } + } + + acm->config_index_by_sw_if_index[sw_if_index] = ci; + } + return 0; +} + +VNET_SW_INTERFACE_ADD_DEL_FUNCTION (adl_sw_interface_add_del); + +static clib_error_t * +adl_init (vlib_main_t * vm) +{ + adl_main_t *cm = &adl_main; + + cm->vlib_main = vm; + cm->vnet_main = vnet_get_main (); + + /* + * Setup the packet generator so we can inject ethernet + * frames into this node + */ + ethernet_setup_node (vm, adl_input_node.index); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_INIT_FUNCTION (adl_init) = +{ + .runs_after = VLIB_INITS ("ip4_allowlist_init", "ip6_allowlist_init"), +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT (adl, static) = +{ + .arc_name = "device-input", + .node_name = "adl-input", + .runs_before = VNET_FEATURES ("ethernet-input"), +}; +/* *INDENT-ON */ + +int adl_interface_enable_disable (u32 sw_if_index, int enable_disable) +{ + /* + * Redirect pkts from the driver to the adl node. + */ + vnet_feature_enable_disable ("device-input", "adl-input", + sw_if_index, enable_disable, 0, 0); + return 0; +} + +static clib_error_t * +adl_enable_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + adl_main_t * cm = &adl_main; + u32 sw_if_index = ~0; + int enable_disable = 1; + + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat (input, "disable")) + enable_disable = 0; + else if (unformat (input, "%U", unformat_vnet_sw_interface, + cm->vnet_main, &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + return clib_error_return (0, "Please specify an interface..."); + + rv = adl_interface_enable_disable (sw_if_index, enable_disable); + + switch(rv) { + case 0: + break; + + case VNET_API_ERROR_INVALID_SW_IF_INDEX: + return clib_error_return + (0, "Invalid interface, only works on physical ports"); + break; + + case VNET_API_ERROR_UNIMPLEMENTED: + return clib_error_return (0, "Device driver doesn't support redirection"); + break; + + default: + return clib_error_return (0, "adl_interface_enable_disable returned %d", + rv); + } + return 0; +} + +VLIB_CLI_COMMAND (adl_interface_command, static) = { + .path = "adl interface", + .short_help = + "adl interface <interface-name> [disable]", + .function = adl_enable_disable_command_fn, +}; + + +int adl_allowlist_enable_disable (adl_allowlist_enable_disable_args_t *a) +{ + adl_main_t * cm = &adl_main; + vlib_main_t * vm = cm->vlib_main; + ip4_main_t * im4 = &ip4_main; + ip6_main_t * im6 = &ip6_main; + int address_family; + int is_add; + adl_config_main_t * acm; + u32 next_to_add_del = 0; + uword * p; + u32 fib_index = 0; + u32 ci; + adl_config_data_t _data, *data=&_data; + + /* + * Enable / disable allowlist processing on the specified interface + */ + + for (address_family = VNET_ADL_IP4; address_family < VNET_N_ADLS; + address_family++) + { + acm = &cm->adl_config_mains[address_family]; + + switch(address_family) + { + case VNET_ADL_IP4: + is_add = (a->ip4 != 0); + next_to_add_del = IP4_RX_ADL_ALLOWLIST; + /* configured opaque data must match, or no supper */ + p = hash_get (im4->fib_index_by_table_id, a->fib_id); + if (p) + fib_index = p[0]; + else + { + if (is_add) + return VNET_API_ERROR_NO_SUCH_FIB; + else + continue; + } + break; + + case VNET_ADL_IP6: + is_add = (a->ip6 != 0); + next_to_add_del = IP6_RX_ADL_ALLOWLIST; + p = hash_get (im6->fib_index_by_table_id, a->fib_id); + if (p) + fib_index = p[0]; + else + { + if (is_add) + return VNET_API_ERROR_NO_SUCH_FIB; + else + continue; + } + break; + + case VNET_ADL_DEFAULT: + is_add = (a->default_adl != 0); + next_to_add_del = DEFAULT_RX_ADL_ALLOWLIST; + break; + + default: + clib_warning ("BUG"); + } + + ci = acm->config_index_by_sw_if_index[a->sw_if_index]; + data->fib_index = fib_index; + + if (is_add) + ci = vnet_config_add_feature (vm, &acm->config_main, + ci, + next_to_add_del, + data, sizeof (*data)); + else + { + /* If the feature was actually configured... */ + if (ci != ~0) + { + /* delete it */ + ci = vnet_config_del_feature (vm, &acm->config_main, + ci, + next_to_add_del, + data, sizeof (*data)); + } + } + + acm->config_index_by_sw_if_index[a->sw_if_index] = ci; + } + return 0; +} + +static clib_error_t * +adl_allowlist_enable_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + adl_main_t * cm = &adl_main; + u32 sw_if_index = ~0; + u8 ip4 = 0; + u8 ip6 = 0; + u8 default_adl = 0; + u32 fib_id = 0; + int rv; + adl_allowlist_enable_disable_args_t _a, * a = &_a; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat (input, "ip4")) + ip4 = 1; + else if (unformat (input, "ip6")) + ip6 = 1; + else if (unformat (input, "default")) + default_adl = 1; + else if (unformat (input, "%U", unformat_vnet_sw_interface, + cm->vnet_main, &sw_if_index)) + ; + else if (unformat (input, "fib-id %d", &fib_id)) + ; + else + break; + } + + if (sw_if_index == ~0) + return clib_error_return (0, "Please specify an interface..."); + + a->sw_if_index = sw_if_index; + a->ip4 = ip4; + a->ip6 = ip6; + a->default_adl = default_adl; + a->fib_id = fib_id; + + rv = adl_allowlist_enable_disable (a); + + switch(rv) { + case 0: + break; + + case VNET_API_ERROR_INVALID_SW_IF_INDEX: + return clib_error_return + (0, "Invalid interface, only works on physical ports"); + break; + + case VNET_API_ERROR_NO_SUCH_FIB: + return clib_error_return + (0, "Invalid fib"); + break; + + case VNET_API_ERROR_UNIMPLEMENTED: + return clib_error_return (0, "Device driver doesn't support redirection"); + break; + + default: + return clib_error_return (0, "adl_allowlist_enable_disable returned %d", + rv); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (adl_allowlist_command, static) = +{ + .path = "adl allowlist", + .short_help = + "adl allowlist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]", + .function = adl_allowlist_enable_disable_command_fn, +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = +{ + .version = VPP_BUILD_VER, + .description = "Allow/deny list plugin", +}; +/* *INDENT-ON* */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |