* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/** @file Definitions for all things IP (v4|v6) unicast and multicast lookup related.
+ - Adjacency definitions and registration
+ - callbacks on route add
+ - callbacks on interface address change
+ */
#ifndef included_ip_lookup_h
#define included_ip_lookup_h
#include <vnet/vnet.h>
#include <vlib/buffer.h>
#include <vnet/ip/ip4_packet.h>
+#include <vnet/ip/ip6_packet.h>
-/* Next index stored in adjacency. */
+/** @brief Common (IP4/IP6) next index stored in adjacency. */
typedef enum {
- /* Packet does not match any route in table. */
+ /** Packet does not match any route in table. */
IP_LOOKUP_NEXT_MISS,
- /* Adjacency says to drop or punt this packet. */
+ /** Adjacency to drop this packet. */
IP_LOOKUP_NEXT_DROP,
+ /** Adjacency to punt this packet. */
IP_LOOKUP_NEXT_PUNT,
- /* This packet is for one of our own IP addresses. */
+ /** This packet is for one of our own IP addresses. */
IP_LOOKUP_NEXT_LOCAL,
- /* This packet matches an "interface route" and packets
+ /** This packet matches an "interface route" and packets
need to be passed to ARP to find rewrite string for
this destination. */
IP_LOOKUP_NEXT_ARP,
- /* This packet is to be rewritten and forwarded to the next
+ /** This packet is to be rewritten and forwarded to the next
processing node. This is typically the output interface but
might be another node for further output processing. */
IP_LOOKUP_NEXT_REWRITE,
- /* This packet needs to be classified */
+ /** This packet needs to be classified */
IP_LOOKUP_NEXT_CLASSIFY,
- /* This packet needs to go to MAP - RFC7596, RFC7597 */
+ /** This packet needs to go to MAP - RFC7596, RFC7597 */
IP_LOOKUP_NEXT_MAP,
- /* This packet needs to go to MAP with Translation - RFC7599 */
+ /** This packet needs to go to MAP with Translation - RFC7599 */
IP_LOOKUP_NEXT_MAP_T,
- /* This packets needs to go to 6RD (RFC5969) */
- IP_LOOKUP_NEXT_SIXRD,
+ /** This packets needs to go to indirect next hop */
+ IP_LOOKUP_NEXT_INDIRECT,
- /* Hop-by-hop header handling */
- IP_LOOKUP_NEXT_HOP_BY_HOP,
- IP_LOOKUP_NEXT_ADD_HOP_BY_HOP,
- IP_LOOKUP_NEXT_POP_HOP_BY_HOP,
+ /** This packets needs to go to ICMP error */
+ IP_LOOKUP_NEXT_ICMP_ERROR,
IP_LOOKUP_N_NEXT,
} ip_lookup_next_t;
-/* Flow hash configuration */
+typedef enum {
+ IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT,
+} ip4_lookup_next_t;
+
+typedef enum {
+ /** Hop-by-hop header handling */
+ IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT,
+ IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP,
+ IP6_LOOKUP_NEXT_POP_HOP_BY_HOP,
+ IP6_LOOKUP_N_NEXT,
+} ip6_lookup_next_t;
+
+#define IP4_LOOKUP_NEXT_NODES { \
+ [IP_LOOKUP_NEXT_MISS] = "ip4-miss", \
+ [IP_LOOKUP_NEXT_DROP] = "ip4-drop", \
+ [IP_LOOKUP_NEXT_PUNT] = "ip4-punt", \
+ [IP_LOOKUP_NEXT_LOCAL] = "ip4-local", \
+ [IP_LOOKUP_NEXT_ARP] = "ip4-arp", \
+ [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite-transit", \
+ [IP_LOOKUP_NEXT_CLASSIFY] = "ip4-classify", \
+ [IP_LOOKUP_NEXT_MAP] = "ip4-map", \
+ [IP_LOOKUP_NEXT_MAP_T] = "ip4-map-t", \
+ [IP_LOOKUP_NEXT_INDIRECT] = "ip4-indirect", \
+ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \
+}
+
+#define IP6_LOOKUP_NEXT_NODES { \
+ [IP_LOOKUP_NEXT_MISS] = "ip6-miss", \
+ [IP_LOOKUP_NEXT_DROP] = "ip6-drop", \
+ [IP_LOOKUP_NEXT_PUNT] = "ip6-punt", \
+ [IP_LOOKUP_NEXT_LOCAL] = "ip6-local", \
+ [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \
+ [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \
+ [IP_LOOKUP_NEXT_CLASSIFY] = "ip6-classify", \
+ [IP_LOOKUP_NEXT_MAP] = "ip6-map", \
+ [IP_LOOKUP_NEXT_MAP_T] = "ip6-map-t", \
+ [IP_LOOKUP_NEXT_INDIRECT] = "ip6-indirect", \
+ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error", \
+ [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \
+ [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \
+ [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \
+}
+
+/** Flow hash configuration */
#define IP_FLOW_HASH_SRC_ADDR (1<<0)
#define IP_FLOW_HASH_DST_ADDR (1<<1)
#define IP_FLOW_HASH_PROTO (1<<2)
#define IP_FLOW_HASH_DST_PORT (1<<4)
#define IP_FLOW_HASH_REVERSE_SRC_DST (1<<5)
-/* Default: 5-tuple without the "reverse" bit */
+/** Default: 5-tuple without the "reverse" bit */
#define IP_FLOW_HASH_DEFAULT (0x1F)
#define foreach_flow_hash_bit \
_(proto, IP_FLOW_HASH_PROTO) \
_(reverse, IP_FLOW_HASH_REVERSE_SRC_DST)
-/* IP unicast adjacency. */
+#define IP_ADJACENCY_OPAQUE_SZ 16
+/** @brief IP unicast adjacency.
+ @note cache aligned.
+*/
typedef struct {
CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
- /* Handle for this adjacency in adjacency heap. */
+ /** Handle for this adjacency in adjacency heap. */
u32 heap_handle;
STRUCT_MARK(signature_start);
- /* Interface address index for this local/arp adjacency. */
+ /** Interface address index for this local/arp adjacency. */
u32 if_address_index;
- /* Number of adjecencies in block. Greater than 1 means multipath;
+ /** Number of adjecencies in block. Greater than 1 means multipath;
otherwise equal to 1. */
u16 n_adj;
- /* Next hop after ip4-lookup. */
+ /** Next hop after ip4-lookup. */
union {
ip_lookup_next_t lookup_next_index : 16;
u16 lookup_next_index_as_int;
};
- /* Force re-lookup in a different FIB. ~0 => normal behavior */
+ /** Force re-lookup in a different FIB. ~0 => normal behavior */
i16 explicit_fib_index;
u16 mcast_group_index;
- /* Highest possible perf subgraph arc interposition, e.g. for ip6 ioam */
+ /** Highest possible perf subgraph arc interposition, e.g. for ip6 ioam */
u16 saved_lookup_next_index;
union {
- /* IP_LOOKUP_NEXT_ARP only */
+ /** IP_LOOKUP_NEXT_ARP only */
struct {
- union {
- ip4_address_t ip4;
- } next_hop;
- u32 next_adj_index_with_same_next_hop;
+ ip46_address_t next_hop;
} arp;
- /* IP_LOOKUP_NEXT_CLASSIFY only */
+ /** IP_LOOKUP_NEXT_CLASSIFY only */
struct {
u16 table_index;
} classify;
+ /** IP_LOOKUP_NEXT_INDIRECT only */
+ struct {
+ ip46_address_t next_hop;
+ } indirect;
+ u8 opaque[IP_ADJACENCY_OPAQUE_SZ];
};
+ /** @brief Special format function for this adjacency.
+ * Specifically good for cases which use the entire rewrite
+ * for their own purposes. Can easily reduce to a u16 or a u8 if/when
+ * the first cache line reads "full" on the free space gas gauge.
+ */
+ u32 special_adjacency_format_function_index; /* 0 is invalid */
STRUCT_MARK(signature_end);
- /* Number of FIB entries sharing this adjacency */
+ /** Number of FIB entries sharing this adjacency */
u32 share_count;
- /* Use this adjacency instead */
+ /** Use this adjacency instead */
u32 next_adj_with_signature;
CLIB_CACHE_LINE_ALIGN_MARK(cacheline1);
- /* Rewrite in second/third cache lines */
+ /** Rewrite in second/third cache lines */
vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
} ip_adjacency_t;
uword signature = 0xfeedfaceULL;
/* Skip heap handle, sum everything up to but not including share_count */
- signature = hash_memory64
+ signature = hash_memory
(STRUCT_MARK_PTR(adj, signature_start),
STRUCT_OFFSET_OF(ip_adjacency_t, signature_end)
- STRUCT_OFFSET_OF(ip_adjacency_t, signature_start),
signature);
/* and the rewrite */
- signature = hash_memory64 (&adj->rewrite_header, VLIB_BUFFER_PRE_DATA_SIZE,
+ signature = hash_memory (&adj->rewrite_header, VLIB_BUFFER_PRE_DATA_SIZE,
signature);
return signature;
}
u32 * config_index_by_sw_if_index;
} ip_config_main_t;
+//Function type used to register formatting of a custom adjacency formatting
+typedef u8 *(* ip_adjacency_format_fn)(u8 * s,
+ struct ip_lookup_main_t * lm,
+ ip_adjacency_t *adj);
+
+typedef struct ip_adj_register_struct {
+ struct ip_adj_register_struct *next;
+ char *node_name; //Name of the node for this registered adjacency
+ ip_adjacency_format_fn fn; //Formatting function of this adjacency
+ u32 *next_index; //some place where the next index to be used will be put at init
+} ip_adj_register_t;
+
typedef struct ip_lookup_main_t {
- /* Adjacency heap. */
+ /** Adjacency heap. */
ip_adjacency_t * adjacency_heap;
- /* Adjacency packet/byte counters indexed by adjacency index. */
+ /** Adjacency packet/byte counters indexed by adjacency index. */
vlib_combined_counter_main_t adjacency_counters;
- /* Heap of (next hop, weight) blocks. Sorted by next hop. */
+ /** Heap of (next hop, weight) blocks. Sorted by next hop. */
ip_multipath_next_hop_t * next_hop_heap;
- /* Indexed by heap_handle from ip_adjacency_t. */
+ /** Indexed by heap_handle from ip_adjacency_t. */
ip_multipath_adjacency_t * multipath_adjacencies;
- /* Adjacency by signature hash */
+ /** Adjacency by signature hash */
uword * adj_index_by_signature;
- /* Temporary vectors for looking up next hops in hash. */
+ /** Temporary vectors for looking up next hops in hash. */
ip_multipath_next_hop_t * next_hop_hash_lookup_key;
ip_multipath_next_hop_t * next_hop_hash_lookup_key_normalized;
- /* Hash table mapping normalized next hops and weights
+ /** Hash table mapping normalized next hops and weights
to multipath adjacency index. */
uword * multipath_adjacency_by_next_hops;
u32 * adjacency_remap_table;
u32 n_adjacency_remaps;
- /* If average error per adjacency is less than this threshold adjacency block
+ /** If average error per adjacency is less than this threshold adjacency block
size is accepted. */
f64 multipath_next_hop_error_tolerance;
- /* Adjacency index for routing table misses, local punts, and drops. */
+ /** Adjacency index for routing table misses, local punts, and drops. */
u32 miss_adj_index, drop_adj_index, local_adj_index;
- /* Miss adjacency is always first in adjacency table. */
+ /** Miss adjacency is always first in adjacency table. */
#define IP_LOOKUP_MISS_ADJ_INDEX 0
ip_add_del_adjacency_callback_t * add_del_adjacency_callbacks;
- /* Pool of addresses that are assigned to interfaces. */
+ /** Pool of addresses that are assigned to interfaces. */
ip_interface_address_t * if_address_pool;
- /* Hash table mapping address to index in interface address pool. */
+ /** Hash table mapping address to index in interface address pool. */
mhash_t address_to_if_address_index;
- /* Head of doubly linked list of interface addresses for each software interface.
+ /** Head of doubly linked list of interface addresses for each software interface.
~0 means this interface has no address. */
u32 * if_address_pool_index_by_sw_if_index;
- /* First table index to use for this interface, ~0 => none */
+ /** First table index to use for this interface, ~0 => none */
u32 * classify_table_index_by_sw_if_index;
- /* rx/tx interface/feature configuration. */
+ /** rx/tx interface/feature configuration. */
ip_config_main_t rx_config_mains[VNET_N_CAST], tx_config_main;
- /* Number of bytes in a fib result. Must be at least
+ /** Number of bytes in a fib result. Must be at least
sizeof (uword). First word is always adjacency index. */
u32 fib_result_n_bytes, fib_result_n_words;
format_function_t * format_fib_result;
- /* 1 for ip6; 0 for ip4. */
+ /** 1 for ip6; 0 for ip4. */
u32 is_ip6;
- /* Either format_ip4_address_and_length or format_ip6_address_and_length. */
+ /** Either format_ip4_address_and_length or format_ip6_address_and_length. */
format_function_t * format_address_and_length;
- /* Table mapping ip protocol to ip[46]-local node next index. */
+ /** Special adjacency format functions */
+ format_function_t ** special_adjacency_format_functions;
+
+ /** Table mapping ip protocol to ip[46]-local node next index. */
u8 local_next_by_ip_protocol[256];
- /* IP_BUILTIN_PROTOCOL_{TCP,UDP,ICMP,OTHER} by protocol in IP header. */
+ /** IP_BUILTIN_PROTOCOL_{TCP,UDP,ICMP,OTHER} by protocol in IP header. */
u8 builtin_protocol_by_ip_protocol[256];
+
+ /** Registered adjacencies */
+ ip_adj_register_t *registered_adjacencies;
} ip_lookup_main_t;
always_inline ip_adjacency_t *
CLIB_PREFETCH (_adj, sizeof (_adj[0]), type); \
} while (0)
+/* Adds a next node to ip4 or ip6 lookup node which can be then used in adjacencies.
+ * @param vlib_main pointer
+ * @param lm ip4_main.lookup_main or ip6_main.lookup_main
+ * @param reg registration structure
+ * @param next_node_index Returned index to be used in adjacencies.
+ * @return 0 on success. -1 on failure.
+ */
+int ip_register_adjacency(vlib_main_t *vm, u8 is_ip4,
+ ip_adj_register_t *reg);
+
+/*
+ * Construction helpers to add IP adjacency at init.
+ */
+#define VNET_IP_REGISTER_ADJACENCY(ip,x,...) \
+ __VA_ARGS__ ip_adj_register_t ip##adj_##x; \
+static void __vnet_##ip##_register_adjacency_##x (void) \
+ __attribute__((__constructor__)) ; \
+static void __vnet_##ip##_register_adjacency_##x (void) \
+{ \
+ ip_lookup_main_t *lm = &ip##_main.lookup_main; \
+ ip##adj_##x.next = lm->registered_adjacencies; \
+ lm->registered_adjacencies = &ip##adj_##x; \
+} \
+__VA_ARGS__ ip_adj_register_t ip##adj_##x
+
+#define VNET_IP4_REGISTER_ADJACENCY(x,...) \
+ VNET_IP_REGISTER_ADJACENCY(ip4, x, __VA_ARGS__)
+
+#define VNET_IP6_REGISTER_ADJACENCY(x,...) \
+ VNET_IP_REGISTER_ADJACENCY(ip6, x, __VA_ARGS__)
+
static inline void
ip_register_add_del_adjacency_callback(ip_lookup_main_t * lm,
ip_add_del_adjacency_callback_t cb)
static inline int
ip_adjacency_is_multipath(ip_lookup_main_t * lm, u32 adj_index)
{
+ if (!vec_len(lm->multipath_adjacencies))
+ return 0;
+
if (vec_len(lm->multipath_adjacencies) < adj_index - 1)
return 0;
+
return (lm->multipath_adjacencies[adj_index].adj_index == adj_index &&
lm->multipath_adjacencies[adj_index].n_adj_in_block > 0);
}
vec_elt (lm->if_address_pool_index_by_sw_if_index, sw_if_index)
: if_address_index);
- return pool_elt_at_index (lm->if_address_pool, if_address_index);
+ return (if_address_index != ~0)?pool_elt_at_index (lm->if_address_pool, if_address_index):NULL;
}
#define foreach_ip_interface_address(lm,a,sw_if_index,loop,body) \
} while (0)
void ip_lookup_init (ip_lookup_main_t * lm, u32 ip_lookup_node_index);
+u32 vnet_register_special_adjacency_format_function
+(ip_lookup_main_t * lm, format_function_t * fp);
#endif /* included_ip_lookup_h */