session: memory leaks on various transports when session disable and enable

When toggling session disable and enable, memory leaks found on various
transports.

Don't create the timer wheels on enable when they are already creaded.
Don't create the spin locks when they are already created.
Add session enable disable test in session unit test.

Type: fix

Change-Id: I08988a96bbf2d67a67c743b50b63f5b1e27402a3
Signed-off-by: Steven Luong <sluong@cisco.com>
This commit is contained in:
Steven Luong
2024-06-28 15:12:11 -07:00
parent 6d44aabe8d
commit d2d41bc34e
4 changed files with 76 additions and 3 deletions

View File

@ -71,6 +71,8 @@ http_timers_init (vlib_main_t *vm, http_conn_timeout_fn *cb_fn)
http_tw_ctx_t *twc = &http_tw_ctx;
vlib_node_t *n;
if (twc->tw.timers)
return;
tw_timer_wheel_init_2t_1w_2048sl (&twc->tw, http_timer_process_expired_cb,
1.0 /* timer interval */, ~0);
clib_spinlock_init (&twc->tw_lock);

View File

@ -2073,6 +2073,63 @@ session_test_mq_basic (vlib_main_t * vm, unformat_input_t * input)
return 0;
}
static f32
session_get_memory_usage (void)
{
clib_mem_heap_t *heap = clib_mem_get_per_cpu_heap ();
u8 *s = 0;
char *ss;
f32 used;
s = format (s, "%U\n", format_clib_mem_heap, heap, 0);
ss = strstr ((char *) s, "used:");
sscanf (ss, "used: %f", &used);
vec_free (s);
return (used);
}
static int
session_test_enable_disable (vlib_main_t *vm, unformat_input_t *input)
{
u32 iteration = 100, i;
uword was_enabled;
f32 was_using, now_using;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "repeat %d", &iteration))
;
else
{
vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
input);
return -1;
}
}
was_enabled = clib_mem_trace_enable_disable (0);
/* warm up */
for (i = 0; i < 10; i++)
{
vnet_session_enable_disable (vm, 0);
vnet_session_enable_disable (vm, 1);
}
was_using = session_get_memory_usage ();
for (i = 0; i < iteration; i++)
{
vnet_session_enable_disable (vm, 0);
vnet_session_enable_disable (vm, 1);
}
now_using = session_get_memory_usage ();
clib_mem_trace_enable_disable (was_enabled);
SESSION_TEST ((was_using == now_using), "was using %.2fM, now using %.2fM",
was_using, now_using);
return 0;
}
static clib_error_t *
session_test (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd_arg)
@ -2099,6 +2156,8 @@ session_test (vlib_main_t * vm,
res = session_test_mq_speed (vm, input);
else if (unformat (input, "mq-basic"))
res = session_test_mq_basic (vm, input);
else if (unformat (input, "enable-disable"))
res = session_test_enable_disable (vm, input);
else if (unformat (input, "all"))
{
if ((res = session_test_basic (vm, input)))
@ -2117,6 +2176,8 @@ session_test (vlib_main_t * vm,
goto done;
if ((res = session_test_mq_basic (vm, input)))
goto done;
if ((res = session_test_enable_disable (vm, input)))
goto done;
}
else
break;

View File

@ -1350,13 +1350,21 @@ ct_enable_disable (vlib_main_t * vm, u8 is_en)
ct_main_t *cm = &ct_main;
ct_worker_t *wrk;
if (is_en == 0)
return 0;
cm->n_workers = vlib_num_workers ();
cm->fwrk_thread = transport_cl_thread ();
vec_validate (cm->wrk, vtm->n_vlib_mains);
vec_foreach (wrk, cm->wrk)
clib_spinlock_init (&wrk->pending_connects_lock);
clib_spinlock_init (&cm->ho_reuseable_lock);
clib_rwlock_init (&cm->app_segs_lock);
{
if (wrk->pending_connects_lock == 0)
clib_spinlock_init (&wrk->pending_connects_lock);
}
if (cm->ho_reuseable_lock == 0)
clib_spinlock_init (&cm->ho_reuseable_lock);
if (cm->app_segs_lock == 0)
clib_rwlock_init (&cm->app_segs_lock);
vec_validate (cm->fwrk_pending_connects, cm->n_workers);
return 0;
}

View File

@ -20,6 +20,8 @@ void
tcp_timer_initialize_wheel (tcp_timer_wheel_t * tw,
void (*expired_timer_cb) (u32 *), f64 now)
{
if (tw->timers)
return;
tw_timer_wheel_init_tcp_twsl (tw, expired_timer_cb, TCP_TIMER_TICK, ~0);
tw->last_run_time = now;
}