From 3e7b569361f97368b0cad3468fac76ef2a398bfa Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 21 Feb 2017 18:28:34 +0100 Subject: Add GPE CLI/API for setting encap mode Change-Id: Id89e23fb5d275572b2356c073dfa0f55719e1a76 Signed-off-by: Filip Tehlar --- src/vnet/api_errno.h | 4 +- src/vnet/lisp-gpe/decap.c | 11 +++- src/vnet/lisp-gpe/lisp_gpe.api | 45 ++++++++++++++++ src/vnet/lisp-gpe/lisp_gpe.c | 104 ++++++++++++++++++++++++++++++++++++ src/vnet/lisp-gpe/lisp_gpe.h | 12 +++++ src/vnet/lisp-gpe/lisp_gpe_api.c | 28 +++++++++- src/vnet/lisp-gpe/lisp_gpe_tunnel.c | 5 ++ 7 files changed, 205 insertions(+), 4 deletions(-) (limited to 'src/vnet') 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; -- cgit 1.2.3-korg