X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fadj%2Fadj_bfd.c;h=624d22fbccf75146e4822c9236a6826dbbb15f30;hb=8797168fe2f4fd32d241126181ad0d06c62c4eb4;hp=2d845ffcfd8769b2460bf809fadf5c5fddf4f7b2;hpb=a44b015aa012d3b07ed873925d47c6d5955b7dd2;p=vpp.git diff --git a/src/vnet/adj/adj_bfd.c b/src/vnet/adj/adj_bfd.c index 2d845ffcfd8..624d22fbccf 100644 --- a/src/vnet/adj/adj_bfd.c +++ b/src/vnet/adj/adj_bfd.c @@ -19,6 +19,64 @@ #include #include +/** + * Distillation of the BFD session states into a go/no-go for using + * the associated tracked adjacency + */ +typedef enum adj_bfd_state_t_ +{ + ADJ_BFD_STATE_DOWN, + 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 + */ +typedef struct adj_bfd_delegate_t_ +{ + /** + * BFD session state + */ + adj_bfd_state_t abd_state; + + /** + * BFD session index + */ + u32 abd_index; +} adj_bfd_delegate_t; + +/** + * Pool of delegates +*/ +static adj_bfd_delegate_t *abd_pool; + +static inline adj_bfd_delegate_t* +adj_bfd_from_base (adj_delegate_t *ad) +{ + if (NULL != ad) + { + return (pool_elt_at_index(abd_pool, ad->ad_index)); + } + return (NULL); +} + +static inline const adj_bfd_delegate_t* +adj_bfd_from_const_base (const adj_delegate_t *ad) +{ + if (NULL != ad) + { + return (pool_elt_at_index(abd_pool, ad->ad_index)); + } + return (NULL); +} + static adj_bfd_state_t adj_bfd_bfd_state_to_fib (bfd_state_e bstate) { @@ -57,6 +115,7 @@ 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; @@ -107,17 +166,23 @@ adj_bfd_notify (bfd_listen_event_e event, */ adj_lock(ai); - aed = adj_delegate_find_or_add(adj_get(ai), ADJ_DELEGATE_BFD); + /* + * 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 posible because + * BFD sessions are created in the down state, and can remain this + * way without transitioning to another state if the peer is + * unresponxive. So we have to assuem down and wait for up. */ - aed->ad_bfd_state = ADJ_BFD_STATE_UP; - aed->ad_bfd_index = session->bs_idx; + 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; @@ -125,11 +190,11 @@ adj_bfd_notify (bfd_listen_event_e event, /* * state change up/dowm and */ - aed = adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD); + abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD)); - if (NULL != aed) + if (NULL != abd) { - aed->ad_bfd_state = adj_bfd_bfd_state_to_fib(session->local_state); + abd->abd_state = adj_bfd_bfd_state_to_fib(session->local_state); adj_bfd_update_walk(ai); } /* @@ -142,15 +207,17 @@ adj_bfd_notify (bfd_listen_event_e event, /* * session has been removed. */ + abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD)); - if (adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD)) + if (NULL != abd) { /* * has an associated BFD tracking delegate * remove the BFD tracking deletgate, update children, then * unlock the adj */ - adj_delegate_remove(adj_get(ai), ADJ_DELEGATE_BFD); + adj_delegate_remove(ai, ADJ_DELEGATE_BFD); + pool_put(abd_pool, abd); adj_bfd_update_walk(ai); adj_unlock(ai); @@ -168,15 +235,40 @@ adj_bfd_notify (bfd_listen_event_e event, adj_unlock(ai); } +int +adj_bfd_is_up (adj_index_t ai) +{ + const adj_bfd_delegate_t *abd; + + abd = adj_bfd_from_base(adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD)); + + if (NULL == abd) + { + /* + * no BFD tracking - resolved + */ + return (!0); + } + else + { + /* + * defer to the state of the BFD tracking + */ + return (ADJ_BFD_STATE_UP == abd->abd_state); + } +} + /** * Print a delegate that represents BFD tracking */ static u8 * adj_delegate_fmt_bfd (const adj_delegate_t *aed, u8 *s) { - s = format(s, "BFD:[state:%d index:%d]", - aed->ad_bfd_state, - aed->ad_bfd_index); + const adj_bfd_delegate_t *abd = adj_bfd_from_const_base(aed); + + s = format(s, "BFD:[state:%s index:%d]", + adj_bfd_state_names[abd->abd_state], + abd->abd_index); return (s); }