aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/adj
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/adj')
-rw-r--r--src/vnet/adj/adj.c28
-rw-r--r--src/vnet/adj/adj.h2
-rw-r--r--src/vnet/adj/adj_bfd.c113
-rw-r--r--src/vnet/adj/adj_delegate.c122
-rw-r--r--src/vnet/adj/adj_delegate.h125
-rw-r--r--src/vnet/adj/adj_internal.h12
6 files changed, 269 insertions, 133 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index e1d7821fd39..386070ed3f8 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -129,18 +129,13 @@ format_ip_adjacency (u8 * s, va_list * args)
if (fiaf & FORMAT_IP_ADJACENCY_DETAIL)
{
- adj_delegate_type_t adt;
- adj_delegate_t *aed;
vlib_counter_t counts;
vlib_get_combined_counter(&adjacency_counters, adj_index, &counts);
s = format (s, "\n counts:[%Ld:%Ld]", counts.packets, counts.bytes);
s = format (s, "\n locks:%d", adj->ia_node.fn_locks);
s = format(s, "\n delegates:\n ");
- FOR_EACH_ADJ_DELEGATE(adj, adt, aed,
- {
- s = format(s, " %U\n", format_adj_delegate, aed);
- });
+ adj_delegate_format(s, adj);
s = format(s, "\n children:\n ");
s = fib_node_children_format(adj->ia_node.fn_children, s);
@@ -162,7 +157,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
ASSERT(0 == fib_node_list_get_size(adj->ia_node.fn_children));
ADJ_DBG(adj, "last-lock-gone");
- adj_delegate_vft_lock_gone(adj);
+ adj_delegate_adj_deleted(adj);
vlib_worker_thread_barrier_sync (vm);
@@ -430,24 +425,7 @@ adj_get_sw_if_index (adj_index_t ai)
int
adj_is_up (adj_index_t ai)
{
- const adj_delegate_t *aed;
-
- aed = adj_delegate_get(adj_get(ai), ADJ_DELEGATE_BFD);
-
- if (NULL == aed)
- {
- /*
- * no BFD tracking - resolved
- */
- return (!0);
- }
- else
- {
- /*
- * defer to the state of the BFD tracking
- */
- return (ADJ_BFD_STATE_UP == aed->ad_bfd_state);
- }
+ return (adj_bfd_is_up(ai));
}
/**
diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h
index bcf6c041209..0434d7c89e5 100644
--- a/src/vnet/adj/adj.h
+++ b/src/vnet/adj/adj.h
@@ -273,7 +273,7 @@ typedef struct ip_adjacency_t_
/**
* A sorted vector of delegates
*/
- struct adj_delegate_t_ *ia_delegates;
+ struct adj_delegate_t_ **ia_delegates;
} ip_adjacency_t;
diff --git a/src/vnet/adj/adj_bfd.c b/src/vnet/adj/adj_bfd.c
index 2d845ffcfd8..a4e7e277298 100644
--- a/src/vnet/adj/adj_bfd.c
+++ b/src/vnet/adj/adj_bfd.c
@@ -19,6 +19,66 @@
#include <vnet/adj/adj_nbr.h>
#include <vnet/fib/fib_walk.h>
+/**
+ * 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;
+
+/**
+ * BFD delegate daa
+ */
+typedef struct adj_bfd_delegate_t_
+{
+ /**
+ * Base class,linkage to the adjacency
+ */
+ adj_delegate_t abd_link;
+
+ /**
+ * 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 (NULL);
+ }
+ return ((adj_bfd_delegate_t*)((char*)ad -
+ STRUCT_OFFSET_OF(adj_bfd_delegate_t,
+ abd_link)));
+}
+
+static inline const adj_bfd_delegate_t*
+adj_bfd_from_const_base (const adj_delegate_t *ad)
+{
+ if (NULL == ad)
+ {
+ return (NULL);
+ }
+ return ((adj_bfd_delegate_t*)((char*)ad -
+ STRUCT_OFFSET_OF(adj_bfd_delegate_t,
+ abd_link)));
+}
+
static adj_bfd_state_t
adj_bfd_bfd_state_to_fib (bfd_state_e bstate)
{
@@ -57,6 +117,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,7 +168,10 @@ 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.
@@ -116,8 +180,10 @@ adj_bfd_notify (bfd_listen_event_e event,
* for the first BFD UP/DOWN before we let the session's state
* influence forwarding.
*/
- aed->ad_bfd_state = ADJ_BFD_STATE_UP;
- aed->ad_bfd_index = session->bs_idx;
+ abd->abd_state = ADJ_BFD_STATE_UP;
+ abd->abd_index = session->bs_idx;
+
+ adj_delegate_add(adj_get(ai), ADJ_DELEGATE_BFD, &abd->abd_link);
}
break;
@@ -125,11 +191,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 +208,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 +236,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)
{
+ const adj_bfd_delegate_t *abd = adj_bfd_from_const_base(aed);
+
s = format(s, "BFD:[state:%d index:%d]",
- aed->ad_bfd_state,
- aed->ad_bfd_index);
+ abd->abd_state,
+ abd->abd_index);
return (s);
}
diff --git a/src/vnet/adj/adj_delegate.c b/src/vnet/adj/adj_delegate.c
index 0125c89f5fb..1cc7c4b94bd 100644
--- a/src/vnet/adj/adj_delegate.c
+++ b/src/vnet/adj/adj_delegate.c
@@ -22,23 +22,28 @@
*/
static adj_delegate_vft_t *ad_vfts;
+/**
+ * The value of the last dynamically allocated delegeate value
+ */
+static adj_delegate_type_t ad_max_id = ADJ_DELEGATE_BFD;
+
static adj_delegate_t *
adj_delegate_find_i (const ip_adjacency_t *adj,
adj_delegate_type_t type,
u32 *index)
{
- adj_delegate_t *delegate;
+ adj_delegate_t **delegate;
int ii;
ii = 0;
vec_foreach(delegate, adj->ia_delegates)
{
- if (delegate->ad_type == type)
+ if ((*delegate)->ad_type == type)
{
if (NULL != index)
*index = ii;
- return (delegate);
+ return (*delegate);
}
else
{
@@ -57,12 +62,14 @@ adj_delegate_get (const ip_adjacency_t *adj,
}
void
-adj_delegate_remove (ip_adjacency_t *adj,
+adj_delegate_remove (adj_index_t ai,
adj_delegate_type_t type)
{
+ ip_adjacency_t *adj;
adj_delegate_t *aed;
u32 index = ~0;
+ adj = adj_get(ai);
aed = adj_delegate_find_i(adj, type, &index);
ASSERT(NULL != aed);
@@ -74,29 +81,29 @@ static int
adj_delegate_cmp_for_sort (void * v1,
void * v2)
{
- adj_delegate_t *delegate1 = v1, *delegate2 = v2;
+ adj_delegate_t **delegate1 = v1, **delegate2 = v2;
- return (delegate1->ad_type - delegate2->ad_type);
+ return ((*delegate1)->ad_type - (*delegate2)->ad_type);
}
static void
adj_delegate_init (ip_adjacency_t *adj,
- adj_delegate_type_t type)
+ adj_delegate_type_t adt,
+ adj_delegate_t *aed)
{
- adj_delegate_t delegate = {
- .ad_adj_index = adj_get_index(adj),
- .ad_type = type,
- };
+ aed->ad_adj_index = adj_get_index(adj);
+ aed->ad_type = adt;
- vec_add1(adj->ia_delegates, delegate);
+ vec_add1(adj->ia_delegates, aed);
vec_sort_with_function(adj->ia_delegates,
adj_delegate_cmp_for_sort);
}
-adj_delegate_t *
-adj_delegate_find_or_add (ip_adjacency_t *adj,
- adj_delegate_type_t adt)
+int
+adj_delegate_add (ip_adjacency_t *adj,
+ adj_delegate_type_t adt,
+ adj_delegate_t *ad)
{
adj_delegate_t *delegate;
@@ -104,30 +111,52 @@ adj_delegate_find_or_add (ip_adjacency_t *adj,
if (NULL == delegate)
{
- adj_delegate_init(adj, adt);
+ adj_delegate_init(adj, adt, ad);
+ }
+ else
+ {
+ return (-1);
}
- return (adj_delegate_get(adj, adt));
+ return (0);
}
-void adj_delegate_vft_lock_gone (ip_adjacency_t *adj)
+void
+adj_delegate_adj_deleted (ip_adjacency_t *adj)
{
- adj_delegate_t *delegate;
- vec_foreach(delegate, adj->ia_delegates) {
- if (ad_vfts[delegate->ad_type].adv_last_lock)
- ad_vfts[delegate->ad_type].adv_last_lock(adj, delegate);
+ adj_delegate_t **delegate;
+
+ vec_foreach(delegate, adj->ia_delegates)
+ {
+ if (ad_vfts[(*delegate)->ad_type].adv_adj_deleted)
+ {
+ ad_vfts[(*delegate)->ad_type].adv_adj_deleted(*delegate);
+ }
}
+
+ vec_reset_length(adj->ia_delegates);
}
-u8 *
-format_adj_delegate (u8 * s, va_list * args)
+u8*
+adj_delegate_format (u8* s, ip_adjacency_t *adj)
{
- adj_delegate_t *aed;
+ adj_delegate_t **aed;
- aed = va_arg (*args, adj_delegate_t *);
- if (ad_vfts[aed->ad_type].adv_format)
- return ad_vfts[aed->ad_type].adv_format(aed, s);
- return format(s, "unknown delegate");
+ vec_foreach(aed, adj->ia_delegates)
+ {
+ if (ad_vfts[(*aed)->ad_type].adv_format)
+ {
+ s = format(s, "{");
+ s = ad_vfts[(*aed)->ad_type].adv_format(*aed, s);
+ s = format(s, "}");
+ }
+ else
+ {
+ s = format(s, "{unknown delegate}");
+ }
+ }
+
+ return (s);
}
/**
@@ -135,17 +164,34 @@ format_adj_delegate (u8 * s, va_list * args)
*
* Register the function table for a given type
*/
-
void
adj_delegate_register_type (adj_delegate_type_t type,
const adj_delegate_vft_t *vft)
{
- /*
- * assert that one only registration is made per-node type
- */
- if (vec_len(ad_vfts) > type)
- ASSERT(NULL == ad_vfts[type].adv_last_lock);
-
- vec_validate(ad_vfts, type);
- ad_vfts[type] = *vft;
+ /*
+ * assert that one only registration is made per-node type
+ */
+ if (vec_len(ad_vfts) > type)
+ ASSERT(NULL == ad_vfts[type].adv_adj_deleted);
+
+ vec_validate(ad_vfts, type);
+ ad_vfts[type] = *vft;
+}
+
+/**
+ * adj_delegate_register_new_type
+ *
+ * Register the function table for a new type
+ */
+adj_delegate_type_t
+adj_delegate_register_new_type (const adj_delegate_vft_t *vft)
+{
+ adj_delegate_type_t type;
+
+ type = ++ad_max_id;
+
+ vec_validate(ad_vfts, type);
+ ad_vfts[type] = *vft;
+
+ return (type);
}
diff --git a/src/vnet/adj/adj_delegate.h b/src/vnet/adj/adj_delegate.h
index 9f7d8c64afc..b57900bf595 100644
--- a/src/vnet/adj/adj_delegate.h
+++ b/src/vnet/adj/adj_delegate.h
@@ -12,6 +12,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * A Delagate is a means to implement the Delagation design pattern;
+ * the extension of an object's functionality through the composition of,
+ * and delgation to, other objects.
+ * These 'other' objects are delegates. Delagates are thus attached to
+ * ADJ objects to extend their functionality.
+ */
#ifndef __ADJ_DELEGATE_T__
#define __ADJ_DELEGATE_T__
@@ -19,7 +26,10 @@
#include <vnet/adj/adj.h>
/**
- * Delegate types
+ * Built-in delegate types.
+ * When adding new types, if your code is within the vnet subsystem, then add a
+ * new type here. If not then use the adj_delegate_register_new_type API to
+ * register a new type.
*/
typedef enum adj_delegate_type_t_ {
/**
@@ -28,35 +38,12 @@ typedef enum adj_delegate_type_t_ {
ADJ_DELEGATE_BFD,
} adj_delegate_type_t;
-#define FOR_EACH_ADJ_DELEGATE(_adj, _adt, _aed, _body) \
-{ \
- for (_adt = ADJ_DELEGATE_BFD; \
- _adt <= ADJ_DELEGATE_BFD; \
- _adt++) \
- { \
- _aed = adj_delegate_get(_adj, _adt); \
- if (NULL != _aed) { \
- _body; \
- } \
- } \
-}
-
-/**
- * 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;
-
/**
- * A Delagate is a means to implement the Delagation design pattern;
- * the extension of an object's functionality through the composition of,
- * and delgation to, other objects.
- * These 'other' objects are delegates. Delagates are thus attached to
- * ADJ objects to extend their functionality.
+ * Adj delegate. This object should be contained within all type specific
+ * delegates. i.e. this is the base class to all type specific derived classes.
+ * With this model the delegate provider is free to manage the memory of the
+ * delegate in the way it chooses. Specifically it can assign them from its own
+ * pools and thus, for example, add the delegates to the FIB node graph.
*/
typedef struct adj_delegate_t_
{
@@ -69,47 +56,69 @@ typedef struct adj_delegate_t_
* The delagate type
*/
adj_delegate_type_t ad_type;
-
- /**
- * A union of data for the different delegate types
- */
- union
- {
- /**
- * BFD delegate daa
- */
- struct {
- /**
- * BFD session state
- */
- adj_bfd_state_t ad_bfd_state;
- /**
- * BFD session index
- */
- u32 ad_bfd_index;
- };
- };
} adj_delegate_t;
/**
- * An ADJ delegate virtual function table
+ * Indication that the adjacency has been deleted. The delegate provider should free
+ * the delegate.
+ */
+typedef void (*adj_delegate_adj_deleted_t)(adj_delegate_t *aed);
+
+/**
+ * Format function for the delegate
*/
-typedef void (*adj_delegate_last_lock_gone_t)(ip_adjacency_t *adj, adj_delegate_t *aed);
typedef u8 * (*adj_delegate_format_t)(const adj_delegate_t *aed, u8 *s);
+
+/**
+ * An ADJ delegate virtual function table
+ */
typedef struct adj_delegate_vft_t_ {
- adj_delegate_format_t adv_format;
- adj_delegate_last_lock_gone_t adv_last_lock;
+ adj_delegate_format_t adv_format;
+ adj_delegate_adj_deleted_t adv_adj_deleted;
} adj_delegate_vft_t;
-extern void adj_delegate_remove(ip_adjacency_t *adj,
+/**
+ * @brief Remove a delegate from an adjacency
+ *
+ * @param ai The adjacency to remove the delegate from
+ * @param type The type of delegate being removed
+ */
+extern void adj_delegate_remove(adj_index_t ai,
adj_delegate_type_t type);
-extern adj_delegate_t *adj_delegate_find_or_add(ip_adjacency_t *adj,
- adj_delegate_type_t fdt);
+/**
+ * @brief Add a delegate to an adjacency
+ *
+ * @param ai The adjacency to add the delegate to
+ * @param type The type of delegate being added
+ * @param ad The delegate. The provider should allocate memory for this object
+ * Typically this is a 'derived' class with the
+ * adj_delegate_t struct embedded within.
+ */
+extern int adj_delegate_add(ip_adjacency_t *adj,
+ adj_delegate_type_t fdt,
+ adj_delegate_t *ad);
+
+
+/**
+ * @brief Get a delegate from an adjacency
+ *
+ * @param ai The adjacency to get the delegate from
+ * @param type The type of delegate being sought
+ */
extern adj_delegate_t *adj_delegate_get(const ip_adjacency_t *adj,
adj_delegate_type_t type);
-extern u8 *format_adj_delegate(u8 * s, va_list * args);
-extern void adj_delegate_register_type(adj_delegate_type_t type, const adj_delegate_vft_t *vft);
+/**
+ * @brief Register a VFT for one of the built-in types
+ */
+extern void adj_delegate_register_type(adj_delegate_type_t type,
+ const adj_delegate_vft_t *vft);
+
+/**
+ * @brief create a new delegate type and register a new VFT
+ */
+extern adj_delegate_type_t adj_delegate_register_new_type(
+ const adj_delegate_vft_t *vft);
#endif
diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h
index 55afe55fa79..efaa11d5346 100644
--- a/src/vnet/adj/adj_internal.h
+++ b/src/vnet/adj/adj_internal.h
@@ -126,6 +126,16 @@ extern void adj_mcast_remove(fib_protocol_t proto,
u32 sw_if_index);
extern u32 adj_dpo_get_urpf(const dpo_id_t *dpo);
-extern void adj_delegate_vft_lock_gone(ip_adjacency_t *adj);
+
+/*
+ * Adj BFD
+ */
+extern int adj_bfd_is_up (adj_index_t ai);
+
+/*
+ * Adj delegates
+ */
+extern void adj_delegate_adj_deleted(ip_adjacency_t *adj);
+extern u8* adj_delegate_format(u8* s, ip_adjacency_t *adj);
#endif