summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/test_bfd.py6
-rw-r--r--vnet/vnet/bfd/bfd_debug.h41
-rw-r--r--vnet/vnet/bfd/bfd_main.c97
-rw-r--r--vnet/vnet/bfd/bfd_main.h14
-rw-r--r--vnet/vnet/bfd/bfd_udp.c2
5 files changed, 88 insertions, 72 deletions
diff --git a/test/test_bfd.py b/test/test_bfd.py
index b48c3cc4..bf0e88dd 100644
--- a/test/test_bfd.py
+++ b/test/test_bfd.py
@@ -252,14 +252,14 @@ class BFDTestCase(VppTestCase):
e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
self.verify_event(e, expected_state=BFDState.down)
- @unittest.skip("this test is not working yet")
def test_large_required_min_rx(self):
+ """ large remote RequiredMinRxInterval """
self.bfd_session_up()
- interval = 5000000
+ interval = 3000000
self.test_session.update(required_min_rx_interval=interval)
self.test_session.send_packet()
now = time.time()
- count = 1
+ count = 0
while time.time() < now + interval / 1000000:
try:
p = self.wait_for_bfd_packet()
diff --git a/vnet/vnet/bfd/bfd_debug.h b/vnet/vnet/bfd/bfd_debug.h
index 0072ff8f..707ebab2 100644
--- a/vnet/vnet/bfd/bfd_debug.h
+++ b/vnet/vnet/bfd/bfd_debug.h
@@ -23,32 +23,30 @@
#define BFD_DEBUG (0)
#if BFD_DEBUG
-#define BFD_DEBUG_FILE_DEF \
- static const char *__file = NULL; \
- if (!__file) \
- { \
- __file = strrchr (__FILE__, '/'); \
- if (__file) \
- { \
- ++__file; \
- } \
- else \
- { \
- __file = __FILE__; \
- } \
- }
+#define BFD_DEBUG_FILE_DEF \
+ static const char *__file = NULL; \
+ { \
+ __file = strrchr (__FILE__, '/'); \
+ if (__file) \
+ { \
+ ++__file; \
+ } \
+ else \
+ { \
+ __file = __FILE__; \
+ } \
+ }
#define BFD_DBG(fmt, ...) \
do \
{ \
BFD_DEBUG_FILE_DEF \
- u8 *_s = NULL; \
+ static u8 *_s = NULL; \
vlib_main_t *vm = vlib_get_main (); \
_s = format (_s, "%6.02f:DBG:%s:%d:%s():" fmt, vlib_time_now (vm), \
__file, __LINE__, __func__, ##__VA_ARGS__); \
- printf ("%s\n", _s); \
- fflush (stdout); \
- vec_free (_s); \
+ printf ("%.*s\n", vec_len (_s), _s); \
+ vec_reset_length (_s); \
} \
while (0);
@@ -56,13 +54,12 @@
do \
{ \
BFD_DEBUG_FILE_DEF \
- u8 *_s = NULL; \
+ static u8 *_s = NULL; \
vlib_main_t *vm = vlib_get_main (); \
_s = format (_s, "%6.02f:ERR:%s:%d:%s():" fmt, vlib_time_now (vm), \
__file, __LINE__, __func__, ##__VA_ARGS__); \
- printf ("%s\n", _s); \
- fflush (stdout); \
- vec_free (_s); \
+ printf ("%.*s\n", vec_len (_s), _s); \
+ vec_reset_length (_s); \
} \
while (0);
diff --git a/vnet/vnet/bfd/bfd_main.c b/vnet/vnet/bfd/bfd_main.c
index ffc04ee4..e25eadfc 100644
--- a/vnet/vnet/bfd/bfd_main.c
+++ b/vnet/vnet/bfd/bfd_main.c
@@ -129,6 +129,17 @@ bfd_calc_next_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now)
bs->tx_timeout_clocks = now +
(1 - .25 * (random_f64 (&bm->random_seed))) *
bs->transmit_interval_clocks;
+ if (bs->tx_timeout_clocks < now)
+ {
+ /* huh, we've missed it already, skip the missed events */
+ const u64 missed =
+ (now - bs->tx_timeout_clocks) / bs->transmit_interval_clocks;
+ BFD_ERR ("Missed %lu transmit events (now is %lu, calc "
+ "tx_timeout is %lu)!",
+ missed, now, bs->tx_timeout_clocks);
+ bs->tx_timeout_clocks +=
+ (missed + 1) * bs->transmit_interval_clocks;
+ }
}
else
{
@@ -137,6 +148,17 @@ bfd_calc_next_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now)
now +
(.9 - .15 * (random_f64 (&bm->random_seed))) *
bs->transmit_interval_clocks;
+ if (bs->tx_timeout_clocks < now)
+ {
+ /* huh, we've missed it already, skip the missed events */
+ const u64 missed =
+ (now - bs->tx_timeout_clocks) / bs->transmit_interval_clocks;
+ BFD_ERR ("Missed %lu transmit events (now is %lu, calc "
+ "tx_timeout is %lu)!",
+ missed, now, bs->tx_timeout_clocks);
+ bs->tx_timeout_clocks +=
+ (missed + 1) * bs->transmit_interval_clocks;
+ }
}
}
else
@@ -200,12 +222,11 @@ bfd_set_timer (bfd_main_t * bm, bfd_session_t * bs, u64 now,
BFD_DBG ("bs_idx=%u, tx_timeout=%lu, rx_timeout=%lu, next=%s", bs->bs_idx,
bs->tx_timeout_clocks, rx_timeout,
next == bs->tx_timeout_clocks ? "tx" : "rx");
- if (next && (next < bs->wheel_time_clocks || !bs->wheel_time_clocks))
+ /* sometimes the wheel expires an event a bit sooner than requested, account
+ for that here */
+ if (next && (now + bm->wheel_inaccuracy > bs->wheel_time_clocks ||
+ next < bs->wheel_time_clocks || !bs->wheel_time_clocks))
{
- if (bs->wheel_time_clocks)
- {
- timing_wheel_delete (&bm->wheel, bs->bs_idx);
- }
bs->wheel_time_clocks = next;
BFD_DBG ("timing_wheel_insert(%p, %lu (%ld clocks/%.2fs in the "
"future), %u);",
@@ -238,6 +259,22 @@ bfd_set_desired_min_tx (bfd_main_t * bm, bfd_session_t * bs, u64 now,
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,
+ 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);
+ bfd_recalc_detection_time (bm, bs);
+ bfd_recalc_tx_interval (bm, bs);
+ bfd_calc_next_tx (bm, bs, now);
+ bfd_set_timer (bm, bs, now, handling_wakeup);
+}
+
void
bfd_session_start (bfd_main_t * bm, bfd_session_t * bs)
{
@@ -470,7 +507,9 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt,
bfd.SessionState is Up, and bfd.RemoteSessionState is Up) and a Poll
Sequence is not being transmitted.
*/
- if (now >= bs->tx_timeout_clocks)
+ /* sometimes the wheel expires an event a bit sooner than requested, account
+ for that here */
+ if (now + bm->wheel_inaccuracy >= bs->tx_timeout_clocks)
{
BFD_DBG ("Send periodic control frame for bs_idx=%lu", bs->bs_idx);
vlib_buffer_t *b = bfd_create_frame (vm, rt, bs);
@@ -484,7 +523,9 @@ bfd_send_periodic (vlib_main_t * vm, vlib_node_runtime_t * rt,
}
else
{
- BFD_DBG ("No need to send control frame now");
+ BFD_DBG
+ ("No need to send control frame now, now is %lu, tx_timeout is %lu",
+ now, bs->tx_timeout_clocks);
}
bfd_set_timer (bm, bs, now, handling_wakeup);
}
@@ -502,7 +543,10 @@ static void
bfd_check_rx_timeout (bfd_main_t * bm, bfd_session_t * bs, u64 now,
int handling_wakeup)
{
- if (bs->last_rx_clocks + bs->detection_time_clocks < now)
+ /* sometimes the wheel expires an event a bit sooner than requested, account
+ for that here */
+ if (bs->last_rx_clocks + bs->detection_time_clocks <=
+ now + bm->wheel_inaccuracy)
{
BFD_DBG ("Rx timeout, session goes down");
bfd_set_diag (bs, BFD_DIAG_CODE_det_time_exp);
@@ -538,31 +582,6 @@ bfd_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * rt, bfd_main_t * bm,
}
/*
- * bfd input routine
- */
-bfd_error_t
-bfd_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
-{
- // bfd_main_t *bm = &bfd_main;
- bfd_error_t e;
-
- /* find our interface */
- bfd_session_t *s = NULL;
- // bfd_get_intf (lm, vnet_buffer (b0)->sw_if_index[VLIB_RX]);
-
- if (!s)
- {
- /* bfd disabled on this interface, we're done */
- return BFD_ERROR_DISABLED;
- }
-
- /* Actually scan the packet */
- e = BFD_ERROR_NONE; // bfd_packet_scan (lm, n, vlib_buffer_get_current (b0));
-
- return e;
-}
-
-/*
* bfd process node function
*/
static uword
@@ -637,7 +656,6 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
if (!pool_is_free_index (bm->sessions, bs_idx))
{
bfd_session_t *bs = pool_elt_at_index (bm->sessions, bs_idx);
- bs->wheel_time_clocks = 0; /* no longer scheduled */
bfd_on_timeout (vm, rt, bm, bs, now);
}
}
@@ -714,6 +732,7 @@ bfd_main_init (vlib_main_t * vm)
BFD_DBG ("cps is %.2f", bm->cpu_cps);
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;
return 0;
}
@@ -864,14 +883,12 @@ bfd_consume_pkt (bfd_main_t * bm, const bfd_pkt_t * pkt, u32 bs_idx)
bs->remote_discr = pkt->my_disc;
bs->remote_state = bfd_pkt_get_state (pkt);
bs->remote_demand = bfd_pkt_get_demand (pkt);
- bs->remote_min_rx_us = clib_net_to_host_u32 (pkt->req_min_rx);
- bs->remote_min_rx_clocks = bfd_us_to_clocks (bm, bs->remote_min_rx_us);
- BFD_DBG ("Set remote min rx to %lu clocks/%.2fs", bs->remote_min_rx_clocks,
- bs->remote_min_rx_clocks / bm->cpu_cps);
+ u64 now = clib_cpu_time_now ();
+ bs->last_rx_clocks = now;
bs->remote_desired_min_tx_us = clib_net_to_host_u32 (pkt->des_min_tx);
bs->remote_detect_mult = pkt->head.detect_mult;
- bfd_recalc_detection_time (bm, bs);
- bs->last_rx_clocks = clib_cpu_time_now ();
+ bfd_set_remote_required_min_rx (bm, bs, now,
+ clib_net_to_host_u32 (pkt->req_min_rx), 0);
/* FIXME
If the Required Min Echo RX Interval field is zero, the
transmission of Echo packets, if any, MUST cease.
diff --git a/vnet/vnet/bfd/bfd_main.h b/vnet/vnet/bfd/bfd_main.h
index 727903bd..c72ea92a 100644
--- a/vnet/vnet/bfd/bfd_main.h
+++ b/vnet/vnet/bfd/bfd_main.h
@@ -49,7 +49,7 @@ typedef enum
typedef struct
{
/* index in bfd_main.sessions pool */
- uword bs_idx;
+ u32 bs_idx;
/* session state */
bfd_state_e local_state;
@@ -93,10 +93,13 @@ 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;
- /* set to value of timer in timing wheel, 0 if not set */
+ /* set to value of timer in timing wheel, 0 if never set */
u64 wheel_time_clocks;
/* transmit interval */
@@ -134,6 +137,9 @@ typedef struct
/* timing wheel for scheduling timeouts */
timing_wheel_t wheel;
+ /* timing wheel inaccuracy, in clocks */
+ u64 wheel_inaccuracy;
+
/* hashmap - bfd session by discriminator */
u32 *session_by_disc;
@@ -150,9 +156,6 @@ typedef struct
/* for generating random numbers */
u32 random_seed;
- /* pool of event subscribers */
- //event_subscriber_t *subscribers;
-
} bfd_main_t;
extern bfd_main_t bfd_main;
@@ -184,7 +187,6 @@ enum
BFD_EVENT_NEW_SESSION,
} bfd_process_event_e;
-bfd_error_t bfd_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0);
u8 *bfd_input_format_trace (u8 * s, va_list * args);
bfd_session_t *bfd_get_session (bfd_main_t * bm, bfd_transport_t t);
diff --git a/vnet/vnet/bfd/bfd_udp.c b/vnet/vnet/bfd/bfd_udp.c
index 9d75e3ad..3c747d86 100644
--- a/vnet/vnet/bfd/bfd_udp.c
+++ b/vnet/vnet/bfd/bfd_udp.c
@@ -442,7 +442,7 @@ static bfd_udp_error_t bfd_udp4_scan (vlib_main_t *vm, vlib_node_runtime_t *rt,
BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
return BFD_UDP_ERROR_BAD;
}
- BFD_DBG ("BFD session found, bs_idx=%d", bs->bs_idx);
+ BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
if (!bfd_verify_pkt_session (pkt, b->current_length, bs))
{
return BFD_UDP_ERROR_BAD;