Add IP adjacency registration function 07/2107/3
authorPierre Pfister <ppfister@cisco.com>
Wed, 27 Jul 2016 16:46:11 +0000 (17:46 +0100)
committerDave Barach <openvpp@barachs.net>
Thu, 28 Jul 2016 12:19:21 +0000 (12:19 +0000)
Given that it is possible and easy to add dynamic
IP adjacencies, it might be helpful to have an explicit
call to do so.
This way, additional information such as how to display
the adjacency can be provided at the same time.

Change-Id: I5c735ae45ed763560352f637e3462f2931dc97d9
Signed-off-by: Pierre Pfister <ppfister@cisco.com>
plugins/ila-plugin/ila/ila.c
vnet/vnet/ip/lookup.c
vnet/vnet/ip/lookup.h

index 69fbb82..c0e6da1 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <ila/ila.h>
 #include <vnet/plugin/plugin.h>
+#include <vnet/ip/lookup.h>
 
 static ila_main_t ila_main;
 
@@ -794,6 +795,16 @@ vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
   return error;
 }
 
+u8 *ila_format_adjacency(u8 * s,
+                        struct ip_lookup_main_t * lm,
+                        ip_adjacency_t *adj)
+{
+  ila_main_t *ilm = &ila_main;
+  ila_adj_data_t * ad = (ila_adj_data_t *) & adj->opaque;
+  ila_entry_t *ie = pool_elt_at_index (ilm->entries, ad->entry_index);
+  return format(s, "idx:%d sir:%U", ad->entry_index, format_ip6_address, &ie->sir_address);
+}
+
 clib_error_t *
 ila_init (vlib_main_t * vm)
 {
@@ -810,14 +821,15 @@ ila_init (vlib_main_t * vm)
                         "ila id to entry index table",
                         ilm->lookup_table_nbuckets, ilm->lookup_table_size);
 
-  vlib_node_t *ip6_lookup_node =
-    vlib_get_node_by_name (vm, (u8 *) "ip6-lookup");
-
-  ilm->ip6_lookup_next_index =
-    vlib_node_add_next (vm, ip6_lookup_node->index, ila_ila2sir_node.index);
   return NULL;
 }
 
+VNET_IP6_REGISTER_ADJACENCY(ila2sir) = {
+  .node_name = "ila-to-sir",
+  .fn = ila_format_adjacency,
+  .next_index = &ila_main.ip6_lookup_next_index
+};
+
 VLIB_INIT_FUNCTION (ila_init);
 
 static clib_error_t *
index 2d9e01f..126783a 100644 (file)
@@ -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;
index 78a2641..a66b9ed 100644 (file)
@@ -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)