21 #include <openssl/sha.h> 25 #include <x86intrin.h> 43 checksum = _mm_crc32_u64 (0, discriminator);
44 checksum = _mm_crc32_u64 (checksum, expire_time);
45 checksum = _mm_crc32_u64 (checksum, secret);
47 checksum =
clib_xxhash (discriminator ^ expire_time ^ secret);
72 s =
format (s,
"{auth-type=%u:%s, conf-key-id=%u, use-count=%u}, ",
123 BFD_DBG (
"set local_diag, bs_idx=%d: '%d:%s'", bs->
bs_idx, code,
150 return "BFD_POLL_" #x; 162 BFD_DBG (
"Setting poll state=%s, bs_idx=%u",
173 BFD_DBG (
"Recalculated transmit interval " BFD_CLK_FMT,
183 BFD_DBG (
"Recalculated echo transmit interval " BFD_CLK_FMT,
202 BFD_DBG (
"Missed %lu transmit events (now is %lu, calc " 203 "tx_timeout is %lu)",
221 BFD_DBG (
"Missed %lu transmit events (now is %lu, calc " 222 "tx_timeout is %lu)",
230 BFD_DBG (
"Next transmit in %lu clocks/%.02fs@%lu",
245 BFD_DBG (
"Missed %lu echo transmit events (now is %lu, calc tx_timeout " 252 BFD_DBG (
"Next echo transmit in %lu clocks/%.02fs@%lu",
267 BFD_DBG (
"Recalculated detection time %lu clocks/%.2fs",
290 if (tx_timeout && rx_timeout)
292 next =
clib_min (tx_timeout, rx_timeout);
306 BFD_DBG (
"bs_idx=%u, tx_timeout=%lu, echo_tx_timeout=%lu, rx_timeout=%lu, " 317 BFD_DBG (
"timing_wheel_insert(%p, %lu (%ld clocks/%.2fs in the " 324 if (!handling_wakeup)
336 u64 desired_min_tx_clocks)
339 BFD_DBG (
"Set effective desired min tx to " BFD_CLK_FMT,
350 u64 required_min_rx_clocks)
353 BFD_DBG (
"Set effective required min rx to " BFD_CLK_FMT,
360 u64 now,
u32 remote_required_min_rx_usec)
367 BFD_DBG (
"Set remote min rx to " BFD_CLK_FMT,
377 u32 remote_required_min_echo_rx_usec)
384 BFD_DBG (
"Set remote min echo rx to " BFD_CLK_FMT,
430 const bfd_pkt_t *pkt = (bfd_pkt_t *) t->
data;
433 s =
format (s,
"BFD v%u, diag=%u(%s), state=%u(%s),\n" 434 " flags=(P:%u, F:%u, C:%u, A:%u, D:%u, M:%u), " 435 "detect_mult=%u, length=%u\n",
445 if (t->
len >= sizeof (bfd_pkt_t) &&
446 pkt->head.length >= sizeof (bfd_pkt_t))
448 s =
format (s,
" my discriminator: %u\n",
449 clib_net_to_host_u32 (pkt->my_disc));
450 s =
format (s,
" your discriminator: %u\n",
451 clib_net_to_host_u32 (pkt->your_disc));
452 s =
format (s,
" desired min tx interval: %u\n",
453 clib_net_to_host_u32 (pkt->des_min_tx));
454 s =
format (s,
" required min rx interval: %u\n",
455 clib_net_to_host_u32 (pkt->req_min_rx));
456 s =
format (s,
" required min echo rx interval: %u",
457 clib_net_to_host_u32 (pkt->req_min_echo_rx));
459 if (t->
len >= sizeof (bfd_pkt_with_common_auth_t) &&
460 pkt->head.length >= sizeof (bfd_pkt_with_common_auth_t) &&
463 const bfd_pkt_with_common_auth_t *with_auth = (
void *) pkt;
464 const bfd_auth_common_t *common = &with_auth->common_auth;
465 s =
format (s,
"\n auth len: %u\n", common->len);
466 s =
format (s,
" auth type: %u:%s\n", common->type,
468 if (t->
len >= sizeof (bfd_pkt_with_sha1_auth_t) &&
469 pkt->head.length >= sizeof (bfd_pkt_with_sha1_auth_t) &&
470 (BFD_AUTH_TYPE_keyed_sha1 == common->type ||
471 BFD_AUTH_TYPE_meticulous_keyed_sha1 == common->type))
473 const bfd_pkt_with_sha1_auth_t *with_sha1 = (
void *) pkt;
474 const bfd_auth_sha1_t *sha1 = &with_sha1->sha1_auth;
475 s =
format (s,
" seq num: %u\n",
476 clib_net_to_host_u32 (sha1->seq_num));
477 s =
format (s,
" key id: %u\n", sha1->key_id);
479 sizeof (sha1->hash));
499 case BFD_STATE_admin_down:
560 case BFD_TRANSPORT_UDP4:
564 case BFD_TRANSPORT_UDP6:
576 case BFD_TRANSPORT_UDP4:
580 case BFD_TRANSPORT_UDP6:
593 case BFD_TRANSPORT_UDP4:
594 BFD_DBG (
"Transport bfd echo via udp4, bs_idx=%u", bs->
bs_idx);
597 case BFD_TRANSPORT_UDP6:
598 BFD_DBG (
"Transport bfd echo via udp6, bs_idx=%u", bs->
bs_idx);
610 case BFD_TRANSPORT_UDP4:
611 BFD_DBG (
"Transport bfd echo via udp4, bs_idx=%u", bs->
bs_idx);
614 case BFD_TRANSPORT_UDP6:
615 BFD_DBG (
"Transport bfd echo via udp6, bs_idx=%u", bs->
bs_idx);
627 bfd_auth_sha1_t *auth = &pkt->sha1_auth;
629 pkt->pkt.head.length +=
sizeof (*auth);
631 memset (auth, 0,
sizeof (*auth));
638 auth->type_len.len =
sizeof (bfd_auth_sha1_t);
647 unsigned char hash[
sizeof (auth->hash)];
648 SHA1 ((
unsigned char *) pkt,
sizeof (*pkt), hash);
662 case BFD_AUTH_TYPE_reserved:
664 case BFD_AUTH_TYPE_simple_password:
666 case BFD_AUTH_TYPE_keyed_md5:
668 case BFD_AUTH_TYPE_meticulous_keyed_md5:
669 clib_warning (
"Internal error, unexpected BFD auth type '%d'",
673 case BFD_AUTH_TYPE_keyed_sha1:
675 case BFD_AUTH_TYPE_meticulous_keyed_sha1:
676 bfd_add_sha1_auth_section (b, bs);
679 case BFD_AUTH_TYPE_keyed_sha1:
681 case BFD_AUTH_TYPE_meticulous_keyed_sha1:
682 clib_warning (
"Internal error, unexpected BFD auth type '%d'",
698 case BFD_TRANSPORT_UDP4:
700 case BFD_TRANSPORT_UDP6:
713 bfd_length =
sizeof (bfd_pkt_t);
714 memset (pkt, 0,
sizeof (*pkt));
719 pkt->head.length = bfd_length;
734 pkt->req_min_echo_rx = clib_host_to_net_u32 (1);
765 memset (pkt, 0,
sizeof (*pkt));
767 pkt->expire_time_clocks =
775 BFD_ERR (
"cannot send echo packet out, turning echo off");
782 BFD_ERR (
"cannot send echo packet out, turning echo off");
793 (
"No need to send echo packet now, now is %lu, tx_timeout is %lu",
804 BFD_DBG (
"Remote min rx interval is zero, not sending periodic control " 817 BFD_DBG (
"Remote demand is set, not sending periodic control frame");
841 case BFD_POLL_NEEDED:
842 if (now < bs->poll_state_start_or_timeout_clocks)
844 BFD_DBG (
"Cannot start a poll sequence yet, need to wait " 853 case BFD_POLL_IN_PROGRESS:
854 case BFD_POLL_IN_PROGRESS_AND_QUEUED:
856 BFD_DBG (
"Setting poll bit in packet, bs_idx=%u", bs->
bs_idx);
858 case BFD_POLL_NOT_NEEDED:
874 (
"No need to send control frame now, now is %lu, tx_timeout is %lu",
884 BFD_DBG (
"Send final control frame for bs_idx=%lu", bs->
bs_idx);
909 BFD_DBG (
"Rx timeout, session goes down");
926 BFD_DBG (
"Echo rx timeout, session goes down");
939 case BFD_STATE_admin_down:
955 BFD_DBG (
"Switching on echo function, bs_idx=%u", bs->
bs_idx);
982 uword event_type, *event_data = 0;
991 BFD_DBG (
"timing_wheel_next_expiring_elt_time(%p) returns %lu",
992 &bm->
wheel, next_expire);
993 if ((
i64) next_expire < 0)
995 BFD_DBG (
"wait for event without timeout");
1002 BFD_DBG (
"wait for event with timeout %.02f", timeout);
1005 BFD_DBG (
"negative timeout, already expired, skipping wait");
1034 BFD_DBG (
"Ignoring event for non-existent session index %u",
1035 (
u32) * event_data);
1047 BFD_DBG (
"Ignoring event for non-existent session index %u",
1048 (
u32) * event_data);
1055 BFD_DBG (
"advancing wheel, now is %lu", now);
1056 BFD_DBG (
"timing_wheel_advance (%p, %lu, %p, 0);", &bm->
wheel, now,
1063 const u32 bs_idx = *p;
1073 _vec_len (expired) = 0;
1077 _vec_len (event_data) = 0;
1091 .name =
"bfd-process",
1131 setbuf (stdout,
NULL);
1157 memset (result, 0,
sizeof (*result));
1160 const unsigned limit = 1000;
1161 unsigned counter = 0;
1165 if (counter > limit)
1167 clib_warning (
"Couldn't allocate unused session discriminator even " 1168 "after %u tries!", limit);
1228 BFD_ERR (
"BFD verification failed - unexpected version: '%d'",
1232 if (pkt->head.length < sizeof (bfd_pkt_t) ||
1234 pkt->head.length < sizeof (bfd_pkt_with_common_auth_t)))
1236 BFD_ERR (
"BFD verification failed - unexpected length: '%d' (auth " 1241 if (!pkt->head.detect_mult)
1243 BFD_ERR (
"BFD verification failed - unexpected detect-mult: '%d'",
1244 pkt->head.detect_mult);
1249 BFD_ERR (
"BFD verification failed - unexpected multipoint: '%d'",
1255 BFD_ERR (
"BFD verification failed - unexpected my-disc: '%d'",
1259 if (!pkt->your_disc)
1262 if (pkt_state != BFD_STATE_down && pkt_state != BFD_STATE_admin_down)
1264 BFD_ERR (
"BFD verification failed - unexpected state: '%s' " 1275 BFD_DBG (
"Switching authentication key from %U to %U for bs_idx=%u",
1291 if (BFD_AUTH_TYPE_meticulous_keyed_md5 == auth_type ||
1292 BFD_AUTH_TYPE_meticulous_keyed_sha1 == auth_type)
1301 u32 received_seq_num,
int is_meticulous)
1312 BFD_DBG (
"BFD peer unresponsive for %lu clocks, which is > 2 * " 1313 "detection_time=%u clocks, resetting remote_seq_number_known " 1321 const u32 max_u32 = 0xffffffff;
1340 if (received_seq_num > x &&
1341 received_seq_num < bs->auth.remote_seq_number + is_meticulous)
1344 (
"Recvd sequence number=%u out of ranges <0, %u>, <%u, %u>",
1345 received_seq_num, x,
1356 if (received_seq_num < min || received_seq_num > max)
1358 BFD_ERR (
"Recvd sequence number=%u out of range <%u, %u>",
1359 received_seq_num, min, max);
1373 auth_key->
auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1);
1375 u8 result[SHA_DIGEST_LENGTH];
1376 bfd_pkt_with_common_auth_t *with_common = (
void *) pkt;
1377 if (pkt_size <
sizeof (*with_common))
1379 BFD_ERR (
"Packet size too small to hold authentication common header");
1382 if (with_common->common_auth.type != auth_key->
auth_type)
1384 BFD_ERR (
"BFD auth type mismatch, packet auth=%d:%s doesn't match " 1385 "in-use auth=%d:%s",
1386 with_common->common_auth.type,
1391 bfd_pkt_with_sha1_auth_t *with_sha1 = (
void *) pkt;
1392 if (pkt_size <
sizeof (*with_sha1) ||
1393 with_sha1->sha1_auth.type_len.len <
sizeof (with_sha1->sha1_auth))
1396 (
"BFD size mismatch, payload size=%u, expected=%u, auth_len=%u, " 1397 "expected=%u", pkt_size,
sizeof (*with_sha1),
1398 with_sha1->sha1_auth.type_len.len, sizeof (with_sha1->sha1_auth));
1401 if (with_sha1->sha1_auth.key_id != bfd_key_id)
1404 (
"BFD key ID mismatch, packet key ID=%u doesn't match key ID=%u%s",
1405 with_sha1->sha1_auth.key_id, bfd_key_id,
1407 auth.
is_delayed ?
" (but a delayed auth change is scheduled)" :
"");
1411 if (!SHA1_Init (&ctx))
1417 if (!SHA1_Update (&ctx, with_sha1,
1418 sizeof (*with_sha1) -
sizeof (with_sha1->sha1_auth.hash)))
1420 BFD_ERR (
"SHA1_Update failed");
1423 if (!SHA1_Update (&ctx, auth_key->
key, sizeof (auth_key->
key)))
1425 BFD_ERR (
"SHA1_Update failed");
1428 if (!SHA1_Final (result, &ctx))
1430 BFD_ERR (
"SHA1_Final failed");
1433 if (0 == memcmp (result, with_sha1->sha1_auth.hash, SHA_DIGEST_LENGTH))
1437 BFD_ERR (
"SHA1 hash: %U doesn't match the expected value: %U",
1450 case BFD_AUTH_TYPE_reserved:
1451 clib_warning (
"Internal error, unexpected auth_type=%d:%s",
1455 case BFD_AUTH_TYPE_simple_password:
1457 (
"Internal error, not implemented, unexpected auth_type=%d:%s",
1460 case BFD_AUTH_TYPE_keyed_md5:
1462 case BFD_AUTH_TYPE_meticulous_keyed_md5:
1464 (
"Internal error, not implemented, unexpected auth_type=%d:%s",
1467 case BFD_AUTH_TYPE_keyed_sha1:
1469 case BFD_AUTH_TYPE_meticulous_keyed_sha1:
1473 const u32 seq_num = clib_net_to_host_u32 (((bfd_pkt_with_sha1_auth_t
1485 (
"Internal error, attempt to use SHA1 without SSL support");
1552 if (pkt_size >
sizeof (*pkt))
1554 BFD_ERR (
"BFD verification failed - unexpected packet size '%d' " 1555 "(auth not present)", pkt_size);
1581 if (!bs || (pkt->your_disc && pkt->your_disc != bs->
local_discr))
1595 ((bfd_pkt_with_common_auth_t *) (pkt))->common_auth.type;
1598 case BFD_AUTH_TYPE_reserved:
1600 case BFD_AUTH_TYPE_simple_password:
1602 case BFD_AUTH_TYPE_keyed_md5:
1604 case BFD_AUTH_TYPE_meticulous_keyed_md5:
1605 clib_warning (
"Internal error, unexpected auth_type=%d:%s",
1608 case BFD_AUTH_TYPE_keyed_sha1:
1610 case BFD_AUTH_TYPE_meticulous_keyed_sha1:
1613 bfd_pkt_with_sha1_auth_t *with_sha1 =
1614 (bfd_pkt_with_sha1_auth_t *) pkt;
1616 clib_net_to_host_u32 (with_sha1->sha1_auth.seq_num);
1618 BFD_DBG (
"Received sequence number %u",
1628 clib_net_to_host_u32 (pkt->req_min_rx));
1630 clib_net_to_host_u32
1631 (pkt->req_min_echo_rx));
1636 BFD_DBG (
"Poll sequence terminated, bs_idx=%u", bs->
bs_idx);
1646 else if (BFD_POLL_IN_PROGRESS_AND_QUEUED == bs->
poll_state)
1652 BFD_DBG (
"Next poll sequence can commence in " BFD_CLK_FMT,
1658 (
"Poll sequence terminated, but another is needed, bs_idx=%u",
1667 BFD_DBG (
"Session is admin-down, ignoring packet, bs_idx=%u",
1711 bfd_echo_pkt_t *pkt =
NULL;
1722 BFD_DBG (
"Scanning bfd echo packet, bs_idx=%d", bs->
bs_idx);
1726 if (checksum != pkt->checksum)
1728 BFD_DBG (
"Invalid echo packet, checksum mismatch");
1732 if (pkt->expire_time_clocks < now)
1734 BFD_DBG (
"Stale packet received, expire time %lu < now %lu",
1735 pkt->expire_time_clocks, now);
1749 s =
format (s,
"bs_idx=%u local-state=%s remote-state=%s\n" 1750 "%Ulocal-discriminator=%u remote-discriminator=%u\n" 1751 "%Ulocal-diag=%s echo-active=%s\n" 1752 "%Udesired-min-tx=%u required-min-rx=%u\n" 1753 "%Urequired-min-echo-rx=%u detect-mult=%u\n" 1754 "%Uremote-min-rx=%u remote-min-echo-rx=%u\n" 1755 "%Uremote-demand=%s poll-state=%s\n" 1756 "%Uauth: local-seq-num=%u remote-seq-num=%u\n" 1757 "%U is-delayed=%s\n" 1783 if (auth_type == BFD_AUTH_TYPE_keyed_sha1 ||
1784 auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1)
1793 u8 bfd_key_id,
u8 is_delayed)
1796 const uword *key_idx_p =
1800 clib_warning (
"Authentication key with config ID %u doesn't exist)",
1802 return VNET_API_ERROR_BFD_ENOENT;
1804 const uword key_idx = *key_idx_p;
1870 clib_warning (
"SSL missing, cannot deactivate BFD authentication");
1871 return VNET_API_ERROR_BFD_NOTSUPP;
1877 u32 desired_min_tx_usec,
1878 u32 required_min_rx_usec,
u8 detect_mult)
1887 case BFD_POLL_NOT_NEEDED:
1899 case BFD_POLL_NEEDED:
1900 case BFD_POLL_IN_PROGRESS_AND_QUEUED:
1906 case BFD_POLL_IN_PROGRESS:
1911 BFD_DBG (
"Poll in progress, queueing extra poll, bs_idx=%u",
1931 BFD_DBG (
"Ignore parameter change - no change, bs_idx=%u", bs->
bs_idx);
1938 const u8 * key_data)
1944 clib_warning (
"Invalid authentication key length for auth_type=%d:%s " 1945 "(key_len=%u, must be " 1946 "non-zero, expected max=%u)",
1949 return VNET_API_ERROR_INVALID_VALUE;
1953 clib_warning (
"Unsupported auth type=%d:%s", auth_type,
1955 return VNET_API_ERROR_BFD_NOTSUPP;
1962 const uword key_idx = *key_idx_p;
1966 clib_warning (
"Authentication key with conf ID %u in use by %u BFD " 1967 "session(s) - cannot modify",
1969 return VNET_API_ERROR_BFD_EINUSE;
1981 memset (auth_key->
key, 0, sizeof (auth_key->
key));
1985 clib_warning (
"SSL missing, cannot manipulate authentication keys");
1986 return VNET_API_ERROR_BFD_NOTSUPP;
2000 const uword key_idx = *key_idx_p;
2004 clib_warning (
"Authentication key with conf ID %u in use by %u BFD " 2005 "session(s) - cannot delete",
2007 return VNET_API_ERROR_BFD_EINUSE;
2010 memset (auth_key, 0,
sizeof (*auth_key));
2016 clib_warning (
"Authentication key with conf ID %u does not exist",
2018 return VNET_API_ERROR_BFD_ENOENT;
2022 clib_warning (
"SSL missing, cannot manipulate authentication keys");
2023 return VNET_API_ERROR_BFD_NOTSUPP;
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(bfd_hw_interface_up_down)
static u64 bfd_usec_to_clocks(const bfd_main_t *bm, u64 us)
static int bfd_transport_control_frame(vlib_main_t *vm, u32 bi, bfd_session_t *bs)
u8 bfd_pkt_get_auth_present(const bfd_pkt_t *pkt)
static void bfd_recalc_echo_tx_interval(bfd_main_t *bm, bfd_session_t *bs)
static void bfd_on_state_change(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)
bfd_session_t * bfd_get_session(bfd_main_t *bm, bfd_transport_e t)
#define hash_set(h, key, value)
bfd_auth_type_e auth_type
authentication type for this key
void bfd_consume_pkt(bfd_main_t *bm, const bfd_pkt_t *pkt, u32 bs_idx)
u8 curr_bfd_key_id
current key ID sent out in bfd packet
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
static void bfd_set_effective_required_min_rx(bfd_main_t *bm, bfd_session_t *bs, u64 required_min_rx_clocks)
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)
void bfd_pkt_set_poll(bfd_pkt_t *pkt)
vnet_main_t * vnet_get_main(void)
void bfd_on_timeout(vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, bfd_session_t *bs, u64 now)
u32 * auth_key_by_conf_key_id
hashmap - index in pool auth_keys by conf_key_id
static void bfd_session_switch_auth_to_next(bfd_session_t *bs)
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)
u8 * format_bfd_auth_key(u8 *s, va_list *args)
u64 timing_wheel_next_expiring_elt_time(timing_wheel_t *w)
u64 echo_last_rx_clocks
timestamp of last echo packet received
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)
u32 echo_secret
secret used for calculating/checking checksum of echo packets
bfd_diag_code_e local_diag
local diagnostics
static u64 clib_cpu_time_now(void)
static u64 clib_xxhash(u64 key)
struct _vlib_node_registration vlib_node_registration_t
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)
void bfd_put_session(bfd_main_t *bm, bfd_session_t *bs)
u64 last_tx_clocks
timestamp of last packet transmitted
u8 remote_seq_number_known
set to 1 if remote sequence number is known
static void bfd_set_remote_required_min_rx(bfd_main_t *bm, bfd_session_t *bs, u64 now, u32 remote_required_min_rx_usec)
unsigned bfd_auth_type_supported(bfd_auth_type_e auth_type)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
static void bfd_add_transport_layer(vlib_main_t *vm, u32 bi, 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)
u32 bfd_process_node_index
background process node index
u8 bfd_pkt_get_version(const bfd_pkt_t *pkt)
u64 remote_min_echo_rx_clocks
remote min echo rx interval (clocks)
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).
u64 effective_required_min_rx_clocks
effective required min rx interval (clocks)
u32 remote_seq_number
remote sequence number
int bfd_add_udp4_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
timing_wheel_t wheel
timing wheel for scheduling timeouts
vnet_api_error_t bfd_auth_deactivate(bfd_session_t *bs, u8 is_delayed)
static int bfd_verify_pkt_auth_seq_num(bfd_session_t *bs, u32 received_seq_num, int is_meticulous)
u64 effective_desired_min_tx_clocks
effective desired min tx interval (clocks)
u32 bfd_clocks_to_usec(const bfd_main_t *bm, u64 clocks)
u8 key[20]
key data directly usable for bfd purposes - already padded with zeroes (so we don't need the actual l...
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
const char * bfd_poll_state_string(bfd_poll_state_e state)
u32 random_seed
for generating random numbers
#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...
int bfd_transport_udp4(vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs)
transport packet over udpv4
u64 remote_min_rx_usec
remote min rx interval (microseconds)
u64 tx_timeout_clocks
next time at which to transmit a packet
void bfd_event(bfd_main_t *bm, bfd_session_t *bs)
u64 config_required_min_rx_clocks
configured required min rx interval (clocks)
bfd_auth_key_t * next_key
set to next key to use if delayed switch is enabled - in that case the key is switched when first inc...
static vlib_node_registration_t bfd_process_node
(constructor) VLIB_REGISTER_NODE (bfd_process_node)
static void bfd_set_poll_state(bfd_session_t *bs, bfd_poll_state_e state)
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
static void bfd_calc_next_echo_tx(bfd_main_t *bm, bfd_session_t *bs, u64 now)
bfd_session_t * bfd_find_session_by_idx(bfd_main_t *bm, uword bs_idx)
static u64 bfd_calc_echo_checksum(u32 discriminator, u64 expire_time, u32 secret)
u8 remote_demand
1 if remote system sets demand mode, 0 otherwise
bfd_session_t * sessions
pool of bfd sessions context data
bfd_auth_key_t * auth_keys
pool of authentication keys
bfd_transport_e transport
transport type for this session
#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)
u32 remote_discr
remote discriminator
u64 default_desired_min_tx_clocks
default desired min tx in clocks
u64 echo_last_tx_clocks
timestamp of last echo packet transmitted
bfd_poll_state_e poll_state
state info regarding poll sequence
struct bfd_session_s::@35 auth
authentication information
u8 bfd_pkt_get_control_plane_independent(const bfd_pkt_t *pkt)
f64 cpu_cps
cpu clocks per second
void bfd_pkt_set_auth_present(bfd_pkt_t *pkt)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define pool_put(P, E)
Free an object E in pool P.
u64 echo_tx_timeout_clocks
next time at which to transmit echo packet
static void bfd_set_diag(bfd_session_t *bs, bfd_diag_code_e code)
u8 local_detect_mult
configured detect multiplier
static int bfd_is_echo_possible(bfd_session_t *bs)
u64 last_rx_clocks
timestamp of last packet received
int bfd_transport_udp6(vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs)
transport packet over udpv6
int bfd_add_udp6_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
u8 bfd_pkt_get_final(const bfd_pkt_t *pkt)
void bfd_pkt_set_final(bfd_pkt_t *pkt)
bfd_diag_code_e remote_diag
remote diagnostics
static void bfd_send_periodic(vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, bfd_session_t *bs, u64 now)
#define BFD_DEFAULT_DESIRED_MIN_TX_USEC
default, slow transmission interval for BFD packets, per spec at least 1s
void bfd_session_start(bfd_main_t *bm, bfd_session_t *bs)
const char * bfd_auth_type_str(bfd_auth_type_e auth_type)
u64 transmit_interval_clocks
transmit interval
u8 bfd_pkt_get_multipoint(const bfd_pkt_t *pkt)
static void bfd_set_effective_desired_min_tx(bfd_main_t *bm, bfd_session_t *bs, u64 now, u64 desired_min_tx_clocks)
static void bfd_recalc_tx_interval(bfd_main_t *bm, bfd_session_t *bs)
BFD protocol declarations.
u32 config_desired_min_tx_usec
configured desired min tx interval (microseconds)
u32 bfd_max_key_len_for_auth_type(bfd_auth_type_e auth_type)
get the maximum length of key data for given auth type
static void bfd_calc_next_tx(bfd_main_t *bm, bfd_session_t *bs, u64 now)
#define clib_warning(format, args...)
u8 * format_bfd_session(u8 *s, va_list *args)
#define clib_memcpy(a, b, c)
u32 * timing_wheel_advance(timing_wheel_t *w, u64 advance_cpu_time, u32 *expired_user_data, u64 *next_expiring_element_cpu_time)
const char * bfd_diag_code_string(bfd_diag_code_e diag)
static void bfd_add_auth_section(vlib_buffer_t *b, bfd_session_t *bs)
static int bfd_verify_pkt_auth_key_sha1(const bfd_pkt_t *pkt, u32 pkt_size, bfd_session_t *bs, u8 bfd_key_id, bfd_auth_key_t *auth_key)
u8 bfd_pkt_get_demand(const bfd_pkt_t *pkt)
vnet_api_error_t bfd_auth_activate(bfd_session_t *bs, u32 conf_key_id, u8 bfd_key_id, u8 is_delayed)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
static void bfd_set_remote_required_min_echo_rx(bfd_main_t *bm, bfd_session_t *bs, u64 now, u32 remote_required_min_echo_rx_usec)
u64 poll_state_start_or_timeout_clocks
helper for delayed poll sequence - marks either start of running poll sequence or timeout...
u64 detection_time_clocks
detection time
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
static void bfd_recalc_detection_time(bfd_main_t *bm, bfd_session_t *bs)
u64 config_desired_min_tx_clocks
configured desired min tx interval (clocks)
int bfd_udp_is_echo_available(bfd_transport_e transport)
check if the bfd udp layer is echo-capable at this time
u8 echo
1 is echo function is active, 0 otherwise
u64 wheel_time_clocks
set to value of timer in timing wheel, 0 if never set
u64 remote_desired_min_tx_clocks
remote desired min tx interval (clocks)
vhost_vring_state_t state
u8 bfd_pkt_get_state(const bfd_pkt_t *pkt)
u32 local_discr
local discriminator
static f64 random_f64(u32 *seed)
Generate f64 random number in the interval [0,1].
u32 conf_key_id
global configuration key ID
vnet_api_error_t bfd_auth_del_key(u32 conf_key_id)
delete existing authentication key
vlib_main_t * vlib_main
convenience variables
bfd_state_e local_state
session state
static int bfd_echo_add_transport_layer(vlib_main_t *vm, u32 bi, bfd_session_t *bs)
u32 * session_by_disc
hashmap - bfd session by discriminator
int bfd_consume_echo_pkt(bfd_main_t *bm, vlib_buffer_t *b)
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)
u64 echo_transmit_interval_clocks
transmit interval for echo packets
u32 local_seq_number
sequence number incremented occasionally or always (if meticulous)
u32 config_required_min_rx_usec
configured required min rx interval (microseconds)
static void bfd_set_timer(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)
#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)
u32 use_count
keeps track of how many sessions reference this key
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
u8 next_bfd_key_id
key ID to use when switched to next_key
static int bfd_verify_pkt_auth_key(const bfd_pkt_t *pkt, u32 pkt_size, bfd_session_t *bs, u8 bfd_key_id, bfd_auth_key_t *auth_key)
u8 bfd_pkt_get_poll(const bfd_pkt_t *pkt)
Linear Congruential Random Number Generator.
u32 bs_idx
index in bfd_main.sessions pool
static int bfd_transport_echo(vlib_main_t *vm, u32 bi, bfd_session_t *bs)
static u32 random_u32(u32 *seed)
32-bit random number generator
#define VLIB_REGISTER_NODE(x,...)
u64 remote_min_echo_rx_usec
remote min echo rx interval (microseconds)
vnet_api_error_t bfd_auth_set_key(u32 conf_key_id, u8 auth_type, u8 key_len, const u8 *key_data)
create or modify bfd authentication key
#define STRUCT_SIZE_OF(t, f)
#define vec_foreach(var, vec)
Vector iterator.
bfd_state_e remote_state
remote session state
const char * bfd_state_string(bfd_state_e state)
u64 min_required_min_rx_while_echo_clocks
minimum required min rx while echo function is active - clocks
int bfd_verify_pkt_auth(const bfd_pkt_t *pkt, u16 pkt_size, bfd_session_t *bs)
verify bfd packet - authentication
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
static int bfd_auth_type_is_meticulous(bfd_auth_type_e auth_type)
bfd_auth_key_t * curr_key
current key in use
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
static void bfd_send_echo(vlib_main_t *vm, vlib_node_runtime_t *rt, bfd_main_t *bm, bfd_session_t *bs, u64 now)
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)
u8 remote_detect_mult
remote detect multiplier
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
void bfd_pkt_set_diag_code(bfd_pkt_t *pkt, int value)
#define BFD_REQUIRED_MIN_RX_USEC_WHILE_ECHO
minimum required min rx set locally when echo function is used, per spec should be set to at least 1s...
u64 remote_min_rx_clocks
remote min rx interval (clocks)
u8 is_delayed
set to 1 if delayed action is pending, which might be activation of authentication, change of key or deactivation
static clib_error_t * bfd_main_init(vlib_main_t *vm)
u64 wheel_inaccuracy
timing wheel inaccuracy, in clocks
static void bfd_init_control_frame(bfd_main_t *bm, bfd_session_t *bs, vlib_buffer_t *b)
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(bfd_sw_interface_up_down)
void bfd_session_set_flags(bfd_session_t *bs, u8 admin_up_down)
static void bfd_check_rx_timeout(bfd_main_t *bm, bfd_session_t *bs, u64 now, int handling_wakeup)