39 #define F(t, n) BFD_OUTPUT_##t, 45 static u32 bfd_next_index_by_transport[] = {
46 #define F(t, n) [BFD_TRANSPORT_##t] = BFD_OUTPUT_##t, 84 BFD_DBG (
"set local_diag, bs_idx=%d: '%d:%s'", bs->
bs_idx, code,
116 BFD_DBG (
"Recalculated transmit interval %lu clocks/%.2fs",
137 BFD_ERR (
"Missed %lu transmit events (now is %lu, calc " 138 "tx_timeout is %lu)!",
156 BFD_ERR (
"Missed %lu transmit events (now is %lu, calc " 157 "tx_timeout is %lu)!",
170 BFD_DBG (
"Next transmit in %lu clocks/%.02fs@%lu",
195 BFD_DBG (
"Recalculated detection time %lu clocks/%.2fs",
222 BFD_DBG (
"bs_idx=%u, tx_timeout=%lu, rx_timeout=%lu, next=%s", bs->
bs_idx,
231 BFD_DBG (
"timing_wheel_insert(%p, %lu (%ld clocks/%.2fs in the " 238 if (!handling_wakeup)
249 u32 desired_min_tx_us,
int handling_wakeup)
253 BFD_DBG (
"Set desired min tx to %uus/%lu clocks/%.2fs",
265 u32 remote_required_min_rx_us,
300 return VNET_API_ERROR_BFD_NOENT;
309 case BFD_DIAG_CODE_NAME (t): \ 322 case BFD_STATE_NAME (t): \ 337 BFD_ERR (
"invalid bs_idx=%u", bs_idx);
338 return VNET_API_ERROR_BFD_NOENT;
359 const bfd_pkt_t *pkt = (bfd_pkt_t *) t->
data;
362 s =
format (s,
"BFD v%u, diag=%u(%s), state=%u(%s),\n" 363 " flags=(P:%u, F:%u, C:%u, A:%u, D:%u, M:%u), detect_mult=%u, " 374 if (t->
len >= sizeof (bfd_pkt_t)
375 && pkt->head.length >= sizeof (bfd_pkt_t))
377 s =
format (s,
" my discriminator: %u\n", pkt->my_disc);
378 s =
format (s,
" your discriminator: %u\n", pkt->your_disc);
379 s =
format (s,
" desired min tx interval: %u\n",
380 clib_net_to_host_u32 (pkt->des_min_tx));
381 s =
format (s,
" required min rx interval: %u\n",
382 clib_net_to_host_u32 (pkt->req_min_rx));
383 s =
format (s,
" required min echo rx interval: %u\n",
384 clib_net_to_host_u32 (pkt->req_min_echo_rx));
399 case BFD_STATE_admin_down:
430 case BFD_TRANSPORT_UDP4:
432 case BFD_TRANSPORT_UDP6:
457 to_next, n_left_to_next);
471 const u32 bfd_length = 24;
472 memset (pkt, 0,
sizeof (*pkt));
483 pkt->head.length = clib_host_to_net_u32 (bfd_length);
488 pkt->req_min_echo_rx = clib_host_to_net_u32 (0);
500 (
"bfd.RemoteMinRxInterval is zero, not sending periodic control " 514 BFD_DBG (
"Send periodic control frame for bs_idx=%lu", bs->
bs_idx);
527 (
"No need to send control frame now, now is %lu, tx_timeout is %lu",
536 BFD_DBG (
"Send final control frame for bs_idx=%lu", bs->
bs_idx);
551 BFD_DBG (
"Rx timeout, session goes down");
564 case BFD_STATE_admin_down:
565 BFD_ERR (
"Unexpected timeout when in %s state",
573 BFD_ERR (
"Unexpected timeout when in %s state",
592 uword event_type, *event_data = 0;
601 BFD_DBG (
"timing_wheel_next_expiring_elt_time(%p) returns %lu",
602 &bm->
wheel, next_expire);
603 if ((
i64) next_expire < 0)
605 BFD_DBG (
"wait for event without timeout");
612 BFD_DBG (
"wait for event with timeout %.02f", timeout);
615 BFD_DBG (
"negative timeout, already expired, skipping wait");
647 BFD_DBG (
"advancing wheel, now is %lu", now);
648 BFD_DBG (
"timing_wheel_advance (%p, %lu, %p, 0);", &bm->
wheel, now,
655 const u32 bs_idx = *p;
664 _vec_len (expired) = 0;
668 _vec_len (event_data) = 0;
682 .name =
"bfd-process",
683 .n_next_nodes = BFD_OUTPUT_N_NEXT,
686 #define F(t, n) [BFD_OUTPUT_##t] = n, 747 memset (result, 0,
sizeof (*result));
796 BFD_ERR (
"BFD verification failed - unexpected version: '%d'",
800 if (pkt->head.length < sizeof (bfd_pkt_t) ||
802 pkt->head.length < sizeof (bfd_pkt_with_auth_t)))
804 BFD_ERR (
"BFD verification failed - unexpected length: '%d' (auth " 809 if (!pkt->head.detect_mult)
811 BFD_ERR (
"BFD verification failed - unexpected detect-mult: '%d'",
812 pkt->head.detect_mult);
817 BFD_ERR (
"BFD verification failed - unexpected multipoint: '%d'",
823 BFD_ERR (
"BFD verification failed - unexpected my-disc: '%d'",
830 if (pkt_state != BFD_STATE_down && pkt_state != BFD_STATE_admin_down)
832 BFD_ERR (
"BFD verification failed - unexpected state: '%s' " 851 const bfd_pkt_with_auth_t *with_auth = (bfd_pkt_with_auth_t *) pkt;
854 if (pkt_size >
sizeof (*pkt))
856 BFD_ERR (
"BFD verification failed - unexpected packet size '%d' " 857 "(auth not present)", pkt_size);
863 if (!with_auth->auth.type)
865 BFD_ERR (
"BFD verification failed - unexpected auth type: '%d'",
866 with_auth->auth.type);
891 clib_net_to_host_u32 (pkt->req_min_rx), 0);
942 return format (s,
"BFD(%u): bfd.SessionState=%s, " 943 "bfd.RemoteSessionState=%s, " 944 "bfd.LocalDiscr=%u, " 945 "bfd.RemoteDiscr=%u, " 947 "bfd.DesiredMinTxInterval=%u, " 948 "bfd.RequiredMinRxInterval=%u, " 949 "bfd.RemoteMinRxInterval=%u, " 950 "bfd.DemandMode=%s, " 951 "bfd.RemoteDemandMode=%s, " 952 "bfd.DetectMult=%u, ",
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(bfd_hw_interface_up_down)
u8 bfd_pkt_get_auth_present(const bfd_pkt_t *pkt)
static void bfd_on_state_change(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)
#define hash_set(h, key, value)
void bfd_consume_pkt(bfd_main_t *bm, const bfd_pkt_t *pkt, u32 bs_idx)
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
#define hash_unset(h, key)
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
const char * bfd_state_string(bfd_state_e state)
void bfd_on_timeout(vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, bfd_session_t *bs, u64 now)
void timing_wheel_init(timing_wheel_t *w, u64 current_cpu_time, f64 cpu_clocks_per_second)
u8 bfd_pkt_get_diag_code(const bfd_pkt_t *pkt)
static uword bfd_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
bfd_session_t * bfd_find_session_by_disc(bfd_main_t *bm, u32 disc)
u64 timing_wheel_next_expiring_elt_time(timing_wheel_t *w)
int bfd_verify_pkt_common(const bfd_pkt_t *pkt)
verify bfd packet - common checks
static void bfd_set_state(bfd_main_t *bm, bfd_session_t *bs, bfd_state_e new_state, int handling_wakeup)
static u64 clib_cpu_time_now(void)
struct _vlib_node_registration vlib_node_registration_t
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)
void bfd_put_session(bfd_main_t *bm, bfd_session_t *bs)
u32 config_desired_min_tx_us
static u64 bfd_us_to_clocks(bfd_main_t *bm, u64 us)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
u32 bfd_process_node_index
u8 bfd_pkt_get_version(const bfd_pkt_t *pkt)
void timing_wheel_insert(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
u32 remote_desired_min_tx_us
bfd_transport_t transport
vnet_main_t * vnet_get_main(void)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static vlib_buffer_t * bfd_create_frame(vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_session_t *bs)
#define VLIB_INIT_FUNCTION(x)
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
u64 transmit_interval_clocks
void bfd_send_final(vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t *bs)
#define clib_warning(format, args...)
static vlib_node_registration_t bfd_process_node
(constructor) VLIB_REGISTER_NODE (bfd_process_node)
static void bfd_add_transport_layer(vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t *bs)
static void bfd_set_remote_required_min_rx(bfd_main_t *bm, bfd_session_t *bs, u64 now, u32 remote_required_min_rx_us, int handling_wakeup)
void bfd_event(bfd_main_t *bm, bfd_session_t *bs)
bfd_session_t * bfd_find_session_by_idx(bfd_main_t *bm, uword bs_idx)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static clib_error_t * bfd_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
u16 current_length
Nbytes between current data and the end of this buffer.
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
u8 bfd_pkt_get_control_plane_independent(const bfd_pkt_t *pkt)
#define pool_put(P, E)
Free an object E in pool P.
static void bfd_set_diag(bfd_session_t *bs, bfd_diag_code_e code)
vnet_api_error_t bfd_del_session(uword bs_idx)
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
u8 bfd_pkt_get_final(const bfd_pkt_t *pkt)
static void bfd_init_control_frame(vlib_buffer_t *b, bfd_session_t *bs)
void bfd_pkt_set_final(bfd_pkt_t *pkt)
void bfd_session_start(bfd_main_t *bm, bfd_session_t *bs)
u8 bfd_pkt_get_multipoint(const bfd_pkt_t *pkt)
void bfd_pkt_set_demand(bfd_pkt_t *pkt)
static void bfd_recalc_tx_interval(bfd_main_t *bm, bfd_session_t *bs)
BFD protocol declarations.
static void bfd_calc_next_tx(bfd_main_t *bm, bfd_session_t *bs, u64 now)
u8 * format_bfd_session(u8 *s, va_list *args)
u32 * timing_wheel_advance(timing_wheel_t *w, u64 advance_cpu_time, u32 *expired_user_data, u64 *next_expiring_element_cpu_time)
u8 bfd_pkt_get_demand(const bfd_pkt_t *pkt)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
u8 * bfd_input_format_trace(u8 *s, va_list *args)
void bfd_pkt_set_version(bfd_pkt_t *pkt, int version)
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
void bfd_add_udp_transport(vlib_main_t *vm, vlib_buffer_t *b, bfd_udp_session_t *bus)
static void bfd_recalc_detection_time(bfd_main_t *bm, bfd_session_t *bs)
static void 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)
vhost_vring_state_t state
u8 bfd_pkt_get_state(const bfd_pkt_t *pkt)
static f64 random_f64(u32 *seed)
Generate f64 random number in the interval [0,1].
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
u64 desired_min_tx_clocks
static void bfd_set_timer(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)
bfd_diag_code_e local_diag
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void bfd_set_defaults(bfd_main_t *bm, bfd_session_t *bs)
u8 bfd_pkt_get_poll(const bfd_pkt_t *pkt)
Linear Congruential Random Number Generator.
static u32 random_u32(u32 *seed)
32-bit random number generator
#define VLIB_REGISTER_NODE(x,...)
#define STRUCT_SIZE_OF(t, f)
u64 detection_time_clocks
#define vec_foreach(var, vec)
Vector iterator.
#define BFD_DEFAULT_DESIRED_MIN_TX_US
const char * bfd_diag_code_string(bfd_diag_code_e diag)
bfd_session_t * bfd_get_session(bfd_main_t *bm, bfd_transport_t t)
void bfd_pkt_set_state(bfd_pkt_t *pkt, int value)
static clib_error_t * bfd_hw_interface_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
int bfd_verify_pkt_session(const bfd_pkt_t *pkt, u16 pkt_size, const bfd_session_t *bs)
verify bfd packet - authentication
void bfd_pkt_set_diag_code(bfd_pkt_t *pkt, int value)
static clib_error_t * bfd_main_init(vlib_main_t *vm)
vnet_api_error_t bfd_session_set_flags(u32 bs_idx, u8 admin_up_down)
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(bfd_sw_interface_up_down)
static void bfd_check_rx_timeout(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)