summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/ip/lookup.c56
-rw-r--r--vnet/vnet/ip/lookup.h46
2 files changed, 98 insertions, 4 deletions
diff --git a/vnet/vnet/ip/lookup.c b/vnet/vnet/ip/lookup.c
index 2d9e01f24b9..126783a23d4 100644
--- a/vnet/vnet/ip/lookup.c
+++ b/vnet/vnet/ip/lookup.c
@@ -134,6 +134,34 @@ ip_unshare_adjacency(ip_lookup_main_t * lm, u32 adj_index)
}
}
+int ip_register_adjacency(vlib_main_t *vm,
+ u8 is_ip4,
+ ip_adj_register_t *reg)
+{
+ ip_lookup_main_t *lm = (is_ip4)?&ip4_main.lookup_main:&ip6_main.lookup_main;
+ vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) ((is_ip4)?"ip4-lookup":"ip6-lookup"));
+ vlib_node_t *next_node = vlib_get_node_by_name(vm, (u8 *) reg->node_name);
+ *reg->next_index = vlib_node_add_next (vm, node->index, next_node->index);
+ vec_validate(lm->registered_adjacencies, *reg->next_index);
+ lm->registered_adjacencies[*reg->next_index] = *reg;
+ return 0;
+}
+
+int ip_init_registered_adjacencies(u8 is_ip4)
+{
+ vlib_main_t *vm = vlib_get_main();
+ ip_lookup_main_t *lm = (is_ip4)?&ip4_main.lookup_main:&ip6_main.lookup_main;
+ ip_adj_register_t *reg = lm->registered_adjacencies;
+ lm->registered_adjacencies = 0; //Init vector
+ int rv;
+ while (reg) {
+ if((rv = ip_register_adjacency(vm, is_ip4, reg)))
+ return rv;
+ reg = reg->next;
+ }
+ return 0;
+}
+
/* Create new block of given number of contiguous adjacencies. */
ip_adjacency_t *
ip_add_adjacency (ip_lookup_main_t * lm,
@@ -915,6 +943,8 @@ void ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] = IP_BUILTIN_PROTOCOL_UDP;
lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 : IP_PROTOCOL_ICMP] = IP_BUILTIN_PROTOCOL_ICMP;
}
+
+ ip_init_registered_adjacencies(!is_ip6);
}
u8 * format_ip_flow_hash_config (u8 * s, va_list * args)
@@ -930,13 +960,22 @@ u8 * format_ip_flow_hash_config (u8 * s, va_list * args)
u8 * format_ip_lookup_next (u8 * s, va_list * args)
{
- ip_lookup_next_t n = va_arg (*args, ip_lookup_next_t);
+ ip_lookup_main_t * lm = va_arg (*args, ip_lookup_main_t *);
+ ip_lookup_next_t n = va_arg (*args, u32);
+ ip_adj_register_t *reg;
+
char * t = 0;
switch (n)
{
default:
- s = format (s, "unknown %d", n);
+ vec_validate(lm->registered_adjacencies, n);
+ reg = vec_elt_at_index(lm->registered_adjacencies, n);
+ if (reg->node_name) {
+ s = format (s, "%s:", reg->node_name);
+ } else {
+ s = format (s, "unknown %d", n);
+ }
return s;
case IP_LOOKUP_NEXT_MISS: t = "miss"; break;
@@ -977,6 +1016,7 @@ u8 * format_ip_adjacency (u8 * s, va_list * args)
ip_lookup_main_t * lm = va_arg (*args, ip_lookup_main_t *);
u32 adj_index = va_arg (*args, u32);
ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
+ ip_adj_register_t *reg;
switch (adj->lookup_next_index)
{
@@ -987,7 +1027,7 @@ u8 * format_ip_adjacency (u8 * s, va_list * args)
break;
default:
- s = format (s, "%U", format_ip_lookup_next, adj->lookup_next_index);
+ s = format (s, "%U", format_ip_lookup_next, lm, adj->lookup_next_index);
if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP)
s = format (s, " %U",
format_vnet_sw_interface_name,
@@ -1009,11 +1049,19 @@ u8 * format_ip_adjacency (u8 * s, va_list * args)
case IP_LOOKUP_NEXT_CLASSIFY:
s = format (s, " table %d", adj->classify.table_index);
-
+ break;
case IP_LOOKUP_NEXT_INDIRECT:
s = format (s, " via %U", format_ip46_address,
&adj->indirect.next_hop, IP46_TYPE_ANY);
+ break;
default:
+ //Fallback to registered format functions
+ vec_validate(lm->registered_adjacencies, adj->lookup_next_index);
+ reg = vec_elt_at_index(lm->registered_adjacencies, adj->lookup_next_index);
+ if (reg->fn) {
+ s = format(s, " ");
+ s = reg->fn(s, lm, adj);
+ }
break;
}
break;
diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h
index 78a2641dc36..a66b9ed1f3e 100644
--- a/vnet/vnet/ip/lookup.h
+++ b/vnet/vnet/ip/lookup.h
@@ -350,6 +350,18 @@ typedef struct {
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;
@@ -422,6 +434,9 @@ typedef struct ip_lookup_main_t {
/* 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 *
@@ -443,6 +458,37 @@ do { \
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)