gre: Tunnel encap/decap flags
[vpp.git] / src / vnet / gre / gre.h
index b6544b9..0cc60b8 100644 (file)
 #include <vnet/vnet.h>
 #include <vnet/gre/packet.h>
 #include <vnet/ip/ip.h>
-#include <vnet/ip/ip4.h>
-#include <vnet/ip/ip4_packet.h>
 #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 {
+typedef enum
+{
 #define gre_error(n,s) GRE_ERROR_##n,
 #include <vnet/gre/error.def>
 #undef gre_error
   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_
+{
+#define _(n, s) GRE_TUNNEL_TYPE_##n,
+  foreach_gre_tunnel_type
+#undef _
+} __clib_packed gre_tunnel_type_t;
+
+extern u8 *format_gre_tunnel_type (u8 * s, va_list * args);
+
+
 /**
  * A GRE payload protocol registration
  */
-typedef struct {
+typedef struct
+{
   /** Name (a c string). */
-  char * name;
+  char *name;
 
   /** GRE protocol type in host byte order. */
   gre_protocol_t protocol;
 
+  /** GRE tunnel type */
+  gre_tunnel_type_t tunnel_type;
+
   /** Node which handles this type. */
   u32 node_index;
 
@@ -54,44 +86,118 @@ typedef struct {
 } gre_protocol_info_t;
 
 /**
- * @brief The GRE tunnel type
+ * 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
  */
-typedef enum gre_tunnel_tyoe_t_
+typedef struct gre_tunnel_key4_t_
 {
   /**
-   * L3 GRE (i.e. this tunnel is in L3 mode)
+   * Source and destination IP addresses
    */
-  GRE_TUNNEL_TYPE_L3,
+  union
+  {
+    struct
+    {
+      ip4_address_t gtk_src;
+      ip4_address_t gtk_dst;
+    };
+    u64 gtk_as_u64;
+  };
+
+  /** 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
+ */
+typedef struct gre_tunnel_key6_t_
+{
   /**
-   * Transparent Ethernet Bridging - the tunnel is in L2 mode
+   * Source and destination IP addresses
    */
-  GRE_TUNNEL_TYPE_TEB,
-} gre_tunnel_type_t;
+  ip6_address_t gtk_src;
+  ip6_address_t gtk_dst;
 
-#define GRE_TUNNEL_TYPE_NAMES {    \
-    [GRE_TUNNEL_TYPE_L3] = "L3",   \
-    [GRE_TUNNEL_TYPE_TEB] = "TEB", \
-}
+  /** address independent attributes */
+  gre_tunnel_key_common_t gtk_common;
+} __attribute__ ((packed)) gre_tunnel_key6_t;
+
+STATIC_ASSERT_SIZEOF (gre_tunnel_key6_t, 5 * sizeof (u64));
 
-#define GRE_TUNNEL_N_TYPES ((gre_tunnel_type_t)GRE_TUNNEL_TYPE_TEB+1)
+/**
+ * Union of the two possible key types
+ */
+typedef union gre_tunnel_key_t_
+{
+  gre_tunnel_key4_t gtk_v4;
+  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
+ */
+typedef struct
+{
+  u32 seq_num;
+  u32 ref_count;
+} gre_sn_t;
+
+/**
+ * Hash key for GRE header seq number generation for ERSPAN encap
+ */
+typedef struct
+{
+  ip46_address_t src;
+  ip46_address_t dst;
+  u32 fib_index;
+} gre_sn_key_t;
 
 /**
  * @brief A representation of a GRE tunnel
  */
-typedef struct {
+typedef struct
+{
   /**
-   * Linkage into the FIB object graph
+   * Required for pool_get_aligned
    */
-  fib_node_t node;
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
 
   /**
    * The tunnel's source/local address
    */
-  ip4_address_t tunnel_src;
+  ip46_address_t tunnel_src;
   /**
    * The tunnel's destination/remote address
    */
-  ip4_address_t tunnel_dst;
+  fib_prefix_t tunnel_dst;
   /**
    * The FIB in which the src.dst address are present
    */
@@ -99,35 +205,43 @@ typedef struct {
   u32 hw_if_index;
   u32 sw_if_index;
   gre_tunnel_type_t type;
+  tunnel_mode_t mode;
+  tunnel_encap_decap_flags_t flags;
 
   /**
-   * The FIB entry sourced by the tunnel for its destination prefix
+   * an L2 tunnel always rquires an L2 midchain. cache here for DP.
    */
-  fib_node_index_t fib_entry_index;
+  adj_index_t l2_adj_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.
+   * ERSPAN type 2 session ID, least significant 10 bits of u16
    */
-  u32 sibling_index;
+  u16 session_id;
 
   /**
-   * on a L2 tunnel this is the VLIB arc from the L2-tx to the l2-midchain
+   * GRE header sequence number (SN) used for ERSPAN type 2 header, must be
+   * bumped automically to be thread safe. As multiple GRE tunnels are created
+   * for the same fib-idx/DIP/SIP with different ERSPAN session number, they all
+   * share the same SN which is kept per FIB/DIP/SIP, as specified by RFC2890.
    */
-  u32 l2_tx_arc;
+  gre_sn_t *gre_sn;
 
-  /**
-   * an L2 tunnel always rquires an L2 midchain. cache here for DP.
-   */
-  adj_index_t l2_adj_index;
+
+  u32 dev_instance;            /* Real device instance in tunnel vector */
+  u32 user_instance;           /* Instance name being shown to user */
 } gre_tunnel_t;
 
+typedef struct
+{
+  u8 next_index;
+  u8 tunnel_type;
+} next_info_t;
+
 /**
  * @brief GRE related global data
  */
-typedef struct {
+typedef struct
+{
   /**
    * pool of tunnel instances
    */
@@ -136,73 +250,98 @@ typedef struct {
   /**
    * GRE payload protocol registrations
    */
-  gre_protocol_info_t * protocol_infos;
+  gre_protocol_info_t *protocol_infos;
 
   /**
    *  Hash tables mapping name/protocol to protocol info index.
    */
-  uword * protocol_info_by_name, * protocol_info_by_protocol;
+  uword *protocol_info_by_name, *protocol_info_by_protocol;
+
+  /**
+   * Hash mapping to tunnels with ipv4 src/dst addr
+   */
+  uword *tunnel_by_key4;
+
   /**
-   * Hash mapping src/dst addr pair to tunnel
+   * Hash mapping to tunnels with ipv6 src/dst addr
    */
-  uword * tunnel_by_key;
+  uword *tunnel_by_key6;
 
   /**
-   * Free vlib hw_if_indices.
-   * A free list per-tunnel type since the interfaces ctreated are fo different
-   * types and we cannot change the type.
+   * Hash mapping tunnel src/dst addr and fib-idx to sequence number
    */
-  u32 * free_gre_tunnel_hw_if_indices[GRE_TUNNEL_N_TYPES];
+  uword *seq_num_by_key;
 
   /**
    * Mapping from sw_if_index to tunnel index
    */
-  u32 * tunnel_index_by_sw_if_index;
+  u32 *tunnel_index_by_sw_if_index;
+
+  /* Sparse vector mapping gre protocol in network byte order
+     to next index. */
+  next_info_t *next_by_protocol;
 
   /* convenience */
-  vlib_main_t * vlib_main;
-  vnet_main_t * vnet_main;
+  vlib_main_t *vlib_main;
+  vnet_main_t *vnet_main;
+
+  /* Record used instances */
+  uword *instance_used;
 } gre_main_t;
 
 /**
  * @brief IPv4 and GRE header.
  */
+/* *INDENT-OFF* */
 typedef CLIB_PACKED (struct {
   ip4_header_t ip4;
   gre_header_t gre;
 }) ip4_and_gre_header_t;
+/* *INDENT-ON* */
+
+/**
+ * @brief IPv6 and GRE header.
+ */
+/* *INDENT-OFF* */
+typedef CLIB_PACKED (struct {
+  ip6_header_t ip6;
+  gre_header_t gre;
+}) ip6_and_gre_header_t;
+/* *INDENT-ON* */
 
 always_inline gre_protocol_info_t *
 gre_get_protocol_info (gre_main_t * em, gre_protocol_t protocol)
 {
-  uword * p = hash_get (em->protocol_info_by_protocol, protocol);
+  uword *p = hash_get (em->protocol_info_by_protocol, protocol);
   return p ? vec_elt_at_index (em->protocol_infos, p[0]) : 0;
 }
 
-gre_main_t gre_main;
+extern gre_main_t gre_main;
 
-/* Register given node index to take input for given gre type. */
-void
-gre_register_input_type (vlib_main_t * vm,
-                        gre_protocol_t protocol,
-                        u32 node_index);
-
-extern  clib_error_t * gre_interface_admin_up_down (vnet_main_t * vnm,
-                                                   u32 hw_if_index,
-                                                   u32 flags);
+extern clib_error_t *gre_interface_admin_up_down (vnet_main_t * vnm,
+                                                 u32 hw_if_index, u32 flags);
 
 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);
+                           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;
 
-extern vlib_node_registration_t gre_input_node;
+extern vlib_node_registration_t gre4_input_node;
+extern vlib_node_registration_t gre6_input_node;
+extern vlib_node_registration_t gre_encap_node;
 extern vnet_device_class_t gre_device_class;
-extern vnet_device_class_t gre_device_teb_class;
 
 /* Parse gre protocol as 0xXXXX or protocol name.
    In either host or network byte order. */
@@ -214,22 +353,89 @@ unformat_function_t unformat_gre_header;
 unformat_function_t unformat_pg_gre_header;
 
 void
-gre_register_input_protocol (vlib_main_t * vm,
-                            gre_protocol_t protocol,
-                            u32 node_index);
+gre_register_input_protocol (vlib_main_t * vm, gre_protocol_t protocol,
+                            u32 node_index, gre_tunnel_type_t tunnel_type);
 
 /* manually added to the interface output node in gre.c */
 #define GRE_OUTPUT_NEXT_LOOKUP 1
 
-typedef struct {
+typedef struct
+{
   u8 is_add;
+  gre_tunnel_type_t type;
+  tunnel_mode_t mode;
+  u8 is_ipv6;
+  u32 instance;
+  ip46_address_t src, dst;
+  u32 outer_table_id;
+  u16 session_id;
+  tunnel_encap_decap_flags_t flags;
+} vnet_gre_tunnel_add_del_args_t;
+
+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,
+            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_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_key4 (const gre_tunnel_key4_t * key1,
+               const gre_tunnel_key4_t * key2)
+{
+  return ((key1->gtk_as_u64 == key2->gtk_as_u64) &&
+         (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,
+            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_common.type = ttype;
+  key->gtk_common.mode = tmode;
+  key->gtk_common.fib_index = fib_index;
+  key->gtk_common.session_id = session_id;
+}
 
-  ip4_address_t src, dst;
-  u32 outer_fib_id;
-  u8 teb;
-} vnet_gre_add_del_tunnel_args_t;
+static inline int
+gre_match_key6 (const gre_tunnel_key6_t * key1,
+               const gre_tunnel_key6_t * key2)
+{
+  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));
+}
 
-int vnet_gre_add_del_tunnel
-  (vnet_gre_add_del_tunnel_args_t *a, u32 * sw_if_indexp);
+static inline void
+gre_mk_sn_key (const gre_tunnel_t * gt, gre_sn_key_t * key)
+{
+  key->src = gt->tunnel_src;
+  key->dst = gt->tunnel_dst.fp_addr;
+  key->fib_index = gt->outer_fib_index;
+}
 
 #endif /* included_gre_h */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */