diff options
Diffstat (limited to 'src/vnet/bfd')
-rw-r--r-- | src/vnet/bfd/bfd.api | 121 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_api.c | 29 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_api.h | 9 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_cli.c | 134 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_main.c | 373 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_main.h | 51 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_protocol.h | 10 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_udp.c | 555 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_udp.h | 14 |
9 files changed, 760 insertions, 536 deletions
diff --git a/src/vnet/bfd/bfd.api b/src/vnet/bfd/bfd.api index f53cc7630fd..d3b3ed21a26 100644 --- a/src/vnet/bfd/bfd.api +++ b/src/vnet/bfd/bfd.api @@ -107,6 +107,26 @@ autoreply define bfd_udp_add u8 bfd_key_id; u32 conf_key_id; }; +define bfd_udp_upd +{ + u32 client_index; + u32 context; + vl_api_interface_index_t sw_if_index; + u32 desired_min_tx; + u32 required_min_rx; + vl_api_address_t local_addr; + vl_api_address_t peer_addr; + u8 detect_mult; + bool is_authenticated; + u8 bfd_key_id; + u32 conf_key_id; +}; +define bfd_udp_upd_reply +{ + u32 context; + i32 retval; + u32 stats_index; +}; /** \brief Modify UDP BFD session on interface @param client_index - opaque cookie to identify the sender @@ -339,6 +359,107 @@ autoreply define bfd_udp_auth_deactivate bool is_delayed; }; +/* must be compatible with bfd_error_t */ +counters bfd_udp { + none { + severity info; + type counter64; + units "packets"; + description "OK"; + }; + bad { + severity error; + type counter64; + units "packets"; + description "bad packet"; + }; + disabled { + severity error; + type counter64; + units "packets"; + description "bfd packets received on disabled interfaces"; + }; + version { + severity error; + type counter64; + units "packets"; + description "version"; + }; + length { + severity error; + type counter64; + units "packets"; + description "too short"; + }; + detect_multi { + severity error; + type counter64; + units "packets"; + description "detect-multi"; + }; + multi_point { + severity error; + type counter64; + units "packets"; + description "multi-point"; + }; + my_disc { + severity error; + type counter64; + units "packets"; + description "my-disc"; + }; + your_disc { + severity error; + type counter64; + units "packets"; + description "your-disc"; + }; + admin_down { + severity error; + type counter64; + units "packets"; + description "session admin-down"; + }; + no_session { + severity error; + type counter64; + units "packets"; + description "no-session"; + }; + failed_verification { + severity error; + type counter64; + units "packets"; + description "failed-verification"; + }; + src_mismatch { + severity error; + type counter64; + units "packets"; + description "src-mismatch"; + }; + dst_mismatch { + severity error; + type counter64; + units "packets"; + description "dst-mismatch"; + }; + ttl { + severity error; + type counter64; + units "packets"; + description "ttl"; + }; +}; + +paths { + "/err/bfd-udp4-input" "bfd"; + "/err/bfd-udp6-input" "bfd"; + "/err/bfd-udp4-echo-input" "bfd"; + "/err/bfd-udp6-echo-input" "bfd"; +}; + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/vnet/bfd/bfd_api.c b/src/vnet/bfd/bfd_api.c index 0ae8508f865..816e71081ff 100644 --- a/src/vnet/bfd/bfd_api.c +++ b/src/vnet/bfd/bfd_api.c @@ -71,6 +71,27 @@ vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp) } static void +vl_api_bfd_udp_upd_t_handler (vl_api_bfd_udp_add_t *mp) +{ + vl_api_bfd_udp_upd_reply_t *rmp; + int rv; + + VALIDATE_SW_IF_INDEX (mp); + + BFD_UDP_API_PARAM_COMMON_CODE; + + rv = bfd_udp_upd_session ( + BFD_UDP_API_PARAM_FROM_MP (mp), clib_net_to_host_u32 (mp->desired_min_tx), + clib_net_to_host_u32 (mp->required_min_rx), mp->detect_mult, + mp->is_authenticated, clib_net_to_host_u32 (mp->conf_key_id), + mp->bfd_key_id); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO2 (VL_API_BFD_UDP_UPD_REPLY, + ({ rmp->stats_index = clib_host_to_net_u32 (0); })); +} + +static void vl_api_bfd_udp_mod_t_handler (vl_api_bfd_udp_mod_t * mp) { vl_api_bfd_udp_mod_reply_t *rmp; @@ -196,7 +217,6 @@ bfd_event (bfd_main_t * bm, bfd_session_t * bs) vpe_api_main_t *vam = &vpe_api_main; vpe_client_registration_t *reg; vl_api_registration_t *vl_reg; - /* *INDENT-OFF* */ pool_foreach (reg, vam->bfd_events_registrations) { vl_reg = vl_api_client_index_to_registration (reg->client_index); if (vl_reg) @@ -210,7 +230,6 @@ bfd_event (bfd_main_t * bm, bfd_session_t * bs) } } } - /* *INDENT-ON* */ } static void @@ -223,13 +242,11 @@ vl_api_bfd_udp_session_dump_t_handler (vl_api_bfd_udp_session_dump_t * mp) return; bfd_session_t *bs = NULL; - /* *INDENT-OFF* */ pool_foreach (bs, bfd_main.sessions) { if (bs->transport == BFD_TRANSPORT_UDP4 || bs->transport == BFD_TRANSPORT_UDP6) send_bfd_udp_session_details (reg, mp->context, bs); } - /* *INDENT-ON* */ } static void @@ -280,7 +297,6 @@ vl_api_bfd_auth_keys_dump_t_handler (vl_api_bfd_auth_keys_dump_t * mp) bfd_auth_key_t *key = NULL; vl_api_bfd_auth_keys_details_t *rmp = NULL; - /* *INDENT-OFF* */ pool_foreach (key, bfd_main.auth_keys) { rmp = vl_msg_api_alloc (sizeof (*rmp)); clib_memset (rmp, 0, sizeof (*rmp)); @@ -291,7 +307,6 @@ vl_api_bfd_auth_keys_dump_t_handler (vl_api_bfd_auth_keys_dump_t * mp) rmp->use_count = clib_host_to_net_u32 (key->use_count); vl_api_send_msg (reg, (u8 *)rmp); } - /* *INDENT-ON* */ } static void @@ -373,7 +388,6 @@ vl_api_bfd_udp_get_echo_source_t_handler (vl_api_bfd_udp_get_echo_source_t * bfd_udp_get_echo_source (&is_set, &sw_if_index, &have_usable_ip4, &ip4, &have_usable_ip6, &ip6); - /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_BFD_UDP_GET_ECHO_SOURCE_REPLY, ({ rmp->sw_if_index = ntohl (sw_if_index); @@ -407,7 +421,6 @@ vl_api_bfd_udp_get_echo_source_t_handler (vl_api_bfd_udp_get_echo_source_t * rmp->have_usable_ip6 = false; } })) - /* *INDENT-ON* */ } #include <vnet/bfd/bfd.api.c> diff --git a/src/vnet/bfd/bfd_api.h b/src/vnet/bfd/bfd_api.h index 2a6c69b78b6..f051e6b679c 100644 --- a/src/vnet/bfd/bfd_api.h +++ b/src/vnet/bfd/bfd_api.h @@ -45,6 +45,15 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, u8 bfd_key_id); /** + * @brief create a new or modify and existing bfd session + */ +vnet_api_error_t +bfd_udp_upd_session (u32 sw_if_index, const ip46_address_t *local_addr, + const ip46_address_t *peer_addr, u32 desired_min_tx_usec, + u32 required_min_rx_usec, u8 detect_mult, + u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id); + +/** * @brief modify existing session */ vnet_api_error_t diff --git a/src/vnet/bfd/bfd_cli.c b/src/vnet/bfd/bfd_cli.c index 1d100b077eb..33942bb89e6 100644 --- a/src/vnet/bfd/bfd_cli.c +++ b/src/vnet/bfd/bfd_cli.c @@ -134,12 +134,10 @@ show_bfd (vlib_main_t * vm, unformat_input_t * input, 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); vec_free (s); vlib_cli_output (vm, "Number of configured BFD keys: %lu\n", @@ -149,11 +147,9 @@ show_bfd (vlib_main_t * vm, unformat_input_t * input, { 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, vm, bs); } - /* *INDENT-ON* */ vlib_cli_output (vm, "%v", s); vec_free (s); vlib_cli_output (vm, "Number of configured BFD sessions: %lu\n", @@ -212,13 +208,11 @@ show_bfd (vlib_main_t * vm, unformat_input_t * input, 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 clib_error_t * bfd_cli_key_add (vlib_main_t * vm, unformat_input_t * input, @@ -310,7 +304,6 @@ out: return ret; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (bfd_cli_key_add_command, static) = { .path = "bfd key set", .short_help = "bfd key set" @@ -319,7 +312,6 @@ VLIB_CLI_COMMAND (bfd_cli_key_add_command, static) = { " secret <secret>", .function = bfd_cli_key_add, }; -/* *INDENT-ON* */ static clib_error_t * bfd_cli_key_del (vlib_main_t * vm, unformat_input_t * input, @@ -355,13 +347,11 @@ 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 <id>", .function = bfd_cli_key_del, }; -/* *INDENT-ON* */ #define INTERFACE_STR "interface" #define LOCAL_ADDR_STR "local-addr" @@ -397,23 +387,30 @@ WARN_OFF(tautological-compare) \ goto out; \ } +static uword +bfd_cli_unformat_ip46_address (unformat_input_t *input, va_list *args) +{ + ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); + return unformat_user (input, unformat_ip46_address, ip46, IP46_TYPE_ANY); +} + 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; unformat_input_t _line_input, *line_input = &_line_input; -#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") \ +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_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); @@ -477,7 +474,6 @@ 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" @@ -493,7 +489,6 @@ VLIB_CLI_COMMAND (bfd_cli_udp_session_add_command, static) = { "]", .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, @@ -501,15 +496,15 @@ bfd_cli_udp_session_mod (vlib_main_t * vm, unformat_input_t * input, { clib_error_t *ret = NULL; unformat_input_t _line_input, *line_input = &_line_input; -#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") \ +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_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); @@ -556,7 +551,6 @@ 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" @@ -568,7 +562,6 @@ VLIB_CLI_COMMAND (bfd_cli_udp_session_mod_command, static) = { " <detect multiplier> ", .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, @@ -576,13 +569,13 @@ bfd_cli_udp_session_del (vlib_main_t * vm, unformat_input_t * input, { clib_error_t *ret = NULL; unformat_input_t _line_input, *line_input = &_line_input; -#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) +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_unformat_ip46_address) foreach_bfd_cli_udp_session_del_cli_param (DECLARE); @@ -620,7 +613,6 @@ 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" @@ -629,7 +621,6 @@ VLIB_CLI_COMMAND (bfd_cli_udp_session_del_command, static) = { "<peer-address> ", .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, @@ -637,14 +628,14 @@ bfd_cli_udp_session_set_flags (vlib_main_t * vm, unformat_input_t * input, { clib_error_t *ret = NULL; unformat_input_t _line_input, *line_input = &_line_input; -#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", \ +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_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); @@ -702,7 +693,6 @@ 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" @@ -712,7 +702,6 @@ VLIB_CLI_COMMAND (bfd_cli_udp_session_set_flags_command, static) = { " admin <up|down>", .function = bfd_cli_udp_session_set_flags, }; -/* *INDENT-ON* */ static clib_error_t * bfd_cli_udp_session_auth_activate (vlib_main_t * vm, @@ -721,15 +710,15 @@ bfd_cli_udp_session_auth_activate (vlib_main_t * vm, { clib_error_t *ret = NULL; unformat_input_t _line_input, *line_input = &_line_input; -#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") \ +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_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); @@ -799,7 +788,6 @@ 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" @@ -818,13 +806,13 @@ bfd_cli_udp_session_auth_deactivate (vlib_main_t *vm, unformat_input_t *input, { clib_error_t *ret = NULL; unformat_input_t _line_input, *line_input = &_line_input; -#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) \ +#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", \ + bfd_cli_unformat_ip46_address) \ + F (ip46_address_t, peer_addr, PEER_ADDR_STR, mandatory, "%U", \ + bfd_cli_unformat_ip46_address) \ F (u8 *, delayed_token, DELAYED_STR, optional, "%v") foreach_bfd_cli_udp_session_auth_deactivate_cli_param (DECLARE); @@ -884,7 +872,6 @@ 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" @@ -894,7 +881,6 @@ VLIB_CLI_COMMAND (bfd_cli_udp_session_auth_deactivate_command, static) = { "[ delayed <yes|no> ]", .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, @@ -941,13 +927,11 @@ 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 <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, @@ -964,13 +948,11 @@ bfd_cli_udp_del_echo_source (vlib_main_t * vm, unformat_input_t * input, 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 diff --git a/src/vnet/bfd/bfd_main.c b/src/vnet/bfd/bfd_main.c index 27616db3deb..1423da91158 100644 --- a/src/vnet/bfd/bfd_main.c +++ b/src/vnet/bfd/bfd_main.c @@ -30,14 +30,25 @@ #include <vlib/log.h> #include <vnet/crypto/crypto.h> +static void +bfd_validate_counters (bfd_main_t *bm) +{ + vlib_validate_combined_counter (&bm->rx_counter, pool_elts (bm->sessions)); + vlib_validate_combined_counter (&bm->rx_echo_counter, + pool_elts (bm->sessions)); + vlib_validate_combined_counter (&bm->tx_counter, pool_elts (bm->sessions)); + vlib_validate_combined_counter (&bm->tx_echo_counter, + pool_elts (bm->sessions)); +} + static u64 bfd_calc_echo_checksum (u32 discriminator, u64 expire_time, u32 secret) { u64 checksum = 0; #if defined(clib_crc32c_uses_intrinsics) && !defined (__i386__) - checksum = crc32_u64 (0, discriminator); - checksum = crc32_u64 (checksum, expire_time); - checksum = crc32_u64 (checksum, secret); + checksum = clib_crc32c_u64 (0, discriminator); + checksum = clib_crc32c_u64 (checksum, expire_time); + checksum = clib_crc32c_u64 (checksum, secret); #else checksum = clib_xxhash (discriminator ^ expire_time ^ secret); #endif @@ -172,7 +183,7 @@ bfd_set_poll_state (bfd_session_t * bs, bfd_poll_state_e state) } static void -bfd_recalc_tx_interval (bfd_main_t * bm, bfd_session_t * bs) +bfd_recalc_tx_interval (bfd_session_t *bs) { bs->transmit_interval_nsec = clib_max (bs->effective_desired_min_tx_nsec, bs->remote_min_rx_nsec); @@ -181,7 +192,7 @@ bfd_recalc_tx_interval (bfd_main_t * bm, bfd_session_t * bs) } static void -bfd_recalc_echo_tx_interval (bfd_main_t * bm, bfd_session_t * bs) +bfd_recalc_echo_tx_interval (bfd_session_t *bs) { bs->echo_transmit_interval_nsec = clib_max (bs->effective_desired_min_tx_nsec, bs->remote_min_echo_rx_nsec); @@ -240,7 +251,7 @@ bfd_calc_next_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now) } static void -bfd_calc_next_echo_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now) +bfd_calc_next_echo_tx (bfd_session_t *bs, u64 now) { bs->echo_tx_timeout_nsec = bs->echo_last_tx_nsec + bs->echo_transmit_interval_nsec; @@ -261,7 +272,7 @@ 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) +bfd_recalc_detection_time (bfd_session_t *bs) { if (bs->local_state == BFD_STATE_init || bs->local_state == BFD_STATE_up) { @@ -385,26 +396,24 @@ bfd_set_effective_desired_min_tx (bfd_main_t * bm, bs->effective_desired_min_tx_nsec = desired_min_tx_nsec; BFD_DBG ("Set effective desired min tx to " BFD_CLK_FMT, BFD_CLK_PRN (bs->effective_desired_min_tx_nsec)); - bfd_recalc_detection_time (bm, bs); - bfd_recalc_tx_interval (bm, bs); - bfd_recalc_echo_tx_interval (bm, bs); + bfd_recalc_detection_time (bs); + bfd_recalc_tx_interval (bs); + bfd_recalc_echo_tx_interval (bs); bfd_calc_next_tx (bm, bs, now); } static void -bfd_set_effective_required_min_rx (bfd_main_t * bm, - bfd_session_t * bs, - u64 required_min_rx_nsec) +bfd_set_effective_required_min_rx (bfd_session_t *bs, u64 required_min_rx_nsec) { bs->effective_required_min_rx_nsec = required_min_rx_nsec; BFD_DBG ("Set effective required min rx to " BFD_CLK_FMT, BFD_CLK_PRN (bs->effective_required_min_rx_nsec)); - bfd_recalc_detection_time (bm, bs); + bfd_recalc_detection_time (bs); } static void -bfd_set_remote_required_min_rx (bfd_main_t * bm, bfd_session_t * bs, - u64 now, u32 remote_required_min_rx_usec) +bfd_set_remote_required_min_rx (bfd_session_t *bs, + u32 remote_required_min_rx_usec) { if (bs->remote_min_rx_usec != remote_required_min_rx_usec) { @@ -412,14 +421,13 @@ bfd_set_remote_required_min_rx (bfd_main_t * bm, bfd_session_t * bs, bs->remote_min_rx_nsec = bfd_usec_to_nsec (remote_required_min_rx_usec); BFD_DBG ("Set remote min rx to " BFD_CLK_FMT, BFD_CLK_PRN (bs->remote_min_rx_nsec)); - bfd_recalc_detection_time (bm, bs); - bfd_recalc_tx_interval (bm, bs); + bfd_recalc_detection_time (bs); + bfd_recalc_tx_interval (bs); } } static void -bfd_set_remote_required_min_echo_rx (bfd_main_t * bm, bfd_session_t * bs, - u64 now, +bfd_set_remote_required_min_echo_rx (bfd_session_t *bs, u32 remote_required_min_echo_rx_usec) { if (bs->remote_min_echo_rx_usec != remote_required_min_echo_rx_usec) @@ -429,7 +437,7 @@ bfd_set_remote_required_min_echo_rx (bfd_main_t * bm, bfd_session_t * bs, bfd_usec_to_nsec (bs->remote_min_echo_rx_usec); BFD_DBG ("Set remote min echo rx to " BFD_CLK_FMT, BFD_CLK_PRN (bs->remote_min_echo_rx_nsec)); - bfd_recalc_echo_tx_interval (bm, bs); + bfd_recalc_echo_tx_interval (bs); } } @@ -450,14 +458,21 @@ bfd_session_start (bfd_main_t * bm, bfd_session_t * bs) BFD_DBG ("\nStarting session: %U", format_bfd_session, bs); vlib_log_info (bm->log_class, "start BFD session: %U", format_bfd_session_brief, bs); - bfd_set_effective_required_min_rx (bm, bs, bs->config_required_min_rx_nsec); - bfd_recalc_tx_interval (bm, bs); + bfd_set_effective_required_min_rx (bs, bs->config_required_min_rx_nsec); + bfd_recalc_tx_interval (bs); vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index, BFD_EVENT_NEW_SESSION, bs->bs_idx); bfd_notify_listeners (bm, BFD_LISTEN_EVENT_CREATE, bs); } void +bfd_session_stop (bfd_main_t *bm, bfd_session_t *bs) +{ + BFD_DBG ("\nStopping session: %U", format_bfd_session, bs); + bfd_notify_listeners (bm, BFD_LISTEN_EVENT_DELETE, bs); +} + +void bfd_session_set_flags (vlib_main_t * vm, bfd_session_t * bs, u8 admin_up_down) { bfd_main_t *bm = &bfd_main; @@ -485,30 +500,29 @@ bfd_session_set_flags (vlib_main_t * vm, bfd_session_t * bs, u8 admin_up_down) } u8 * -bfd_input_format_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - const bfd_input_trace_t *t = va_arg (*args, bfd_input_trace_t *); - const bfd_pkt_t *pkt = (bfd_pkt_t *) t->data; - if (t->len > STRUCT_SIZE_OF (bfd_pkt_t, head)) - { - s = format (s, "BFD v%u, diag=%u(%s), state=%u(%s),\n" - " flags=(P:%u, F:%u, C:%u, A:%u, D:%u, M:%u), " - "detect_mult=%u, length=%u\n", - bfd_pkt_get_version (pkt), bfd_pkt_get_diag_code (pkt), - bfd_diag_code_string (bfd_pkt_get_diag_code (pkt)), - bfd_pkt_get_state (pkt), - bfd_state_string (bfd_pkt_get_state (pkt)), - bfd_pkt_get_poll (pkt), bfd_pkt_get_final (pkt), - bfd_pkt_get_control_plane_independent (pkt), - bfd_pkt_get_auth_present (pkt), bfd_pkt_get_demand (pkt), - bfd_pkt_get_multipoint (pkt), pkt->head.detect_mult, - pkt->head.length); - if (t->len >= sizeof (bfd_pkt_t) && - pkt->head.length >= sizeof (bfd_pkt_t)) +format_bfd_pkt (u8 *s, va_list *args) +{ + u32 len = va_arg (*args, u32); + u8 *data = va_arg (*args, u8 *); + + const bfd_pkt_t *pkt = (bfd_pkt_t *) data; + if (len > STRUCT_SIZE_OF (bfd_pkt_t, head)) + { + s = format ( + s, + "BFD v%u, diag=%u(%s), state=%u(%s),\n" + " flags=(P:%u, F:%u, C:%u, A:%u, D:%u, M:%u), " + "detect_mult=%u, length=%u", + bfd_pkt_get_version (pkt), bfd_pkt_get_diag_code (pkt), + bfd_diag_code_string (bfd_pkt_get_diag_code (pkt)), + bfd_pkt_get_state (pkt), bfd_state_string (bfd_pkt_get_state (pkt)), + bfd_pkt_get_poll (pkt), bfd_pkt_get_final (pkt), + bfd_pkt_get_control_plane_independent (pkt), + bfd_pkt_get_auth_present (pkt), bfd_pkt_get_demand (pkt), + bfd_pkt_get_multipoint (pkt), pkt->head.detect_mult, pkt->head.length); + if (len >= sizeof (bfd_pkt_t) && pkt->head.length >= sizeof (bfd_pkt_t)) { - s = format (s, " my discriminator: %u\n", + s = format (s, "\n my discriminator: %u\n", clib_net_to_host_u32 (pkt->my_disc)); s = format (s, " your discriminator: %u\n", clib_net_to_host_u32 (pkt->your_disc)); @@ -519,16 +533,16 @@ bfd_input_format_trace (u8 * s, va_list * args) s = format (s, " required min echo rx interval: %u", clib_net_to_host_u32 (pkt->req_min_echo_rx)); } - if (t->len >= sizeof (bfd_pkt_with_common_auth_t) && + if (len >= sizeof (bfd_pkt_with_common_auth_t) && pkt->head.length >= sizeof (bfd_pkt_with_common_auth_t) && bfd_pkt_get_auth_present (pkt)) { const bfd_pkt_with_common_auth_t *with_auth = (void *) pkt; const bfd_auth_common_t *common = &with_auth->common_auth; s = format (s, "\n auth len: %u\n", common->len); - s = format (s, " auth type: %u:%s\n", common->type, + s = format (s, " auth type: %u:%s", common->type, bfd_auth_type_str (common->type)); - if (t->len >= sizeof (bfd_pkt_with_sha1_auth_t) && + if (len >= sizeof (bfd_pkt_with_sha1_auth_t) && pkt->head.length >= sizeof (bfd_pkt_with_sha1_auth_t) && (BFD_AUTH_TYPE_keyed_sha1 == common->type || BFD_AUTH_TYPE_meticulous_keyed_sha1 == common->type)) @@ -542,15 +556,23 @@ bfd_input_format_trace (u8 * s, va_list * args) sizeof (sha1->hash)); } } - else - { - s = format (s, "\n"); - } } return s; } +u8 * +bfd_input_format_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + const bfd_input_trace_t *t = va_arg (*args, bfd_input_trace_t *); + + s = format (s, "%U", format_bfd_pkt, t->len, t->data); + + return s; +} + typedef struct { u32 bs_idx; @@ -651,8 +673,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, clib_max (bs->config_desired_min_tx_nsec, bm->default_desired_min_tx_nsec)); - bfd_set_effective_required_min_rx (bm, bs, - bs->config_required_min_rx_nsec); + bfd_set_effective_required_min_rx (bs, bs->config_required_min_rx_nsec); bfd_set_timer (bm, bs, now, handling_wakeup); break; case BFD_STATE_down: @@ -661,8 +682,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, clib_max (bs->config_desired_min_tx_nsec, bm->default_desired_min_tx_nsec)); - bfd_set_effective_required_min_rx (bm, bs, - bs->config_required_min_rx_nsec); + bfd_set_effective_required_min_rx (bs, bs->config_required_min_rx_nsec); bfd_set_timer (bm, bs, now, handling_wakeup); break; case BFD_STATE_init: @@ -676,7 +696,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, bs->config_desired_min_tx_nsec); if (BFD_POLL_NOT_NEEDED == bs->poll_state) { - bfd_set_effective_required_min_rx (bm, bs, + bfd_set_effective_required_min_rx (bs, bs->config_required_min_rx_nsec); } bfd_set_timer (bm, bs, now, handling_wakeup); @@ -694,8 +714,7 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, } static void -bfd_on_config_change (vlib_main_t * vm, vlib_node_runtime_t * rt, - bfd_main_t * bm, bfd_session_t * bs, u64 now) +bfd_on_config_change (bfd_main_t *bm, bfd_session_t *bs, u64 now) { /* * if remote demand mode is set and we need to do a poll, set the next @@ -706,7 +725,7 @@ bfd_on_config_change (vlib_main_t * vm, vlib_node_runtime_t * rt, { bs->tx_timeout_nsec = now; } - bfd_recalc_detection_time (bm, bs); + bfd_recalc_detection_time (bs); bfd_set_timer (bm, bs, now, 0); } @@ -727,17 +746,18 @@ bfd_add_transport_layer (vlib_main_t * vm, u32 bi, bfd_session_t * bs) } static int -bfd_transport_control_frame (vlib_main_t * vm, u32 bi, bfd_session_t * bs) +bfd_transport_control_frame (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + bfd_session_t *bs) { switch (bs->transport) { case BFD_TRANSPORT_UDP4: BFD_DBG ("Transport bfd via udp4, bs_idx=%u", bs->bs_idx); - return bfd_transport_udp4 (vm, bi, bs); + return bfd_transport_udp4 (vm, rt, bi, bs, 0 /* is_echo */); break; case BFD_TRANSPORT_UDP6: BFD_DBG ("Transport bfd via udp6, bs_idx=%u", bs->bs_idx); - return bfd_transport_udp6 (vm, bi, bs); + return bfd_transport_udp6 (vm, rt, bi, bs, 0 /* is_echo */); break; } return 0; @@ -761,17 +781,18 @@ bfd_echo_add_transport_layer (vlib_main_t * vm, u32 bi, bfd_session_t * bs) } static int -bfd_transport_echo (vlib_main_t * vm, u32 bi, bfd_session_t * bs) +bfd_transport_echo (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + bfd_session_t *bs) { switch (bs->transport) { case BFD_TRANSPORT_UDP4: BFD_DBG ("Transport bfd echo via udp4, bs_idx=%u", bs->bs_idx); - return bfd_transport_udp4 (vm, bi, bs); + return bfd_transport_udp4 (vm, rt, bi, bs, 1 /* is_echo */); break; case BFD_TRANSPORT_UDP6: BFD_DBG ("Transport bfd echo via udp6, bs_idx=%u", bs->bs_idx); - return bfd_transport_udp6 (vm, bi, bs); + return bfd_transport_udp6 (vm, rt, bi, bs, 1 /* is_echo */); break; } return 0; @@ -861,8 +882,7 @@ bfd_is_echo_possible (bfd_session_t * bs) } static void -bfd_init_control_frame (bfd_main_t * bm, bfd_session_t * bs, - vlib_buffer_t * b) +bfd_init_control_frame (bfd_session_t *bs, vlib_buffer_t *b) { bfd_pkt_t *pkt = vlib_buffer_get_current (b); u32 bfd_length = 0; @@ -891,9 +911,39 @@ bfd_init_control_frame (bfd_main_t * bm, bfd_session_t * bs, b->current_length = bfd_length; } +typedef struct +{ + u32 bs_idx; + u32 len; + u8 data[400]; +} bfd_process_trace_t; + static void -bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt, - bfd_main_t * bm, bfd_session_t * bs, u64 now) +bfd_process_trace_buf (vlib_main_t *vm, vlib_node_runtime_t *rt, + vlib_buffer_t *b, bfd_session_t *bs) +{ + u32 n_trace = vlib_get_trace_count (vm, rt); + if (n_trace > 0) + { + bfd_process_trace_t *tr; + if (vlib_trace_buffer (vm, rt, 0, b, 0)) + { + tr = vlib_add_trace (vm, rt, b, sizeof (*tr)); + tr->bs_idx = bs->bs_idx; + u64 len = (b->current_length < sizeof (tr->data)) ? + b->current_length : + sizeof (tr->data); + tr->len = len; + clib_memcpy_fast (tr->data, vlib_buffer_get_current (b), len); + --n_trace; + vlib_set_trace_count (vm, rt, n_trace); + } + } +} + +static void +bfd_send_echo (vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, + bfd_session_t *bs, u64 now) { if (!bfd_is_echo_possible (bs)) { @@ -921,6 +971,7 @@ bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_calc_echo_checksum (bs->local_discr, pkt->expire_time_nsec, bs->echo_secret); b->current_length = sizeof (*pkt); + bfd_process_trace_buf (vm, rt, b, bs); if (!bfd_echo_add_transport_layer (vm, bi, bs)) { BFD_ERR ("cannot send echo packet out, turning echo off"); @@ -928,7 +979,7 @@ bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_buffer_free_one (vm, bi); return; } - if (!bfd_transport_echo (vm, bi, bs)) + if (!bfd_transport_echo (vm, rt, bi, bs)) { BFD_ERR ("cannot send echo packet out, turning echo off"); bs->echo = 0; @@ -936,7 +987,7 @@ bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt, return; } bs->echo_last_tx_nsec = now; - bfd_calc_next_echo_tx (bm, bs, now); + bfd_calc_next_echo_tx (bs, now); } else { @@ -947,8 +998,8 @@ bfd_send_echo (vlib_main_t * vm, vlib_node_runtime_t * rt, } static void -bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, - bfd_main_t * bm, bfd_session_t * bs, u64 now) +bfd_send_periodic (vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, + bfd_session_t *bs, u64 now) { if (!bs->remote_min_rx_usec && BFD_POLL_NOT_NEEDED == bs->poll_state) { @@ -980,7 +1031,7 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, } vlib_buffer_t *b = vlib_get_buffer (vm, bi); ASSERT (b->current_data == 0); - bfd_init_control_frame (bm, bs, b); + bfd_init_control_frame (bs, b); switch (bs->poll_state) { case BFD_POLL_NEEDED: @@ -1005,8 +1056,9 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, break; } bfd_add_auth_section (vm, b, bs); + bfd_process_trace_buf (vm, rt, b, bs); bfd_add_transport_layer (vm, bi, bs); - if (!bfd_transport_control_frame (vm, bi, bs)) + if (!bfd_transport_control_frame (vm, rt, bi, bs)) { vlib_buffer_free_one (vm, bi); } @@ -1022,12 +1074,11 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, } void -bfd_init_final_control_frame (vlib_main_t * vm, vlib_buffer_t * b, - bfd_main_t * bm, bfd_session_t * bs, - int is_local) +bfd_init_final_control_frame (vlib_main_t *vm, vlib_buffer_t *b, + bfd_session_t *bs) { BFD_DBG ("Send final control frame for bs_idx=%lu", bs->bs_idx); - bfd_init_control_frame (bm, bs, b); + bfd_init_control_frame (bs, b); bfd_pkt_set_final (vlib_buffer_get_current (b)); bfd_add_auth_section (vm, b, bs); u32 bi = vlib_get_buffer_index (vm, b); @@ -1069,7 +1120,7 @@ bfd_check_rx_timeout (vlib_main_t * vm, bfd_main_t * bm, bfd_session_t * bs, * since it is no longer required to maintain previous session state) * and then can transmit at its own rate. */ - bfd_set_remote_required_min_rx (bm, bs, now, 1); + bfd_set_remote_required_min_rx (bs, 1); } else if (bs->echo && bs->echo_last_rx_nsec + @@ -1082,15 +1133,14 @@ bfd_check_rx_timeout (vlib_main_t * vm, bfd_main_t * bm, bfd_session_t * bs, } void -bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm, - bfd_session_t * bs, u64 now) +bfd_on_timeout (vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, + bfd_session_t *bs, u64 now) { BFD_DBG ("Timeout for bs_idx=%lu", bs->bs_idx); switch (bs->local_state) { case BFD_STATE_admin_down: - bfd_send_periodic (vm, rt, bm, bs, now); - break; + /* fallthrough */ case BFD_STATE_down: bfd_send_periodic (vm, rt, bm, bs, now); break; @@ -1108,10 +1158,9 @@ bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm, bs->echo = 1; bs->echo_last_rx_nsec = now; bs->echo_tx_timeout_nsec = now; - bfd_set_effective_required_min_rx (bm, bs, - clib_max - (bm->min_required_min_rx_while_echo_nsec, - bs->config_required_min_rx_nsec)); + bfd_set_effective_required_min_rx ( + bs, clib_max (bm->min_required_min_rx_while_echo_nsec, + bs->config_required_min_rx_nsec)); bfd_set_poll_state (bs, BFD_POLL_NEEDED); } bfd_send_periodic (vm, rt, bm, bs, now); @@ -1123,11 +1172,25 @@ bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm, } } +u8 * +format_bfd_process_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + bfd_process_trace_t *t = va_arg (*args, bfd_process_trace_t *); + + s = + format (s, "bs_idx=%u => %U", t->bs_idx, format_bfd_pkt, t->len, t->data); + + return s; +} + /* * bfd process node function */ static uword -bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) +bfd_process (vlib_main_t *vm, vlib_node_runtime_t *rt, + CLIB_UNUSED (vlib_frame_t *f)) { bfd_main_t *bm = &bfd_main; u32 *expired = 0; @@ -1168,7 +1231,9 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) now + first_expires_in_ticks * bm->nsec_per_tw_tick; bm->bfd_process_next_wakeup_nsec = next_expire_nsec; bfd_unlock (bm); - timeout = (next_expire_nsec - now) * SEC_PER_NSEC; + ASSERT (next_expire_nsec - now <= UINT32_MAX); + // cast to u32 to avoid warning + timeout = (u32) (next_expire_nsec - now) * SEC_PER_NSEC; } BFD_DBG ("vlib_process_wait_for_event_or_clock(vm, %.09f)", timeout); @@ -1224,7 +1289,7 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { bfd_session_t *bs = pool_elt_at_index (bm->sessions, *session_index); - bfd_on_config_change (vm, rt, bm, bs, now); + bfd_on_config_change (bm, bs, now); } else { @@ -1258,11 +1323,11 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) bfd_unlock (bm); if (expired) { - _vec_len (expired) = 0; + vec_set_len (expired, 0); } if (event_data) { - _vec_len (event_data) = 0; + vec_set_len (event_data, 0); } } @@ -1272,18 +1337,29 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) /* * bfd process node declaration */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (bfd_process_node, static) = { +// clang-format off +VLIB_REGISTER_NODE (bfd_process_node, static) = +{ .function = bfd_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "bfd-process", - .n_next_nodes = 0, - .next_nodes = {}, + .flags = (VLIB_NODE_FLAG_TRACE_SUPPORTED), + .format_trace = format_bfd_process_trace, + .n_next_nodes = BFD_TX_N_NEXT, + .next_nodes = { + [BFD_TX_IP4_ARP] = "ip4-arp", + [BFD_TX_IP6_NDP] = "ip6-discover-neighbor", + [BFD_TX_IP4_REWRITE] = "ip4-rewrite", + [BFD_TX_IP6_REWRITE] = "ip6-rewrite", + [BFD_TX_IP4_MIDCHAIN] = "ip4-midchain", + [BFD_TX_IP6_MIDCHAIN] = "ip6-midchain", + } }; -/* *INDENT-ON* */ +// clang-format on static clib_error_t * -bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) +bfd_sw_interface_up_down (CLIB_UNUSED (vnet_main_t *vnm), + CLIB_UNUSED (u32 sw_if_index), u32 flags) { // bfd_main_t *bm = &bfd_main; // vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); @@ -1297,7 +1373,8 @@ bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bfd_sw_interface_up_down); static clib_error_t * -bfd_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) +bfd_hw_interface_up_down (CLIB_UNUSED (vnet_main_t *vnm), + CLIB_UNUSED (u32 hw_if_index), u32 flags) { // bfd_main_t *bm = &bfd_main; if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP) @@ -1346,6 +1423,14 @@ bfd_main_init (vlib_main_t * vm) bm->owner_thread_index = ~0; if (n_vlib_mains > 1) clib_spinlock_init (&bm->lock); + bm->rx_counter.name = "bfd rx session counters"; + bm->rx_counter.stat_segment_name = "/bfd/rx-session-counters"; + bm->rx_echo_counter.name = "bfd rx session echo counters"; + bm->rx_echo_counter.stat_segment_name = "/bfd/rx-session-echo-counters"; + bm->tx_counter.name = "bfd tx session counters"; + bm->tx_counter.stat_segment_name = "/bfd/tx-session-counters"; + bm->tx_echo_counter.name = "bfd tx session echo counters"; + bm->tx_echo_counter.stat_segment_name = "/bfd/tx-session-echo-counters"; return 0; } @@ -1381,6 +1466,11 @@ bfd_get_session (bfd_main_t * bm, bfd_transport_e t) while (hash_get (bm->session_by_disc, result->local_discr)); bfd_set_defaults (bm, result); hash_set (bm->session_by_disc, result->local_discr, result->bs_idx); + bfd_validate_counters (bm); + vlib_zero_combined_counter (&bm->rx_counter, result->bs_idx); + vlib_zero_combined_counter (&bm->rx_echo_counter, result->bs_idx); + vlib_zero_combined_counter (&bm->tx_counter, result->bs_idx); + vlib_zero_combined_counter (&bm->tx_echo_counter, result->bs_idx); bfd_unlock (bm); return result; } @@ -1392,7 +1482,6 @@ bfd_put_session (bfd_main_t * bm, bfd_session_t * bs) vlib_log_info (bm->log_class, "delete session: %U", format_bfd_session_brief, bs); - bfd_notify_listeners (bm, BFD_LISTEN_EVENT_DELETE, bs); if (bs->auth.curr_key) { --bs->auth.curr_key->use_count; @@ -1402,6 +1491,10 @@ bfd_put_session (bfd_main_t * bm, bfd_session_t * bs) --bs->auth.next_key->use_count; } hash_unset (bm->session_by_disc, bs->local_discr); + vlib_zero_combined_counter (&bm->rx_counter, bs->bs_idx); + vlib_zero_combined_counter (&bm->rx_echo_counter, bs->bs_idx); + vlib_zero_combined_counter (&bm->tx_counter, bs->bs_idx); + vlib_zero_combined_counter (&bm->tx_echo_counter, bs->bs_idx); pool_put (bm->sessions, bs); bfd_unlock (bm); } @@ -1436,14 +1529,14 @@ bfd_find_session_by_disc (bfd_main_t * bm, u32 disc) * * @return 1 if bfd packet is valid */ -int -bfd_verify_pkt_common (const bfd_pkt_t * pkt) +bfd_error_t +bfd_verify_pkt_common (const bfd_pkt_t *pkt) { if (1 != bfd_pkt_get_version (pkt)) { BFD_ERR ("BFD verification failed - unexpected version: '%d'", bfd_pkt_get_version (pkt)); - return 0; + return BFD_ERROR_VERSION; } if (pkt->head.length < sizeof (bfd_pkt_t) || (bfd_pkt_get_auth_present (pkt) && @@ -1452,25 +1545,25 @@ bfd_verify_pkt_common (const bfd_pkt_t * pkt) BFD_ERR ("BFD verification failed - unexpected length: '%d' (auth " "present: %d)", pkt->head.length, bfd_pkt_get_auth_present (pkt)); - return 0; + return BFD_ERROR_LENGTH; } if (!pkt->head.detect_mult) { BFD_ERR ("BFD verification failed - unexpected detect-mult: '%d'", pkt->head.detect_mult); - return 0; + return BFD_ERROR_DETECT_MULTI; } if (bfd_pkt_get_multipoint (pkt)) { BFD_ERR ("BFD verification failed - unexpected multipoint: '%d'", bfd_pkt_get_multipoint (pkt)); - return 0; + return BFD_ERROR_MULTI_POINT; } if (!pkt->my_disc) { BFD_ERR ("BFD verification failed - unexpected my-disc: '%d'", pkt->my_disc); - return 0; + return BFD_ERROR_MY_DISC; } if (!pkt->your_disc) { @@ -1479,10 +1572,10 @@ bfd_verify_pkt_common (const bfd_pkt_t * pkt) { BFD_ERR ("BFD verification failed - unexpected state: '%s' " "(your-disc is zero)", bfd_state_string (pkt_state)); - return 0; + return BFD_ERROR_YOUR_DISC; } } - return 1; + return BFD_ERROR_NONE; } static void @@ -1581,8 +1674,8 @@ bfd_verify_pkt_auth_seq_num (vlib_main_t * vm, bfd_session_t * bs, static int bfd_verify_pkt_auth_key_sha1 (vlib_main_t *vm, const bfd_pkt_t *pkt, - u32 pkt_size, bfd_session_t *bs, u8 bfd_key_id, - bfd_auth_key_t *auth_key) + u32 pkt_size, CLIB_UNUSED (bfd_session_t *bs), + u8 bfd_key_id, bfd_auth_key_t *auth_key) { ASSERT (auth_key->auth_type == BFD_AUTH_TYPE_keyed_sha1 || auth_key->auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1); @@ -1634,6 +1727,11 @@ bfd_verify_pkt_auth_key_sha1 (vlib_main_t *vm, const bfd_pkt_t *pkt, op.len = sizeof (*with_sha1); op.digest = calculated_hash; vnet_crypto_process_ops (vm, &op, 1); + + /* Restore the modified data within the packet */ + clib_memcpy (with_sha1->sha1_auth.hash, hash_from_packet, + sizeof (with_sha1->sha1_auth.hash)); + if (0 == memcmp (calculated_hash, hash_from_packet, sizeof (calculated_hash))) { @@ -1662,18 +1760,14 @@ bfd_verify_pkt_auth_key (vlib_main_t * vm, const bfd_pkt_t * pkt, bfd_auth_type_str (auth_key->auth_type)); return 0; case BFD_AUTH_TYPE_simple_password: - vlib_log_err (bm->log_class, - "internal error, not implemented, unexpected auth_type=%d:%s", - auth_key->auth_type, - bfd_auth_type_str (auth_key->auth_type)); - return 0; + /* fallthrough */ case BFD_AUTH_TYPE_keyed_md5: /* fallthrough */ case BFD_AUTH_TYPE_meticulous_keyed_md5: - vlib_log_err - (bm->log_class, - "internal error, not implemented, unexpected auth_type=%d:%s", - auth_key->auth_type, bfd_auth_type_str (auth_key->auth_type)); + vlib_log_err ( + bm->log_class, + "internal error, not implemented, unexpected auth_type=%d:%s", + auth_key->auth_type, bfd_auth_type_str (auth_key->auth_type)); return 0; case BFD_AUTH_TYPE_keyed_sha1: /* fallthrough */ @@ -1780,8 +1874,8 @@ bfd_verify_pkt_auth (vlib_main_t * vm, const bfd_pkt_t * pkt, u16 pkt_size, return 0; } -void -bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, +bfd_error_t +bfd_consume_pkt (vlib_main_t *vm, bfd_main_t *bm, const bfd_pkt_t *pkt, u32 bs_idx) { bfd_lock_check (bm); @@ -1789,7 +1883,7 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, bfd_session_t *bs = bfd_find_session_by_idx (bm, bs_idx); if (!bs || (pkt->your_disc && pkt->your_disc != bs->local_discr)) { - return; + return BFD_ERROR_YOUR_DISC; } BFD_DBG ("Scanning bfd packet, bs_idx=%d", bs->bs_idx); bs->remote_discr = pkt->my_disc; @@ -1834,11 +1928,9 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, bs->remote_desired_min_tx_nsec = bfd_usec_to_nsec (clib_net_to_host_u32 (pkt->des_min_tx)); bs->remote_detect_mult = pkt->head.detect_mult; - bfd_set_remote_required_min_rx (bm, bs, now, - clib_net_to_host_u32 (pkt->req_min_rx)); - bfd_set_remote_required_min_echo_rx (bm, bs, now, - clib_net_to_host_u32 - (pkt->req_min_echo_rx)); + bfd_set_remote_required_min_rx (bs, clib_net_to_host_u32 (pkt->req_min_rx)); + bfd_set_remote_required_min_echo_rx ( + bs, clib_net_to_host_u32 (pkt->req_min_echo_rx)); if (bfd_pkt_get_final (pkt)) { if (BFD_POLL_IN_PROGRESS == bs->poll_state) @@ -1849,10 +1941,10 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, { bfd_set_effective_desired_min_tx ( bm, bs, now, bs->config_desired_min_tx_nsec); - bfd_set_effective_required_min_rx (bm, bs, - clib_max (bs->echo * - bm->min_required_min_rx_while_echo_nsec, - bs->config_required_min_rx_nsec)); + bfd_set_effective_required_min_rx ( + bs, + clib_max (bs->echo * bm->min_required_min_rx_while_echo_nsec, + bs->config_required_min_rx_nsec)); } } else if (BFD_POLL_IN_PROGRESS_AND_QUEUED == bs->poll_state) @@ -1877,7 +1969,7 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, { BFD_DBG ("Session is admin-down, ignoring packet, bs_idx=%u", bs->bs_idx); - return; + return BFD_ERROR_ADMIN_DOWN; } if (BFD_STATE_admin_down == bs->remote_state) { @@ -1914,10 +2006,11 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, bfd_set_state (vm, bm, bs, BFD_STATE_down, 0); } } + return BFD_ERROR_NONE; } -int -bfd_consume_echo_pkt (vlib_main_t * vm, bfd_main_t * bm, vlib_buffer_t * b) +bfd_session_t * +bfd_consume_echo_pkt (vlib_main_t *vm, bfd_main_t *bm, vlib_buffer_t *b) { bfd_echo_pkt_t *pkt = NULL; if (b->current_length != sizeof (*pkt)) @@ -1937,7 +2030,7 @@ bfd_consume_echo_pkt (vlib_main_t * vm, bfd_main_t * bm, vlib_buffer_t * b) if (checksum != pkt->checksum) { BFD_DBG ("Invalid echo packet, checksum mismatch"); - return 1; + return 0; } u64 now = bfd_time_now_nsec (vm, NULL); if (pkt->expire_time_nsec < now) @@ -1949,7 +2042,7 @@ bfd_consume_echo_pkt (vlib_main_t * vm, bfd_main_t * bm, vlib_buffer_t * b) { bs->echo_last_rx_nsec = now; } - return 1; + return bs; } u8 * diff --git a/src/vnet/bfd/bfd_main.h b/src/vnet/bfd/bfd_main.h index 0bdcfb87622..1d4617e1d7c 100644 --- a/src/vnet/bfd/bfd_main.h +++ b/src/vnet/bfd/bfd_main.h @@ -258,7 +258,7 @@ typedef enum } bfd_listen_event_e; /** - * session nitification call back function type + * session notification call back function type */ typedef void (*bfd_notify_fn_t) (bfd_listen_event_e, const bfd_session_t *); @@ -322,15 +322,27 @@ typedef struct vlib_log_class_t log_class; u16 msg_id_base; + + vlib_combined_counter_main_t rx_counter; + vlib_combined_counter_main_t rx_echo_counter; + vlib_combined_counter_main_t tx_counter; + vlib_combined_counter_main_t tx_echo_counter; } bfd_main_t; extern bfd_main_t bfd_main; /** Packet counters */ -#define foreach_bfd_error(F) \ - F (NONE, "good bfd packets (processed)") \ - F (BAD, "invalid bfd packets") \ - F (DISABLED, "bfd packets received on disabled interfaces") +#define foreach_bfd_error(F) \ + F (NONE, "good bfd packets (processed)") \ + F (BAD, "invalid bfd packets") \ + F (DISABLED, "bfd packets received on disabled interfaces") \ + F (VERSION, "version") \ + F (LENGTH, "length") \ + F (DETECT_MULTI, "detect-multi") \ + F (MULTI_POINT, "multi-point") \ + F (MY_DISC, "my-disc") \ + F (YOUR_DISC, "your-disc") \ + F (ADMIN_DOWN, "session admin-down") typedef enum { @@ -354,7 +366,6 @@ typedef enum BFD_EVENT_CONFIG_CHANGED, } bfd_process_event_e; -/* *INDENT-OFF* */ /** echo packet structure */ typedef CLIB_PACKED (struct { /** local discriminator */ @@ -364,7 +375,6 @@ typedef CLIB_PACKED (struct { /** checksum - based on discriminator, local secret and expire time */ u64 checksum; }) bfd_echo_pkt_t; -/* *INDENT-ON* */ static inline void bfd_lock (bfd_main_t * bm) @@ -412,17 +422,17 @@ void bfd_put_session (bfd_main_t * bm, bfd_session_t * bs); bfd_session_t *bfd_find_session_by_idx (bfd_main_t * bm, uword bs_idx); bfd_session_t *bfd_find_session_by_disc (bfd_main_t * bm, u32 disc); void bfd_session_start (bfd_main_t * bm, bfd_session_t * bs); -void bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, - const bfd_pkt_t * bfd, u32 bs_idx); -int bfd_consume_echo_pkt (vlib_main_t * vm, bfd_main_t * bm, - vlib_buffer_t * b); -int bfd_verify_pkt_common (const bfd_pkt_t * pkt); +void bfd_session_stop (bfd_main_t *bm, bfd_session_t *bs); +bfd_error_t bfd_consume_pkt (vlib_main_t *vm, bfd_main_t *bm, + const bfd_pkt_t *bfd, u32 bs_idx); +bfd_session_t *bfd_consume_echo_pkt (vlib_main_t *vm, bfd_main_t *bm, + vlib_buffer_t *b); +bfd_error_t bfd_verify_pkt_common (const bfd_pkt_t *pkt); int bfd_verify_pkt_auth (vlib_main_t * vm, const bfd_pkt_t * pkt, u16 pkt_size, bfd_session_t * bs); 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, - int is_local); +void bfd_init_final_control_frame (vlib_main_t *vm, vlib_buffer_t *b, + bfd_session_t *bs); u8 *format_bfd_session (u8 * s, va_list * args); u8 *format_bfd_session_brief (u8 * s, va_list * args); u8 *format_bfd_auth_key (u8 * s, va_list * args); @@ -464,6 +474,17 @@ const char *bfd_poll_state_string (bfd_poll_state_e state); */ void bfd_register_listener (bfd_notify_fn_t fn); +typedef enum +{ + BFD_TX_IP4_ARP, + BFD_TX_IP6_NDP, + BFD_TX_IP4_REWRITE, + BFD_TX_IP6_REWRITE, + BFD_TX_IP4_MIDCHAIN, + BFD_TX_IP6_MIDCHAIN, + BFD_TX_N_NEXT, +} bfd_tx_next_t; + #endif /* __included_bfd_main_h__ */ /* diff --git a/src/vnet/bfd/bfd_protocol.h b/src/vnet/bfd/bfd_protocol.h index 210c561b430..16ee3231ef0 100644 --- a/src/vnet/bfd/bfd_protocol.h +++ b/src/vnet/bfd/bfd_protocol.h @@ -46,14 +46,11 @@ typedef enum u32 bfd_max_key_len_for_auth_type (bfd_auth_type_e auth_type); const char *bfd_auth_type_str (bfd_auth_type_e auth_type); -/* *INDENT-OFF* */ typedef CLIB_PACKED (struct { u8 type; u8 len; }) bfd_auth_common_t; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ typedef CLIB_PACKED (struct { /* * 4.4. Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format @@ -88,9 +85,7 @@ typedef CLIB_PACKED (struct { */ u8 hash[20]; }) bfd_auth_sha1_t; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ typedef CLIB_PACKED (struct { /* * The Mandatory Section of a BFD Control packet has the following @@ -125,21 +120,16 @@ typedef CLIB_PACKED (struct { u32 req_min_rx; u32 req_min_echo_rx; }) bfd_pkt_t; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ typedef CLIB_PACKED (struct { bfd_pkt_t pkt; bfd_auth_common_t common_auth; }) bfd_pkt_with_common_auth_t; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ typedef CLIB_PACKED (struct { bfd_pkt_t pkt; bfd_auth_sha1_t sha1_auth; }) bfd_pkt_with_sha1_auth_t; -/* *INDENT-ON* */ u8 bfd_pkt_get_version (const bfd_pkt_t * pkt); void bfd_pkt_set_version (bfd_pkt_t * pkt, int version); diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c index 4ad5660fdf6..ec42cda1bc4 100644 --- a/src/vnet/bfd/bfd_udp.c +++ b/src/vnet/bfd/bfd_udp.c @@ -35,10 +35,20 @@ #include <vnet/dpo/receive_dpo.h> #include <vnet/fib/fib_entry.h> #include <vnet/fib/fib_table.h> +#include <vlib/stats/stats.h> #include <vnet/bfd/bfd_debug.h> #include <vnet/bfd/bfd_udp.h> #include <vnet/bfd/bfd_main.h> #include <vnet/bfd/bfd_api.h> +#include <vnet/bfd/bfd.api_enum.h> + +#define F(sym, str) \ + STATIC_ASSERT ((int) BFD_ERROR_##sym == (int) BFD_UDP_ERROR_##sym, \ + "BFD error enums mismatch"); +foreach_bfd_error (F) +#undef F + STATIC_ASSERT ((int) BFD_N_ERROR <= (int) BFD_UDP_N_ERROR, + "BFD error enum sizes mismatch"); typedef struct { @@ -52,24 +62,14 @@ typedef struct int echo_source_is_set; /* loopback interface used to get echo source ip */ u32 echo_source_sw_if_index; - /* node index of "ip4-arp" node */ - u32 ip4_arp_idx; - /* node index of "ip6-discover-neighbor" node */ - u32 ip6_ndp_idx; - /* node index of "ip4-rewrite" node */ - u32 ip4_rewrite_idx; - /* node index of "ip6-rewrite" node */ - u32 ip6_rewrite_idx; - /* node index of "ip4-midchain" node */ - u32 ip4_midchain_idx; - /* node index of "ip6-midchain" node */ - u32 ip6_midchain_idx; /* log class */ vlib_log_class_t log_class; /* number of active udp4 sessions */ u32 udp4_sessions_count; + u32 udp4_sessions_count_stat_seg_entry; /* number of active udp6 sessions */ u32 udp6_sessions_count; + u32 udp6_sessions_count_stat_seg_entry; } bfd_udp_main_t; static vlib_node_registration_t bfd_udp4_input_node; @@ -79,6 +79,14 @@ static vlib_node_registration_t bfd_udp_echo6_input_node; bfd_udp_main_t bfd_udp_main; +void +bfd_udp_update_stat_segment_entry (u32 entry, u64 value) +{ + vlib_stats_segment_lock (); + vlib_stats_set_gauge (entry, value); + vlib_stats_segment_unlock (); +} + vnet_api_error_t bfd_udp_set_echo_source (u32 sw_if_index) { @@ -94,7 +102,7 @@ bfd_udp_set_echo_source (u32 sw_if_index) } vnet_api_error_t -bfd_udp_del_echo_source (u32 sw_if_index) +bfd_udp_del_echo_source () { bfd_udp_main.echo_source_sw_if_index = ~0; bfd_udp_main.echo_source_is_set = 0; @@ -123,7 +131,6 @@ bfd_udp_is_echo_available (bfd_transport_e transport) { ip4_main_t *im = &ip4_main; ip_interface_address_t *ia = NULL; - /* *INDENT-OFF* */ foreach_ip_interface_address (&im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index, 0 /* honor unnumbered */, ({ @@ -132,13 +139,11 @@ bfd_udp_is_echo_available (bfd_transport_e transport) return 1; } })); - /* *INDENT-ON* */ } else if (BFD_TRANSPORT_UDP6 == transport) { ip6_main_t *im = &ip6_main; ip_interface_address_t *ia = NULL; - /* *INDENT-OFF* */ foreach_ip_interface_address (&im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index, 0 /* honor unnumbered */, ({ @@ -147,7 +152,6 @@ bfd_udp_is_echo_available (bfd_transport_e transport) return 1; } })); - /* *INDENT-ON* */ } } BFD_DBG ("No usable IP address for UDP echo - echo not available"); @@ -179,7 +183,6 @@ bfd_udp_get_echo_src_ip4 (ip4_address_t * addr) ip_interface_address_t *ia = NULL; ip4_main_t *im = &ip4_main; - /* *INDENT-OFF* */ foreach_ip_interface_address ( &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index, 0 /* honor unnumbered */, ({ @@ -197,7 +200,6 @@ bfd_udp_get_echo_src_ip4 (ip4_address_t * addr) return 1; } })); - /* *INDENT-ON* */ BFD_ERR ("cannot find ip4 address, no usable address found"); return 0; } @@ -213,7 +215,6 @@ bfd_udp_get_echo_src_ip6 (ip6_address_t * addr) ip_interface_address_t *ia = NULL; ip6_main_t *im = &ip6_main; - /* *INDENT-OFF* */ foreach_ip_interface_address ( &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index, 0 /* honor unnumbered */, ({ @@ -226,7 +227,6 @@ bfd_udp_get_echo_src_ip6 (ip6_address_t * addr) return 1; } })); - /* *INDENT-ON* */ BFD_ERR ("cannot find ip6 address, no usable address found"); return 0; } @@ -372,13 +372,25 @@ bfd_add_udp6_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs, } static void -bfd_create_frame_to_next_node (vlib_main_t * vm, u32 bi, u32 next_node) +bfd_create_frame_to_next_node (vlib_main_t *vm, vlib_node_runtime_t *rt, + u32 bi, const bfd_session_t *bs, u32 next, + vlib_combined_counter_main_t *tx_counter) { - vlib_frame_t *f = vlib_get_frame_to_node (vm, next_node); + vlib_buffer_t *b = vlib_get_buffer (vm, bi); + vlib_node_t *from_node = vlib_get_node (vm, rt->node_index); + ASSERT (next < vec_len (from_node->next_nodes)); + u32 to_node_index = from_node->next_nodes[next]; + vlib_frame_t *f = vlib_get_frame_to_node (vm, to_node_index); u32 *to_next = vlib_frame_vector_args (f); to_next[0] = bi; f->n_vectors = 1; - vlib_put_frame_to_node (vm, next_node, f); + if (b->flags & VLIB_BUFFER_IS_TRACED) + { + f->frame_flags |= VLIB_NODE_FLAG_TRACE; + } + vlib_put_frame_to_node (vm, to_node_index, f); + vlib_increment_combined_counter (tx_counter, vm->thread_index, bs->bs_idx, 1, + vlib_buffer_length_in_chain (vm, b)); } int @@ -398,10 +410,10 @@ bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) switch (bs->transport) { case BFD_TRANSPORT_UDP4: - *next_node = bfd_udp_main.ip4_arp_idx; + *next_node = BFD_TX_IP4_ARP; return 1; case BFD_TRANSPORT_UDP6: - *next_node = bfd_udp_main.ip6_ndp_idx; + *next_node = BFD_TX_IP6_NDP; return 1; } break; @@ -409,10 +421,10 @@ bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) switch (bs->transport) { case BFD_TRANSPORT_UDP4: - *next_node = bfd_udp_main.ip4_rewrite_idx; + *next_node = BFD_TX_IP4_REWRITE; return 1; case BFD_TRANSPORT_UDP6: - *next_node = bfd_udp_main.ip6_rewrite_idx; + *next_node = BFD_TX_IP6_REWRITE; return 1; } break; @@ -420,10 +432,10 @@ bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) switch (bs->transport) { case BFD_TRANSPORT_UDP4: - *next_node = bfd_udp_main.ip4_midchain_idx; + *next_node = BFD_TX_IP4_MIDCHAIN; return 1; case BFD_TRANSPORT_UDP6: - *next_node = bfd_udp_main.ip6_midchain_idx; + *next_node = BFD_TX_IP6_MIDCHAIN; return 1; } break; @@ -435,27 +447,35 @@ bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) } int -bfd_transport_udp4 (vlib_main_t * vm, u32 bi, const struct bfd_session_s *bs) +bfd_transport_udp4 (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + const struct bfd_session_s *bs, int is_echo) { u32 next_node; int rv = bfd_udp_calc_next_node (bs, &next_node); + bfd_main_t *bm = bfd_udp_main.bfd_main; if (rv) { - bfd_create_frame_to_next_node (vm, bi, next_node); + bfd_create_frame_to_next_node (vm, rt, bi, bs, next_node, + is_echo ? &bm->tx_echo_counter : + &bm->tx_counter); } return rv; } int -bfd_transport_udp6 (vlib_main_t * vm, u32 bi, const struct bfd_session_s *bs) +bfd_transport_udp6 (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + const struct bfd_session_s *bs, int is_echo) { u32 next_node; int rv = bfd_udp_calc_next_node (bs, &next_node); + bfd_main_t *bm = bfd_udp_main.bfd_main; if (rv) { - bfd_create_frame_to_next_node (vm, bi, next_node); + bfd_create_frame_to_next_node (vm, rt, bi, bs, next_node, + is_echo ? &bm->tx_echo_counter : + &bm->tx_counter); } - return 1; + return rv; } static bfd_session_t * @@ -503,6 +523,7 @@ bfd_udp_add_session_internal (vlib_main_t * vm, bfd_udp_main_t * bum, } bfd_udp_session_t *bus = &bs->udp; clib_memset (bus, 0, sizeof (*bus)); + bus->adj_index = ADJ_INDEX_INVALID; bfd_udp_key_t *key = &bus->key; bfd_udp_key_init (key, sw_if_index, local_addr, peer_addr); const bfd_session_t *tmp = bfd_lookup_session (bum, key); @@ -521,15 +542,21 @@ bfd_udp_add_session_internal (vlib_main_t * vm, bfd_udp_main_t * bum, &key->peer_addr, IP46_TYPE_ANY); vlib_log_info (bum->log_class, "create BFD session: %U", format_bfd_session, bs); + const ip46_address_t *peer = + (vnet_sw_interface_is_p2p (vnet_get_main (), key->sw_if_index) ? + &zero_addr : + &key->peer_addr); if (BFD_TRANSPORT_UDP4 == t) { bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, VNET_LINK_IP4, - &key->peer_addr, - key->sw_if_index); + peer, key->sw_if_index); BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, VNET_LINK_IP4, %U, %d) " - "returns %d", format_ip46_address, &key->peer_addr, - IP46_TYPE_ANY, key->sw_if_index, bus->adj_index); + "returns %d", + format_ip46_address, peer, IP46_TYPE_ANY, key->sw_if_index, + bus->adj_index); ++bum->udp4_sessions_count; + bfd_udp_update_stat_segment_entry ( + bum->udp4_sessions_count_stat_seg_entry, bum->udp4_sessions_count); if (1 == bum->udp4_sessions_count) { udp_register_dst_port (vm, UDP_DST_PORT_bfd4, @@ -541,12 +568,14 @@ bfd_udp_add_session_internal (vlib_main_t * vm, bfd_udp_main_t * bum, else { bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, - &key->peer_addr, - key->sw_if_index); + peer, key->sw_if_index); BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, VNET_LINK_IP6, %U, %d) " - "returns %d", format_ip46_address, &key->peer_addr, - IP46_TYPE_ANY, key->sw_if_index, bus->adj_index); + "returns %d", + format_ip46_address, peer, IP46_TYPE_ANY, key->sw_if_index, + bus->adj_index); ++bum->udp6_sessions_count; + bfd_udp_update_stat_segment_entry ( + bum->udp6_sessions_count_stat_seg_entry, bum->udp6_sessions_count); if (1 == bum->udp6_sessions_count) { udp_register_dst_port (vm, UDP_DST_PORT_bfd6, @@ -568,8 +597,6 @@ bfd_udp_validate_api_input (u32 sw_if_index, bfd_udp_main_t *bum = &bfd_udp_main; vnet_sw_interface_t *sw_if = vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index); - u8 local_ip_valid = 0; - ip_interface_address_t *ia = NULL; if (!sw_if) { vlib_log_err (bum->log_class, @@ -585,21 +612,6 @@ bfd_udp_validate_api_input (u32 sw_if_index, "IP family mismatch (local is ipv4, peer is ipv6)"); return VNET_API_ERROR_INVALID_ARGUMENT; } - ip4_main_t *im = &ip4_main; - - /* *INDENT-OFF* */ - foreach_ip_interface_address ( - &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ - ip4_address_t *x = - ip_interface_address_get_address (&im->lookup_main, ia); - if (x->as_u32 == local_addr->ip4.as_u32) - { - /* valid address for this interface */ - local_ip_valid = 1; - break; - } - })); - /* *INDENT-ON* */ } else { @@ -609,44 +621,6 @@ bfd_udp_validate_api_input (u32 sw_if_index, "IP family mismatch (local is ipv6, peer is ipv4)"); return VNET_API_ERROR_INVALID_ARGUMENT; } - - if (ip6_address_is_link_local_unicast (&local_addr->ip6)) - { - const ip6_address_t *ll_addr; - ll_addr = ip6_get_link_local_address (sw_if_index); - if (ip6_address_is_equal (ll_addr, &local_addr->ip6)) - { - /* valid address for this interface */ - local_ip_valid = 1; - } - } - else - { - ip6_main_t *im = &ip6_main; - /* *INDENT-OFF* */ - foreach_ip_interface_address ( - &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ - ip6_address_t *x = - ip_interface_address_get_address (&im->lookup_main, ia); - if (local_addr->ip6.as_u64[0] == x->as_u64[0] && - local_addr->ip6.as_u64[1] == x->as_u64[1]) - { - /* valid address for this interface */ - local_ip_valid = 1; - break; - } - })); - /* *INDENT-ON* */ - } - } - - if (!local_ip_valid) - { - vlib_log_err (bum->log_class, - "local address %U not found on interface with index %u", - format_ip46_address, local_addr, IP46_TYPE_ANY, - sw_if_index); - return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE; } return 0; @@ -685,9 +659,8 @@ bfd_udp_find_session_by_api_input (u32 sw_if_index, static vnet_api_error_t bfd_api_verify_common (u32 sw_if_index, u32 desired_min_tx_usec, - u32 required_min_rx_usec, u8 detect_mult, - const ip46_address_t * local_addr, - const ip46_address_t * peer_addr) + u8 detect_mult, const ip46_address_t *local_addr, + const ip46_address_t *peer_addr) { bfd_udp_main_t *bum = &bfd_udp_main; vnet_api_error_t rv = @@ -714,12 +687,15 @@ bfd_udp_del_session_internal (vlib_main_t * vm, bfd_session_t * bs) { bfd_udp_main_t *bum = &bfd_udp_main; BFD_DBG ("free bfd-udp session, bs_idx=%d", bs->bs_idx); + bfd_session_stop (bum->bfd_main, bs); mhash_unset (&bum->bfd_session_idx_by_bfd_key, &bs->udp.key, NULL); adj_unlock (bs->udp.adj_index); switch (bs->transport) { case BFD_TRANSPORT_UDP4: --bum->udp4_sessions_count; + bfd_udp_update_stat_segment_entry ( + bum->udp4_sessions_count_stat_seg_entry, bum->udp4_sessions_count); if (!bum->udp4_sessions_count) { udp_unregister_dst_port (vm, UDP_DST_PORT_bfd4, 1); @@ -728,6 +704,8 @@ bfd_udp_del_session_internal (vlib_main_t * vm, bfd_session_t * bs) break; case BFD_TRANSPORT_UDP6: --bum->udp6_sessions_count; + bfd_udp_update_stat_segment_entry ( + bum->udp6_sessions_count_stat_seg_entry, bum->udp6_sessions_count); if (!bum->udp6_sessions_count) { udp_unregister_dst_port (vm, UDP_DST_PORT_bfd6, 0); @@ -738,33 +716,26 @@ bfd_udp_del_session_internal (vlib_main_t * vm, bfd_session_t * bs) bfd_put_session (bum->bfd_main, bs); } -vnet_api_error_t -bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, - const ip46_address_t * peer_addr, - u32 desired_min_tx_usec, u32 required_min_rx_usec, - u8 detect_mult, u8 is_authenticated, u32 conf_key_id, - u8 bfd_key_id) +static vnet_api_error_t +bfd_udp_add_and_start_session (u32 sw_if_index, + const ip46_address_t *local_addr, + const ip46_address_t *peer_addr, + u32 desired_min_tx_usec, + u32 required_min_rx_usec, u8 detect_mult, + u8 is_authenticated, u32 conf_key_id, + u8 bfd_key_id) { - bfd_main_t *bm = &bfd_main; - bfd_lock (bm); - - vnet_api_error_t rv = - bfd_api_verify_common (sw_if_index, desired_min_tx_usec, - required_min_rx_usec, detect_mult, - local_addr, peer_addr); bfd_session_t *bs = NULL; - if (!rv) - { - rv = - bfd_udp_add_session_internal (vlib_get_main (), &bfd_udp_main, - sw_if_index, desired_min_tx_usec, - required_min_rx_usec, detect_mult, - local_addr, peer_addr, &bs); - } + vnet_api_error_t rv; + + rv = bfd_udp_add_session_internal ( + vlib_get_main (), &bfd_udp_main, sw_if_index, desired_min_tx_usec, + required_min_rx_usec, detect_mult, local_addr, peer_addr, &bs); + if (!rv && is_authenticated) { rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id, - 0 /* is not delayed */ ); + 0 /* is not delayed */); if (rv) { bfd_udp_del_session_internal (vlib_get_main (), bs); @@ -775,15 +746,67 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, bfd_session_start (bfd_udp_main.bfd_main, bs); } - bfd_unlock (bm); return rv; } vnet_api_error_t -bfd_udp_mod_session (u32 sw_if_index, - const ip46_address_t * local_addr, +bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, const ip46_address_t * peer_addr, - u32 desired_min_tx_usec, + u32 desired_min_tx_usec, u32 required_min_rx_usec, + u8 detect_mult, u8 is_authenticated, u32 conf_key_id, + u8 bfd_key_id) +{ + bfd_main_t *bm = &bfd_main; + bfd_lock (bm); + + vnet_api_error_t rv = bfd_api_verify_common ( + sw_if_index, desired_min_tx_usec, detect_mult, local_addr, peer_addr); + + if (!rv) + rv = bfd_udp_add_and_start_session ( + sw_if_index, local_addr, peer_addr, desired_min_tx_usec, + required_min_rx_usec, detect_mult, is_authenticated, conf_key_id, + bfd_key_id); + + bfd_unlock (bm); + return rv; +} + +vnet_api_error_t +bfd_udp_upd_session (u32 sw_if_index, const ip46_address_t *local_addr, + const ip46_address_t *peer_addr, u32 desired_min_tx_usec, + u32 required_min_rx_usec, u8 detect_mult, + u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id) +{ + bfd_main_t *bm = &bfd_main; + bfd_lock (bm); + + vnet_api_error_t rv = bfd_api_verify_common ( + sw_if_index, desired_min_tx_usec, detect_mult, local_addr, peer_addr); + if (!rv) + { + bfd_session_t *bs = NULL; + + rv = bfd_udp_find_session_by_api_input (sw_if_index, local_addr, + peer_addr, &bs); + if (VNET_API_ERROR_BFD_ENOENT == rv) + rv = bfd_udp_add_and_start_session ( + sw_if_index, local_addr, peer_addr, desired_min_tx_usec, + required_min_rx_usec, detect_mult, is_authenticated, conf_key_id, + bfd_key_id); + else + rv = bfd_session_set_params (bfd_udp_main.bfd_main, bs, + desired_min_tx_usec, required_min_rx_usec, + detect_mult); + } + + bfd_unlock (bm); + return rv; +} + +vnet_api_error_t +bfd_udp_mod_session (u32 sw_if_index, const ip46_address_t *local_addr, + const ip46_address_t *peer_addr, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult) { bfd_session_t *bs = NULL; @@ -903,29 +926,6 @@ typedef enum BFD_UDP_INPUT_N_NEXT, } bfd_udp_input_next_t; -/* Packet counters - BFD control frames */ -#define foreach_bfd_udp_error(F) \ - F (NONE, "good bfd packets (processed)") \ - F (BAD, "invalid bfd packets") - -#define F(sym, string) static char BFD_UDP_ERR_##sym##_STR[] = string; -foreach_bfd_udp_error (F); -#undef F - -static char *bfd_udp_error_strings[] = { -#define F(sym, string) BFD_UDP_ERR_##sym##_STR, - foreach_bfd_udp_error (F) -#undef F -}; - -typedef enum -{ -#define F(sym, str) BFD_UDP_ERROR_##sym, - foreach_bfd_udp_error (F) -#undef F - BFD_UDP_N_ERROR, -} bfd_udp_error_t; - typedef enum { BFD_UDP_ECHO_INPUT_NEXT_NORMAL, @@ -934,28 +934,12 @@ typedef enum BFD_UDP_ECHO_INPUT_N_NEXT, } bfd_udp_echo_input_next_t; -/* Packet counters - BFD ECHO packets */ -#define foreach_bfd_udp_echo_error(F) \ - F (NONE, "good bfd echo packets (processed)") \ - F (BAD, "invalid bfd echo packets") - -#define F(sym, string) static char BFD_UDP_ECHO_ERR_##sym##_STR[] = string; -foreach_bfd_udp_echo_error (F); -#undef F - -static char *bfd_udp_echo_error_strings[] = { -#define F(sym, string) BFD_UDP_ECHO_ERR_##sym##_STR, - foreach_bfd_udp_echo_error (F) -#undef F -}; - -typedef enum +static_always_inline vl_counter_bfd_udp_enum_t +bfd_error_to_udp (bfd_error_t e) { -#define F(sym, str) BFD_UDP_ECHO_ERROR_##sym, - foreach_bfd_udp_echo_error (F) -#undef F - BFD_UDP_ECHO_N_ERROR, -} bfd_udp_echo_error_t; + /* The UDP error is a super set of the proto independent errors */ + return ((vl_counter_bfd_udp_enum_t) e); +} static void bfd_udp4_find_headers (vlib_buffer_t * b, ip4_header_t ** ip4, @@ -963,7 +947,7 @@ bfd_udp4_find_headers (vlib_buffer_t * b, ip4_header_t ** ip4, { /* sanity check first */ const i32 start = vnet_buffer (b)->l3_hdr_offset; - if (start < 0 && start < sizeof (b->pre_data)) + if (start < -(signed) sizeof (b->pre_data)) { BFD_ERR ("Start of ip header is before pre_data, ignoring"); *ip4 = NULL; @@ -981,9 +965,9 @@ bfd_udp4_find_headers (vlib_buffer_t * b, ip4_header_t ** ip4, *udp = (udp_header_t *) ((*ip4) + 1); } -static bfd_udp_error_t -bfd_udp4_verify_transport (const ip4_header_t * ip4, - const udp_header_t * udp, const bfd_session_t * bs) +static vl_counter_bfd_udp_enum_t +bfd_udp4_verify_transport (const ip4_header_t *ip4, const udp_header_t *udp, + const bfd_session_t *bs) { const bfd_udp_session_t *bus = &bs->udp; const bfd_udp_key_t *key = &bus->key; @@ -992,21 +976,21 @@ bfd_udp4_verify_transport (const ip4_header_t * ip4, BFD_ERR ("IPv4 src addr mismatch, got %U, expected %U", format_ip4_address, ip4->src_address.as_u8, format_ip4_address, key->peer_addr.ip4.as_u8); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_SRC_MISMATCH; } if (ip4->dst_address.as_u32 != key->local_addr.ip4.as_u32) { BFD_ERR ("IPv4 dst addr mismatch, got %U, expected %U", format_ip4_address, ip4->dst_address.as_u8, format_ip4_address, key->local_addr.ip4.as_u8); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_DST_MISMATCH; } const u8 expected_ttl = 255; if (ip4->ttl != expected_ttl) { BFD_ERR ("IPv4 unexpected TTL value %u, expected %u", ip4->ttl, expected_ttl); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_TTL; } if (clib_net_to_host_u16 (udp->src_port) < 49152) { @@ -1022,18 +1006,20 @@ typedef struct bfd_pkt_t pkt; } bfd_rpc_update_t; -static void -bfd_rpc_update_session (vlib_main_t * vm, u32 bs_idx, const bfd_pkt_t * pkt) +static bfd_error_t +bfd_rpc_update_session (vlib_main_t *vm, u32 bs_idx, const bfd_pkt_t *pkt) { bfd_main_t *bm = &bfd_main; + bfd_error_t err; bfd_lock (bm); - bfd_consume_pkt (vm, bm, pkt, bs_idx); + err = bfd_consume_pkt (vm, bm, pkt, bs_idx); bfd_unlock (bm); + + return err; } -static bfd_udp_error_t -bfd_udp4_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_buffer_t * b, bfd_session_t ** bs_out) +static vl_counter_bfd_udp_enum_t +bfd_udp4_scan (vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t **bs_out) { const bfd_pkt_t *pkt = vlib_buffer_get_current (b); if (sizeof (*pkt) > b->current_length) @@ -1057,11 +1043,13 @@ bfd_udp4_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, BFD_ERR ("BFD packet length is larger than udp payload length (%u > %u)", pkt->head.length, udp_payload_length); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_LENGTH; } - if (!bfd_verify_pkt_common (pkt)) + vl_counter_bfd_udp_enum_t err; + if (BFD_UDP_ERROR_NONE != + (err = bfd_error_to_udp (bfd_verify_pkt_common (pkt)))) { - return BFD_UDP_ERROR_BAD; + return err; } bfd_session_t *bs = NULL; if (pkt->your_disc) @@ -1086,22 +1074,21 @@ bfd_udp4_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, if (!bs) { BFD_ERR ("BFD session lookup failed - no session matches BFD pkt"); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_NO_SESSION; } BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx); if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs)) { BFD_ERR ("Packet verification failed, dropping packet"); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_FAILED_VERIFICATION; } - bfd_udp_error_t err; if (BFD_UDP_ERROR_NONE != (err = bfd_udp4_verify_transport (ip4, udp, bs))) { return err; } - bfd_rpc_update_session (vm, bs->bs_idx, pkt); + err = bfd_error_to_udp (bfd_rpc_update_session (vm, bs->bs_idx, pkt)); *bs_out = bs; - return BFD_UDP_ERROR_NONE; + return err; } static void @@ -1110,7 +1097,7 @@ bfd_udp6_find_headers (vlib_buffer_t * b, ip6_header_t ** ip6, { /* sanity check first */ const i32 start = vnet_buffer (b)->l3_hdr_offset; - if (start < 0 && start < sizeof (b->pre_data)) + if (start < -(signed) sizeof (b->pre_data)) { BFD_ERR ("Start of ip header is before pre_data, ignoring"); *ip6 = NULL; @@ -1136,9 +1123,9 @@ bfd_udp6_find_headers (vlib_buffer_t * b, ip6_header_t ** ip6, *udp = (udp_header_t *) ((*ip6) + 1); } -static bfd_udp_error_t -bfd_udp6_verify_transport (const ip6_header_t * ip6, - const udp_header_t * udp, const bfd_session_t * bs) +static vl_counter_bfd_udp_enum_t +bfd_udp6_verify_transport (const ip6_header_t *ip6, const udp_header_t *udp, + const bfd_session_t *bs) { const bfd_udp_session_t *bus = &bs->udp; const bfd_udp_key_t *key = &bus->key; @@ -1148,7 +1135,7 @@ bfd_udp6_verify_transport (const ip6_header_t * ip6, BFD_ERR ("IP src addr mismatch, got %U, expected %U", format_ip6_address, ip6, format_ip6_address, &key->peer_addr.ip6); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_SRC_MISMATCH; } if (ip6->dst_address.as_u64[0] != key->local_addr.ip6.as_u64[0] && ip6->dst_address.as_u64[1] != key->local_addr.ip6.as_u64[1]) @@ -1156,14 +1143,14 @@ bfd_udp6_verify_transport (const ip6_header_t * ip6, BFD_ERR ("IP dst addr mismatch, got %U, expected %U", format_ip6_address, ip6, format_ip6_address, &key->local_addr.ip6); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_DST_MISMATCH; } const u8 expected_hop_limit = 255; if (ip6->hop_limit != expected_hop_limit) { BFD_ERR ("IPv6 unexpected hop-limit value %u, expected %u", ip6->hop_limit, expected_hop_limit); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_TTL; } if (clib_net_to_host_u16 (udp->src_port) < 49152) { @@ -1173,9 +1160,8 @@ bfd_udp6_verify_transport (const ip6_header_t * ip6, return BFD_UDP_ERROR_NONE; } -static bfd_udp_error_t -bfd_udp6_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_buffer_t * b, bfd_session_t ** bs_out) +static vl_counter_bfd_udp_enum_t +bfd_udp6_scan (vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t **bs_out) { const bfd_pkt_t *pkt = vlib_buffer_get_current (b); if (sizeof (*pkt) > b->current_length) @@ -1201,9 +1187,11 @@ bfd_udp6_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, pkt->head.length, udp_payload_length); return BFD_UDP_ERROR_BAD; } - if (!bfd_verify_pkt_common (pkt)) + vl_counter_bfd_udp_enum_t err; + if (BFD_UDP_ERROR_NONE != + (err = bfd_error_to_udp (bfd_verify_pkt_common (pkt)))) { - return BFD_UDP_ERROR_BAD; + return err; } bfd_session_t *bs = NULL; if (pkt->your_disc) @@ -1230,22 +1218,21 @@ bfd_udp6_scan (vlib_main_t * vm, vlib_node_runtime_t * rt, if (!bs) { BFD_ERR ("BFD session lookup failed - no session matches BFD pkt"); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_NO_SESSION; } BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx); if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs)) { BFD_ERR ("Packet verification failed, dropping packet"); - return BFD_UDP_ERROR_BAD; + return BFD_UDP_ERROR_FAILED_VERIFICATION; } - bfd_udp_error_t err; if (BFD_UDP_ERROR_NONE != (err = bfd_udp6_verify_transport (ip6, udp, bs))) { return err; } - bfd_rpc_update_session (vm, bs->bs_idx, pkt); + err = bfd_error_to_udp (bfd_rpc_update_session (vm, bs->bs_idx, pkt)); *bs_out = bs; - return BFD_UDP_ERROR_NONE; + return err; } /* @@ -1277,7 +1264,7 @@ bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt, /* If this pkt is traced, snapshot the data */ if (b0->flags & VLIB_BUFFER_IS_TRACED) { - int len; + u64 len; t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0)); len = (b0->current_length < sizeof (t0->data)) ? b0->current_length : sizeof (t0->data); @@ -1289,17 +1276,20 @@ bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_lock (bm); if (is_ipv6) { - error0 = bfd_udp6_scan (vm, rt, b0, &bs); + error0 = bfd_udp6_scan (vm, b0, &bs); } else { - error0 = bfd_udp4_scan (vm, rt, b0, &bs); + error0 = bfd_udp4_scan (vm, b0, &bs); } b0->error = rt->errors[error0]; next0 = BFD_UDP_INPUT_NEXT_NORMAL; if (BFD_UDP_ERROR_NONE == error0) { + vlib_increment_combined_counter ( + &bm->rx_counter, vm->thread_index, bs->bs_idx, 1, + vlib_buffer_length_in_chain (vm, b0)); /* * if everything went fine, check for poll bit, if present, re-use * the buffer and based on (now updated) session parameters, send @@ -1310,17 +1300,16 @@ bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt, { b0->current_data = 0; b0->current_length = 0; - bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main, bs, - 0); + bfd_init_final_control_frame (vm, b0, bs); if (is_ipv6) { vlib_node_increment_counter (vm, bfd_udp6_input_node.index, - b0->error, 1); + error0, 1); } else { vlib_node_increment_counter (vm, bfd_udp4_input_node.index, - b0->error, 1); + error0, 1); } const bfd_udp_session_t *bus = &bs->udp; ip_adjacency_t *adj = adj_get (bus->adj_index); @@ -1360,7 +1349,6 @@ bfd_udp4_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) /* * bfd input graph node declaration */ -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = { .function = bfd_udp4_input, .name = "bfd-udp4-input", @@ -1368,7 +1356,7 @@ VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = { .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = BFD_UDP_N_ERROR, - .error_strings = bfd_udp_error_strings, + .error_counters = bfd_udp_error_counters, .format_trace = bfd_input_format_trace, @@ -1381,7 +1369,6 @@ VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = { [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip4-midchain", }, }; -/* *INDENT-ON* */ static uword bfd_udp6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) @@ -1389,7 +1376,6 @@ bfd_udp6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) return bfd_udp_input (vm, rt, f, 1); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = { .function = bfd_udp6_input, .name = "bfd-udp6-input", @@ -1397,7 +1383,7 @@ VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = { .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = BFD_UDP_N_ERROR, - .error_strings = bfd_udp_error_strings, + .error_counters = bfd_udp_error_counters, .format_trace = bfd_input_format_trace, @@ -1410,7 +1396,6 @@ VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = { [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip6-midchain", }, }; -/* *INDENT-ON* */ /* * Process a frame of bfd echo packets @@ -1439,7 +1424,7 @@ bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt, /* If this pkt is traced, snapshot the data */ if (b0->flags & VLIB_BUFFER_IS_TRACED) { - int len; + u64 len; t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0)); len = (b0->current_length < sizeof (t0->data)) ? b0->current_length : sizeof (t0->data); @@ -1447,8 +1432,9 @@ bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt, clib_memcpy_fast (t0->data, vlib_buffer_get_current (b0), len); } + bfd_session_t *bs = NULL; bfd_lock (bm); - if (bfd_consume_echo_pkt (vm, bfd_udp_main.bfd_main, b0)) + if ((bs = bfd_consume_echo_pkt (vm, bfd_udp_main.bfd_main, b0))) { b0->error = rt->errors[BFD_UDP_ERROR_NONE]; next0 = BFD_UDP_ECHO_INPUT_NEXT_NORMAL; @@ -1460,17 +1446,25 @@ bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt, if (is_ipv6) { vlib_node_increment_counter (vm, bfd_udp_echo6_input_node.index, - b0->error, 1); + BFD_UDP_ERROR_NONE, 1); } else { vlib_node_increment_counter (vm, bfd_udp_echo4_input_node.index, - b0->error, 1); + BFD_UDP_ERROR_NONE, 1); } next0 = BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE; } bfd_unlock (bm); + + if (bs) + { + vlib_increment_combined_counter ( + &bm->rx_echo_counter, vm->thread_index, bs->bs_idx, 1, + vlib_buffer_length_in_chain (vm, b0)); + } + vlib_set_next_frame_buffer (vm, rt, next0, bi0); from += 1; @@ -1506,15 +1500,14 @@ bfd_echo_input_format_trace (u8 * s, va_list * args) /* * bfd input graph node declaration */ -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (bfd_udp_echo4_input_node, static) = { .function = bfd_udp_echo4_input, .name = "bfd-udp-echo4-input", .vector_size = sizeof (u32), .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = BFD_UDP_ECHO_N_ERROR, - .error_strings = bfd_udp_error_strings, + .n_errors = BFD_UDP_N_ERROR, + .error_counters = bfd_udp_error_counters, .format_trace = bfd_echo_input_format_trace, @@ -1526,7 +1519,6 @@ VLIB_REGISTER_NODE (bfd_udp_echo4_input_node, static) = { [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup", }, }; -/* *INDENT-ON* */ static uword bfd_udp_echo6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, @@ -1535,15 +1527,14 @@ bfd_udp_echo6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, return bfd_udp_echo_input (vm, rt, f, 1); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (bfd_udp_echo6_input_node, static) = { .function = bfd_udp_echo6_input, .name = "bfd-udp-echo6-input", .vector_size = sizeof (u32), .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = BFD_UDP_ECHO_N_ERROR, - .error_strings = bfd_udp_echo_error_strings, + .n_errors = BFD_UDP_N_ERROR, + .error_counters = bfd_udp_error_counters, .format_trace = bfd_echo_input_format_trace, @@ -1556,46 +1547,73 @@ VLIB_REGISTER_NODE (bfd_udp_echo6_input_node, static) = { }, }; -/* *INDENT-ON* */ static clib_error_t * -bfd_udp_sw_if_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_create) +bfd_udp_sw_if_add_del (CLIB_UNUSED (vnet_main_t *vnm), u32 sw_if_index, + u32 is_create) { - bfd_session_t **to_be_freed = NULL; + u32 *to_be_freed = NULL; bfd_udp_main_t *bum = &bfd_udp_main; BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index, is_create); if (!is_create) { bfd_session_t *bs; - pool_foreach (bs, bfd_udp_main.bfd_main->sessions) - { - if (bs->transport != BFD_TRANSPORT_UDP4 && - bs->transport != BFD_TRANSPORT_UDP6) - { - continue; - } - if (bs->udp.key.sw_if_index != sw_if_index) - { - continue; - } - vec_add1 (to_be_freed, bs); - } - } - bfd_session_t **bs; - vec_foreach (bs, to_be_freed) - { - vlib_log_notice (bum->log_class, - "removal of sw_if_index=%u forces removal of bfd session " - "with bs_idx=%u", sw_if_index, (*bs)->bs_idx); - bfd_session_set_flags (vlib_get_main (), *bs, 0); - bfd_udp_del_session_internal (vlib_get_main (), *bs); - } + pool_foreach (bs, bum->bfd_main->sessions) + { + if (bs->transport != BFD_TRANSPORT_UDP4 && + bs->transport != BFD_TRANSPORT_UDP6) + { + continue; + } + if (bs->udp.key.sw_if_index != sw_if_index) + { + continue; + } + vec_add1 (to_be_freed, bs->bs_idx); + } + } + u32 *bs_idx; + vec_foreach (bs_idx, to_be_freed) + { + bfd_session_t *bs = pool_elt_at_index (bum->bfd_main->sessions, *bs_idx); + vlib_log_notice (bum->log_class, + "removal of sw_if_index=%u forces removal of bfd " + "session with bs_idx=%u", + sw_if_index, bs->bs_idx); + bfd_session_set_flags (vlib_get_main (), bs, 0); + bfd_udp_del_session_internal (vlib_get_main (), bs); + } return 0; } VNET_SW_INTERFACE_ADD_DEL_FUNCTION (bfd_udp_sw_if_add_del); +clib_error_t * +bfd_udp_stats_init (bfd_udp_main_t *bum) +{ + const char *name4 = "/bfd/udp4/sessions"; + bum->udp4_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name4); + + vlib_stats_set_gauge (bum->udp4_sessions_count_stat_seg_entry, 0); + if (~0 == bum->udp4_sessions_count_stat_seg_entry) + { + return clib_error_return ( + 0, "Could not create stat segment entry for %s", name4); + } + const char *name6 = "/bfd/udp6/sessions"; + bum->udp6_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name6); + + vlib_stats_set_gauge (bum->udp6_sessions_count_stat_seg_entry, 0); + if (~0 == bum->udp6_sessions_count_stat_seg_entry) + { + return clib_error_return ( + 0, "Could not create stat segment entry for %s", name6); + } + + return 0; +} + /* * setup function */ @@ -1608,24 +1626,7 @@ bfd_udp_init (vlib_main_t * vm) sizeof (bfd_udp_key_t)); bfd_udp_main.bfd_main = &bfd_main; bfd_udp_main.vnet_main = vnet_get_main (); - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp"); - ASSERT (node); - bfd_udp_main.ip4_arp_idx = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip6-discover-neighbor"); - ASSERT (node); - bfd_udp_main.ip6_ndp_idx = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip4-rewrite"); - ASSERT (node); - bfd_udp_main.ip4_rewrite_idx = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite"); - ASSERT (node); - bfd_udp_main.ip6_rewrite_idx = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip4-midchain"); - ASSERT (node); - bfd_udp_main.ip4_midchain_idx = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip6-midchain"); - ASSERT (node); - bfd_udp_main.ip6_midchain_idx = node->index; + bfd_udp_stats_init (&bfd_udp_main); bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp"); vlib_log_debug (bfd_udp_main.log_class, "initialized"); diff --git a/src/vnet/bfd/bfd_udp.h b/src/vnet/bfd/bfd_udp.h index 87868104f98..8f4bfee2bd7 100644 --- a/src/vnet/bfd/bfd_udp.h +++ b/src/vnet/bfd/bfd_udp.h @@ -24,7 +24,6 @@ #include <vnet/ip/ip6_packet.h> #include <vnet/bfd/bfd_api.h> -/* *INDENT-OFF* */ /** identifier of BFD session based on UDP transport only */ typedef CLIB_PACKED (struct { union { @@ -38,7 +37,6 @@ typedef CLIB_PACKED (struct { /** peer address */ ip46_address_t peer_addr; }) bfd_udp_key_t; -/* *INDENT-ON* */ /** UDP transport specific data embedded in bfd_session's union */ typedef struct @@ -82,22 +80,18 @@ int bfd_add_udp6_transport (vlib_main_t * vm, u32 bi, /** * @brief transport packet over udpv4 * - * @param is_echo 1 if this is echo packet, 0 if control frame - * * @return 1 on success, 0 on failure */ -int bfd_transport_udp4 (vlib_main_t * vm, u32 bi, - const struct bfd_session_s *bs); +int bfd_transport_udp4 (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + const struct bfd_session_s *bs, int is_echo); /** * @brief transport packet over udpv6 * - * @param is_echo 1 if this is echo packet, 0 if control frame - * * @return 1 on success, 0 on failure */ -int bfd_transport_udp6 (vlib_main_t * vm, u32 bi, - const struct bfd_session_s *bs); +int bfd_transport_udp6 (vlib_main_t *vm, vlib_node_runtime_t *rt, u32 bi, + const struct bfd_session_s *bs, int is_echo); /** * @brief check if the bfd udp layer is echo-capable at this time |