diff options
author | John Lo <loj@cisco.com> | 2018-02-13 17:15:23 -0500 |
---|---|---|
committer | Neale Ranns <nranns@cisco.com> | 2018-02-15 11:07:56 +0000 |
commit | a43ccaefc3bd50c03c90f7c3bee02eac9709df56 (patch) | |
tree | bd2820c08864b8c3094cc6f6dddb279926c625cc /src/vnet/gre/gre.h | |
parent | 5fda7a3925be145f0c326d0aecc36d883cbcb2ee (diff) |
Optimize GRE Tunnel and add support for ERSPAN encap
Change GRE tunnel to use the interface type where the same encap
node is used as output node for all GRE tunnels, instead of having
dedicated output and tx node for each tunnel. This allows for more
efficient tunnel creation and deletion at scale tested at 1000's
of GRE tunnels.
Add support for ERSPAN encap as another tunnel type, in addition
to the existing L3 and TEB types. The GRE ERSPAN encap supported
is type 2 thus GRE encap need to include sequence number and GRE-
ERSPAN tunnel can be created with user secified ERSPAN session ID.
The GRE tunnel lookup hash key is updated to inclue tunnel type
and session ID, in addition to SIP/DIP and FIB index.
Thus, GRE-ERSPAN tunnel can be created, with the appropriate
session ID, to be used as output interface for SPAN config to
send mirrored packets.
Change interface naming so that all GRE tunnels, irrespective of
tunnel type, uses "greN" where N is the instance number. Removed
interface reuse on tunnel creation and deletion to enable unfied
tunnel interface name.
Add support of user specified instance on GRE tunnel creation.
Thus, N in the "greN" interface name can optionally be specified
by user via CLI/API.
Optimize GRE tunnel encap DPO stacking to bypass load-balance DPO
node since packet output on GRE tunnel always belong to the same
flow after 5-tupple hash.
Change-Id: Ifa83915744a1a88045c998604777cc3583f4da52
Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'src/vnet/gre/gre.h')
-rw-r--r-- | src/vnet/gre/gre.h | 189 |
1 files changed, 127 insertions, 62 deletions
diff --git a/src/vnet/gre/gre.h b/src/vnet/gre/gre.h index 83bab76f087..b3b0b545190 100644 --- a/src/vnet/gre/gre.h +++ b/src/vnet/gre/gre.h @@ -36,44 +36,55 @@ typedef enum } gre_error_t; /** - * A GRE payload protocol registration - */ -typedef struct -{ - /** Name (a c string). */ - char *name; - - /** GRE protocol type in host byte order. */ - gre_protocol_t protocol; - - /** Node which handles this type. */ - u32 node_index; - - /** Next index for this type. */ - u32 next_index; -} gre_protocol_info_t; - -/** * @brief The GRE tunnel type */ -typedef enum gre_tunnel_tyoe_t_ +typedef enum gre_tunnel_type_t_ { /** * L3 GRE (i.e. this tunnel is in L3 mode) */ - GRE_TUNNEL_TYPE_L3, + GRE_TUNNEL_TYPE_L3 = 0, /** * Transparent Ethernet Bridging - the tunnel is in L2 mode */ - GRE_TUNNEL_TYPE_TEB, + 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, + + GRE_TUNNEL_TYPE_N } gre_tunnel_type_t; #define GRE_TUNNEL_TYPE_NAMES { \ [GRE_TUNNEL_TYPE_L3] = "L3", \ [GRE_TUNNEL_TYPE_TEB] = "TEB", \ + [GRE_TUNNEL_TYPE_ERSPAN] = "ERSPAN", \ } -#define GRE_TUNNEL_N_TYPES ((gre_tunnel_type_t)GRE_TUNNEL_TYPE_TEB+1) +/** + * A GRE payload protocol registration + */ +typedef struct +{ + /** Name (a c string). */ + 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; + + /** Next index for this type. */ + u32 next_index; +} gre_protocol_info_t; /** * @brief Key for a IPv4 GRE Tunnel @@ -94,11 +105,12 @@ typedef struct gre_tunnel_key4_t_ }; /** - * The FIB table the src,dst addresses are in. - * tunnels with the same IP addresses in different FIBs are not - * the same tunnel + * 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_fib_index; + u32 gtk_fidx_ssid_type; } __attribute__ ((packed)) gre_tunnel_key4_t; /** @@ -114,13 +126,22 @@ typedef struct gre_tunnel_key6_t_ ip6_address_t gtk_dst; /** - * The FIB table the src,dst addresses are in. - * tunnels with the same IP addresses in different FIBs are not - * the same tunnel + * 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_fib_index; + u32 gtk_fidx_ssid_type; } __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) + /** * Union of the two possible key types */ @@ -131,6 +152,25 @@ typedef union gre_tunnel_key_t_ } gre_tunnel_key_t; /** + * 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 @@ -176,16 +216,34 @@ typedef struct u32 sibling_index; /** - * on a L2 tunnel this is the VLIB arc from the L2-tx to the l2-midchain + * an L2 tunnel always rquires an L2 midchain. cache here for DP. */ - u32 l2_tx_arc; + adj_index_t l2_adj_index; /** - * an L2 tunnel always rquires an L2 midchain. cache here for DP. + * ERSPAN type 2 session ID, least significant 10 bits of u16 */ - adj_index_t l2_adj_index; + u16 session_id; + + /** + * 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. + */ + gre_sn_t *gre_sn; + + + 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 */ @@ -207,21 +265,19 @@ typedef struct uword *protocol_info_by_name, *protocol_info_by_protocol; /** - * Hash mapping ipv4 src/dst addr pair to tunnel + * Hash mapping to tunnels with ipv4 src/dst addr */ uword *tunnel_by_key4; /** - * Hash mapping ipv6 src/dst addr pair to tunnel + * Hash mapping to tunnels with ipv6 src/dst addr */ 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 @@ -230,11 +286,14 @@ typedef struct /* Sparse vector mapping gre protocol in network byte order to next index. */ - u16 *next_by_protocol; + next_info_t *next_by_protocol; /* convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; + + /* Record used instances */ + uword *instance_used; } gre_main_t; /** @@ -266,11 +325,6 @@ gre_get_protocol_info (gre_main_t * em, gre_protocol_t protocol) 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); @@ -284,8 +338,8 @@ format_function_t format_gre_header_with_length; 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. */ @@ -297,8 +351,8 @@ 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 @@ -306,24 +360,26 @@ gre_register_input_protocol (vlib_main_t * vm, typedef struct { u8 is_add; - - ip46_address_t src, dst; + u8 tunnel_type; u8 is_ipv6; + u32 instance; + ip46_address_t src, dst; u32 outer_fib_id; - u8 teb; + u16 session_id; } vnet_gre_add_del_tunnel_args_t; int vnet_gre_add_del_tunnel (vnet_gre_add_del_tunnel_args_t * a, u32 * sw_if_indexp); static inline void -gre_mk_key4 (const ip4_address_t * src, - const ip4_address_t * dst, - u32 fib_index, gre_tunnel_key4_t * key) +gre_mk_key4 (ip4_address_t src, + ip4_address_t dst, + u32 fib_index, u8 ttype, u16 session_id, gre_tunnel_key4_t * key) { - key->gtk_src = *src; - key->gtk_dst = *dst; - key->gtk_fib_index = fib_index; + 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); } static inline int @@ -331,17 +387,18 @@ 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_fib_index == key2->gtk_fib_index)); + (key1->gtk_fidx_ssid_type == key2->gtk_fidx_ssid_type)); } static inline void gre_mk_key6 (const ip6_address_t * src, const ip6_address_t * dst, - u32 fib_index, gre_tunnel_key6_t * key) + u32 fib_index, u8 ttype, u16 session_id, gre_tunnel_key6_t * key) { key->gtk_src = *src; key->gtk_dst = *dst; - key->gtk_fib_index = fib_index; + key->gtk_fidx_ssid_type = ttype | + (fib_index << GTK_FIB_INDEX_SHIFT) | (session_id << GTK_SESSION_ID_SHIFT); } static inline int @@ -352,7 +409,15 @@ gre_match_key6 (const gre_tunnel_key6_t * key1, (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_fib_index == key2->gtk_fib_index)); + (key1->gtk_fidx_ssid_type == key2->gtk_fidx_ssid_type)); +} + +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 */ |