6rd: Move to plugin
[vpp.git] / vnet / vnet / ip / lookup.h
index ccce889..35c19a7 100644 (file)
 
 #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. */
+/* Common (IP4/IP6) next index stored in adjacency. */
 typedef enum {
   /* Packet does not match any route in table. */
   IP_LOOKUP_NEXT_MISS,
@@ -74,17 +76,57 @@ typedef enum {
   /* 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_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)
@@ -106,9 +148,12 @@ _(reverse, IP_FLOW_HASH_REVERSE_SRC_DST)
 
 /* IP unicast adjacency. */
 typedef struct {
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);
   /* Handle for this adjacency in adjacency heap. */
   u32 heap_handle;
 
+  STRUCT_MARK(signature_start);
+
   /* Interface address index for this local/arp adjacency. */
   u32 if_address_index;
 
@@ -126,14 +171,69 @@ typedef struct {
   i16 explicit_fib_index;
   u16 mcast_group_index;  
 
-  /* When classifying, start here */
-  u16 classify_table_index;
   /* Highest possible perf subgraph arc interposition, e.g. for ip6 ioam */
   u16 saved_lookup_next_index;
 
-  vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE - 5*sizeof(u32));
+  union {
+    /* IP_LOOKUP_NEXT_ARP only */
+    struct {
+      ip46_address_t 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;
+  };
+
+  STRUCT_MARK(signature_end);
+
+  /* Number of FIB entries sharing this adjacency */
+  u32 share_count;
+  /* Use this adjacency instead */
+  u32 next_adj_with_signature;
+
+  CLIB_CACHE_LINE_ALIGN_MARK(cacheline1);
+
+  /* Rewrite in second/third cache lines */
+  vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
 } ip_adjacency_t;
 
+static inline uword
+vnet_ip_adjacency_signature (ip_adjacency_t * adj)
+{
+  uword signature = 0xfeedfaceULL;
+
+  /* Skip heap handle, sum everything up to but not including share_count */
+  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_memory (&adj->rewrite_header, VLIB_BUFFER_PRE_DATA_SIZE,
+                             signature);
+  return signature;
+}
+
+static inline int
+vnet_ip_adjacency_share_compare (ip_adjacency_t * a1, ip_adjacency_t *a2)
+{
+  if (memcmp (STRUCT_MARK_PTR(a1, signature_start),
+              STRUCT_MARK_PTR(a2, signature_start),
+              STRUCT_OFFSET_OF(ip_adjacency_t, signature_end)
+              - STRUCT_OFFSET_OF(ip_adjacency_t, signature_start)))
+    return 0;
+  if (memcmp (&a1->rewrite_header, &a2->rewrite_header,
+              VLIB_BUFFER_PRE_DATA_SIZE))
+    return 0;
+  return 1;
+}
+
 /* Index into adjacency table. */
 typedef u32 ip_adjacency_index_t;
 
@@ -261,6 +361,9 @@ typedef struct ip_lookup_main_t {
   /* Indexed by heap_handle from ip_adjacency_t. */
   ip_multipath_adjacency_t * multipath_adjacencies;
 
+  /* Adjacency by signature hash */
+  uword * adj_index_by_signature;
+
   /* 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;
@@ -325,9 +428,9 @@ ip_get_adjacency (ip_lookup_main_t * lm,
 {
   ip_adjacency_t * adj;
 
-  adj = heap_elt_at_index (lm->adjacency_heap, adj_index);
+  adj = vec_elt_at_index (lm->adjacency_heap, adj_index);
 
-  ASSERT (! heap_is_free_handle (lm->adjacency_heap, adj->heap_handle));
+  ASSERT (adj->heap_handle != ~0);
 
   return adj;
 }
@@ -338,6 +441,13 @@ do {                                                               \
   CLIB_PREFETCH (_adj, sizeof (_adj[0]), type);                        \
 } while (0)
 
+static inline void
+ip_register_add_del_adjacency_callback(ip_lookup_main_t * lm,
+                                      ip_add_del_adjacency_callback_t cb)
+{
+  vec_add1(lm->add_del_adjacency_callbacks, cb);
+}
+
 always_inline void
 ip_call_add_del_adjacency_callbacks (ip_lookup_main_t * lm, u32 adj_index, u32 is_del)
 {
@@ -356,6 +466,24 @@ ip_add_adjacency (ip_lookup_main_t * lm,
                  u32 * adj_index_result);
 
 void ip_del_adjacency (ip_lookup_main_t * lm, u32 adj_index);
+void
+ip_update_adjacency (ip_lookup_main_t * lm,
+                    u32 adj_index,
+                    ip_adjacency_t * copy_adj);
+
+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);
+}
 
 void
 ip_multipath_adjacency_free (ip_lookup_main_t * lm,
@@ -435,7 +563,4 @@ do {                                                                    \
 
 void ip_lookup_init (ip_lookup_main_t * lm, u32 ip_lookup_node_index);
 
-serialize_function_t serialize_ip_lookup_main, unserialize_ip_lookup_main;
-serialize_function_t serialize_vec_ip_adjacency, unserialize_vec_ip_adjacency;
-
 #endif /* included_ip_lookup_h */