aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/hs_apps/sapi/vpp_echo_proto_quic.c6
-rw-r--r--src/vnet/session/session.h12
-rwxr-xr-xsrc/vnet/session/session_cli.c341
-rw-r--r--src/vnet/session/session_types.h31
-rw-r--r--src/vnet/session/transport.c85
-rw-r--r--src/vnet/session/transport_types.h19
-rw-r--r--src/vnet/tcp/tcp.c2
7 files changed, 348 insertions, 148 deletions
diff --git a/src/plugins/hs_apps/sapi/vpp_echo_proto_quic.c b/src/plugins/hs_apps/sapi/vpp_echo_proto_quic.c
index 28c89a65fbf..41f9cd9e09c 100644
--- a/src/plugins/hs_apps/sapi/vpp_echo_proto_quic.c
+++ b/src/plugins/hs_apps/sapi/vpp_echo_proto_quic.c
@@ -54,7 +54,7 @@ quic_echo_on_connected_connect (session_connected_msg_t * mp,
{
echo_main_t *em = &echo_main;
quic_echo_proto_main_t *eqm = &quic_echo_proto_main;
- u8 *uri = format (0, "QUIC://session/%lu", mp->handle);
+ u8 *uri = format (0, "quic://session/%lu", mp->handle);
u64 i;
echo_notify_event (em, ECHO_EVT_FIRST_SCONNECT);
@@ -107,7 +107,7 @@ quic_echo_on_accept_connect (session_accepted_msg_t * mp, u32 session_index)
echo_main_t *em = &echo_main;
quic_echo_proto_main_t *eqm = &quic_echo_proto_main;
ECHO_LOG (1, "Accept on QSession 0x%lx %u", mp->handle);
- u8 *uri = format (0, "QUIC://session/%lu", mp->handle);
+ u8 *uri = format (0, "quic://session/%lu", mp->handle);
u32 i;
echo_notify_event (em, ECHO_EVT_FIRST_SCONNECT);
@@ -303,7 +303,7 @@ quic_echo_retry_connect (u32 session_index)
else
{
session = pool_elt_at_index (em->sessions, session_index);
- uri = format (0, "QUIC://session/%lu", session->vpp_session_handle);
+ uri = format (0, "quic://session/%lu", session->vpp_session_handle);
ECHO_LOG (1, "Retrying connect %s", uri);
echo_send_rpc (em, echo_send_connect, (void *) uri, session_index);
}
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index 04fdebed791..cb0cac7cda6 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -584,6 +584,14 @@ session_main_get_worker (u32 thread_index)
return &session_main.wrk[thread_index];
}
+static inline session_worker_t *
+session_main_get_worker_if_valid (u32 thread_index)
+{
+ if (pool_is_free_index (session_main.wrk, thread_index))
+ return 0;
+ return &session_main.wrk[thread_index];
+}
+
always_inline svm_msg_q_t *
session_main_get_vpp_event_queue (u32 thread_index)
{
@@ -598,8 +606,8 @@ session_main_is_enabled ()
#define session_cli_return_if_not_enabled() \
do { \
- if (!session_main.is_enabled) \
- return clib_error_return(0, "session layer is not enabled"); \
+ if (!session_main.is_enabled) \
+ return clib_error_return (0, "session layer is not enabled"); \
} while (0)
int session_main_flush_enqueue_events (u8 proto, u32 thread_index);
diff --git a/src/vnet/session/session_cli.c b/src/vnet/session/session_cli.c
index fd598f45d3e..d8aedd64e23 100755
--- a/src/vnet/session/session_cli.c
+++ b/src/vnet/session/session_cli.c
@@ -162,6 +162,27 @@ unformat_stream_session_id (unformat_input_t * input, va_list * args)
}
uword
+unformat_session_state (unformat_input_t * input, va_list * args)
+{
+ session_state_t *state = va_arg (*args, session_state_t *);
+ u8 *state_vec = 0;
+ int rv = 0;
+
+#define _(sym, str) \
+ if (unformat (input, str)) \
+ { \
+ *state = SESSION_STATE_ ## sym; \
+ rv = 1; \
+ goto done; \
+ }
+ foreach_session_state
+#undef _
+done:
+ vec_free (state_vec);
+ return rv;
+}
+
+uword
unformat_session (unformat_input_t * input, va_list * args)
{
session_t **result = va_arg (*args, session_t **);
@@ -227,42 +248,270 @@ unformat_transport_connection (unformat_input_t * input, va_list * args)
return 0;
}
+static void
+session_cli_show_all_sessions (vlib_main_t * vm, int verbose)
+{
+ session_main_t *smm = &session_main;
+ u32 n_closed = 0, thread_index;
+ session_t *pool, *s;
+
+ for (thread_index = 0; thread_index < vec_len (smm->wrk); thread_index++)
+ {
+ pool = smm->wrk[thread_index].sessions;
+
+ if (!pool_elts (pool))
+ {
+ vlib_cli_output (vm, "Thread %d: no sessions", thread_index);
+ continue;
+ }
+
+ if (!verbose)
+ {
+ vlib_cli_output (vm, "Thread %d: %d sessions", thread_index,
+ pool_elts (pool));
+ continue;
+ }
+
+ if (pool_elts (pool) > 50)
+ {
+ vlib_cli_output (vm, "Thread %u: %d sessions. Verbose output "
+ "suppressed. For more details use filters.",
+ thread_index, pool_elts (pool));
+ continue;
+ }
+
+ if (verbose == 1)
+ vlib_cli_output (vm, "%s%-50s%-15s%-10s%-10s",
+ thread_index ? "\n" : "",
+ "Connection", "State", "Rx-f", "Tx-f");
+
+ /* *INDENT-OFF* */
+ pool_foreach(s, pool, ({
+ if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED)
+ {
+ n_closed += 1;
+ continue;
+ }
+ vlib_cli_output (vm, "%U", format_session, s, verbose);
+ }));
+ /* *INDENT-ON* */
+
+ if (!n_closed)
+ vlib_cli_output (vm, "Thread %d: active sessions %u", thread_index,
+ pool_elts (pool) - n_closed);
+ else
+ vlib_cli_output (vm, "Thread %d: active sessions %u closed %u",
+ thread_index, pool_elts (pool) - n_closed, n_closed);
+ }
+}
+
+static int
+session_cli_filter_check (session_t * s, session_state_t * states,
+ transport_proto_t tp)
+{
+ if (states)
+ {
+ session_state_t *state;
+ vec_foreach (state, states) if (s->session_state == *state)
+ goto check_transport;
+ return 0;
+ }
+
+check_transport:
+
+ if (tp != TRANSPORT_N_PROTO && session_get_transport_proto (s) != tp)
+ return 0;
+
+ return 1;
+}
+
+static void
+session_cli_show_session_filter (vlib_main_t * vm, u32 thread_index,
+ u32 start, u32 end, session_state_t * states,
+ transport_proto_t tp, int verbose)
+{
+ u8 output_suppressed = 0;
+ session_worker_t *wrk;
+ session_t *pool, *s;
+ u32 count = 0, max_index;
+ int i;
+
+ wrk = session_main_get_worker_if_valid (thread_index);
+ if (!wrk)
+ {
+ vlib_cli_output (vm, "invalid thread index %u", thread_index);
+ return;
+ }
+
+ pool = wrk->sessions;
+
+ if (tp == TRANSPORT_N_PROTO && states == 0 && !verbose
+ && (start == 0 && end == ~0))
+ {
+ vlib_cli_output (vm, "Thread %d: %u sessions", thread_index,
+ pool_elts (pool));
+ return;
+ }
+
+ max_index = pool_elts (pool) ? pool_elts (pool) - 1 : 0;
+ for (i = start; i <= clib_min (end, max_index); i++)
+ {
+ if (pool_is_free_index (pool, i))
+ continue;
+
+ s = pool_elt_at_index (pool, i);
+
+ if (session_cli_filter_check (s, states, tp))
+ {
+ count += 1;
+ if (verbose)
+ {
+ if (count > 50 || (verbose > 1 && count > 10))
+ {
+ output_suppressed = 1;
+ continue;
+ }
+ if (s->session_state < SESSION_STATE_TRANSPORT_DELETED)
+ vlib_cli_output (vm, "%U", format_session, s, verbose);
+ }
+ }
+ }
+
+ if (!output_suppressed)
+ vlib_cli_output (vm, "Thread %d: %u sessions matched filter",
+ thread_index, count);
+ else
+ vlib_cli_output (vm, "Thread %d: %u sessions matched filter. Not all"
+ " shown. Use finer grained filter.", thread_index,
+ count);
+}
+
+static void
+session_cli_print_transport_protos (vlib_main_t * vm)
+{
+#define _(sym, str, sstr) vlib_cli_output (vm, str);
+ foreach_transport_proto
+#undef _
+}
+
+static void
+session_cli_print_session_states (vlib_main_t * vm)
+{
+#define _(sym, str) vlib_cli_output (vm, str);
+ foreach_session_state
+#undef _
+}
+
static clib_error_t *
show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- u8 one_session = 0, do_listeners = 0, sst, do_elog = 0;
+ u8 one_session = 0, do_listeners = 0, sst, do_elog = 0, do_filter = 0;
+ u32 track_index, thread_index = 0, start = 0, end = ~0, session_index;
+ unformat_input_t _line_input, *line_input = &_line_input;
+ transport_proto_t transport_proto = TRANSPORT_N_PROTO;
+ session_state_t state = SESSION_N_STATES, *states = 0;
session_main_t *smm = &session_main;
- u32 transport_proto = ~0, track_index;
- session_t *pool, *s;
- transport_connection_t *tc;
+ clib_error_t *error = 0;
app_worker_t *app_wrk;
- int verbose = 0, i;
+ u32 transport_index;
const u8 *app_name;
+ int verbose = 0;
+ session_t *s;
- if (!smm->is_enabled)
+ session_cli_return_if_not_enabled ();
+
+ if (!unformat_user (input, unformat_line_input, line_input))
{
- return clib_error_return (0, "session layer is not enabled");
+ session_cli_show_all_sessions (vm, 0);
+ return 0;
}
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat (input, "verbose %d", &verbose))
+ if (unformat (line_input, "verbose %d", &verbose))
;
- else if (unformat (input, "verbose"))
+ else if (unformat (line_input, "verbose"))
verbose = 1;
- else if (unformat (input, "listeners %U", unformat_transport_proto,
+ else if (unformat (line_input, "listeners %U", unformat_transport_proto,
&transport_proto))
do_listeners = 1;
- else if (unformat (input, "%U", unformat_session, &s))
+ else if (unformat (line_input, "%U", unformat_session, &s))
{
one_session = 1;
}
- else if (unformat (input, "elog"))
+ else if (unformat (line_input, "thread %u index %u", &thread_index,
+ &session_index))
+ {
+ s = session_get_if_valid (session_index, thread_index);
+ if (!s)
+ {
+ vlib_cli_output (vm, "session is not allocated");
+ goto done;
+ }
+ one_session = 1;
+ }
+ else if (unformat (line_input, "thread %u", &thread_index))
+ {
+ do_filter = 1;
+ }
+ else
+ if (unformat (line_input, "state %U", unformat_session_state, &state))
+ {
+ vec_add1 (states, state);
+ do_filter = 1;
+ }
+ else if (unformat (line_input, "proto %U index %u",
+ unformat_transport_proto, &transport_proto,
+ &transport_index))
+ {
+ transport_connection_t *tc;
+ tc = transport_get_connection (transport_proto, transport_index,
+ thread_index);
+ if (!tc)
+ {
+ vlib_cli_output (vm, "transport connection %u thread %u is not"
+ " allocated", transport_index, thread_index);
+ goto done;
+ }
+ s = session_get_if_valid (tc->s_index, thread_index);
+ if (!s)
+ {
+ vlib_cli_output (vm, "session for transport connection %u "
+ "thread %u does not exist", transport_index,
+ thread_index);
+ goto done;
+ }
+ one_session = 1;
+ }
+ else if (unformat (line_input, "proto %U", unformat_transport_proto,
+ &transport_proto))
+ do_filter = 1;
+ else if (unformat (line_input, "range %u %u", &start, &end))
+ do_filter = 1;
+ else if (unformat (line_input, "range %u", &start))
+ {
+ end = start + 50;
+ do_filter = 1;
+ }
+ else if (unformat (line_input, "elog"))
do_elog = 1;
+ else if (unformat (line_input, "protos"))
+ {
+ session_cli_print_transport_protos (vm);
+ goto done;
+ }
+ else if (unformat (line_input, "states"))
+ {
+ session_cli_print_session_states (vm);
+ goto done;
+ }
else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
if (one_session)
@@ -271,6 +520,7 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
if (do_elog && s->session_state != SESSION_STATE_LISTENING)
{
elog_main_t *em = &vm->elog_main;
+ transport_connection_t *tc;
f64 dt;
tc = session_get_transport (s);
@@ -283,7 +533,7 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
}
vlib_cli_output (vm, "%v", str);
vec_free (str);
- return 0;
+ goto done;
}
if (do_listeners)
@@ -301,53 +551,28 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input,
app_name);
}));
/* *INDENT-ON* */
- return 0;
+ goto done;
}
- for (i = 0; i < vec_len (smm->wrk); i++)
+ if (do_filter)
{
- u32 once_per_pool = 1, n_closed = 0;
-
- pool = smm->wrk[i].sessions;
- if (!pool_elts (pool))
- {
- vlib_cli_output (vm, "Thread %d: no sessions", i);
- continue;
- }
-
- if (!verbose)
- {
- vlib_cli_output (vm, "Thread %d: %d sessions", i, pool_elts (pool));
- continue;
- }
-
- if (once_per_pool && verbose == 1)
+ if (end < start)
{
- vlib_cli_output (vm, "%s%-50s%-15s%-10s%-10s", i ? "\n" : "",
- "Connection", "State", "Rx-f", "Tx-f");
- once_per_pool = 0;
+ error = clib_error_return (0, "invalid range start: %u end: %u",
+ start, end);
+ goto done;
}
-
- /* *INDENT-OFF* */
- pool_foreach (s, pool, ({
- if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED)
- {
- n_closed += 1;
- continue;
- }
- vlib_cli_output (vm, "%U", format_session, s, verbose);
- }));
- /* *INDENT-ON* */
-
- if (!n_closed)
- vlib_cli_output (vm, "Thread %d: active sessions %u", i,
- pool_elts (pool) - n_closed);
- else
- vlib_cli_output (vm, "Thread %d: active sessions %u closed %u", i,
- pool_elts (pool) - n_closed, n_closed);
+ session_cli_show_session_filter (vm, thread_index, start, end, states,
+ transport_proto, verbose);
+ goto done;
}
- return 0;
+ session_cli_show_all_sessions (vm, verbose);
+
+done:
+ unformat_free (line_input);
+ vec_free (states);
+ return error;
}
/* *INDENT-OFF* */
@@ -355,7 +580,9 @@ VLIB_CLI_COMMAND (vlib_cli_show_session_command) =
{
.path = "show session",
.short_help = "show session [verbose [n]] [listeners <proto>] "
- "[<session-id> [elog]]",
+ "[<session-id> [elog]] [thread <n> [index <n>] "
+ "[proto <proto>] [state <state>] [range <min> [<max>]] "
+ "[protos] [states] ",
.function = show_session_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/vnet/session/session_types.h b/src/vnet/session/session_types.h
index 52a79e3beb5..bf45855e264 100644
--- a/src/vnet/session/session_types.h
+++ b/src/vnet/session/session_types.h
@@ -121,21 +121,26 @@ typedef enum
/*
* Session states
*/
+#define foreach_session_state \
+ _(CREATED, "created") \
+ _(LISTENING, "listening") \
+ _(CONNECTING, "connecting") \
+ _(ACCEPTING, "accepting") \
+ _(READY, "ready") \
+ _(OPENED, "opened") \
+ _(TRANSPORT_CLOSING, "transport-closing") \
+ _(CLOSING, "closing") \
+ _(APP_CLOSED, "app-closed") \
+ _(TRANSPORT_CLOSED, "transport-closed") \
+ _(TRANSPORT_DELETED, "transport-deleted") \
+ _(CLOSED, "closed") \
+
typedef enum
{
- SESSION_STATE_CREATED,
- SESSION_STATE_LISTENING,
- SESSION_STATE_CONNECTING,
- SESSION_STATE_ACCEPTING,
- SESSION_STATE_READY,
- SESSION_STATE_OPENED,
- SESSION_STATE_TRANSPORT_CLOSING,
- SESSION_STATE_CLOSING,
- SESSION_STATE_APP_CLOSED,
- SESSION_STATE_TRANSPORT_CLOSED,
- SESSION_STATE_TRANSPORT_DELETED,
- SESSION_STATE_CLOSED,
- SESSION_STATE_N_STATES,
+#define _(sym, str) SESSION_STATE_ ## sym,
+ foreach_session_state
+#undef _
+ SESSION_N_STATES,
} session_state_t;
typedef enum session_flags_
diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c
index aa8deac5400..c1c908eae1a 100644
--- a/src/vnet/session/transport.c
+++ b/src/vnet/session/transport.c
@@ -57,27 +57,12 @@ format_transport_proto (u8 * s, va_list * args)
u32 transport_proto = va_arg (*args, u32);
switch (transport_proto)
{
- case TRANSPORT_PROTO_TCP:
- s = format (s, "TCP");
- break;
- case TRANSPORT_PROTO_UDP:
- s = format (s, "UDP");
- break;
- case TRANSPORT_PROTO_SCTP:
- s = format (s, "SCTP");
- break;
- case TRANSPORT_PROTO_NONE:
- s = format (s, "NONE");
- break;
- case TRANSPORT_PROTO_TLS:
- s = format (s, "TLS");
- break;
- case TRANSPORT_PROTO_UDPC:
- s = format (s, "UDPC");
- break;
- case TRANSPORT_PROTO_QUIC:
- s = format (s, "QUIC");
+#define _(sym, str, sstr) \
+ case TRANSPORT_PROTO_ ## sym: \
+ s = format (s, str); \
break;
+ foreach_transport_proto
+#undef _
default:
s = format (s, "UNKNOWN");
break;
@@ -91,27 +76,12 @@ format_transport_proto_short (u8 * s, va_list * args)
u32 transport_proto = va_arg (*args, u32);
switch (transport_proto)
{
- case TRANSPORT_PROTO_TCP:
- s = format (s, "T");
- break;
- case TRANSPORT_PROTO_UDP:
- s = format (s, "U");
- break;
- case TRANSPORT_PROTO_SCTP:
- s = format (s, "S");
- break;
- case TRANSPORT_PROTO_NONE:
- s = format (s, "N");
- break;
- case TRANSPORT_PROTO_TLS:
- s = format (s, "J");
- break;
- case TRANSPORT_PROTO_UDPC:
- s = format (s, "U");
- break;
- case TRANSPORT_PROTO_QUIC:
- s = format (s, "Q");
+#define _(sym, str, sstr) \
+ case TRANSPORT_PROTO_ ## sym: \
+ s = format (s, sstr); \
break;
+ foreach_transport_proto
+#undef _
default:
s = format (s, "?");
break;
@@ -179,33 +149,16 @@ uword
unformat_transport_proto (unformat_input_t * input, va_list * args)
{
u32 *proto = va_arg (*args, u32 *);
- if (unformat (input, "tcp"))
- *proto = TRANSPORT_PROTO_TCP;
- else if (unformat (input, "TCP"))
- *proto = TRANSPORT_PROTO_TCP;
- else if (unformat (input, "udpc"))
- *proto = TRANSPORT_PROTO_UDPC;
- else if (unformat (input, "UDPC"))
- *proto = TRANSPORT_PROTO_UDPC;
- else if (unformat (input, "udp"))
- *proto = TRANSPORT_PROTO_UDP;
- else if (unformat (input, "UDP"))
- *proto = TRANSPORT_PROTO_UDP;
- else if (unformat (input, "sctp"))
- *proto = TRANSPORT_PROTO_SCTP;
- else if (unformat (input, "SCTP"))
- *proto = TRANSPORT_PROTO_SCTP;
- else if (unformat (input, "tls"))
- *proto = TRANSPORT_PROTO_TLS;
- else if (unformat (input, "TLS"))
- *proto = TRANSPORT_PROTO_TLS;
- else if (unformat (input, "quic"))
- *proto = TRANSPORT_PROTO_QUIC;
- else if (unformat (input, "QUIC"))
- *proto = TRANSPORT_PROTO_QUIC;
- else
+
+#define _(sym, str, sstr) \
+ if (unformat (input, str)) \
+ { \
+ *proto = TRANSPORT_PROTO_ ## sym; \
+ return 1; \
+ }
+ foreach_transport_proto
+#undef _
return 0;
- return 1;
}
u32
diff --git a/src/vnet/session/transport_types.h b/src/vnet/session/transport_types.h
index 41897c6d170..ac2177c77b0 100644
--- a/src/vnet/session/transport_types.h
+++ b/src/vnet/session/transport_types.h
@@ -139,15 +139,20 @@ STATIC_ASSERT (STRUCT_OFFSET_OF (transport_connection_t, s_index)
STATIC_ASSERT (sizeof (transport_connection_t) <= 128,
"moved into 3rd cache line");
+#define foreach_transport_proto \
+ _(TCP, "tcp", "T") \
+ _(UDP, "udp", "U") \
+ _(SCTP, "sctp", "S") \
+ _(NONE, "ct", "C") \
+ _(TLS, "tls", "J") \
+ _(UDPC, "udpc", "U") \
+ _(QUIC, "quic", "Q") \
+
typedef enum _transport_proto
{
- TRANSPORT_PROTO_TCP,
- TRANSPORT_PROTO_UDP,
- TRANSPORT_PROTO_SCTP,
- TRANSPORT_PROTO_NONE,
- TRANSPORT_PROTO_TLS,
- TRANSPORT_PROTO_UDPC,
- TRANSPORT_PROTO_QUIC,
+#define _(sym, str, sstr) TRANSPORT_PROTO_ ## sym,
+ foreach_transport_proto
+#undef _
TRANSPORT_N_PROTO
} transport_proto_t;
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index d060654a037..5090b7dd2d7 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -1165,6 +1165,8 @@ static transport_connection_t *
tcp_session_get_transport (u32 conn_index, u32 thread_index)
{
tcp_connection_t *tc = tcp_connection_get (conn_index, thread_index);
+ if (PREDICT_FALSE (!tc))
+ return 0;
return &tc->connection;
}