diff options
Diffstat (limited to 'vnet')
-rw-r--r-- | vnet/vnet/ip/lookup.c | 56 | ||||
-rw-r--r-- | vnet/vnet/ip/lookup.h | 46 |
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) |