diff options
author | Klement Sekera <ksekera@cisco.com> | 2017-02-02 06:58:07 +0100 |
---|---|---|
committer | Klement Sekera <ksekera@cisco.com> | 2017-02-08 07:47:00 +0100 |
commit | a57a970952be2c3403c57dd7a16cd3d73660ef79 (patch) | |
tree | 89c0aab21b2c5f15d3b3cd355fb54c2c7ae7c66d /src/vnet/bfd | |
parent | 8ea6d7153b053f1b9bf837ef3a927136f44b41fd (diff) |
BFD: modify session parameters
Change-Id: I666e5c0cc71a3693640960c93cdd1907f84fbe23
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Diffstat (limited to 'src/vnet/bfd')
-rw-r--r-- | src/vnet/bfd/bfd.api | 40 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_api.c | 24 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_api.h | 14 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_debug.h | 7 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_main.c | 296 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_main.h | 57 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_protocol.c | 26 | ||||
-rw-r--r-- | src/vnet/bfd/bfd_udp.c | 61 |
8 files changed, 412 insertions, 113 deletions
diff --git a/src/vnet/bfd/bfd.api b/src/vnet/bfd/bfd.api index 17ca35b6004..f307ed2a193 100644 --- a/src/vnet/bfd/bfd.api +++ b/src/vnet/bfd/bfd.api @@ -107,6 +107,40 @@ define bfd_udp_add_reply i32 retval; }; +/** \brief Modify UDP BFD session on interface + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - sw index of the interface + @param desired_min_tx - desired min transmit interval (microseconds) + @param required_min_rx - required min receive interval (microseconds) + @param local_addr - local address + @param peer_addr - peer address + @param is_ipv6 - local_addr, peer_addr are IPv6 if non-zero, otherwise IPv4 + @param detect_mult - detect multiplier (# of packets missed before connection goes down) +*/ +define bfd_udp_mod +{ + u32 client_index; + u32 context; + u32 sw_if_index; + u32 desired_min_tx; + u32 required_min_rx; + u8 local_addr[16]; + u8 peer_addr[16]; + u8 is_ipv6; + u8 detect_mult; +}; + +/** \brief Modify UDP BFD session response + @param context - sender context, to match reply w/ request + @param retval - return code for the request +*/ +define bfd_udp_mod_reply +{ + u32 context; + i32 retval; +}; + /** \brief Delete UDP BFD session on interface @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -155,6 +189,9 @@ define bfd_udp_session_dump @param is_authenticated - non-zero if authentication in-use, zero otherwise @param bfd_key_id - ID of key currently in-use if auth is on @param conf_key_id - configured key ID for this session + @param required_min_rx - required min receive interval (microseconds) + @param desired_min_tx - desired min transmit interval (microseconds) + @param detect_mult - detect multiplier (# of packets missed before connection goes down) */ define bfd_udp_session_details { @@ -167,6 +204,9 @@ define bfd_udp_session_details u8 is_authenticated; u8 bfd_key_id; u32 conf_key_id; + u32 required_min_rx; + u32 desired_min_tx; + u8 detect_mult; }; /** \brief Set flags of BFD UDP session diff --git a/src/vnet/bfd/bfd_api.c b/src/vnet/bfd/bfd_api.c index cfc3a38d575..af70f0ec2d5 100644 --- a/src/vnet/bfd/bfd_api.c +++ b/src/vnet/bfd/bfd_api.c @@ -45,6 +45,7 @@ #define foreach_vpe_api_msg \ _ (BFD_UDP_ADD, bfd_udp_add) \ + _ (BFD_UDP_MOD, bfd_udp_mod) \ _ (BFD_UDP_DEL, bfd_udp_del) \ _ (BFD_UDP_SESSION_DUMP, bfd_udp_session_dump) \ _ (BFD_UDP_SESSION_SET_FLAGS, bfd_udp_session_set_flags) \ @@ -98,6 +99,25 @@ vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp) } static void +vl_api_bfd_udp_mod_t_handler (vl_api_bfd_udp_mod_t * mp) +{ + vl_api_bfd_udp_mod_reply_t *rmp; + int rv; + + VALIDATE_SW_IF_INDEX (mp); + + BFD_UDP_API_PARAM_COMMON_CODE; + + rv = bfd_udp_mod_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); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_BFD_UDP_MOD_REPLY); +} + +static void vl_api_bfd_udp_del_t_handler (vl_api_bfd_udp_del_t * mp) { vl_api_bfd_udp_del_reply_t *rmp; @@ -146,6 +166,10 @@ send_bfd_udp_session_details (unix_shared_memory_queue_t * q, u32 context, sizeof (key->peer_addr.ip4.data)); } + mp->required_min_rx = + clib_host_to_net_u32 (bs->config_required_min_rx_usec); + mp->desired_min_tx = clib_host_to_net_u32 (bs->config_desired_min_tx_usec); + mp->detect_mult = bs->local_detect_mult; vl_msg_api_send_shmem (q, (u8 *) & mp); } diff --git a/src/vnet/bfd/bfd_api.h b/src/vnet/bfd/bfd_api.h index 128a3dc42bf..f4486a79196 100644 --- a/src/vnet/bfd/bfd_api.h +++ b/src/vnet/bfd/bfd_api.h @@ -26,9 +26,17 @@ 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_us, - u32 required_min_rx_us, u8 detect_mult, - u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id); + 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); + +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); vnet_api_error_t bfd_udp_del_session (u32 sw_if_index, const ip46_address_t * local_addr, diff --git a/src/vnet/bfd/bfd_debug.h b/src/vnet/bfd/bfd_debug.h index 707ebab2ddd..a06e934f560 100644 --- a/src/vnet/bfd/bfd_debug.h +++ b/src/vnet/bfd/bfd_debug.h @@ -63,6 +63,13 @@ } \ while (0); +#define BFD_CLK_FMT "%luus/%lu clocks/%.2fs" +#define BFD_CLK_PRN(clocks) \ + (u64) ((((f64)clocks) / vlib_get_main ()->clib_time.clocks_per_second) * \ + USEC_PER_SECOND), \ + (clocks), \ + (((f64)clocks) / vlib_get_main ()->clib_time.clocks_per_second) + #else #define BFD_DBG(...) #define BFD_ERR(...) diff --git a/src/vnet/bfd/bfd_main.c b/src/vnet/bfd/bfd_main.c index 8f2fae2b795..798d0631dd7 100644 --- a/src/vnet/bfd/bfd_main.c +++ b/src/vnet/bfd/bfd_main.c @@ -30,11 +30,16 @@ #endif static u64 -bfd_us_to_clocks (bfd_main_t * bm, u64 us) +bfd_usec_to_clocks (const bfd_main_t * bm, u64 us) { return bm->cpu_cps * ((f64) us / USEC_PER_SECOND); } +// static u64 bfd_clocks_to_usec (const bfd_main_t *bm, u64 clocks) +//{ +// return (clocks / bm->cpu_cps) * USEC_PER_SECOND; +//} + static vlib_node_registration_t bfd_process_node; /* set to 0 here, real values filled at startup */ @@ -83,9 +88,11 @@ bfd_set_defaults (bfd_main_t * bm, bfd_session_t * bs) bs->remote_state = BFD_STATE_down; bs->local_demand = 0; bs->remote_discr = 0; - bs->desired_min_tx_us = BFD_DEFAULT_DESIRED_MIN_TX_US; - bs->desired_min_tx_clocks = bfd_us_to_clocks (bm, bs->desired_min_tx_us); - bs->remote_min_rx_us = 1; + bs->config_desired_min_tx_usec = BFD_DEFAULT_DESIRED_MIN_TX_US; + bs->config_desired_min_tx_clocks = bm->default_desired_min_tx_clocks; + bs->effective_desired_min_tx_clocks = bm->default_desired_min_tx_clocks; + bs->remote_min_rx_usec = 1; + bs->remote_min_rx_clocks = bfd_usec_to_clocks (bm, bs->remote_min_rx_usec); bs->remote_demand = 0; bs->auth.remote_seq_number = 0; bs->auth.remote_seq_number_known = 0; @@ -123,7 +130,8 @@ bfd_recalc_tx_interval (bfd_main_t * bm, bfd_session_t * bs) if (!bs->local_demand) { bs->transmit_interval_clocks = - clib_max (bs->desired_min_tx_clocks, bs->remote_min_rx_clocks); + clib_max (bs->effective_desired_min_tx_clocks, + bs->remote_min_rx_clocks); } else { @@ -193,18 +201,18 @@ bfd_recalc_detection_time (bfd_main_t * bm, bfd_session_t * bs) { if (!bs->local_demand) { + /* asynchronous mode */ bs->detection_time_clocks = bs->remote_detect_mult * - bfd_us_to_clocks (bm, clib_max (bs->required_min_rx_us, - bs->remote_desired_min_tx_us)); + clib_max (bs->effective_required_min_rx_clocks, + bs->remote_desired_min_tx_clocks); } else { + /* demand mode */ bs->detection_time_clocks = - bs->local_detect_mult * - bfd_us_to_clocks (bm, - clib_max (bs->desired_min_tx_us, - bs->remote_min_rx_us)); + bs->local_detect_mult * clib_max (bs->config_desired_min_tx_clocks, + bs->remote_min_rx_clocks); } BFD_DBG ("Recalculated detection time %lu clocks/%.2fs", bs->detection_time_clocks, @@ -259,14 +267,14 @@ bfd_set_timer (bfd_main_t * bm, bfd_session_t * bs, u64 now, } static void -bfd_set_desired_min_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now, - u32 desired_min_tx_us, int handling_wakeup) +bfd_set_effective_desired_min_tx (bfd_main_t * bm, + bfd_session_t * bs, u64 now, + u64 desired_min_tx_clocks, + int handling_wakeup) { - bs->desired_min_tx_us = desired_min_tx_us; - bs->desired_min_tx_clocks = bfd_us_to_clocks (bm, bs->desired_min_tx_us); - BFD_DBG ("Set desired min tx to %uus/%lu clocks/%.2fs", - bs->desired_min_tx_us, bs->desired_min_tx_clocks, - bs->desired_min_tx_clocks / bm->cpu_cps); + bs->effective_desired_min_tx_clocks = desired_min_tx_clocks; + BFD_DBG ("Set effective desired min tx to " BFD_CLK_FMT, + BFD_CLK_PRN (bs->effective_desired_min_tx_clocks)); bfd_recalc_detection_time (bm, bs); bfd_recalc_tx_interval (bm, bs); bfd_calc_next_tx (bm, bs, now); @@ -274,15 +282,29 @@ bfd_set_desired_min_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now, } static void +bfd_set_effective_required_min_rx (bfd_main_t * bm, + bfd_session_t * bs, u64 now, + u64 required_min_rx_clocks, + int handling_wakeup) +{ + bs->effective_required_min_rx_clocks = required_min_rx_clocks; + BFD_DBG ("Set effective required min rx to " BFD_CLK_FMT, + BFD_CLK_PRN (bs->effective_required_min_rx_clocks)); + bfd_recalc_detection_time (bm, bs); + bfd_set_timer (bm, bs, now, handling_wakeup); +} + +static void bfd_set_remote_required_min_rx (bfd_main_t * bm, bfd_session_t * bs, u64 now, - u32 remote_required_min_rx_us, + u32 remote_required_min_rx_usec, int handling_wakeup) { - bs->remote_min_rx_us = remote_required_min_rx_us; - bs->remote_min_rx_clocks = bfd_us_to_clocks (bm, bs->remote_min_rx_us); - BFD_DBG ("Set remote min rx to %uus/%lu clocks/%.2fs", bs->remote_min_rx_us, - bs->remote_min_rx_clocks, bs->remote_min_rx_clocks / bm->cpu_cps); + bs->remote_min_rx_usec = remote_required_min_rx_usec; + bs->remote_min_rx_clocks = + bfd_usec_to_clocks (bm, remote_required_min_rx_usec); + BFD_DBG ("Set remote min rx to " BFD_CLK_FMT, + BFD_CLK_PRN (bs->remote_min_rx_clocks)); bfd_recalc_detection_time (bm, bs); bfd_recalc_tx_interval (bm, bs); bfd_calc_next_tx (bm, bs, now); @@ -316,32 +338,6 @@ bfd_del_session (uword bs_idx) return 0; } -const char * -bfd_diag_code_string (bfd_diag_code_e diag) -{ -#define F(n, t, s) \ - case BFD_DIAG_CODE_NAME (t): \ - return s; - switch (diag) - { - foreach_bfd_diag_code (F)} - return "UNKNOWN"; -#undef F -} - -const char * -bfd_state_string (bfd_state_e state) -{ -#define F(n, t, s) \ - case BFD_STATE_NAME (t): \ - return s; - switch (state) - { - foreach_bfd_state (F)} - return "UNKNOWN"; -#undef F -} - void bfd_session_set_flags (bfd_session_t * bs, u8 admin_up_down) { @@ -404,31 +400,63 @@ bfd_on_state_change (bfd_main_t * bm, bfd_session_t * bs, u64 now, switch (bs->local_state) { case BFD_STATE_admin_down: - bfd_set_desired_min_tx (bm, bs, now, - clib_max (bs->config_desired_min_tx_us, - BFD_DEFAULT_DESIRED_MIN_TX_US), - handling_wakeup); + bfd_set_effective_required_min_rx (bm, bs, now, + bs->config_required_min_rx_clocks, + handling_wakeup); + bfd_set_effective_desired_min_tx (bm, bs, now, + clib_max + (bs->config_desired_min_tx_clocks, + bm->default_desired_min_tx_clocks), + handling_wakeup); break; case BFD_STATE_down: - bfd_set_desired_min_tx (bm, bs, now, - clib_max (bs->config_desired_min_tx_us, - BFD_DEFAULT_DESIRED_MIN_TX_US), - handling_wakeup); + bfd_set_effective_required_min_rx (bm, bs, now, + bs->config_required_min_rx_clocks, + handling_wakeup); + bfd_set_effective_desired_min_tx (bm, bs, now, + clib_max + (bs->config_desired_min_tx_clocks, + bm->default_desired_min_tx_clocks), + handling_wakeup); break; case BFD_STATE_init: - bfd_set_desired_min_tx (bm, bs, now, - clib_max (bs->config_desired_min_tx_us, - BFD_DEFAULT_DESIRED_MIN_TX_US), - handling_wakeup); + bfd_set_effective_desired_min_tx (bm, bs, now, + clib_max + (bs->config_desired_min_tx_clocks, + bm->default_desired_min_tx_clocks), + handling_wakeup); break; case BFD_STATE_up: - bfd_set_desired_min_tx (bm, bs, now, bs->config_desired_min_tx_us, - handling_wakeup); + if (POLL_NOT_NEEDED == bs->poll_state) + { + bfd_set_effective_required_min_rx (bm, bs, now, + bs->config_required_min_rx_clocks, + handling_wakeup); + } + bfd_set_effective_desired_min_tx (bm, bs, now, + bs->config_desired_min_tx_clocks, + handling_wakeup); break; } } 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) +{ + if (bs->remote_demand) + { + /* TODO - initiate poll sequence here */ + } + else + { + /* asynchronous - poll is part of periodic - nothing to do here */ + } + bfd_recalc_detection_time (bm, bs); + bfd_set_timer (bm, bs, now, 0); +} + +static void bfd_add_transport_layer (vlib_main_t * vm, vlib_buffer_t * b, bfd_session_t * bs) { @@ -557,11 +585,10 @@ bfd_init_control_frame (vlib_buffer_t * b, bfd_session_t * bs) pkt->head.length = clib_host_to_net_u32 (bfd_length); pkt->my_disc = bs->local_discr; pkt->your_disc = bs->remote_discr; - pkt->des_min_tx = clib_host_to_net_u32 (bs->desired_min_tx_us); - pkt->req_min_rx = clib_host_to_net_u32 (bs->required_min_rx_us); - pkt->req_min_echo_rx = clib_host_to_net_u32 (bs->required_min_echo_rx_us); + pkt->des_min_tx = clib_host_to_net_u32 (bs->config_desired_min_tx_usec); + pkt->req_min_rx = clib_host_to_net_u32 (bs->config_required_min_rx_usec); + pkt->req_min_echo_rx = clib_host_to_net_u32 (1); b->current_length = bfd_length; - bfd_add_auth_section (b, bs); } static void @@ -569,7 +596,7 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm, bfd_session_t * bs, u64 now, int handling_wakeup) { - if (!bs->remote_min_rx_us) + if (!bs->remote_min_rx_usec) { BFD_DBG ("bfd.RemoteMinRxInterval is zero, not sending periodic control " @@ -593,6 +620,14 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt, return; } bfd_init_control_frame (b, bs); + if (POLL_NOT_NEEDED != bs->poll_state) + { + /* here we are either beginning a new poll sequence or retrying .. */ + bfd_pkt_set_poll (vlib_buffer_get_current (b)); + bs->poll_state = POLL_IN_PROGRESS; + BFD_DBG ("Setting poll bit in packet, bs_idx=%u", bs->bs_idx); + } + bfd_add_auth_section (b, bs); bfd_add_transport_layer (vm, b, bs); bs->last_tx_clocks = now; bfd_calc_next_tx (bm, bs, now); @@ -613,8 +648,14 @@ bfd_init_final_control_frame (vlib_main_t * vm, vlib_buffer_t * b, BFD_DBG ("Send final control frame for bs_idx=%lu", bs->bs_idx); bfd_init_control_frame (b, bs); bfd_pkt_set_final (vlib_buffer_get_current (b)); + bfd_add_auth_section (b, bs); bfd_add_transport_layer (vm, b, bs); bs->last_tx_clocks = clib_cpu_time_now (); + /* + * RFC allows to include changes in final frame, so if there were any + * pending, we already did that, thus we can clear any pending poll needs + */ + bs->poll_state = POLL_NOT_NEEDED; } static void @@ -629,6 +670,14 @@ bfd_check_rx_timeout (bfd_main_t * bm, bfd_session_t * bs, u64 now, BFD_DBG ("Rx timeout, session goes down"); bfd_set_diag (bs, BFD_DIAG_CODE_det_time_exp); bfd_set_state (bm, bs, BFD_STATE_down, handling_wakeup); + /* + * If the remote system does not receive any + * BFD Control packets for a Detection Time, it SHOULD reset + * bfd.RemoteMinRxInterval to its initial value of 1 (per section 6.8.1, + * 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, handling_wakeup); } } @@ -722,6 +771,19 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) (u32) * event_data); } break; + case BFD_EVENT_CONFIG_CHANGED: + if (!pool_is_free_index (bm->sessions, *event_data)) + { + bfd_session_t *bs = + pool_elt_at_index (bm->sessions, *event_data); + bfd_on_config_change (vm, rt, bm, bs, now); + } + else + { + BFD_DBG ("Ignoring event for non-existent session index %u", + (u32) * event_data); + } + break; default: clib_warning ("BUG: event type 0x%wx", event_type); break; @@ -810,6 +872,8 @@ bfd_main_init (vlib_main_t * vm) memset (&bm->wheel, 0, sizeof (bm->wheel)); bm->cpu_cps = vm->clib_time.clocks_per_second; BFD_DBG ("cps is %.2f", bm->cpu_cps); + bm->default_desired_min_tx_clocks = + bfd_usec_to_clocks (bm, BFD_DEFAULT_DESIRED_MIN_TX_US); const u64 now = clib_cpu_time_now (); timing_wheel_init (&bm->wheel, now, bm->cpu_cps); bm->wheel_inaccuracy = 2 << bm->wheel.log2_clocks_per_bin; @@ -1283,7 +1347,8 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx) while (0); } } - bs->remote_desired_min_tx_us = clib_net_to_host_u32 (pkt->des_min_tx); + bs->remote_desired_min_tx_clocks = + bfd_usec_to_clocks (bm, 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), 0); @@ -1297,6 +1362,18 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx) */ /* FIXME 6.8.2 */ /* FIXME 6.8.4 */ + if (bs->poll_state == POLL_IN_PROGRESS && bfd_pkt_get_final (pkt)) + { + bs->poll_state = POLL_NOT_NEEDED; + BFD_DBG ("Poll sequence terminated, bs_idx=%u", bs->bs_idx); + if (BFD_STATE_up == bs->local_state) + { + bfd_set_effective_required_min_rx (bm, bs, now, + bs->config_required_min_rx_clocks, + 0); + bfd_recalc_detection_time (bm, bs); + } + } if (BFD_STATE_admin_down == bs->local_state) return; if (BFD_STATE_admin_down == bs->remote_state) @@ -1333,6 +1410,20 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx) } } +static const char * +bfd_poll_state_string (bfd_poll_state_e state) +{ + switch (state) + { +#define F(x) \ + case POLL_##x: \ + return "POLL_" #x; + foreach_bfd_poll_state (F) +#undef F + } + return "UNKNOWN"; +} + u8 * format_bfd_session (u8 * s, va_list * args) { @@ -1353,17 +1444,18 @@ format_bfd_session (u8 * s, va_list * args) "remote-seq-num=%u, " "is-delayed=%s, " "curr-key=%U, " - "next-key=%U}", + "next-key=%U}," + "poll-state: %s", bs->bs_idx, bfd_state_string (bs->local_state), bfd_state_string (bs->remote_state), bs->local_discr, bs->remote_discr, bfd_diag_code_string (bs->local_diag), - bs->desired_min_tx_us, bs->required_min_rx_us, - bs->required_min_echo_rx_us, bs->remote_min_rx_us, - (bs->local_demand ? "yes" : "no"), + bs->config_desired_min_tx_usec, bs->config_required_min_rx_usec, + 1, bs->remote_min_rx_usec, (bs->local_demand ? "yes" : "no"), (bs->remote_demand ? "yes" : "no"), bs->local_detect_mult, bs->auth.local_seq_number, bs->auth.remote_seq_number, (bs->auth.is_delayed ? "yes" : "no"), format_bfd_auth_key, - bs->auth.curr_key, format_bfd_auth_key, bs->auth.next_key); + bs->auth.curr_key, format_bfd_auth_key, bs->auth.next_key, + bfd_poll_state_string (bs->poll_state)); return s; } @@ -1462,6 +1554,62 @@ bfd_auth_deactivate (bfd_session_t * bs, u8 is_delayed) #endif } +vnet_api_error_t +bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs, + u32 desired_min_tx_usec, + u32 required_min_rx_usec, u8 detect_mult) +{ + if (bs->local_detect_mult != detect_mult || + bs->config_desired_min_tx_usec != desired_min_tx_usec || + bs->config_required_min_rx_usec != required_min_rx_usec) + { + BFD_DBG ("Changing session params: %U", format_bfd_session, bs); + switch (bs->poll_state) + { + case POLL_NOT_NEEDED: + if (BFD_STATE_up == bs->local_state || + BFD_STATE_init == bs->local_state) + { + /* poll sequence is not needed for detect multiplier change */ + if (bs->config_desired_min_tx_usec != desired_min_tx_usec || + bs->config_required_min_rx_usec != required_min_rx_usec) + { + bs->poll_state = POLL_NEEDED; + BFD_DBG ("Set poll state=%s, bs_idx=%u", + bfd_poll_state_string (bs->poll_state), + bs->bs_idx); + } + } + break; + case POLL_NEEDED: + /* nothing to do */ + break; + case POLL_IN_PROGRESS: + /* can't change params now ... */ + BFD_ERR ("Poll in progress, cannot change params for session with " + "bs_idx=%u", bs->bs_idx); + return VNET_API_ERROR_BFD_EAGAIN; + } + + bs->local_detect_mult = detect_mult; + bs->config_desired_min_tx_usec = desired_min_tx_usec; + bs->config_desired_min_tx_clocks = + bfd_usec_to_clocks (bm, desired_min_tx_usec); + bs->config_required_min_rx_usec = required_min_rx_usec; + bs->config_required_min_rx_clocks = + bfd_usec_to_clocks (bm, required_min_rx_usec); + BFD_DBG ("Changed session params: %U", format_bfd_session, bs); + + vlib_process_signal_event (bm->vlib_main, bm->bfd_process_node_index, + BFD_EVENT_CONFIG_CHANGED, bs->bs_idx); + } + else + { + BFD_DBG ("Ignore parameter change - no change, bs_idx=%u", bs->bs_idx); + } + return 0; +} + bfd_main_t bfd_main; /* diff --git a/src/vnet/bfd/bfd_main.h b/src/vnet/bfd/bfd_main.h index b66b79e71a0..361ff0b7e1c 100644 --- a/src/vnet/bfd/bfd_main.h +++ b/src/vnet/bfd/bfd_main.h @@ -64,6 +64,18 @@ typedef struct bfd_auth_type_e auth_type; } bfd_auth_key_t; +#define foreach_bfd_poll_state(F)\ + F(NOT_NEEDED)\ +F(NEEDED)\ +F(IN_PROGRESS) + +typedef enum +{ +#define F(x) POLL_##x, + foreach_bfd_poll_state (F) +#undef F +} bfd_poll_state_e; + typedef struct { /* index in bfd_main.sessions pool */ @@ -85,28 +97,34 @@ typedef struct u32 remote_discr; /* configured desired min tx interval (microseconds) */ - u32 config_desired_min_tx_us; + u32 config_desired_min_tx_usec; + + /* configured desired min tx interval (clocks) */ + u64 config_desired_min_tx_clocks; - /* desired min tx interval (microseconds) */ - u32 desired_min_tx_us; + /* effective desired min tx interval (clocks) */ + u64 effective_desired_min_tx_clocks; - /* desired min tx interval (clocks) */ - u64 desired_min_tx_clocks; + /* configured required min rx interval (microseconds) */ + u32 config_required_min_rx_usec; - /* required min rx interval (microseconds) */ - u32 required_min_rx_us; + /* configured required min rx interval (clocks) */ + u64 config_required_min_rx_clocks; - /* required min echo rx interval (microseconds) */ - u32 required_min_echo_rx_us; + /* effective required min rx interval (clocks) */ + u64 effective_required_min_rx_clocks; /* remote min rx interval (microseconds) */ - u32 remote_min_rx_us; + u64 remote_min_rx_usec; /* remote min rx interval (clocks) */ u64 remote_min_rx_clocks; - /* remote desired min tx interval (microseconds) */ - u32 remote_desired_min_tx_us; + /* remote desired min tx interval (clocks) */ + u64 remote_desired_min_tx_clocks; + + /* configured detect multiplier */ + u8 local_detect_mult; /* 1 if in demand mode, 0 otherwise */ u8 local_demand; @@ -114,9 +132,6 @@ typedef struct /* 1 if remote system sets demand mode, 0 otherwise */ u8 remote_demand; - /* local detect multiplier */ - u8 local_detect_mult; - /* remote detect multiplier */ u8 remote_detect_mult; @@ -138,6 +153,9 @@ typedef struct /* detection time */ u64 detection_time_clocks; + /* state info regarding poll sequence */ + bfd_poll_state_e poll_state; + /* authentication information */ struct { @@ -175,6 +193,7 @@ typedef struct /* transport type for this session */ bfd_transport_t transport; + /* union of transport-specific data */ union { bfd_udp_session_t udp; @@ -205,6 +224,9 @@ typedef struct /* cpu clocks per second */ f64 cpu_cps; + /* default desired min tx in clocks */ + u64 default_desired_min_tx_clocks; + /* for generating random numbers */ u32 random_seed; @@ -243,6 +265,7 @@ enum { BFD_EVENT_RESCHEDULE = 1, BFD_EVENT_NEW_SESSION, + BFD_EVENT_CONFIG_CHANGED, } bfd_process_event_e; u8 *bfd_input_format_trace (u8 * s, va_list * args); @@ -265,6 +288,10 @@ unsigned bfd_auth_type_supported (bfd_auth_type_e auth_type); vnet_api_error_t bfd_auth_activate (bfd_session_t * bs, u32 conf_key_id, u8 bfd_key_id, u8 is_delayed); vnet_api_error_t bfd_auth_deactivate (bfd_session_t * bs, u8 is_delayed); +vnet_api_error_t +bfd_session_set_params (bfd_main_t * bm, bfd_session_t * bs, + u32 desired_min_tx_usec, + u32 required_min_rx_usec, u8 detect_mult); #define USEC_PER_MS 1000LL #define USEC_PER_SECOND (1000 * USEC_PER_MS) diff --git a/src/vnet/bfd/bfd_protocol.c b/src/vnet/bfd/bfd_protocol.c index 180fc6df8fd..92b226bda8b 100644 --- a/src/vnet/bfd/bfd_protocol.c +++ b/src/vnet/bfd/bfd_protocol.c @@ -150,6 +150,32 @@ bfd_auth_type_str (bfd_auth_type_e auth_type) return "UNKNOWN"; } +const char * +bfd_diag_code_string (bfd_diag_code_e diag) +{ +#define F(n, t, s) \ + case BFD_DIAG_CODE_NAME (t): \ + return s; + switch (diag) + { + foreach_bfd_diag_code (F)} + return "UNKNOWN"; +#undef F +} + +const char * +bfd_state_string (bfd_state_e state) +{ +#define F(n, t, s) \ + case BFD_STATE_NAME (t): \ + return s; + switch (state) + { + foreach_bfd_state (F)} + return "UNKNOWN"; +#undef F +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c index 443f4253b96..e21b887c47e 100644 --- a/src/vnet/bfd/bfd_udp.c +++ b/src/vnet/bfd/bfd_udp.c @@ -141,8 +141,8 @@ bfd_udp_key_init (bfd_udp_key_t * key, u32 sw_if_index, static vnet_api_error_t bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index, - u32 desired_min_tx_us, u32 required_min_rx_us, - u8 detect_mult, + 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, bfd_session_t ** bs_out) @@ -189,12 +189,9 @@ bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index, "returns %d", format_ip46_address, &key->peer_addr, IP46_TYPE_ANY, key->sw_if_index, bus->adj_index); } - bs->config_desired_min_tx_us = desired_min_tx_us; - bs->required_min_rx_us = required_min_rx_us; - bs->required_min_echo_rx_us = required_min_rx_us; /* FIXME */ - bs->local_detect_mult = detect_mult; *bs_out = bs; - return 0; + return bfd_session_set_params (bum->bfd_main, bs, desired_min_tx_usec, + required_min_rx_usec, detect_mult); } static vnet_api_error_t @@ -298,8 +295,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_us, - u32 required_min_rx_us, u8 detect_mult, +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) { @@ -314,9 +311,9 @@ bfd_api_verify_common (u32 sw_if_index, u32 desired_min_tx_us, clib_warning ("detect_mult < 1"); return VNET_API_ERROR_INVALID_ARGUMENT; } - if (desired_min_tx_us < 1) + if (desired_min_tx_usec < 1) { - clib_warning ("desired_min_tx_us < 1"); + clib_warning ("desired_min_tx_usec < 1"); return VNET_API_ERROR_INVALID_ARGUMENT; } return 0; @@ -334,22 +331,23 @@ bfd_udp_del_session_internal (bfd_session_t * 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_us, - u32 required_min_rx_us, u8 detect_mult, - u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id) + 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) { - vnet_api_error_t rv = bfd_api_verify_common (sw_if_index, desired_min_tx_us, - required_min_rx_us, - detect_mult, - local_addr, peer_addr); + 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 (&bfd_udp_main, sw_if_index, - desired_min_tx_us, required_min_rx_us, - detect_mult, local_addr, peer_addr, - &bs); + desired_min_tx_usec, + required_min_rx_usec, detect_mult, + local_addr, peer_addr, &bs); } if (!rv && is_authenticated) { @@ -374,6 +372,27 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, } 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; + vnet_api_error_t rv = + bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr, + &bs); + if (rv) + { + return rv; + } + + return bfd_session_set_params (bfd_udp_main.bfd_main, bs, + desired_min_tx_usec, required_min_rx_usec, + detect_mult); +} + +vnet_api_error_t bfd_udp_del_session (u32 sw_if_index, const ip46_address_t * local_addr, const ip46_address_t * peer_addr) |