From: Filip Tehlar Date: Tue, 21 Feb 2017 17:28:34 +0000 (+0100) Subject: Add GPE CLI/API for setting encap mode X-Git-Tag: v17.04-rc1~163 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=3e7b569361f97368b0cad3468fac76ef2a398bfa Add GPE CLI/API for setting encap mode Change-Id: Id89e23fb5d275572b2356c073dfa0f55719e1a76 Signed-off-by: Filip Tehlar --- 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 ") \ _(lisp_gpe_fwd_entries_get, "vni ") \ _(lisp_gpe_fwd_entry_path_dump, "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 [leid ] 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;