From 0f2c6cd1ab5b5a627b78e4d7019d5f8a15a76613 Mon Sep 17 00:00:00 2001 From: Stanislav Zaikin Date: Fri, 8 Sep 2023 10:27:15 +0200 Subject: ikev2: handoff packets current approach saves state in per-thread data structure. in multi-worker + nat-t cases udp/500 and udp/4500 might be dispatched on different workers. this patch adds hands off packet to 1 explicit thread - 1st worker (or main thread in case there're no workers) or to thread that was explicitly set by user via configuration Type: improvement Change-Id: Ib5cd9a4b8612dfaa63b276035709524f7a492d4f Signed-off-by: Stanislav Zaikin --- src/plugins/ikev2/ikev2.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'src/plugins/ikev2/ikev2.c') diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index 9bea2c96d12..f66469a24d1 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -97,6 +97,7 @@ format_ikev2_gen_sa_error (u8 * s, va_list * args) typedef enum { IKEV2_NEXT_IP4_LOOKUP, + IKEV2_NEXT_IP4_HANDOFF, IKEV2_NEXT_IP4_ERROR_DROP, IKEV2_IP4_N_NEXT, } ikev2_ip4_next_t; @@ -104,6 +105,7 @@ typedef enum typedef enum { IKEV2_NEXT_IP6_LOOKUP, + IKEV2_NEXT_IP6_HANDOFF, IKEV2_NEXT_IP6_ERROR_DROP, IKEV2_IP6_N_NEXT, } ikev2_ip6_next_t; @@ -3187,6 +3189,7 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; u16 nexts[VLIB_FRAME_SIZE], *next = nexts; ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data (); + u32 thread_index = vm->thread_index; ikev2_stats_t _stats, *stats = &_stats; int res; @@ -3213,6 +3216,14 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node, int ip_hdr_sz = 0; int is_req = 0; + if (PREDICT_TRUE (thread_index != km->handoff_thread)) + { + vlib_node_increment_counter (vm, node->node_index, + IKEV2_ERROR_HANDOFF, 1); + + next[0] = is_ip4 ? IKEV2_NEXT_IP4_HANDOFF : IKEV2_NEXT_IP6_HANDOFF; + goto out; + } if (natt) { u8 *ptr = vlib_buffer_get_current (b0); @@ -3723,6 +3734,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node, ikev2_delete_sa (ptd, sa0); } + + out: if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) { @@ -3775,6 +3788,7 @@ VLIB_REGISTER_NODE (ikev2_node_ip4,static) = { .n_next_nodes = IKEV2_IP4_N_NEXT, .next_nodes = { [IKEV2_NEXT_IP4_LOOKUP] = "ip4-lookup", + [IKEV2_NEXT_IP4_HANDOFF] = "ikev2-ip4-handoff", [IKEV2_NEXT_IP4_ERROR_DROP] = "error-drop", }, }; @@ -3792,6 +3806,7 @@ VLIB_REGISTER_NODE (ikev2_node_ip4_natt,static) = { .n_next_nodes = IKEV2_IP4_N_NEXT, .next_nodes = { [IKEV2_NEXT_IP4_LOOKUP] = "ip4-lookup", + [IKEV2_NEXT_IP4_HANDOFF] = "ikev2-ip4-natt-handoff", [IKEV2_NEXT_IP4_ERROR_DROP] = "error-drop", }, }; @@ -3809,6 +3824,7 @@ VLIB_REGISTER_NODE (ikev2_node_ip6,static) = { .n_next_nodes = IKEV2_IP6_N_NEXT, .next_nodes = { [IKEV2_NEXT_IP6_LOOKUP] = "ip6-lookup", + [IKEV2_NEXT_IP4_HANDOFF] = "ikev2-ip6-handoff", [IKEV2_NEXT_IP6_ERROR_DROP] = "error-drop", }, }; @@ -5126,6 +5142,8 @@ ikev2_init (vlib_main_t * vm) km->liveness_period = IKEV2_LIVENESS_PERIOD_CHECK; km->liveness_max_retries = IKEV2_LIVENESS_RETRIES; + km->handoff_thread = vlib_num_workers () ? 1 : 0; + return 0; } @@ -5133,6 +5151,31 @@ VLIB_INIT_FUNCTION (ikev2_init) = { .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init"), }; +static clib_error_t * +ikev2_config (vlib_main_t *vm, unformat_input_t *input) +{ + ikev2_main_t *km = &ikev2_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "handoff-thread %d", &km->handoff_thread)) + { + if (km->handoff_thread > vlib_num_workers ()) + { + return clib_error_return (0, "wrong handoff-thread %d", + km->handoff_thread); + } + } + else + return clib_error_return (0, "unknown input `%U'", format_unformat_error, + input); + } + + return 0; +} + +VLIB_CONFIG_FUNCTION (ikev2_config, "ikev2"); + static u8 ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa, u8 del_old_ids) @@ -5447,6 +5490,7 @@ ikev2_send_informational_request (ikev2_sa_t * sa) } dp = sa->dst_port ? sa->dst_port : ikev2_get_port (sa); + ikev2_send_ike (km->vlib_main, src, dst, bi0, len, ikev2_get_port (sa), dp, sa->sw_if_index); } @@ -5625,6 +5669,15 @@ ikev2_lazy_init (ikev2_main_t *km) if (!km->dns_resolve_name_ptr) ikev2_log_error ("cannot load symbols from dns plugin"); + km->handoff_ip4_fq_index = + vlib_frame_queue_main_init (ikev2_node_ip4.index, 0); + + km->handoff_ip4_natt_fq_index = + vlib_frame_queue_main_init (ikev2_node_ip4_natt.index, 0); + + km->handoff_ip6_fq_index = + vlib_frame_queue_main_init (ikev2_node_ip6.index, 0); + /* wake up ikev2 process */ vlib_process_signal_event (vlib_get_first_main (), ikev2_mngr_process_node.index, 0, 0); -- cgit 1.2.3-korg