session: track number of tries to alloc lcl port

Track number of tries to alloc local port and report it in stats
segment. Could be used to gauge how busy the port allocator is.

Also add cli to dump trasport sub-layer state.

Type: improvement

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I3736a48488c491dee85aa2b074b87519a3857057
This commit is contained in:
Florin Coras
2024-11-13 22:54:14 -08:00
committed by Dave Barach
parent 80ae7e5307
commit da237e8b98
6 changed files with 71 additions and 8 deletions

View File

@ -1981,11 +1981,14 @@ session_stats_collector_fn (vlib_stats_collector_data_t *d)
}
vlib_stats_set_gauge (d->private_data, n_sessions);
vlib_stats_set_gauge (smm->stats_seg_idx.tp_port_alloc_max_tries,
transport_port_alloc_max_tries ());
}
static void
session_stats_collector_init (void)
{
session_main_t *smm = &session_main;
vlib_stats_collector_reg_t reg = {};
reg.entry_index =
@ -1994,6 +1997,10 @@ session_stats_collector_init (void)
reg.collect_fn = session_stats_collector_fn;
vlib_stats_register_collector_fn (&reg);
vlib_stats_validate (reg.entry_index, 0, vlib_get_n_threads ());
smm->stats_seg_idx.tp_port_alloc_max_tries =
vlib_stats_add_gauge ("/sys/session/transport_port_alloc_max_tries");
vlib_stats_set_gauge (smm->stats_seg_idx.tp_port_alloc_max_tries, 0);
}
static clib_error_t *

View File

@ -197,6 +197,11 @@ typedef enum
#undef _
} session_rt_engine_type_t;
typedef struct session_stats_seg_indices_
{
u32 tp_port_alloc_max_tries;
} session_stats_segs_indicies_t;
typedef struct session_main_
{
/** Worker contexts */
@ -294,6 +299,7 @@ typedef struct session_main_
/** Query nat44-ed session to get original dst ip4 & dst port. */
nat44_original_dst_lookup_fn original_dst_lookup;
session_stats_segs_indicies_t stats_seg_idx;
} session_main_t;
extern session_main_t session_main;

View File

@ -613,6 +613,11 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_output (vm, "%U", format_transport_protos);
goto done;
}
else if (unformat (input, "transport"))
{
vlib_cli_output (vm, "%U", format_transport_state);
goto done;
}
else if (unformat (input, "rt-backend"))
{
vlib_cli_output (vm, "%U", format_rt_backend, smm->rt_engine_type);
@ -799,7 +804,7 @@ VLIB_CLI_COMMAND (vlib_cli_show_session_command) = {
.path = "show session",
.short_help =
"show session [protos][states][rt-backend][verbose [n]] "
"[events][listeners <proto>] "
"[transport][events][listeners <proto>] "
"[<session-id>][thread <n> [[proto <p>] index <n>]][elog] "
"[thread <n>][proto <proto>][state <state>][range <min> [<max>]] "
"[lcl|rmt|ep <ip>[:<port>]][force-print]",
@ -1061,6 +1066,7 @@ clear_session_stats_fn (vlib_main_t *vm, unformat_input_t *input,
{
clib_memset (&wrk->stats, 0, sizeof (wrk->stats));
}
transport_clear_stats ();
return 0;
}

View File

@ -35,6 +35,7 @@ typedef struct transport_main_
local_endpoint_t *local_endpoints;
u32 *lcl_endpts_freelist;
u32 port_allocator_seed;
u16 port_alloc_max_tries;
u16 port_allocator_min_src_port;
u16 port_allocator_max_src_port;
u8 lcl_endpts_cleanup_pending;
@ -212,14 +213,39 @@ unformat_transport_proto (unformat_input_t * input, va_list * args)
u8 *
format_transport_protos (u8 * s, va_list * args)
{
u32 indent = format_get_indent (s) + 1;
transport_proto_vft_t *tp_vft;
vec_foreach (tp_vft, tp_vfts)
s = format (s, "%s\n", tp_vft->transport_options.name);
if (tp_vft->transport_options.name)
s = format (s, "%U%s\n", format_white_space, indent,
tp_vft->transport_options.name);
return s;
}
u8 *
format_transport_state (u8 *s, va_list *args)
{
transport_main_t *tm = &tp_main;
s = format (s, "registered protos:\n%U", format_transport_protos);
s = format (s, "configs:\n");
s =
format (s, " min_lcl_port: %u max_lcl_port: %u\n",
tm->port_allocator_min_src_port, tm->port_allocator_max_src_port);
s = format (s, "state:\n");
s = format (s, " lcl ports alloced: %u\n lcl ports freelist: %u \n",
pool_elts (tm->local_endpoints),
vec_len (tm->lcl_endpts_freelist));
s =
format (s, " port_alloc_max_tries: %u\n lcl_endpts_cleanup_pending: %u\n",
tm->port_alloc_max_tries, tm->lcl_endpts_cleanup_pending);
return s;
}
u32
transport_endpoint_lookup (transport_endpoint_table_t * ht, u8 proto,
ip46_address_t * ip, u16 port)
@ -606,7 +632,7 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
transport_main_t *tm = &tp_main;
u16 min = tm->port_allocator_min_src_port;
u16 max = tm->port_allocator_max_src_port;
int tries, limit;
int tries, limit, port = -1;
limit = max - min;
@ -616,8 +642,6 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
/* Search for first free slot */
for (tries = 0; tries < limit; tries++)
{
u16 port = 0;
/* Find a port in the specified range */
while (1)
{
@ -630,7 +654,7 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
}
if (!transport_endpoint_mark_used (proto, lcl_addr, port))
return port;
break;
/* IP:port pair already in use, check if 6-tuple available */
if (session_lookup_connection (rmt->fib_index, lcl_addr, &rmt->ip, port,
@ -640,9 +664,26 @@ transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr,
/* 6-tuple is available so increment lcl endpoint refcount */
transport_share_local_endpoint (proto, lcl_addr, port);
return port;
break;
}
return -1;
tm->port_alloc_max_tries = clib_max (tm->port_alloc_max_tries, tries);
return port;
}
u16
transport_port_alloc_max_tries ()
{
transport_main_t *tm = &tp_main;
return tm->port_alloc_max_tries;
}
void
transport_clear_stats ()
{
transport_main_t *tm = &tp_main;
tm->port_alloc_max_tries = 0;
}
static session_error_t

View File

@ -252,6 +252,8 @@ void transport_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip,
u16 port);
int transport_release_local_endpoint (u8 proto, ip46_address_t *lcl_ip,
u16 port);
u16 transport_port_alloc_max_tries ();
void transport_clear_stats ();
void transport_enable_disable (vlib_main_t * vm, u8 is_en);
void transport_init (void);

View File

@ -196,6 +196,7 @@ u8 *format_transport_half_open_connection (u8 * s, va_list * args);
uword unformat_transport_proto (unformat_input_t * input, va_list * args);
u8 *format_transport_protos (u8 * s, va_list * args);
u8 *format_transport_state (u8 *s, va_list *args);
#define foreach_transport_endpoint_fields \
_(ip46_address_t, ip) /**< ip address in net order */ \