diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/acl/acl.c | 8 | ||||
-rw-r--r-- | src/plugins/acl/acl.h | 8 | ||||
-rw-r--r-- | src/plugins/acl/fa_node.h | 6 | ||||
-rw-r--r-- | src/plugins/acl/sess_mgmt_node.c | 93 | ||||
-rw-r--r-- | src/plugins/acl/session_inlines.h | 10 |
5 files changed, 93 insertions, 32 deletions
diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index b6e491cf897..866c6ffc5f0 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -3900,6 +3900,10 @@ acl_plugin_show_sessions (acl_main_t * am, pw->interrupt_is_unwanted); vlib_cli_output (vm, " interrupt generation: %d", pw->interrupt_generation); + vlib_cli_output (vm, " received session change requests: %d", + pw->rcvd_session_change_requests); + vlib_cli_output (vm, " sent session change requests: %d", + pw->sent_session_change_requests); } vlib_cli_output (vm, "\n\nConn cleaner thread counters:"); #define _(cnt, desc) vlib_cli_output(vm, " %20lu: %s", am->cnt, desc); @@ -4212,6 +4216,10 @@ acl_init (vlib_main_t * vm) for (wk = 0; wk < vec_len (am->per_worker_data); wk++) { acl_fa_per_worker_data_t *pw = &am->per_worker_data[wk]; + if (tm->n_vlib_mains > 1) + { + clib_spinlock_init (&pw->pending_session_change_request_lock); + } vec_validate (pw->expired, ACL_N_TIMEOUTS * am->fa_max_deleted_sessions_per_interval); diff --git a/src/plugins/acl/acl.h b/src/plugins/acl/acl.h index 310f80bfddc..c17946a9719 100644 --- a/src/plugins/acl/acl.h +++ b/src/plugins/acl/acl.h @@ -385,4 +385,12 @@ extern acl_main_t acl_main; void *acl_plugin_set_heap(); +typedef enum { + ACL_FA_REQ_SESS_RESCHEDULE = 0, + ACL_FA_N_REQ, +} acl_fa_sess_req_t; + +void aclp_post_session_change_request(acl_main_t *am, u32 target_thread, u32 target_session, acl_fa_sess_req_t request_type); +void aclp_swap_wip_and_pending_session_change_requests(acl_main_t *am, u32 target_thread); + #endif diff --git a/src/plugins/acl/fa_node.h b/src/plugins/acl/fa_node.h index e41dd0ad6fd..74b71b93cd9 100644 --- a/src/plugins/acl/fa_node.h +++ b/src/plugins/acl/fa_node.h @@ -145,6 +145,12 @@ CT_ASSERT_EQUAL(fa_5tuple_opaque_t_must_match_5tuple, sizeof(fa_5tuple_opaque_t) typedef struct { /* The pool of sessions managed by this worker */ fa_session_t *fa_sessions_pool; + /* incoming session change requests from other workers */ + clib_spinlock_t pending_session_change_request_lock; + u64 *pending_session_change_requests; + u64 *wip_session_change_requests; + u64 rcvd_session_change_requests; + u64 sent_session_change_requests; /* per-worker ACL_N_TIMEOUTS of conn lists */ u32 *fa_conn_list_head; u32 *fa_conn_list_tail; diff --git a/src/plugins/acl/sess_mgmt_node.c b/src/plugins/acl/sess_mgmt_node.c index abb1e7cf0e4..f38677f8d5a 100644 --- a/src/plugins/acl/sess_mgmt_node.c +++ b/src/plugins/acl/sess_mgmt_node.c @@ -30,25 +30,6 @@ #include <plugins/acl/public_inlines.h> #include <plugins/acl/session_inlines.h> -// #include <vppinfra/bihash_40_8.h> - - -static u64 -fa_session_get_shortest_timeout (acl_main_t * am) -{ - int timeout_type; - u64 timeout = ~0LL; - for (timeout_type = ACL_TIMEOUT_UDP_IDLE; - timeout_type < ACL_N_USER_TIMEOUTS; timeout_type++) - { - if (timeout > am->session_timeout_sec[timeout_type]) - { - timeout = am->session_timeout_sec[timeout_type]; - } - } - return timeout; -} - static u8 * format_ip6_session_bihash_kv (u8 * s, va_list * args) { @@ -138,14 +119,9 @@ static u64 fa_session_get_list_timeout (acl_main_t * am, fa_session_t * sess) { u64 timeout = am->vlib_main->clib_time.clocks_per_second / 1000; - /* - * we have the shortest possible timeout type in all the lists - * (see README-multicore for the rationale) - */ - if (sess->link_list_id == ACL_TIMEOUT_PURGATORY) - timeout = fa_session_get_timeout (am, sess); - else - timeout *= fa_session_get_shortest_timeout (am); + timeout = fa_session_get_timeout (am, sess); + /* for all user lists, check them twice per timeout */ + timeout >>= (sess->link_list_id != ACL_TIMEOUT_PURGATORY); return timeout; } @@ -183,6 +159,28 @@ acl_fa_check_idle_sessions (acl_main_t * am, u16 thread_index, u64 now) fsid.thread_index = thread_index; int total_expired = 0; + /* let the other threads enqueue more requests while we process, if they like */ + aclp_swap_wip_and_pending_session_change_requests (am, thread_index); + u64 *psr = NULL; + + vec_foreach (psr, pw->wip_session_change_requests) + { + acl_fa_sess_req_t op = *psr >> 32; + fsid.session_index = *psr & 0xffffffff; + switch (op) + { + case ACL_FA_REQ_SESS_RESCHEDULE: + acl_fa_restart_timer_for_session (am, now, fsid); + break; + default: + /* do nothing */ + break; + } + } + if (pw->wip_session_change_requests) + _vec_len (pw->wip_session_change_requests) = 0; + + { u8 tt = 0; int n_pending_swipes = 0; @@ -240,6 +238,9 @@ acl_fa_check_idle_sessions (acl_main_t * am, u16 thread_index, u64 now) clib_bitmap_get (pw->pending_clear_sw_if_index_bitmap, sw_if_index); if (am->trace_sessions > 3) { + elog_acl_maybe_trace_X2 (am, + "acl_fa_check_idle_sessions: now %lu sess_timeout_time %lu", + "i8i8", now, sess_timeout_time); elog_acl_maybe_trace_X4 (am, "acl_fa_check_idle_sessions: session %d sw_if_index %d timeout_passed %d clearing_interface %d", "i4i4i4i4", (u32) fsid.session_index, @@ -361,6 +362,44 @@ send_one_worker_interrupt (vlib_main_t * vm, acl_main_t * am, } } +void +aclp_post_session_change_request (acl_main_t * am, u32 target_thread, + u32 target_session, u32 request_type) +{ + acl_fa_per_worker_data_t *pw_me = + &am->per_worker_data[os_get_thread_index ()]; + acl_fa_per_worker_data_t *pw = &am->per_worker_data[target_thread]; + clib_spinlock_lock_if_init (&pw->pending_session_change_request_lock); + /* vec_add1 might cause a reallocation, change the heap just in case */ + void *oldheap = clib_mem_set_heap (am->acl_mheap); + vec_add1 (pw->pending_session_change_requests, + (((u64) request_type) << 32) | target_session); + clib_mem_set_heap (oldheap); + + pw->rcvd_session_change_requests++; + pw_me->sent_session_change_requests++; + if (vec_len (pw->pending_session_change_requests) == 1) + { + /* ensure the requests get processed */ + send_one_worker_interrupt (am->vlib_main, am, target_thread); + } + clib_spinlock_unlock_if_init (&pw->pending_session_change_request_lock); +} + +void +aclp_swap_wip_and_pending_session_change_requests (acl_main_t * am, + u32 target_thread) +{ + acl_fa_per_worker_data_t *pw = &am->per_worker_data[target_thread]; + u64 *tmp; + clib_spinlock_lock_if_init (&pw->pending_session_change_request_lock); + tmp = pw->pending_session_change_requests; + pw->pending_session_change_requests = pw->wip_session_change_requests; + pw->wip_session_change_requests = tmp; + clib_spinlock_unlock_if_init (&pw->pending_session_change_request_lock); +} + + static int purgatory_has_connections (vlib_main_t * vm, acl_main_t * am, int thread_index) diff --git a/src/plugins/acl/session_inlines.h b/src/plugins/acl/session_inlines.h index db878c003e2..5e975300142 100644 --- a/src/plugins/acl/session_inlines.h +++ b/src/plugins/acl/session_inlines.h @@ -247,12 +247,12 @@ acl_fa_restart_timer_for_session (acl_main_t * am, u64 now, else { /* - * Our thread does not own this connection, so we can not delete - * The session. To avoid the complicated signaling, we simply - * pick the list waiting time to be the shortest of the timeouts. - * This way we do not have to do anything special, and let - * the regular requeue check take care of everything. + * Our thread does not own this connection, so we can not requeue + * The session. So we post the signal to the owner. */ + aclp_post_session_change_request (am, sess_id.thread_index, + sess_id.session_index, + ACL_FA_REQ_SESS_RESCHEDULE); return 0; } } |