#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
-/* Next index stored in adjacency. */
+/* Common (IP4/IP6) next index stored in adjacency. */
typedef enum {
/* Packet does not match any route in table. */
IP_LOOKUP_NEXT_MISS,
/* 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,
+ IP_LOOKUP_NEXT_ICMP_ERROR,
IP_LOOKUP_N_NEXT,
} ip_lookup_next_t;
+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_CLASSIFY] = "ip4-classify", \
[IP_LOOKUP_NEXT_MAP] = "ip4-map", \
[IP_LOOKUP_NEXT_MAP_T] = "ip4-map-t", \
- [IP_LOOKUP_NEXT_SIXRD] = "ip4-sixrd", \
- [IP_LOOKUP_NEXT_HOP_BY_HOP] = "ip4-hop-by-hop", \
- [IP_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip4-add-hop-by-hop", \
- [IP_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip4-pop-hop-by-hop", \
+ [IP_LOOKUP_NEXT_INDIRECT] = "ip4-indirect", \
+ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \
}
#define IP6_LOOKUP_NEXT_NODES { \
[IP_LOOKUP_NEXT_CLASSIFY] = "ip6-classify", \
[IP_LOOKUP_NEXT_MAP] = "ip6-map", \
[IP_LOOKUP_NEXT_MAP_T] = "ip6-map-t", \
- [IP_LOOKUP_NEXT_SIXRD] = "ip6-sixrd", \
- [IP_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \
- [IP_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \
- [IP_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \
+ [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 */
_(proto, IP_FLOW_HASH_PROTO) \
_(reverse, IP_FLOW_HASH_REVERSE_SRC_DST)
+#define IP_ADJACENCY_OPAQUE_SZ 16
/* IP unicast adjacency. */
typedef struct {
CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
/* IP_LOOKUP_NEXT_ARP only */
struct {
ip46_address_t next_hop;
- u32 next_adj_index_with_same_next_hop;
} arp;
/* 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];
};
STRUCT_MARK(signature_end);
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. */
ip_adjacency_t * adjacency_heap;
/* 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) \