ADJ_BFD_STATE_UP,
} adj_bfd_state_t;
+#define ADJ_BFD_STATES { \
+ [ADJ_BFD_STATE_DOWN] = "down", \
+ [ADJ_BFD_STATE_UP] = "up", \
+}
+
+static const char *adj_bfd_state_names[] = ADJ_BFD_STATES;
+
/**
* BFD delegate daa
*/
adj_bfd_notify (bfd_listen_event_e event,
const bfd_session_t *session)
{
- const bfd_udp_key_t *key;
adj_bfd_delegate_t *abd;
- fib_protocol_t fproto;
adj_delegate_t *aed;
adj_index_t ai;
return;
}
- key = &session->udp.key;
-
- fproto = (ip46_address_is_ip4 (&key->peer_addr) ?
- FIB_PROTOCOL_IP4:
- FIB_PROTOCOL_IP6);
+ switch (session->transport)
+ {
+ case BFD_TRANSPORT_UDP4:
+ case BFD_TRANSPORT_UDP6:
+ /*
+ * pick up the same adjacency that the BFD session is using
+ * to send. The BFD session is holding a lock on this adj.
+ */
+ ai = session->udp.adj_index;
+ break;
+ default:
+ /*
+ * Don't know what adj this session uses
+ */
+ return;
+ }
- /*
- * find the adj that corresponds to the BFD session.
- */
- ai = adj_nbr_add_or_lock(fproto,
- fib_proto_to_link(fproto),
- &key->peer_addr,
- key->sw_if_index);
+ if (INDEX_INVALID == ai)
+ {
+ /* No associated Adjacency with the session */
+ return;
+ }
switch (event)
{
}
else
{
- /*
- * lock the adj. add the delegate.
- * Lockinging the adj prevents it being removed and thus maintains
- * the BFD derived states
- */
- adj_lock(ai);
-
/*
* allocate and init a new delegate struct
*/
pool_get(abd_pool, abd);
/*
- * pretend the session is up and skip the walk.
- * If we set it down then we get traffic loss on new children.
- * if we walk then we lose traffic for existing children. Wait
- * for the first BFD UP/DOWN before we let the session's state
- * influence forwarding.
+ * it would be best here if we could ignore this create and just
+ * wait for the first update, but this is not possible because
+ * BFD sessions are created in the down state, and can remain this
+ * way without transitioning to another state if the peer is
+ * unresponsive. So we have to assume down and wait for up.
*/
- abd->abd_state = ADJ_BFD_STATE_UP;
+ abd->abd_state = ADJ_BFD_STATE_DOWN;
abd->abd_index = session->bs_idx;
adj_delegate_add(adj_get(ai), ADJ_DELEGATE_BFD, abd - abd_pool);
+ adj_bfd_update_walk(ai);
}
break;
case BFD_LISTEN_EVENT_UPDATE:
/*
- * state change up/dowm and
+ * state change up/down and
*/
abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD));
{
/*
* has an associated BFD tracking delegate
- * remove the BFD tracking deletgate, update children, then
- * unlock the adj
+ * remove the BFD tracking delegate, update children
*/
adj_delegate_remove(ai, ADJ_DELEGATE_BFD);
pool_put(abd_pool, abd);
adj_bfd_update_walk(ai);
- adj_unlock(ai);
}
/*
* else
*/
break;
}
-
- /*
- * unlock match of the add-or-lock at the start
- */
- adj_unlock(ai);
}
int
{
const adj_bfd_delegate_t *abd = adj_bfd_from_const_base(aed);
- s = format(s, "BFD:[state:%d index:%d]",
- abd->abd_state,
+ s = format(s, "BFD:[state:%s index:%d]",
+ adj_bfd_state_names[abd->abd_state],
abd->abd_index);
return (s);
static clib_error_t *
adj_bfd_main_init (vlib_main_t * vm)
{
- clib_error_t * error = NULL;
-
- if ((error = vlib_call_init_function (vm, bfd_main_init)))
- return (error);
-
bfd_register_listener(adj_bfd_notify);
adj_delegate_register_type (ADJ_DELEGATE_BFD, &adj_delegate_vft);
- return (error);
+ return (0);
}
-VLIB_INIT_FUNCTION (adj_bfd_main_init);
+VLIB_INIT_FUNCTION (adj_bfd_main_init)=
+{
+ .runs_after = VLIB_INITS("bfd_main_init"),
+};