* 'glean' mean use the packet's destination address as the target
* address in the ARP packet.
* UNSHARED. Only one per-interface.
- * - midchain: a nighbour adj on a virtual/tunnel interface.
+ * - midchain: a neighbour adj on a virtual/tunnel interface.
*
* The API to create and update the adjacency is very sub-type specific. This
* is intentional as it encourages the user to carefully consider which adjacency
* is important to enforce this approach as space in the adjacency is a premium,
* as we need it to fit in 1 cache line.
*
- * the API is also based around an index to an ajdacency not a raw pointer. This
+ * the API is also based around an index to an adjacency not a raw pointer. This
* is so the user doesn't suffer the same limp inducing firearm injuries that
- * the author suffered as the adjacenices can realloc.
+ * the author suffered as the adjacencies can realloc.
*/
#ifndef __ADJ_H__
/** Multicast Adjacency. */
IP_LOOKUP_NEXT_MCAST,
- /** Broadcasr Adjacency. */
+ /** Broadcast Adjacency. */
IP_LOOKUP_NEXT_BCAST,
- /** Multicast Midchain Adjacency. An Adjacency for sending macst packets
+ /** Multicast Midchain Adjacency. An Adjacency for sending multicast packets
* on a tunnel/virtual interface */
IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
extern const ip46_address_t ADJ_BCAST_ADDR;
/**
- * Forward delcartion
+ * Forward declaration
*/
struct ip_adjacency_t_;
* @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);
/**
* Packets TX through the midchain do not increment the interface
* counters. This should be used when the adj is associated with an L2
- * interface and that L2 interface is in a bridege domain. In that case
+ * interface and that L2 interface is in a bridge domain. In that case
* the packet will have traversed the interface's TX node, and hence have
* been counted, before it traverses ths midchain
*/
* If the midchain were to stack on its FIB entry a loop would form.
*/
ADJ_ATTR_MIDCHAIN_LOOPED,
+ /**
+ * the fixup function is standard IP4o4 header
+ */
+ ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR,
+ /**
+ * the fixup function performs the flow hash
+ * this means the flow hash is performed on the inner
+ * header, where the entropy is higher.
+ */
+ ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH,
} adj_attr_t;
#define ADJ_ATTR_NAMES { \
[ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count", \
[ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack", \
[ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped", \
+ [ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup", \
+ [ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH] = "midchain-flow-hash", \
}
-#define FOR_EACH_ADJ_ATTR(_attr) \
- for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \
- _attr <= ADJ_ATTR_MIDCHAIN_LOOPED; \
+#define FOR_EACH_ADJ_ATTR(_attr) \
+ for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \
+ _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH; \
_attr++)
/**
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),
+ ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR),
+ ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH),
} __attribute__ ((packed)) adj_flags_t;
/**
* @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;
-
/**
- * Next hop after ip4-lookup.
- * This is not accessed in the rewrite nodes.
- * 1-bytes
+ * feature [arc] config index
*/
- ip_lookup_next_t lookup_next_index;
-
- /**
- * link/ether-type
- * 1 bytes
- */
- vnet_link_t ia_link;
-
- /**
- * The protocol of the neighbor/peer. i.e. the protocol with
- * which to interpret the 'next-hop' attirbutes of the sub-types.
- * 1-btyes
- */
- fib_protocol_t ia_nh_proto;
-
- /**
- * Flags on the adjacency
- * 1-bytes
- */
- adj_flags_t ia_flags;
+ u32 ia_cfg_index;
union
{
* IP_LOOKUP_NEXT_MIDCHAIN
*
* A nbr adj that is also recursive. Think tunnels.
- * A nbr adj can transition to be of type MDICHAIN
+ * A nbr adj can transition to be of type MIDCHAIN
* so be sure to leave the two structs with the next_hop
* fields aligned.
*/
* loop detection.
*/
fib_node_index_t fei;
+
+ /** spare space */
+ u8 __ia_midchain_pad[4];
+
} midchain;
/**
* IP_LOOKUP_NEXT_GLEAN
*/
struct
{
- ip46_address_t receive_addr;
+ fib_prefix_t rx_pfx;
} glean;
} sub_type;
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
- /* Rewrite in second/third cache lines */
- vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
+ /** Rewrite in second and third cache lines */
+ VNET_DECLARE_REWRITE;
/**
* more control plane members that do not fit on the first cacheline
*/
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline3);
+
/**
* A sorted vector of delegates
*/
struct adj_delegate_t_ *ia_delegates;
+ /**
+ * The VLIB node in which this adj is used to forward packets
+ */
+ u32 ia_node_index;
+
+ /**
+ * Next hop after ip4-lookup.
+ * This is not accessed in the rewrite nodes.
+ * 1-bytes
+ */
+ ip_lookup_next_t lookup_next_index;
+
+ /**
+ * link/ether-type
+ * 1 bytes
+ */
+ vnet_link_t ia_link;
+
+ /**
+ * The protocol of the neighbor/peer. i.e. the protocol with
+ * which to interpret the 'next-hop' attributes of the sub-types.
+ * 1-bytes
+ */
+ fib_protocol_t ia_nh_proto;
+
+ /**
+ * Flags on the adjacency
+ * 1-bytes
+ */
+ adj_flags_t ia_flags;
+
+ /**
+ * Free space on the fourth cacheline (not used in the DP)
+ */
+ u8 __ia_pad[48];
} 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");
+#if defined __x86_64__
+STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline3) ==
+ 3 * CLIB_CACHE_LINE_BYTES),
+ "IP adjacency cacheline 3 is more than one cacheline size offset");
+/* An adj fits into 4 cachelines on your average machine */
+STATIC_ASSERT_SIZEOF (ip_adjacency_t, 4 * 64);
+#endif
/**
* @brief
/**
* @brief
* Add a child dependent to an adjacency. The child will
- * thus be informed via its registerd back-walk function
+ * thus be informed via its registered back-walk function
* when the adjacency state changes.
*/
extern u32 adj_child_add(adj_index_t adj_index,
*/
extern const u8* adj_get_rewrite (adj_index_t ai);
-/**
- * @brief Notify the adjacency subsystem that the features settings for
- * an interface have changed
- */
-extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
-
/**
* @brief descend the FIB graph looking for loops
*
/**
* @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));
}
/**