From 738844871220f853629504f61c248f0c9402dc77 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Thu, 23 Feb 2017 09:26:30 +0100 Subject: BFD: command line interface Implement command line interface to the BFD binary APIs. Add corresponding unit tests. Change-Id: Ia0542d0bc4c8d78e6f7b777a08fd94ebfe4d524f Signed-off-by: Klement Sekera --- src/vnet.am | 1 + src/vnet/api_errno.h | 1 - src/vnet/bfd/bfd.api | 28 +- src/vnet/bfd/bfd_api.c | 22 +- src/vnet/bfd/bfd_api.h | 1 - src/vnet/bfd/bfd_cli.c | 900 ++++++++++++++++++++++++++++++++++++++++++++ src/vnet/bfd/bfd_main.c | 154 ++++++-- src/vnet/bfd/bfd_main.h | 11 +- src/vnet/bfd/bfd_protocol.c | 6 + src/vnet/bfd/bfd_udp.c | 120 ++---- src/vnet/bfd/bfd_udp.h | 5 + 11 files changed, 1081 insertions(+), 168 deletions(-) create mode 100644 src/vnet/bfd/bfd_cli.c (limited to 'src') diff --git a/src/vnet.am b/src/vnet.am index 84930f05b0a..d89d516e81c 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -369,6 +369,7 @@ libvnet_la_SOURCES += \ vnet/bfd/bfd_udp.c \ vnet/bfd/bfd_main.c \ vnet/bfd/bfd_protocol.c \ + vnet/bfd/bfd_cli.c \ vnet/bfd/bfd_api.c API_FILES += vnet/bfd/bfd.api diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h index 861a5767af2..a5bcb3776bb 100644 --- a/src/vnet/api_errno.h +++ b/src/vnet/api_errno.h @@ -51,7 +51,6 @@ _(ADDRESS_LENGTH_MISMATCH, -59, "Address length mismatch") \ _(ADDRESS_NOT_FOUND_FOR_INTERFACE, -60, "Address not found for interface") \ _(ADDRESS_NOT_LINK_LOCAL, -61, "Address not link-local") \ _(IP6_NOT_ENABLED, -62, "ip6 not enabled") \ -_(ADDRESS_MATCHES_INTERFACE_ADDRESS, -63, "Address matches interface address") \ _(IN_PROGRESS, 10, "Operation in progress") \ _(NO_SUCH_NODE, -63, "No such graph node") \ _(NO_SUCH_NODE2, -64, "No such graph node #2") \ diff --git a/src/vnet/bfd/bfd.api b/src/vnet/bfd/bfd.api index 93bf0fb90e8..2cdcfad3fc8 100644 --- a/src/vnet/bfd/bfd.api +++ b/src/vnet/bfd/bfd.api @@ -45,7 +45,7 @@ define bfd_udp_del_echo_source u32 context; }; -/** \brief Delete BFD feature response +/** \brief Delete BFD echo source response @param context - sender context, to match reply w/ request @param retval - return code for the request */ @@ -55,32 +55,6 @@ define bfd_udp_del_echo_source_reply i32 retval; }; -/** \brief Get BFD configuration -*/ -define bfd_get_config -{ - u32 client_index; - u32 context; -}; - -/** \brief Get BFD configuration response - @param context - sender context, to match reply w/ request - @param retval - return code for the request - @param slow_timer - slow timer (seconds) - @param min_tx - desired min tx interval - @param min_rx - desired min rx interval - @param detect_mult - desired detection multiplier -*/ -define bfd_get_config_reply -{ - u32 client_index; - u32 context; - u32 slow_timer; - u32 min_tx; - u32 min_rx; - u8 detect_mult; -}; - /** \brief Add UDP BFD session on interface @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/bfd/bfd_api.c b/src/vnet/bfd/bfd_api.c index 6632eae4c91..e64df48e11f 100644 --- a/src/vnet/bfd/bfd_api.c +++ b/src/vnet/bfd/bfd_api.c @@ -154,6 +154,21 @@ send_bfd_udp_session_details (unix_shared_memory_queue_t * q, u32 context, bfd_udp_key_t *key = &bus->key; mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index); mp->is_ipv6 = !(ip46_address_is_ip4 (&key->local_addr)); + if ((!bs->auth.is_delayed && bs->auth.curr_key) || + (bs->auth.is_delayed && bs->auth.next_key)) + { + mp->is_authenticated = 1; + } + if (bs->auth.is_delayed && bs->auth.next_key) + { + mp->bfd_key_id = bs->auth.next_bfd_key_id; + mp->conf_key_id = clib_host_to_net_u32 (bs->auth.next_key->conf_key_id); + } + else if (!bs->auth.is_delayed && bs->auth.curr_key) + { + mp->bfd_key_id = bs->auth.curr_bfd_key_id; + mp->conf_key_id = clib_host_to_net_u32 (bs->auth.curr_key->conf_key_id); + } if (mp->is_ipv6) { clib_memcpy (mp->local_addr, &key->local_addr, @@ -289,10 +304,9 @@ vl_api_bfd_udp_auth_activate_t_handler (vl_api_bfd_udp_auth_activate_t * mp) BFD_UDP_API_PARAM_COMMON_CODE; - rv = - bfd_udp_auth_activate (BFD_UDP_API_PARAM_FROM_MP (mp), - clib_net_to_host_u32 (mp->conf_key_id), - mp->bfd_key_id, mp->is_delayed); + rv = bfd_udp_auth_activate (BFD_UDP_API_PARAM_FROM_MP (mp), + clib_net_to_host_u32 (mp->conf_key_id), + mp->bfd_key_id, mp->is_delayed); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_BFD_UDP_AUTH_ACTIVATE_REPLY); diff --git a/src/vnet/bfd/bfd_api.h b/src/vnet/bfd/bfd_api.h index 63d4a62e2e3..35ad3cda9ab 100644 --- a/src/vnet/bfd/bfd_api.h +++ b/src/vnet/bfd/bfd_api.h @@ -22,7 +22,6 @@ #include #include #include -#include #define foreach_bfd_transport(F) \ F (UDP4, "ip4-rewrite") \ diff --git a/src/vnet/bfd/bfd_cli.c b/src/vnet/bfd/bfd_cli.c new file mode 100644 index 00000000000..a3736d98b3c --- /dev/null +++ b/src/vnet/bfd/bfd_cli.c @@ -0,0 +1,900 @@ +/* + * Copyright (c) 2011-2016 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. + */ +/** + * @file + * @brief BFD CLI implementation + */ + +#include +#include +#include +#include +#include +#include +#include + +static u8 * +format_bfd_session_cli (u8 * s, va_list * args) +{ + bfd_main_t *bm = va_arg (*args, bfd_main_t *); + bfd_session_t *bs = va_arg (*args, bfd_session_t *); + switch (bs->transport) + { + case BFD_TRANSPORT_UDP4: + s = format (s, "%=10u %-32s %20U %20U\n", bs->bs_idx, "IPv4 address", + format_ip4_address, bs->udp.key.local_addr.ip4.as_u8, + format_ip4_address, bs->udp.key.peer_addr.ip4.as_u8); + break; + case BFD_TRANSPORT_UDP6: + s = format (s, "%=10u %-32s %20U %20U\n", bs->bs_idx, "IPv6 address", + format_ip6_address, &bs->udp.key.local_addr.ip6, + format_ip6_address, &bs->udp.key.peer_addr.ip6); + break; + } + s = format (s, "%10s %-32s %20s %20s\n", "", "Session state", + bfd_state_string (bs->local_state), + bfd_state_string (bs->remote_state)); + s = format (s, "%10s %-32s %20s %20s\n", "", "Diagnostic code", + bfd_diag_code_string (bs->local_diag), + bfd_diag_code_string (bs->remote_diag)); + s = format (s, "%10s %-32s %20u %20u\n", "", "Detect multiplier", + bs->local_detect_mult, bs->remote_detect_mult); + s = format (s, "%10s %-32s %20u %20u\n", "", + "Required Min Rx Interval (usec)", + bs->config_required_min_rx_usec, bs->remote_min_rx_usec); + s = format (s, "%10s %-32s %20u %20u\n", "", + "Desired Min Tx Interval (usec)", + bs->config_desired_min_tx_usec, bfd_clocks_to_usec (bm, + bs->remote_desired_min_tx_clocks)); + s = + format (s, "%10s %-32s %20u\n", "", "Transmit interval", + bfd_clocks_to_usec (bm, bs->transmit_interval_clocks)); + s = + format (s, "%10s %-32s %20s %20s\n", "", "Demand mode", "no", + bs->remote_demand ? "yes" : "no"); + s = + format (s, "%10s %-32s %20s\n", "", "Poll state", + bfd_poll_state_string (bs->poll_state)); + if (bs->auth.curr_key) + { + s = format (s, "%10s %-32s %20u\n", "", "Authentication config key ID", + bs->auth.curr_key->conf_key_id); + s = format (s, "%10s %-32s %20u\n", "", "Authentication BFD key ID", + bs->auth.curr_bfd_key_id); + } + return s; +} + +static clib_error_t * +show_bfd (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + bfd_main_t *bm = &bfd_main; + bfd_session_t *bs = NULL; + + if (unformat (input, "keys")) + { + bfd_auth_key_t *key = NULL; + u8 *s = format (NULL, "%=10s %=25s %=10s\n", "Configuration Key ID", + "Type", "Use Count"); + /* *INDENT-OFF* */ + pool_foreach (key, bm->auth_keys, { + s = format (s, "%10u %-25s %10u\n", key->conf_key_id, + bfd_auth_type_str (key->auth_type), key->use_count); + }); + /* *INDENT-ON* */ + vlib_cli_output (vm, "%v\n", s); + vlib_cli_output (vm, "Number of configured BFD keys: %lu\n", + (u64) pool_elts (bm->auth_keys)); + } + else if (unformat (input, "sessions")) + { + u8 *s = format (NULL, "%=10s %=32s %=20s %=20s\n", "Index", "Property", + "Local value", "Remote value"); + /* *INDENT-OFF* */ + pool_foreach (bs, bm->sessions, + { s = format (s, "%U", format_bfd_session_cli, bm, bs); }); + /* *INDENT-ON* */ + vlib_cli_output (vm, "%v", s); + vec_free (s); + vlib_cli_output (vm, "Number of configured BFD sessions: %lu\n", + (u64) pool_elts (bm->sessions)); + } + else if (unformat (input, "echo-source")) + { + int is_set; + u32 sw_if_index; + int have_usable_ip4; + ip4_address_t ip4; + int have_usable_ip6; + ip6_address_t ip6; + bfd_udp_get_echo_source (&is_set, &sw_if_index, &have_usable_ip4, &ip4, + &have_usable_ip6, &ip6); + if (is_set) + { + vnet_sw_interface_t *sw_if = + vnet_get_sw_interface_safe (&vnet_main, sw_if_index); + vnet_hw_interface_t *hw_if = + vnet_get_hw_interface (&vnet_main, sw_if->hw_if_index); + u8 *s = format (NULL, "UDP echo source is: %v\n", hw_if->name); + s = format (s, "IPv4 address usable as echo source: "); + if (have_usable_ip4) + { + s = format (s, "%U\n", format_ip4_address, &ip4); + } + else + { + s = format (s, "none\n"); + } + s = format (s, "IPv6 address usable as echo source: "); + if (have_usable_ip6) + { + s = format (s, "%U\n", format_ip6_address, &ip6); + } + else + { + s = format (s, "none\n"); + } + vlib_cli_output (vm, "%v", s); + vec_free (s); + } + else + { + vlib_cli_output (vm, "UDP echo source is not set.\n"); + } + } + else + { + vlib_cli_output (vm, "Number of configured BFD sessions: %lu\n", + (u64) pool_elts (bm->sessions)); + vlib_cli_output (vm, "Number of configured BFD keys: %lu\n", + (u64) pool_elts (bm->auth_keys)); + } + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_bfd_command, static) = { + .path = "show bfd", + .short_help = "show bfd [keys|sessions|echo-source]", + .function = show_bfd, +}; +/* *INDENT-ON* */ + +static u8 * +format_vnet_api_errno (u8 * s, va_list * args) +{ + vnet_api_error_t api_error = va_arg (*args, vnet_api_error_t); +#define _(a, b, c) \ + case b: \ + s = format (s, "%s", c); \ + break; + switch (api_error) + { + foreach_vnet_api_error default:s = format (s, "UNKNOWN"); + break; + } + return s; +} + +static clib_error_t * +bfd_cli_key_add (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; + int have_key_id = 0; + u32 key_id = 0; + u8 *vec_auth_type = NULL; + bfd_auth_type_e auth_type = BFD_AUTH_TYPE_reserved; + u8 *secret = NULL; + static const u8 keyed_sha1[] = "keyed-sha1"; + static const u8 meticulous_keyed_sha1[] = "meticulous-keyed-sha1"; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "conf-key-id %u", &key_id)) + { + have_key_id = 1; + } + else if (unformat (input, "type %U", unformat_token, "a-zA-Z0-9-", + &vec_auth_type)) + { + if (vec_len (vec_auth_type) == sizeof (keyed_sha1) - 1 && + 0 == memcmp (vec_auth_type, keyed_sha1, + sizeof (keyed_sha1) - 1)) + { + auth_type = BFD_AUTH_TYPE_keyed_sha1; + } + else if (vec_len (vec_auth_type) == + sizeof (meticulous_keyed_sha1) - 1 && + 0 == memcmp (vec_auth_type, meticulous_keyed_sha1, + sizeof (meticulous_keyed_sha1) - 1)) + { + auth_type = BFD_AUTH_TYPE_meticulous_keyed_sha1; + } + else + { + ret = clib_error_return (0, "invalid type `%v'", vec_auth_type); + goto out; + } + } + else if (unformat (input, "secret %U", unformat_hex_string, &secret)) + { + /* nothing to do here */ + } + else + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + if (!have_key_id) + { + ret = + clib_error_return (0, "required parameter missing: `conf-key-id'"); + goto out; + } + if (!vec_auth_type) + { + ret = clib_error_return (0, "required parameter missing: `type'"); + goto out; + } + if (!secret) + { + ret = clib_error_return (0, "required parameter missing: `secret'"); + goto out; + } + + vnet_api_error_t rv = + bfd_auth_set_key (key_id, auth_type, vec_len (secret), secret); + if (rv) + { + ret = + clib_error_return (0, "`bfd_auth_set_key' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + } + +out: + vec_free (vec_auth_type); + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_key_add_command, static) = { + .path = "bfd key set", + .short_help = "bfd key set" + " conf-key-id " + " type " + " secret ", + .function = bfd_cli_key_add, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_key_del (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; + u32 key_id = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (!unformat (input, "conf-key-id %u", &key_id)) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + vnet_api_error_t rv = bfd_auth_del_key (key_id); + if (rv) + { + ret = + clib_error_return (0, "`bfd_auth_del_key' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_key_del_command, static) = { + .path = "bfd key del", + .short_help = "bfd key del conf-key-id ", + .function = bfd_cli_key_del, +}; +/* *INDENT-ON* */ + +#define INTERFACE_STR "interface" +#define LOCAL_ADDR_STR "local-addr" +#define PEER_ADDR_STR "peer-addr" +#define CONF_KEY_ID_STR "conf-key-id" +#define BFD_KEY_ID_STR "bfd-key-id" +#define DESIRED_MIN_TX_STR "desired-min-tx" +#define REQUIRED_MIN_RX_STR "required-min-rx" +#define DETECT_MULT_STR "detect-mult" +#define ADMIN_STR "admin" +#define DELAYED_STR "delayed" + +static const unsigned mandatory = 1; +static const unsigned optional = 0; + +#define DECLARE(t, n, s, r, ...) \ + int have_##n = 0; \ + t n; + +#define UNFORMAT(t, n, s, r, ...) \ + if (unformat (input, s " " __VA_ARGS__, &n)) \ + { \ + something_parsed = 1; \ + have_##n = 1; \ + } + +#define CHECK_MANDATORY(t, n, s, r, ...) \ + if (mandatory == r && !have_##n) \ + { \ + ret = clib_error_return (0, "Required parameter `%s' missing.", n); \ + goto out; \ + } + +static clib_error_t * +bfd_cli_udp_session_add (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_add_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (u32, desired_min_tx, DESIRED_MIN_TX_STR, mandatory, "%u") \ + F (u32, required_min_rx, REQUIRED_MIN_RX_STR, mandatory, "%u") \ + F (u32, detect_mult, DETECT_MULT_STR, mandatory, "%u") \ + F (u32, conf_key_id, CONF_KEY_ID_STR, optional, "%u") \ + F (u32, bfd_key_id, BFD_KEY_ID_STR, optional, "%u") + + foreach_bfd_cli_udp_session_add_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_add_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_add_cli_param (CHECK_MANDATORY); + + if (1 == have_conf_key_id + have_bfd_key_id) + { + ret = clib_error_return (0, "Incompatible parameter combination, `%s' " + "and `%s' must be either both specified or none", + CONF_KEY_ID_STR, BFD_KEY_ID_STR); + goto out; + } + + if (detect_mult > 255) + { + ret = clib_error_return (0, "%s value `%u' out of range <1,255>", + DETECT_MULT_STR, detect_mult); + goto out; + } + + if (have_bfd_key_id && bfd_key_id > 255) + { + ret = clib_error_return (0, "%s value `%u' out of range <1,255>", + BFD_KEY_ID_STR, bfd_key_id); + goto out; + } + + vnet_api_error_t rv = + bfd_udp_add_session (sw_if_index, &local_addr, &peer_addr, desired_min_tx, + required_min_rx, + detect_mult, have_conf_key_id, conf_key_id, + bfd_key_id); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_add_add_session' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_add_command, static) = { + .path = "bfd udp session add", + .short_help = "bfd udp session add" + " interface " + " local-addr " + " peer-addr " + " desired-min-tx " + " required-min-rx " + " detect-mult " + "[" + " conf-key-id " + " bfd-key-id " + "]", + .function = bfd_cli_udp_session_add, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_session_mod (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_mod_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (u32, desired_min_tx, DESIRED_MIN_TX_STR, mandatory, "%u") \ + F (u32, required_min_rx, REQUIRED_MIN_RX_STR, mandatory, "%u") \ + F (u32, detect_mult, DETECT_MULT_STR, mandatory, "%u") + + foreach_bfd_cli_udp_session_mod_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_mod_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_mod_cli_param (CHECK_MANDATORY); + + if (detect_mult > 255) + { + ret = clib_error_return (0, "%s value `%u' out of range <1,255>", + DETECT_MULT_STR, detect_mult); + goto out; + } + + vnet_api_error_t rv = + bfd_udp_mod_session (sw_if_index, &local_addr, &peer_addr, + desired_min_tx, required_min_rx, detect_mult); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_udp_mod_session' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_mod_command, static) = { + .path = "bfd udp session mod", + .short_help = "bfd udp session mod interface" + " local-addr" + " peer-addr" + " desired-min-tx" + " required-min-rx" + " detect-mult" + " ", + .function = bfd_cli_udp_session_mod, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_session_del (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_del_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) + + foreach_bfd_cli_udp_session_del_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_del_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_del_cli_param (CHECK_MANDATORY); + + vnet_api_error_t rv = + bfd_udp_del_session (sw_if_index, &local_addr, &peer_addr); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_udp_del_session' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_del_command, static) = { + .path = "bfd udp session del", + .short_help = "bfd udp session del interface" + " local-addr" + " peer-addr" + " ", + .function = bfd_cli_udp_session_del, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_session_set_flags (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_set_flags_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (u8 *, admin_up_down_token, ADMIN_STR, mandatory, "%v", \ + &admin_up_down_token) + + foreach_bfd_cli_udp_session_set_flags_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_set_flags_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_set_flags_cli_param (CHECK_MANDATORY); + + u8 admin_up_down; + static const char up[] = "up"; + static const char down[] = "down"; + if (!memcmp (admin_up_down_token, up, sizeof (up) - 1)) + { + admin_up_down = 1; + } + else if (!memcmp (admin_up_down_token, down, sizeof (down) - 1)) + { + admin_up_down = 0; + } + else + { + ret = + clib_error_return (0, "Unrecognized value for `%s' parameter: `%v'", + ADMIN_STR, admin_up_down_token); + goto out; + } + vnet_api_error_t rv = bfd_udp_session_set_flags (sw_if_index, &local_addr, + &peer_addr, admin_up_down); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_udp_session_set_flags' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_set_flags_command, static) = { + .path = "bfd udp session set-flags", + .short_help = "bfd udp session set-flags" + " interface " + " local-addr " + " peer-addr " + " admin ", + .function = bfd_cli_udp_session_set_flags, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_session_auth_activate (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_auth_activate_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (u8 *, delayed_token, DELAYED_STR, optional, "%v") \ + F (u32, conf_key_id, CONF_KEY_ID_STR, mandatory, "%u") \ + F (u32, bfd_key_id, BFD_KEY_ID_STR, mandatory, "%u") + + foreach_bfd_cli_udp_session_auth_activate_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_auth_activate_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_auth_activate_cli_param (CHECK_MANDATORY); + + u8 is_delayed = 0; + if (have_delayed_token) + { + static const char yes[] = "yes"; + static const char no[] = "no"; + if (!memcmp (delayed_token, yes, sizeof (yes) - 1)) + { + is_delayed = 1; + } + else if (!memcmp (delayed_token, no, sizeof (no) - 1)) + { + is_delayed = 0; + } + else + { + ret = + clib_error_return (0, + "Unrecognized value for `%s' parameter: `%v'", + DELAYED_STR, delayed_token); + goto out; + } + } + + if (have_bfd_key_id && bfd_key_id > 255) + { + ret = clib_error_return (0, "%s value `%u' out of range <1,255>", + BFD_KEY_ID_STR, bfd_key_id); + goto out; + } + + vnet_api_error_t rv = + bfd_udp_auth_activate (sw_if_index, &local_addr, &peer_addr, conf_key_id, + bfd_key_id, is_delayed); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_udp_auth_activate' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_auth_activate_command, static) = { + .path = "bfd udp session auth activate", + .short_help = "bfd udp session auth activate" + " interface " + " local-addr " + " peer-addr " + " conf-key-id " + " bfd-key-id " + " [ delayed ]", + .function = bfd_cli_udp_session_auth_activate, +}; + +static clib_error_t * +bfd_cli_udp_session_auth_deactivate (vlib_main_t *vm, unformat_input_t *input, + CLIB_UNUSED (vlib_cli_command_t *lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_session_auth_deactivate_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) \ + F (ip46_address_t, local_addr, LOCAL_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + unformat_ip46_address) \ + F (u8 *, delayed_token, DELAYED_STR, optional, "%v") + + foreach_bfd_cli_udp_session_auth_deactivate_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_session_auth_deactivate_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_session_auth_deactivate_cli_param (CHECK_MANDATORY); + + u8 is_delayed = 0; + if (have_delayed_token) + { + static const char yes[] = "yes"; + static const char no[] = "no"; + if (!memcmp (delayed_token, yes, sizeof (yes) - 1)) + { + is_delayed = 1; + } + else if (!memcmp (delayed_token, no, sizeof (no) - 1)) + { + is_delayed = 0; + } + else + { + ret = clib_error_return ( + 0, "Unrecognized value for `%s' parameter: `%v'", DELAYED_STR, + delayed_token); + goto out; + } + } + + vnet_api_error_t rv = bfd_udp_auth_deactivate (sw_if_index, &local_addr, + &peer_addr, is_delayed); + if (rv) + { + ret = clib_error_return ( + 0, "`bfd_udp_auth_deactivate' API call failed, rv=%d:%U", (int)rv, + format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_session_auth_deactivate_command, static) = { + .path = "bfd udp session auth deactivate", + .short_help = "bfd udp session auth deactivate" + " interface " + " local-addr " + " peer-addr " + "[ delayed ]", + .function = bfd_cli_udp_session_auth_deactivate, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_set_echo_source (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + clib_error_t *ret = NULL; +#define foreach_bfd_cli_udp_set_echo_source_cli_param(F) \ + F (u32, sw_if_index, INTERFACE_STR, mandatory, "%U", \ + unformat_vnet_sw_interface, &vnet_main) + + foreach_bfd_cli_udp_set_echo_source_cli_param (DECLARE); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + int something_parsed = 0; + foreach_bfd_cli_udp_set_echo_source_cli_param (UNFORMAT); + + if (!something_parsed) + { + ret = clib_error_return (0, "Unknown input `%U'", + format_unformat_error, input); + goto out; + } + } + + foreach_bfd_cli_udp_set_echo_source_cli_param (CHECK_MANDATORY); + + vnet_api_error_t rv = bfd_udp_set_echo_source (sw_if_index); + if (rv) + { + ret = + clib_error_return (0, + "`bfd_udp_set_echo_source' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + goto out; + } + +out: + return ret; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_set_echo_source_cmd, static) = { + .path = "bfd udp echo-source set", + .short_help = "bfd udp echo-source set interface ", + .function = bfd_cli_udp_set_echo_source, +}; +/* *INDENT-ON* */ + +static clib_error_t * +bfd_cli_udp_del_echo_source (vlib_main_t * vm, unformat_input_t * input, + CLIB_UNUSED (vlib_cli_command_t * lmd)) +{ + vnet_api_error_t rv = bfd_udp_del_echo_source (); + if (rv) + { + return clib_error_return (0, + "`bfd_udp_del_echo_source' API call failed, rv=%d:%U", + (int) rv, format_vnet_api_errno, rv); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bfd_cli_udp_del_echo_source_cmd, static) = { + .path = "bfd udp echo-source del", + .short_help = "bfd udp echo-source del", + .function = bfd_cli_udp_del_echo_source, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/bfd/bfd_main.c b/src/vnet/bfd/bfd_main.c index 29c40458bf5..01de637531d 100644 --- a/src/vnet/bfd/bfd_main.c +++ b/src/vnet/bfd/bfd_main.c @@ -55,7 +55,7 @@ bfd_usec_to_clocks (const bfd_main_t * bm, u64 us) return bm->cpu_cps * ((f64) us / USEC_PER_SECOND); } -static u32 +u32 bfd_clocks_to_usec (const bfd_main_t * bm, u64 clocks) { return (clocks / bm->cpu_cps) * USEC_PER_SECOND; @@ -70,7 +70,7 @@ static u32 bfd_node_index_by_transport[] = { #undef F }; -static u8 * +u8 * format_bfd_auth_key (u8 * s, va_list * args) { const bfd_auth_key_t *key = va_arg (*args, bfd_auth_key_t *); @@ -147,7 +147,7 @@ bfd_set_state (bfd_main_t * bm, bfd_session_t * bs, } } -static const char * +const char * bfd_poll_state_string (bfd_poll_state_e state) { switch (state) @@ -265,12 +265,16 @@ bfd_calc_next_echo_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now) static void bfd_recalc_detection_time (bfd_main_t * bm, bfd_session_t * bs) { - bs->detection_time_clocks = - bs->remote_detect_mult * clib_max (bs->effective_required_min_rx_clocks, - bs->remote_desired_min_tx_clocks); - BFD_DBG ("Recalculated detection time %lu clocks/%.2fs", - bs->detection_time_clocks, - bs->detection_time_clocks / bm->cpu_cps); + if (bs->local_state == BFD_STATE_init || bs->local_state == BFD_STATE_up) + { + bs->detection_time_clocks = + bs->remote_detect_mult * + clib_max (bs->effective_required_min_rx_clocks, + bs->remote_desired_min_tx_clocks); + BFD_DBG ("Recalculated detection time %lu clocks/%.2fs", + bs->detection_time_clocks, + bs->detection_time_clocks / bm->cpu_cps); + } } static void @@ -284,7 +288,8 @@ bfd_set_timer (bfd_main_t * bm, bfd_session_t * bs, u64 now, { rx_timeout = bs->last_rx_clocks + bs->detection_time_clocks; } - if (BFD_STATE_up != bs->local_state || !bs->remote_demand || + if (BFD_STATE_up != bs->local_state || + (!bs->remote_demand && bs->remote_min_rx_usec) || BFD_POLL_NOT_NEEDED != bs->poll_state) { tx_timeout = bs->tx_timeout_clocks; @@ -348,7 +353,7 @@ bfd_set_effective_desired_min_tx (bfd_main_t * bm, static void bfd_set_effective_required_min_rx (bfd_main_t * bm, - bfd_session_t * bs, u64 now, + bfd_session_t * bs, u64 required_min_rx_clocks) { bs->effective_required_min_rx_clocks = required_min_rx_clocks; @@ -393,44 +398,33 @@ void bfd_session_start (bfd_main_t * bm, bfd_session_t * bs) { BFD_DBG ("\nStarting session: %U", format_bfd_session, bs); + bfd_set_effective_required_min_rx (bm, bs, + bs->config_required_min_rx_clocks); bfd_recalc_tx_interval (bm, bs); vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index, BFD_EVENT_NEW_SESSION, bs->bs_idx); } -vnet_api_error_t -bfd_del_session (uword bs_idx) -{ - const bfd_main_t *bm = &bfd_main; - if (!pool_is_free_index (bm->sessions, bs_idx)) - { - bfd_session_t *bs = pool_elt_at_index (bm->sessions, bs_idx); - pool_put (bm->sessions, bs); - return 0; - } - else - { - BFD_ERR ("no such session"); - return VNET_API_ERROR_BFD_ENOENT; - } - return 0; -} - void bfd_session_set_flags (bfd_session_t * bs, u8 admin_up_down) { bfd_main_t *bm = &bfd_main; + u64 now = clib_cpu_time_now (); if (admin_up_down) { BFD_DBG ("Session set admin-up, bs-idx=%u", bs->bs_idx); bfd_set_state (bm, bs, BFD_STATE_down, 0); bfd_set_diag (bs, BFD_DIAG_CODE_no_diag); + bfd_calc_next_tx (bm, bs, now); + bfd_set_timer (bm, bs, now, 0); } else { BFD_DBG ("Session set admin-down, bs-idx=%u", bs->bs_idx); bfd_set_diag (bs, BFD_DIAG_CODE_admin_down); bfd_set_state (bm, bs, BFD_STATE_admin_down, 0); + bfd_calc_next_tx (bm, bs, now); + bfd_set_timer (bm, bs, now, 0); } } @@ -515,7 +509,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, clib_max (bs->config_desired_min_tx_clocks, bm->default_desired_min_tx_clocks)); - bfd_set_effective_required_min_rx (bm, bs, now, + bfd_set_effective_required_min_rx (bm, bs, bs->config_required_min_rx_clocks); bfd_set_timer (bm, bs, now, handling_wakeup); break; @@ -525,7 +519,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, clib_max (bs->config_desired_min_tx_clocks, bm->default_desired_min_tx_clocks)); - bfd_set_effective_required_min_rx (bm, bs, now, + bfd_set_effective_required_min_rx (bm, bs, bs->config_required_min_rx_clocks); bfd_set_timer (bm, bs, now, handling_wakeup); break; @@ -540,7 +534,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, bs->config_desired_min_tx_clocks); if (BFD_POLL_NOT_NEEDED == bs->poll_state) { - bfd_set_effective_required_min_rx (bm, bs, now, + bfd_set_effective_required_min_rx (bm, bs, bs->config_required_min_rx_clocks); } bfd_set_timer (bm, bs, now, handling_wakeup); @@ -932,7 +926,7 @@ bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm, bs->echo = 1; bs->echo_last_rx_clocks = now; bs->echo_tx_timeout_clocks = now; - bfd_set_effective_required_min_rx (bm, bs, now, + bfd_set_effective_required_min_rx (bm, bs, clib_max (bm->min_required_min_rx_while_echo_clocks, bs->config_required_min_rx_clocks)); @@ -1569,6 +1563,7 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx) bs->remote_discr = pkt->my_disc; bs->remote_state = bfd_pkt_get_state (pkt); bs->remote_demand = bfd_pkt_get_demand (pkt); + bs->remote_diag = bfd_pkt_get_diag_code (pkt); u64 now = clib_cpu_time_now (); bs->last_rx_clocks = now; if (bfd_pkt_get_auth_present (pkt)) @@ -1621,7 +1616,7 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx) bfd_set_poll_state (bs, BFD_POLL_NOT_NEEDED); if (BFD_STATE_up == bs->local_state) { - bfd_set_effective_required_min_rx (bm, bs, now, + bfd_set_effective_required_min_rx (bm, bs, clib_max (bs->echo * bm->min_required_min_rx_while_echo_clocks, bs->config_required_min_rx_clocks)); @@ -1914,6 +1909,97 @@ bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs, return 0; } +vnet_api_error_t +bfd_auth_set_key (u32 conf_key_id, u8 auth_type, u8 key_len, + const u8 * key_data) +{ +#if WITH_LIBSSL > 0 + bfd_auth_key_t *auth_key = NULL; + if (!key_len || key_len > bfd_max_len_for_auth_type (auth_type)) + { + clib_warning ("Invalid authentication key length for auth_type=%d:%s " + "(key_len=%u, must be " + "non-zero, expected max=%u)", + auth_type, bfd_auth_type_str (auth_type), key_len, + (u32) bfd_max_len_for_auth_type (auth_type)); + return VNET_API_ERROR_INVALID_VALUE; + } + if (!bfd_auth_type_supported (auth_type)) + { + clib_warning ("Unsupported auth type=%d:%s", auth_type, + bfd_auth_type_str (auth_type)); + return VNET_API_ERROR_BFD_NOTSUPP; + } + bfd_main_t *bm = &bfd_main; + uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id); + if (key_idx_p) + { + /* modifying existing key - must not be used */ + const uword key_idx = *key_idx_p; + auth_key = pool_elt_at_index (bm->auth_keys, key_idx); + if (auth_key->use_count > 0) + { + clib_warning ("Authentication key with conf ID %u in use by %u BFD " + "session(s) - cannot modify", + conf_key_id, auth_key->use_count); + return VNET_API_ERROR_BFD_EINUSE; + } + } + else + { + /* adding new key */ + pool_get (bm->auth_keys, auth_key); + auth_key->conf_key_id = conf_key_id; + hash_set (bm->auth_key_by_conf_key_id, conf_key_id, + auth_key - bm->auth_keys); + } + auth_key->auth_type = auth_type; + memset (auth_key->key, 0, sizeof (auth_key->key)); + clib_memcpy (auth_key->key, key_data, key_len); + return 0; +#else + clib_warning ("SSL missing, cannot manipulate authentication keys"); + return VNET_API_ERROR_BFD_NOTSUPP; +#endif +} + +vnet_api_error_t +bfd_auth_del_key (u32 conf_key_id) +{ +#if WITH_LIBSSL > 0 + bfd_auth_key_t *auth_key = NULL; + bfd_main_t *bm = &bfd_main; + uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id); + if (key_idx_p) + { + /* deleting existing key - must not be used */ + const uword key_idx = *key_idx_p; + auth_key = pool_elt_at_index (bm->auth_keys, key_idx); + if (auth_key->use_count > 0) + { + clib_warning ("Authentication key with conf ID %u in use by %u BFD " + "session(s) - cannot delete", + conf_key_id, auth_key->use_count); + return VNET_API_ERROR_BFD_EINUSE; + } + hash_unset (bm->auth_key_by_conf_key_id, conf_key_id); + memset (auth_key, 0, sizeof (*auth_key)); + pool_put (bm->auth_keys, auth_key); + } + else + { + /* no such key */ + clib_warning ("Authentication key with conf ID %u does not exist", + conf_key_id); + return VNET_API_ERROR_BFD_ENOENT; + } + return 0; +#else + clib_warning ("SSL missing, cannot manipulate authentication keys"); + return VNET_API_ERROR_BFD_NOTSUPP; +#endif +} + bfd_main_t bfd_main; /* diff --git a/src/vnet/bfd/bfd_main.h b/src/vnet/bfd/bfd_main.h index d8063f9de33..3be3694c0f5 100644 --- a/src/vnet/bfd/bfd_main.h +++ b/src/vnet/bfd/bfd_main.h @@ -74,11 +74,14 @@ typedef struct bfd_session_s /* session state */ bfd_state_e local_state; + /* remote session state */ + bfd_state_e remote_state; + /* local diagnostics */ bfd_diag_code_e local_diag; - /* remote session state */ - bfd_state_e remote_state; + /* remote diagnostics */ + bfd_diag_code_e remote_diag; /* local discriminator */ u32 local_discr; @@ -315,6 +318,7 @@ void bfd_event (bfd_main_t * bm, bfd_session_t * bs); void bfd_init_final_control_frame (vlib_main_t * vm, vlib_buffer_t * b, bfd_main_t * bm, bfd_session_t * bs); u8 *format_bfd_session (u8 * s, va_list * args); +u8 *format_bfd_auth_key (u8 * s, va_list * args); void bfd_session_set_flags (bfd_session_t * bs, u8 admin_up_down); unsigned bfd_auth_type_supported (bfd_auth_type_e auth_type); vnet_api_error_t bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id, @@ -325,6 +329,9 @@ vnet_api_error_t bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs, u32 required_min_rx_usec, u8 detect_mult); +u32 bfd_clocks_to_usec (const bfd_main_t * bm, u64 clocks); +const char *bfd_poll_state_string (bfd_poll_state_e state); + #define USEC_PER_MS 1000LL #define USEC_PER_SECOND (1000 * USEC_PER_MS) diff --git a/src/vnet/bfd/bfd_protocol.c b/src/vnet/bfd/bfd_protocol.c index 92b226bda8b..5deb9702eb3 100644 --- a/src/vnet/bfd/bfd_protocol.c +++ b/src/vnet/bfd/bfd_protocol.c @@ -82,11 +82,13 @@ bfd_pkt_get_control_plane_independent (const bfd_pkt_t * pkt) return (pkt->head.sta_flags >> 3) & 1; } +#if 0 void bfd_pkt_set_control_plane_independent (bfd_pkt_t * pkt) { pkt->head.sta_flags |= 1 << 3; } +#endif u8 bfd_pkt_get_auth_present (const bfd_pkt_t * pkt) @@ -106,11 +108,13 @@ bfd_pkt_get_demand (const bfd_pkt_t * pkt) return (pkt->head.sta_flags >> 1) & 1; } +#if 0 void bfd_pkt_set_demand (bfd_pkt_t * pkt) { pkt->head.sta_flags |= 1 << 1; } +#endif u8 bfd_pkt_get_multipoint (const bfd_pkt_t * pkt) @@ -118,11 +122,13 @@ bfd_pkt_get_multipoint (const bfd_pkt_t * pkt) return (pkt->head.sta_flags >> 0) & 1; } +#if 0 void bfd_pkt_set_multipoint (bfd_pkt_t * pkt) { pkt->head.sta_flags |= 1 << 0; } +#endif u32 bfd_max_len_for_auth_type (bfd_auth_type_e auth_type) diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c index cf05089b430..207f3b8cae9 100644 --- a/src/vnet/bfd/bfd_udp.c +++ b/src/vnet/bfd/bfd_udp.c @@ -60,8 +60,7 @@ vnet_api_error_t bfd_udp_set_echo_source (u32 sw_if_index) { vnet_sw_interface_t *sw_if = - vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, - bfd_udp_main.echo_source_sw_if_index); + vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index); if (sw_if) { bfd_udp_main.echo_source_sw_if_index = sw_if_index; @@ -84,6 +83,7 @@ bfd_udp_is_echo_available (bfd_transport_e transport) { if (!bfd_udp_main.echo_source_is_set) { + BFD_DBG ("UDP echo source not set - echo not available"); return 0; } /* @@ -127,6 +127,7 @@ bfd_udp_is_echo_available (bfd_transport_e transport) /* *INDENT-ON* */ } } + BFD_DBG ("No usable IP address for UDP echo - echo not available"); return 0; } @@ -144,11 +145,6 @@ bfd_udp_bs_idx_to_sport (u32 bs_idx) return 49152 + bs_idx % (65535 - 49152 + 1); } -static void -lol () -{ -} - int bfd_udp_get_echo_src_ip4 (ip4_address_t * addr) { @@ -204,7 +200,6 @@ bfd_udp_get_echo_src_ip6 (ip6_address_t * addr) { *addr = *x; addr->as_u8[15] ^= 1; /* flip the last bit of the address */ - lol (); return 1; } })); @@ -213,6 +208,24 @@ bfd_udp_get_echo_src_ip6 (ip6_address_t * addr) return 0; } +void +bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index, int *have_usable_ip4, + ip4_address_t * ip4, int *have_usable_ip6, + ip6_address_t * ip6) +{ + if (bfd_udp_main.echo_source_is_set) + { + *is_set = 1; + *sw_if_index = bfd_udp_main.echo_source_sw_if_index; + *have_usable_ip4 = bfd_udp_get_echo_src_ip4 (ip4); + *have_usable_ip6 = bfd_udp_get_echo_src_ip6 (ip6); + } + else + { + *is_set = 0; + } +} + int bfd_add_udp4_transport (vlib_main_t * vm, vlib_buffer_t * b, const bfd_session_t * bs, int is_echo) @@ -660,97 +673,6 @@ bfd_udp_session_set_flags (u32 sw_if_index, return 0; } -vnet_api_error_t -bfd_auth_set_key (u32 conf_key_id, u8 auth_type, u8 key_len, - const u8 * key_data) -{ -#if WITH_LIBSSL > 0 - bfd_auth_key_t *auth_key = NULL; - if (!key_len || key_len > bfd_max_len_for_auth_type (auth_type)) - { - clib_warning ("Invalid authentication key length for auth_type=%d:%s " - "(key_len=%u, must be " - "non-zero, expected max=%u)", - auth_type, bfd_auth_type_str (auth_type), key_len, - (u32) bfd_max_len_for_auth_type (auth_type)); - return VNET_API_ERROR_INVALID_VALUE; - } - if (!bfd_auth_type_supported (auth_type)) - { - clib_warning ("Unsupported auth type=%d:%s", auth_type, - bfd_auth_type_str (auth_type)); - return VNET_API_ERROR_BFD_NOTSUPP; - } - bfd_main_t *bm = bfd_udp_main.bfd_main; - uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id); - if (key_idx_p) - { - /* modifying existing key - must not be used */ - const uword key_idx = *key_idx_p; - auth_key = pool_elt_at_index (bm->auth_keys, key_idx); - if (auth_key->use_count > 0) - { - clib_warning ("Authentication key with conf ID %u in use by %u BFD " - "sessions - cannot modify", - conf_key_id, auth_key->use_count); - return VNET_API_ERROR_BFD_EINUSE; - } - } - else - { - /* adding new key */ - pool_get (bm->auth_keys, auth_key); - auth_key->conf_key_id = conf_key_id; - hash_set (bm->auth_key_by_conf_key_id, conf_key_id, - auth_key - bm->auth_keys); - } - auth_key->auth_type = auth_type; - memset (auth_key->key, 0, sizeof (auth_key->key)); - clib_memcpy (auth_key->key, key_data, key_len); - return 0; -#else - clib_warning ("SSL missing, cannot manipulate authentication keys"); - return VNET_API_ERROR_BFD_NOTSUPP; -#endif -} - -vnet_api_error_t -bfd_auth_del_key (u32 conf_key_id) -{ -#if WITH_LIBSSL > 0 - bfd_auth_key_t *auth_key = NULL; - bfd_main_t *bm = bfd_udp_main.bfd_main; - uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id); - if (key_idx_p) - { - /* deleting existing key - must not be used */ - const uword key_idx = *key_idx_p; - auth_key = pool_elt_at_index (bm->auth_keys, key_idx); - if (auth_key->use_count > 0) - { - clib_warning ("Authentication key with conf ID %u in use by %u BFD " - "sessions - cannot delete", - conf_key_id, auth_key->use_count); - return VNET_API_ERROR_BFD_EINUSE; - } - hash_unset (bm->auth_key_by_conf_key_id, conf_key_id); - memset (auth_key, 0, sizeof (*auth_key)); - pool_put (bm->auth_keys, auth_key); - } - else - { - /* no such key */ - clib_warning ("Authentication key with conf ID %u does not exist", - conf_key_id); - return VNET_API_ERROR_BFD_ENOENT; - } - return 0; -#else - clib_warning ("SSL missing, cannot manipulate authentication keys"); - return VNET_API_ERROR_BFD_NOTSUPP; -#endif -} - vnet_api_error_t bfd_udp_auth_activate (u32 sw_if_index, const ip46_address_t * local_addr, diff --git a/src/vnet/bfd/bfd_udp.h b/src/vnet/bfd/bfd_udp.h index ce2ee3cbf48..e33b7407d56 100644 --- a/src/vnet/bfd/bfd_udp.h +++ b/src/vnet/bfd/bfd_udp.h @@ -62,6 +62,11 @@ int bfd_add_udp6_transport (vlib_main_t * vm, vlib_buffer_t * b, */ int bfd_udp_is_echo_available (bfd_transport_e transport); +void +bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index, int *have_usable_ip4, + ip4_address_t * ip4, int *have_usable_ip6, + ip6_address_t * ip6); + #endif /* __included_bfd_udp_h__ */ /* -- cgit 1.2.3-korg