aboutsummaryrefslogtreecommitdiffstats
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
parent646ba9b004055861c6dbce14424cb1d3de757ff6 (diff)
Add GPE CLI/API for setting encap mode
Change-Id: Id89e23fb5d275572b2356c073dfa0f55719e1a76 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
-rw-r--r--src/vat/api_format.c114
-rw-r--r--src/vnet/api_errno.h4
-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
8 files changed, 319 insertions, 4 deletions
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index 226e129e955..999f986922c 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -2729,6 +2729,53 @@ static void
}
}
+static u8 *
+format_gpe_encap_mode (u8 * s, va_list * args)
+{
+ u32 mode = va_arg (*args, u32);
+
+ switch (mode)
+ {
+ case 0:
+ return format (s, "lisp");
+ case 1:
+ return format (s, "vxlan");
+ }
+ return 0;
+}
+
+static void
+ vl_api_gpe_get_encap_mode_reply_t_handler
+ (vl_api_gpe_get_encap_mode_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ print (vam->ofp, "gpe mode: %U", format_gpe_encap_mode, mp->encap_mode);
+ vam->retval = ntohl (mp->retval);
+ vam->result_ready = 1;
+}
+
+static void
+ vl_api_gpe_get_encap_mode_reply_t_handler_json
+ (vl_api_gpe_get_encap_mode_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t node;
+
+ u8 *encap_mode = format (0, "%U", format_gpe_encap_mode, mp->encap_mode);
+ vec_add1 (encap_mode, 0);
+
+ vat_json_init_object (&node);
+ vat_json_object_add_string_copy (&node, "gpe_mode", encap_mode);
+
+ vec_free (encap_mode);
+ vat_json_print (vam->ofp, &node);
+ vat_json_free (&node);
+
+ vam->retval = ntohl (mp->retval);
+ vam->result_ready = 1;
+}
+
static void
vl_api_gpe_fwd_entry_path_details_t_handler
(vl_api_gpe_fwd_entry_path_details_t * mp)
@@ -3900,6 +3947,7 @@ _(one_add_del_map_request_itr_rlocs_reply) \
_(one_eid_table_add_del_map_reply) \
_(gpe_add_del_fwd_entry_reply) \
_(gpe_enable_disable_reply) \
+_(gpe_set_encap_mode_reply) \
_(gpe_add_del_iface_reply) \
_(vxlan_gpe_add_del_tunnel_reply) \
_(af_packet_delete_reply) \
@@ -4160,6 +4208,8 @@ _(ONE_EID_TABLE_VNI_DETAILS, one_eid_table_vni_details) \
_(ONE_MAP_RESOLVER_DETAILS, one_map_resolver_details) \
_(ONE_MAP_SERVER_DETAILS, one_map_server_details) \
_(ONE_ADJACENCIES_GET_REPLY, one_adjacencies_get_reply) \
+_(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply) \
+_(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply) \
_(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \
_(GPE_ENABLE_DISABLE_REPLY, gpe_enable_disable_reply) \
_(GPE_ADD_DEL_FWD_ENTRY_REPLY, gpe_add_del_fwd_entry_reply) \
@@ -14863,6 +14913,68 @@ api_one_add_del_adjacency (vat_main_t * vam)
#define api_lisp_add_del_adjacency api_one_add_del_adjacency
+uword
+unformat_gpe_encap_mode (unformat_input_t * input, va_list * args)
+{
+ u32 *mode = va_arg (*args, u32 *);
+
+ if (unformat (input, "lisp"))
+ *mode = 0;
+ else if (unformat (input, "vxlan"))
+ *mode = 1;
+ else
+ return 0;
+
+ return 1;
+}
+
+static int
+api_gpe_get_encap_mode (vat_main_t * vam)
+{
+ vl_api_gpe_get_encap_mode_t *mp;
+ int ret;
+
+ /* Construct the API message */
+ M (GPE_GET_ENCAP_MODE, mp);
+
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static int
+api_gpe_set_encap_mode (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_gpe_set_encap_mode_t *mp;
+ int ret;
+ u32 mode = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%U", unformat_gpe_encap_mode, &mode))
+ ;
+ else
+ break;
+ }
+
+ /* Construct the API message */
+ M (GPE_SET_ENCAP_MODE, mp);
+
+ mp->mode = mode;
+
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
static int
api_lisp_gpe_add_del_iface (vat_main_t * vam)
{
@@ -18471,6 +18583,8 @@ _(lisp_map_server_dump, "") \
_(lisp_adjacencies_get, "vni <vni>") \
_(lisp_gpe_fwd_entries_get, "vni <vni>") \
_(lisp_gpe_fwd_entry_path_dump, "index <fwd_entry_index>") \
+_(gpe_set_encap_mode, "lisp|vxlan") \
+_(gpe_get_encap_mode, "") \
_(lisp_gpe_add_del_iface, "up|down") \
_(lisp_gpe_enable_disable, "enable|disable") \
_(lisp_gpe_add_del_fwd_entry, "reid <eid> [leid <eid>] vni <vni>" \
diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h
index 0daba1691ef..8680ef7ca63 100644
--- a/src/vnet/api_errno.h
+++ b/src/vnet/api_errno.h
@@ -96,7 +96,9 @@ _(BFD_ENOENT, -102, "No such BFD object") \
_(BFD_EINUSE, -103, "BFD object in use") \
_(BFD_NOTSUPP, -104, "BFD feature not supported") \
_(LISP_RLOC_LOCAL, -105, "RLOC address is local") \
-_(BFD_EAGAIN, -106, "BFD object cannot be manipulated at this time")
+_(BFD_EAGAIN, -106, "BFD object cannot be manipulated at this time") \
+_(INVALID_GPE_MODE, -107, "Invalid GPE mode") \
+_(LISP_GPE_ENTRIES_PRESENT, -108, "LISP GPE entries are present")
typedef enum
{
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;