gre: Tunnel encap/decap flags
[vpp.git] / src / vnet / gre / gre.h
index b3b0b54..0cc60b8 100644 (file)
 #include <vnet/pg/pg.h>
 #include <vnet/ip/format.h>
 #include <vnet/adj/adj_types.h>
+#include <vnet/tunnel/tunnel.h>
+#include <vnet/nhrp/nhrp.h>
 
 extern vnet_hw_interface_class_t gre_hw_interface_class;
+extern vnet_hw_interface_class_t mgre_hw_interface_class;
 
 typedef enum
 {
@@ -35,35 +38,31 @@ typedef enum
   GRE_N_ERROR,
 } gre_error_t;
 
+/**
+ * L3: GRE (i.e. this tunnel is in L3 mode)
+ * TEB: Transparent Ethernet Bridging - the tunnel is in L2 mode
+ * ERSPAN: type 2 - the tunnel is for port mirror SPAN output. Each tunnel is
+ *         associated with a session ID and expected to be used for encap
+ *         and output of mirrored packet from a L2 network only. There is
+ *         no support for receiving ERSPAN packets from a GRE ERSPAN tunnel
+ */
+#define foreach_gre_tunnel_type \
+  _(L3, "L3")                   \
+  _(TEB, "TEB")                 \
+  _(ERSPAN, "ERSPAN")           \
+
 /**
  * @brief The GRE tunnel type
  */
 typedef enum gre_tunnel_type_t_
 {
-  /**
-   * L3 GRE (i.e. this tunnel is in L3 mode)
-   */
-  GRE_TUNNEL_TYPE_L3 = 0,
-  /**
-   * Transparent Ethernet Bridging - the tunnel is in L2 mode
-   */
-  GRE_TUNNEL_TYPE_TEB = 1,
-  /**
-   * ERSPAN type 2 - the tunnel is for port mirror SPAN output. Each tunnel is
-   * associated with a session ID and expected to be used for encap and output
-   * of mirrored packet from a L2 network only. There is no support for
-   * receiving ERSPAN packets from a GRE ERSPAN tunnel in VPP.
-   */
-  GRE_TUNNEL_TYPE_ERSPAN = 2,
+#define _(n, s) GRE_TUNNEL_TYPE_##n,
+  foreach_gre_tunnel_type
+#undef _
+} __clib_packed gre_tunnel_type_t;
 
-  GRE_TUNNEL_TYPE_N
-} gre_tunnel_type_t;
+extern u8 *format_gre_tunnel_type (u8 * s, va_list * args);
 
-#define GRE_TUNNEL_TYPE_NAMES {    \
-    [GRE_TUNNEL_TYPE_L3] = "L3",   \
-    [GRE_TUNNEL_TYPE_TEB] = "TEB", \
-    [GRE_TUNNEL_TYPE_ERSPAN] = "ERSPAN", \
-}
 
 /**
  * A GRE payload protocol registration
@@ -86,6 +85,26 @@ typedef struct
   u32 next_index;
 } gre_protocol_info_t;
 
+/**
+ * Elements of the GRE key that are common for v6 and v6 addresses
+ */
+typedef struct gre_tunnel_key_common_t_
+{
+  union
+  {
+    struct
+    {
+      u32 fib_index;
+      u16 session_id;
+      gre_tunnel_type_t type;
+      tunnel_mode_t mode;
+    };
+    u64 as_u64;
+  };
+} gre_tunnel_key_common_t;
+
+STATIC_ASSERT_SIZEOF (gre_tunnel_key_common_t, sizeof (u64));
+
 /**
  * @brief Key for a IPv4 GRE Tunnel
  */
@@ -104,15 +123,12 @@ typedef struct gre_tunnel_key4_t_
     u64 gtk_as_u64;
   };
 
-  /**
-   * FIB table index, ERSPAN session ID and tunnel type in u32 bit fields:
-   * - The FIB table index the src,dst addresses are in, top 20 bits
-   * - The Session ID for ERSPAN tunnel type and 0 otherwise, next 10 bits
-   * - Tunnel type, bottom 2 bits
-   */
-  u32 gtk_fidx_ssid_type;
+  /** address independent attributes */
+  gre_tunnel_key_common_t gtk_common;
 } __attribute__ ((packed)) gre_tunnel_key4_t;
 
+STATIC_ASSERT_SIZEOF (gre_tunnel_key4_t, 2 * sizeof (u64));
+
 /**
  * @brief Key for a IPv6 GRE Tunnel
  * We use a different type so that the V4 key hash is as small as possible
@@ -125,22 +141,11 @@ typedef struct gre_tunnel_key6_t_
   ip6_address_t gtk_src;
   ip6_address_t gtk_dst;
 
-  /**
-   * FIB table index, ERSPAN session ID and tunnel type in u32 bit fields:
-   * - The FIB table index the src,dst addresses are in, top 20 bits
-   * - The Session ID for ERSPAN tunnel type and 0 otherwise, next 10 bits
-   * - Tunnel type, bottom 2 bits
-   */
-  u32 gtk_fidx_ssid_type;
+  /** address independent attributes */
+  gre_tunnel_key_common_t gtk_common;
 } __attribute__ ((packed)) gre_tunnel_key6_t;
 
-#define GTK_FIB_INDEX_SHIFT    12
-#define GTK_FIB_INDEX_MASK     0xfffff000
-#define GTK_TYPE_SHIFT         0
-#define GTK_TYPE_MASK          0x3
-#define GTK_SESSION_ID_SHIFT   2
-#define GTK_SESSION_ID_MASK    0xffc
-#define GTK_SESSION_ID_MAX     (GTK_SESSION_ID_MASK >> GTK_SESSION_ID_SHIFT)
+STATIC_ASSERT_SIZEOF (gre_tunnel_key6_t, 5 * sizeof (u64));
 
 /**
  * Union of the two possible key types
@@ -151,6 +156,11 @@ typedef union gre_tunnel_key_t_
   gre_tunnel_key6_t gtk_v6;
 } gre_tunnel_key_t;
 
+/**
+ * The session ID is only a 10 bit value
+ */
+#define GTK_SESSION_ID_MAX (0x3ff)
+
 /**
  * Used for GRE header seq number generation for ERSPAN encap
  */
@@ -176,15 +186,9 @@ typedef struct
 typedef struct
 {
   /**
-   * Linkage into the FIB object graph
+   * Required for pool_get_aligned
    */
-  fib_node_t node;
-
-  /**
-   * The hash table's key stored in separate memory since the tunnel_t
-   * memory can realloc.
-   */
-  gre_tunnel_key_t *key;
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
 
   /**
    * The tunnel's source/local address
@@ -201,19 +205,8 @@ typedef struct
   u32 hw_if_index;
   u32 sw_if_index;
   gre_tunnel_type_t type;
-
-  /**
-   * The FIB entry sourced by the tunnel for its destination prefix
-   */
-  fib_node_index_t fib_entry_index;
-
-  /**
-   * The tunnel is a child of the FIB entry for its desintion. This is
-   * so it receives updates when the forwarding information for that entry
-   * changes.
-   * The tunnels sibling index on the FIB entry's dependency list.
-   */
-  u32 sibling_index;
+  tunnel_mode_t mode;
+  tunnel_encap_decap_flags_t flags;
 
   /**
    * an L2 tunnel always rquires an L2 midchain. cache here for DP.
@@ -332,6 +325,15 @@ extern void gre_tunnel_stack (adj_index_t ai);
 extern void gre_update_adj (vnet_main_t * vnm,
                            u32 sw_if_index, adj_index_t ai);
 
+typedef struct mgre_walk_ctx_t_
+{
+  const gre_tunnel_t *t;
+  const nhrp_entry_t *ne;
+} mgre_walk_ctx_t;
+
+adj_walk_rc_t mgre_mk_complete_walk (adj_index_t ai, void *data);
+adj_walk_rc_t mgre_mk_incomplete_walk (adj_index_t ai, void *data);
+
 format_function_t format_gre_protocol;
 format_function_t format_gre_header;
 format_function_t format_gre_header_with_length;
@@ -360,26 +362,32 @@ gre_register_input_protocol (vlib_main_t * vm, gre_protocol_t protocol,
 typedef struct
 {
   u8 is_add;
-  u8 tunnel_type;
+  gre_tunnel_type_t type;
+  tunnel_mode_t mode;
   u8 is_ipv6;
   u32 instance;
   ip46_address_t src, dst;
-  u32 outer_fib_id;
+  u32 outer_table_id;
   u16 session_id;
-} vnet_gre_add_del_tunnel_args_t;
+  tunnel_encap_decap_flags_t flags;
+} vnet_gre_tunnel_add_del_args_t;
 
-int vnet_gre_add_del_tunnel
-  (vnet_gre_add_del_tunnel_args_t * a, u32 * sw_if_indexp);
+extern int vnet_gre_tunnel_add_del (vnet_gre_tunnel_add_del_args_t * a,
+                                   u32 * sw_if_indexp);
 
 static inline void
 gre_mk_key4 (ip4_address_t src,
             ip4_address_t dst,
-            u32 fib_index, u8 ttype, u16 session_id, gre_tunnel_key4_t * key)
+            u32 fib_index,
+            gre_tunnel_type_t ttype,
+            tunnel_mode_t tmode, u16 session_id, gre_tunnel_key4_t * key)
 {
   key->gtk_src = src;
   key->gtk_dst = dst;
-  key->gtk_fidx_ssid_type = ttype |
-    (fib_index << GTK_FIB_INDEX_SHIFT) | (session_id << GTK_SESSION_ID_SHIFT);
+  key->gtk_common.type = ttype;
+  key->gtk_common.mode = tmode;
+  key->gtk_common.fib_index = fib_index;
+  key->gtk_common.session_id = session_id;
 }
 
 static inline int
@@ -387,29 +395,31 @@ gre_match_key4 (const gre_tunnel_key4_t * key1,
                const gre_tunnel_key4_t * key2)
 {
   return ((key1->gtk_as_u64 == key2->gtk_as_u64) &&
-         (key1->gtk_fidx_ssid_type == key2->gtk_fidx_ssid_type));
+         (key1->gtk_common.as_u64 == key2->gtk_common.as_u64));
 }
 
 static inline void
 gre_mk_key6 (const ip6_address_t * src,
             const ip6_address_t * dst,
-            u32 fib_index, u8 ttype, u16 session_id, gre_tunnel_key6_t * key)
+            u32 fib_index,
+            gre_tunnel_type_t ttype,
+            tunnel_mode_t tmode, u16 session_id, gre_tunnel_key6_t * key)
 {
   key->gtk_src = *src;
   key->gtk_dst = *dst;
-  key->gtk_fidx_ssid_type = ttype |
-    (fib_index << GTK_FIB_INDEX_SHIFT) | (session_id << GTK_SESSION_ID_SHIFT);
+  key->gtk_common.type = ttype;
+  key->gtk_common.mode = tmode;
+  key->gtk_common.fib_index = fib_index;
+  key->gtk_common.session_id = session_id;
 }
 
 static inline int
 gre_match_key6 (const gre_tunnel_key6_t * key1,
                const gre_tunnel_key6_t * key2)
 {
-  return ((key1->gtk_src.as_u64[0] == key2->gtk_src.as_u64[0]) &&
-         (key1->gtk_src.as_u64[1] == key2->gtk_src.as_u64[1]) &&
-         (key1->gtk_dst.as_u64[0] == key2->gtk_dst.as_u64[0]) &&
-         (key1->gtk_dst.as_u64[1] == key2->gtk_dst.as_u64[1]) &&
-         (key1->gtk_fidx_ssid_type == key2->gtk_fidx_ssid_type));
+  return (ip6_address_is_equal (&key1->gtk_src, &key2->gtk_src) &&
+         ip6_address_is_equal (&key1->gtk_dst, &key2->gtk_dst) &&
+         (key1->gtk_common.as_u64 == key2->gtk_common.as_u64));
 }
 
 static inline void