From 59fea5a6a3fafe0a5a0d2f543db53af790013e3a Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 31 Mar 2020 05:59:41 +0000 Subject: [PATCH] ikev2: make liveness params configurable Introduce new cli for setting liveness check period and max retries for a peer to consider its partner dead. ikev2 set liveness Type: improvement Change-Id: Iadae1de245d34fe3ee85e09b570f9df8c401772b Signed-off-by: Filip Tehlar --- src/plugins/ikev2/ikev2.api | 16 ++++++++++++++++ src/plugins/ikev2/ikev2.c | 23 +++++++++++++++++++---- src/plugins/ikev2/ikev2.h | 2 ++ src/plugins/ikev2/ikev2_api.c | 20 ++++++++++++++++++++ src/plugins/ikev2/ikev2_cli.c | 39 +++++++++++++++++++++++++++++++++++++++ src/plugins/ikev2/ikev2_priv.h | 6 ++++++ src/plugins/ikev2/ikev2_test.c | 28 ++++++++++++++++++++++++++++ 7 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api index bd330163046..8c56c98f13b 100644 --- a/src/plugins/ikev2/ikev2.api +++ b/src/plugins/ikev2/ikev2.api @@ -346,6 +346,22 @@ autoreply define ikev2_profile_set_ipsec_udp_port u16 port; string name[64]; }; + +/** \brief IKEv2: Set liveness parameters + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param period - how often is liveness check performed + @param max_retries - max retries for liveness check +*/ +autoreply define ikev2_profile_set_liveness +{ + u32 client_index; + u32 context; + + u32 period; + u32 max_retries; +}; + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index 892f57cd1d6..45da023f104 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -29,7 +29,7 @@ #include #include -#define IKEV2_LIVENESS_RETRIES 2 +#define IKEV2_LIVENESS_RETRIES 3 #define IKEV2_LIVENESS_PERIOD_CHECK 30 ikev2_main_t ikev2_main; @@ -2309,7 +2309,7 @@ ikev2_init_sa (ikev2_sa_t * sa) { ikev2_main_t *km = &ikev2_main; sa->liveness_period_check = - vlib_time_now (km->vlib_main) + IKEV2_LIVENESS_PERIOD_CHECK; + vlib_time_now (km->vlib_main) + km->liveness_period; } static uword @@ -3710,6 +3710,8 @@ ikev2_init (vlib_main_t * vm) km->vnet_main = vnet_get_main (); km->vlib_main = vm; + km->liveness_period = IKEV2_LIVENESS_PERIOD_CHECK; + km->liveness_max_retries = IKEV2_LIVENESS_RETRIES; ikev2_crypto_init (km); mhash_init_vec_string (&km->profile_index_by_name, sizeof (uword)); @@ -3847,6 +3849,19 @@ ikev2_set_log_level (ikev2_log_level_t log_level) return 0; } +clib_error_t * +ikev2_set_liveness_params (u32 period, u32 max_retries) +{ + ikev2_main_t *km = &ikev2_main; + + if (period == 0 || max_retries == 0) + return clib_error_return (0, "invalid args"); + + km->liveness_period = period; + km->liveness_max_retries = max_retries; + return 0; +} + static void ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa) { @@ -3963,7 +3978,7 @@ ikev2_mngr_process_responder_sas (ikev2_sa_t * sa) if (!sa->sk_ai || !sa->sk_ar) return 0; - if (sa->liveness_retries > IKEV2_LIVENESS_RETRIES) + if (sa->liveness_retries >= km->liveness_max_retries) return 1; f64 now = vlib_time_now (vm); @@ -3971,7 +3986,7 @@ ikev2_mngr_process_responder_sas (ikev2_sa_t * sa) if (sa->liveness_period_check < now) { sa->liveness_retries++; - sa->liveness_period_check = now + IKEV2_LIVENESS_PERIOD_CHECK; + sa->liveness_period_check = now + km->liveness_period; ikev2_send_informational_request (sa); } return 0; diff --git a/src/plugins/ikev2/ikev2.h b/src/plugins/ikev2/ikev2.h index d79a031c490..c701e301ce1 100644 --- a/src/plugins/ikev2/ikev2.h +++ b/src/plugins/ikev2/ikev2.h @@ -431,6 +431,8 @@ uword unformat_ikev2_transform_esn_type (unformat_input_t * input, va_list * args); void ikev2_cli_reference (void); +clib_error_t *ikev2_set_liveness_params (u32 period, u32 max_retries); + #endif /* __included_ikev2_h__ */ diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c index 0064f57483f..ef97898a747 100644 --- a/src/plugins/ikev2/ikev2_api.c +++ b/src/plugins/ikev2/ikev2_api.c @@ -61,6 +61,26 @@ vl_api_ikev2_plugin_get_version_t_handler (vl_api_ikev2_plugin_get_version_t * vl_api_send_msg (reg, (u8 *) rmp); } +static void + vl_api_ikev2_profile_set_liveness_t_handler + (vl_api_ikev2_profile_set_liveness_t * mp) +{ + vl_api_ikev2_profile_set_liveness_reply_t *rmp; + int rv = 0; + +#if WITH_LIBSSL > 0 + clib_error_t *error; + error = ikev2_set_liveness_params (clib_net_to_host_u32 (mp->period), + clib_net_to_host_u32 (mp->max_retries)); + if (error) + rv = VNET_API_ERROR_UNSPECIFIED; +#else + rv = VNET_API_ERROR_UNIMPLEMENTED; +#endif + + REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_LIVENESS_REPLY); +} + static void vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp) { diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c index 03f9efd696f..ec5867adf87 100644 --- a/src/plugins/ikev2/ikev2_cli.c +++ b/src/plugins/ikev2/ikev2_cli.c @@ -528,6 +528,45 @@ VLIB_CLI_COMMAND (show_ikev2_profile_command, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +set_ikev2_liveness_period_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *r = 0; + u32 period = 0, max_retries = 0; + + 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, "%d %d", &period, &max_retries)) + { + r = ikev2_set_liveness_params (period, max_retries); + goto done; + } + else + break; + } + + r = clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + +done: + unformat_free (line_input); + return r; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_ikev2_liveness_command, static) = { + .path = "ikev2 set liveness", + .short_help = "ikev2 set liveness ", + .function = set_ikev2_liveness_period_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * set_ikev2_local_key_command_fn (vlib_main_t * vm, unformat_input_t * input, diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h index c5a632c12a5..a344e716a89 100644 --- a/src/plugins/ikev2/ikev2_priv.h +++ b/src/plugins/ikev2/ikev2_priv.h @@ -490,6 +490,12 @@ typedef struct /* custom ipsec-over-udp ports managed by ike */ uword *udp_ports; + + /* how often a liveness check will be performed */ + u32 liveness_period; + + /* max number of retries before considering peer dead */ + u32 liveness_max_retries; } ikev2_main_t; extern ikev2_main_t ikev2_main; diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c index 8be42fef427..298125d23b0 100644 --- a/src/plugins/ikev2/ikev2_test.c +++ b/src/plugins/ikev2/ikev2_test.c @@ -105,6 +105,34 @@ api_ikev2_profile_set_ipsec_udp_port (vat_main_t * vam) return 0; } +static int +api_ikev2_profile_set_liveness (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_profile_set_liveness_t *mp; + u32 period = 0, max_retries = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (!unformat (i, "period %d max-retries %d", &period, &max_retries)) + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IKEV2_PROFILE_SET_LIVENESS, mp); + + mp->period = clib_host_to_net_u32 (period); + mp->max_retries = clib_host_to_net_u32 (max_retries); + + S (mp); + W (ret); + + return ret; +} + static int api_ikev2_profile_add_del (vat_main_t * vam) { -- 2.16.6