* @brief A function type for post-rewrite fixups on midchain adjacency
*/
typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
- struct ip_adjacency_t_ * adj,
+ const struct ip_adjacency_t_ * adj,
vlib_buffer_t * b0,
const void *data);
/**
* @brief Flags on an IP adjacency
*/
-typedef enum ip_adjacency_flags_t_
+typedef enum adj_attr_t_
{
- ADJ_FLAG_NONE = 0,
-
/**
* Currently a sync walk is active. Used to prevent re-entrant walking
*/
- ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0),
+ ADJ_ATTR_SYNC_WALK_ACTIVE = 0,
/**
* Packets TX through the midchain do not increment the interface
* the packet will have traversed the interface's TX node, and hence have
* been counted, before it traverses ths midchain
*/
- ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1),
+ ADJ_ATTR_MIDCHAIN_NO_COUNT,
+ /**
+ * When stacking midchains on a fib-entry extract the choice from the
+ * load-balance returned based on an IP hash of the adj's rewrite
+ */
+ ADJ_ATTR_MIDCHAIN_IP_STACK,
+ /**
+ * If the midchain were to stack on its FIB entry a loop would form.
+ */
+ ADJ_ATTR_MIDCHAIN_LOOPED,
+} adj_attr_t;
+
+#define ADJ_ATTR_NAMES { \
+ [ADJ_ATTR_SYNC_WALK_ACTIVE] = "walk-active", \
+ [ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count", \
+ [ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack", \
+ [ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped", \
+}
+
+#define FOR_EACH_ADJ_ATTR(_attr) \
+ for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \
+ _attr <= ADJ_ATTR_MIDCHAIN_LOOPED; \
+ _attr++)
+
+/**
+ * @brief Flags on an IP adjacency
+ */
+typedef enum adj_flags_t_
+{
+ ADJ_FLAG_NONE = 0,
+ ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << ADJ_ATTR_SYNC_WALK_ACTIVE),
+ ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << ADJ_ATTR_MIDCHAIN_NO_COUNT),
+ ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
+ ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
} __attribute__ ((packed)) adj_flags_t;
+/**
+ * @brief Format adjacency flags
+ */
+extern u8* format_adj_flags(u8 * s, va_list * args);
+
/**
* @brief IP unicast adjacency.
* @note cache aligned.
*
- * An adjacency is a represenation of a peer on a particular link.
+ * An adjacency is a representation of a peer on a particular link.
*/
typedef struct ip_adjacency_t_
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
/**
- * Linkage into the FIB node grpah. First member since this type
+ * Linkage into the FIB node graph. First member since this type
* has 8 byte alignment requirements.
*/
fib_node_t ia_node;
/**
* The protocol of the neighbor/peer. i.e. the protocol with
- * which to interpret the 'next-hop' attirbutes of the sub-types.
+ * which to interpret the 'next-hop' attributes of the sub-types.
* 1-btyes
*/
fib_protocol_t ia_nh_proto;
* Fixup data passed back to the client in the fixup function
*/
const void *fixup_data;
+ /**
+ * the FIB entry this midchain resolves through. required for recursive
+ * loop detection.
+ */
+ fib_node_index_t fei;
} midchain;
/**
* IP_LOOKUP_NEXT_GLEAN
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
/* Rewrite in second/third cache lines */
- vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
+ VNET_DECLARE_REWRITE;
/**
* more control plane members that do not fit on the first cacheline
} ip_adjacency_t;
STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
- "IP adjacency cachline 0 is not offset");
+ "IP adjacency cacheline 0 is not offset");
STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
CLIB_CACHE_LINE_BYTES),
- "IP adjacency cachline 1 is more than one cachline size offset");
+ "IP adjacency cacheline 1 is more than one cacheline size offset");
/**
* @brief
extern const u8* adj_get_rewrite (adj_index_t ai);
/**
- * @brief Notify the adjacency subsystem that the features settings for
- * an interface have changed
+ * @brief descend the FIB graph looking for loops
+ *
+ * @param ai
+ * The adj index to traverse
+ *
+ * @param entry_indicies)
+ * A pointer to a vector of FIB entries already visited.
*/
-extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
+extern int adj_recursive_loop_detect (adj_index_t ai,
+ fib_node_index_t **entry_indicies);
/**
* @brief
- * The global adjacnecy pool. Exposed for fast/inline data-plane access
+ * The global adjacency pool. Exposed for fast/inline data-plane access
*/
extern ip_adjacency_t *adj_pool;
static inline ip_adjacency_t *
adj_get (adj_index_t adj_index)
{
- return (vec_elt_at_index(adj_pool, adj_index));
+ return (pool_elt_at_index(adj_pool, adj_index));
+}
+
+static inline int
+adj_is_valid(adj_index_t adj_index)
+{
+ return !(pool_is_free_index(adj_pool, adj_index));
}
/**