diff options
Diffstat (limited to 'src/vnet/bfd/bfd_main.c')
-rw-r--r-- | src/vnet/bfd/bfd_main.c | 387 |
1 files changed, 243 insertions, 144 deletions
diff --git a/src/vnet/bfd/bfd_main.c b/src/vnet/bfd/bfd_main.c index c67317f5789..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_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) +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) @@ -1847,10 +1939,12 @@ bfd_consume_pkt (vlib_main_t * vm, bfd_main_t * bm, const bfd_pkt_t * pkt, bfd_set_poll_state (bs, BFD_POLL_NOT_NEEDED); if (BFD_STATE_up == bs->local_state) { - 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_desired_min_tx ( + bm, bs, now, bs->config_desired_min_tx_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) @@ -1875,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) { @@ -1912,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)) @@ -1935,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) @@ -1947,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 * @@ -2020,22 +2115,27 @@ bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id, bfd_auth_key_t *key = pool_elt_at_index (bm->auth_keys, key_idx); if (is_delayed) { - if (bs->auth.next_key == key) + if (bs->auth.next_key == key && bs->auth.next_bfd_key_id == bfd_key_id) { /* already using this key, no changes required */ return 0; } - bs->auth.next_key = key; + if (bs->auth.next_key != key) + { + ++key->use_count; + bs->auth.next_key = key; + } bs->auth.next_bfd_key_id = bfd_key_id; bs->auth.is_delayed = 1; } else { - if (bs->auth.curr_key == key) + if (bs->auth.curr_key == key && bs->auth.curr_bfd_key_id == bfd_key_id) { /* already using this key, no changes required */ return 0; } + ++key->use_count; if (bs->auth.curr_key) { --bs->auth.curr_key->use_count; @@ -2044,7 +2144,6 @@ bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id, bs->auth.curr_bfd_key_id = bfd_key_id; bs->auth.is_delayed = 0; } - ++key->use_count; BFD_DBG ("\nSession auth modified: %U", format_bfd_session, bs); vlib_log_info (bm->log_class, "session auth modified: %U", format_bfd_session_brief, bs); |