summaryrefslogtreecommitdiffstats
path: root/src/vnet/lisp-gpe
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2017-02-21 18:28:34 +0100
committerFlorin Coras <florin.coras@gmail.com>2017-02-27 10:20:50 +0000
commit3e7b569361f97368b0cad3468fac76ef2a398bfa (patch)
treec1184cd493b762c5d868857d71fc919bc14ccfce /src/vnet/lisp-gpe
parent646ba9b004055861c6dbce14424cb1d3de757ff6 (diff)
Add GPE CLI/API for setting encap mode
Change-Id: Id89e23fb5d275572b2356c073dfa0f55719e1a76 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src/vnet/lisp-gpe')
-rw-r--r--src/vnet/lisp-gpe/decap.c11
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.api45
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.c104
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.h12
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_api.c28
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_tunnel.c5
6 files changed, 202 insertions, 3 deletions
diff --git a/src/vnet/lisp-gpe/decap.c b/src/vnet/lisp-gpe/decap.c
index 5fd449cee9b..9c5234e7182 100644
--- a/src/vnet/lisp-gpe/decap.c
+++ b/src/vnet/lisp-gpe/decap.c
@@ -62,10 +62,17 @@ static u32 next_proto_to_next_index[LISP_GPE_NEXT_PROTOS] = {
always_inline u32
next_protocol_to_next_index (lisp_gpe_header_t * lgh, u8 * next_header)
{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+
/* lisp-gpe router */
if (PREDICT_TRUE ((lgh->flags & LISP_GPE_FLAGS_P)
- && lgh->next_protocol < LISP_GPE_NEXT_PROTOS))
- return next_proto_to_next_index[lgh->next_protocol];
+ || GPE_ENCAP_VXLAN == lgm->encap_mode))
+ {
+ if (PREDICT_FALSE (lgh->next_protocol > LISP_GPE_NEXT_PROTOS))
+ return LISP_GPE_INPUT_NEXT_DROP;
+
+ return next_proto_to_next_index[lgh->next_protocol];
+ }
/* legacy lisp router */
else if ((lgh->flags & LISP_GPE_FLAGS_P) == 0)
{
diff --git a/src/vnet/lisp-gpe/lisp_gpe.api b/src/vnet/lisp-gpe/lisp_gpe.api
index d603bd4d5dd..43a6a6cd499 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.api
+++ b/src/vnet/lisp-gpe/lisp_gpe.api
@@ -158,6 +158,51 @@ manual_endian manual_print define gpe_fwd_entry_path_details
vl_api_gpe_locator_t rmt_loc;
};
+/** \brief Set GPE encapsulation mode
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param mode - LISP (value 0) or VXLAN (value 1)
+*/
+define gpe_set_encap_mode
+{
+ u32 client_index;
+ u32 context;
+ u8 mode;
+};
+
+/** \brief Reply for set_encap_mode
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+*/
+define gpe_set_encap_mode_reply
+{
+ u32 context;
+ i32 retval;
+};
+
+/** \brief get GPE encapsulation mode
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param mode - LISP (value 0) or VXLAN (value 1)
+*/
+define gpe_get_encap_mode
+{
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief Reply for set_encap_mode
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+ @param encap_mode - GPE encapsulation mode
+*/
+define gpe_get_encap_mode_reply
+{
+ u32 context;
+ i32 retval;
+ u8 encap_mode;
+};
+
/*
* Local Variables:
* eval: (c-set-style "gnu")
diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c
index 479a6260ea3..446ad445592 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.c
+++ b/src/vnet/lisp-gpe/lisp_gpe.c
@@ -209,6 +209,102 @@ vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a)
return 0;
}
+/** Set GPE encapsulation mode. */
+int
+vnet_gpe_set_encap_mode (gpe_encap_mode_t mode)
+{
+ lisp_gpe_main_t *lgm = &lisp_gpe_main;
+
+ if (mode >= GPE_ENCAP_COUNT)
+ return VNET_API_ERROR_INVALID_GPE_MODE;
+
+ if (pool_elts (lgm->lisp_fwd_entry_pool) != 0)
+ return VNET_API_ERROR_LISP_GPE_ENTRIES_PRESENT;
+
+ lgm->encap_mode = mode;
+ return 0;
+}
+
+/** CLI command to set GPE encap */
+static clib_error_t *
+gpe_set_encap_mode_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ gpe_encap_mode_t mode = GPE_ENCAP_COUNT;
+ vnet_api_error_t rv;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "lisp"))
+ mode = GPE_ENCAP_LISP;
+ else if (unformat (line_input, "vxlan"))
+ mode = GPE_ENCAP_VXLAN;
+ else
+ {
+ return clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, line_input);
+ }
+ }
+ rv = vnet_gpe_set_encap_mode (mode);
+ if (rv)
+ {
+ return clib_error_return (0,
+ "Error: invalid mode or GPE entries are present!");
+ }
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (gpe_set_encap_mode_command, static) = {
+ .path = "gpe encap",
+ .short_help = "gpe encap [lisp|vxlan]",
+ .function = gpe_set_encap_mode_command_fn,
+};
+/* *INDENT-ON* */
+
+/** Format GPE encap mode. */
+u8 *
+format_vnet_gpe_encap_mode (u8 * s, va_list * args)
+{
+ lisp_gpe_main_t *lgm = &lisp_gpe_main;
+
+ switch (lgm->encap_mode)
+ {
+ case GPE_ENCAP_LISP:
+ return format (s, "lisp");
+ case GPE_ENCAP_VXLAN:
+ return format (s, "vxlan");
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/** CLI command to show GPE encap */
+static clib_error_t *
+gpe_show_encap_mode_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vlib_cli_output (vm, "encap mode: %U", format_vnet_gpe_encap_mode);
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (gpe_show_encap_mode_command, static) = {
+ .path = "show gpe encap",
+ .short_help = "show GPE encapulation mode",
+ .function = gpe_show_encap_mode_command_fn,
+};
+/* *INDENT-ON* */
+
/** CLI command to enable/disable LISP-GPE. */
static clib_error_t *
lisp_gpe_enable_disable_command_fn (vlib_main_t * vm,
@@ -318,6 +414,7 @@ lisp_gpe_init (vlib_main_t * vm)
lgm->im6 = &ip6_main;
lgm->lm4 = &ip4_main.lookup_main;
lgm->lm6 = &ip6_main.lookup_main;
+ lgm->encap_mode = GPE_ENCAP_LISP;
lgm->lisp_gpe_fwd_entries =
hash_create_mem (0, sizeof (lisp_gpe_fwd_entry_key_t), sizeof (uword));
@@ -330,6 +427,13 @@ lisp_gpe_init (vlib_main_t * vm)
return 0;
}
+gpe_encap_mode_t
+vnet_gpe_get_encap_mode (void)
+{
+ lisp_gpe_main_t *lgm = &lisp_gpe_main;
+ return lgm->encap_mode;
+}
+
VLIB_INIT_FUNCTION (lisp_gpe_init);
/*
diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h
index c498b7c3d99..c898a7daf6b 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.h
+++ b/src/vnet/lisp-gpe/lisp_gpe.h
@@ -88,6 +88,14 @@ typedef struct tunnel_lookup
uword *vni_by_sw_if_index;
} tunnel_lookup_t;
+
+typedef enum gpe_encap_mode_e
+{
+ GPE_ENCAP_LISP,
+ GPE_ENCAP_VXLAN,
+ GPE_ENCAP_COUNT
+} gpe_encap_mode_t;
+
/** LISP-GPE global state*/
typedef struct lisp_gpe_main
{
@@ -131,6 +139,8 @@ typedef struct lisp_gpe_main
const dpo_id_t *nsh_cp_lkup;
+ gpe_encap_mode_t encap_mode;
+
/** convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
@@ -268,6 +278,8 @@ typedef enum lgpe_ip6_lookup_next
u8 *format_vnet_lisp_gpe_status (u8 * s, va_list * args);
lisp_api_gpe_fwd_entry_t *vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni);
+gpe_encap_mode_t vnet_gpe_get_encap_mode (void);
+int vnet_gpe_set_encap_mode (gpe_encap_mode_t mode);
#endif /* included_vnet_lisp_gpe_h */
diff --git a/src/vnet/lisp-gpe/lisp_gpe_api.c b/src/vnet/lisp-gpe/lisp_gpe_api.c
index 8d19f8ce466..f6bd5440a6d 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_api.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_api.c
@@ -56,7 +56,9 @@ _(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry) \
_(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get) \
_(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump) \
_(GPE_ENABLE_DISABLE, gpe_enable_disable) \
-_(GPE_ADD_DEL_IFACE, gpe_add_del_iface)
+_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \
+_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \
+_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode)
static locator_pair_t *
unformat_gpe_loc_pairs (void *locs, u32 rloc_num)
@@ -373,6 +375,30 @@ vl_api_gpe_add_del_iface_t_handler (vl_api_gpe_add_del_iface_t * mp)
REPLY_MACRO (VL_API_GPE_ADD_DEL_IFACE_REPLY);
}
+static void
+vl_api_gpe_set_encap_mode_t_handler (vl_api_gpe_set_encap_mode_t * mp)
+{
+ vl_api_gpe_set_encap_mode_reply_t *rmp;
+ int rv = 0;
+
+ rv = vnet_gpe_set_encap_mode (mp->mode);
+ REPLY_MACRO (VL_API_GPE_SET_ENCAP_MODE_REPLY);
+}
+
+static void
+vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp)
+{
+ vl_api_gpe_get_encap_mode_reply_t *rmp;
+ int rv = 0;
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2 (VL_API_GPE_GET_ENCAP_MODE_REPLY,
+ ({
+ rmp->encap_mode = vnet_gpe_get_encap_mode ();
+ }));
+ /* *INDENT-ON* */
+}
+
/*
* gpe_api_hookup
* Add vpe's API message handlers to the table.
diff --git a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c b/src/vnet/lisp-gpe/lisp_gpe_tunnel.c
index 2ce4e8bc245..444bfe14d2b 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_tunnel.c
@@ -50,6 +50,7 @@ lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt,
lisp_gpe_header_t *lisp0;
u8 *rw = 0;
int len;
+ gpe_encap_mode_t encap_mode = vnet_gpe_get_encap_mode ();
if (IP4 == ip_addr_version (&lgt->key->lcl))
{
@@ -111,6 +112,10 @@ lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt,
}
lisp0->flags = ladj->flags;
+ if (GPE_ENCAP_VXLAN == encap_mode)
+ /* unset P flag */
+ lisp0->flags &= ~LISP_GPE_FLAGS_P;
+
lisp0->ver_res = 0;
lisp0->res = 0;
lisp0->next_protocol = payload_proto;