vcl_test_stats_t stats;
vppcom_endpt_t endpt;
uint8_t ip[16];
- vppcom_data_segments_t ds;
+ vppcom_data_segment_t ds[2];
} vcl_test_server_conn_t;
typedef struct
conn->stats.stop.tv_sec -= VCL_TEST_DELAY_DISCONNECT;
if (conn->cfg.verbose)
{
- sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd);
+ snprintf (buf, sizeof (buf), "SERVER (fd %d) RESULTS", tc->fd);
vcl_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ ,
is_bi /* show tx */ , conn->cfg.verbose);
}
}
if (vsm->use_ds)
- vppcom_session_free_segments (conn->fd, conn->ds);
+ vppcom_session_free_segments (conn->fd, rx_bytes);
if (conn->stats.rx_bytes >= conn->cfg.total_bytes)
clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
}
+static void
+vts_copy_ds (void *buf, vppcom_data_segment_t * ds, u32 max_bytes)
+{
+ uint32_t n_bytes = 0, ds_idx = 0;
+
+ while (n_bytes < max_bytes)
+ {
+ clib_memcpy_fast (buf + n_bytes, ds[ds_idx].data,
+ clib_min (ds[ds_idx].len, max_bytes - n_bytes));
+ ds_idx += 1;
+ }
+}
+
static void
vts_server_echo (vcl_test_server_conn_t * conn, int rx_bytes)
{
int tx_bytes, nbytes, pos;
if (vsm->use_ds)
- vppcom_data_segment_copy (conn->buf, conn->ds, rx_bytes);
+ vts_copy_ds (conn->buf, conn->ds, rx_bytes);
/* If it looks vaguely like a string, make sure it's terminated */
pos = rx_bytes < conn->buf_size ? rx_bytes : conn->buf_size - 1;
}
static void
-vts_new_client (vcl_test_server_worker_t * wrk)
+vts_new_client (vcl_test_server_worker_t * wrk, int listen_fd)
{
vcl_test_server_conn_t *conn;
struct epoll_event ev;
return;
}
- client_fd = vppcom_session_accept (wrk->listen_fd, &conn->endpt, 0);
+ client_fd = vppcom_session_accept (listen_fd, &conn->endpt, 0);
if (client_fd < 0)
{
vterr ("vppcom_session_accept()", client_fd);
}
conn->fd = client_fd;
- vtinf ("Got a connection -- fd = %d (0x%08x)!", client_fd, client_fd);
+ vtinf ("Got a connection -- fd = %d (0x%08x) on listener fd = %d (0x%08x)",
+ client_fd, client_fd, listen_fd, listen_fd);
ev.events = EPOLLIN;
ev.data.u64 = conn - wrk->conn_pool;
" -h Print this message and exit.\n"
" -6 Use IPv6\n"
" -w <num> Number of workers\n"
+ " -p <PROTO> Use <PROTO> transport layer\n"
" -D Use UDP transport layer\n"
" -L Use TLS transport layer\n");
exit (1);
vsm->cfg.proto = VPPCOM_PROTO_TCP;
opterr = 0;
- while ((c = getopt (argc, argv, "6DLsw:")) != -1)
+ while ((c = getopt (argc, argv, "6DLsw:p:")) != -1)
switch (c)
{
case '6':
vsm->cfg.address_ip6 = 1;
break;
+ case 'p':
+ if (vppcom_unformat_proto (&vsm->cfg.proto, optarg))
+ vtwrn ("Invalid vppcom protocol %s, defaulting to TCP", optarg);
+ break;
+
case 'D':
vsm->cfg.proto = VPPCOM_PROTO_UDP;
break;
case '?':
switch (optopt)
{
+ case 'w':
+ case 'p':
+ vtwrn ("Option `-%c' requires an argument.", optopt);
+ break;
default:
if (isprint (optopt))
vtwrn ("Unknown option `-%c'.", optopt);
vcl_test_init_endpoint_addr (vsm);
}
+static void
+vts_clean_connected_listeners (vcl_test_server_worker_t * wrk,
+ int listener_fd)
+{
+ if ((vppcom_session_n_accepted (listener_fd) == 0) &
+ vppcom_session_is_connectable_listener (listener_fd))
+ {
+ vtinf ("Connected Listener fd %x has no more sessions", listener_fd);
+ vppcom_session_close (listener_fd);
+ wrk->nfds--;
+ }
+}
+
int
vts_handle_cfg (vcl_test_server_worker_t * wrk, vcl_test_cfg_t * rx_cfg,
vcl_test_server_conn_t * conn, int rx_bytes)
{
+ int listener_fd;
if (rx_cfg->verbose)
{
vtinf ("(fd %d): Received a cfg msg!", conn->fd);
case VCL_TEST_TYPE_EXIT:
vtinf ("Session fd %d closing!", conn->fd);
clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
+ listener_fd = vppcom_session_listener (conn->fd);
vppcom_session_close (conn->fd);
conn_pool_free (conn);
wrk->nfds--;
+ vts_clean_connected_listeners (wrk, listener_fd);
break;
default:
if (wrk->listen_fd < 0)
vtfail ("vppcom_session_create()", wrk->listen_fd);
+ if (vsm->cfg.proto == VPPCOM_PROTO_UDP)
+ {
+ vppcom_session_attr (wrk->listen_fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
+ }
- if (vsm->cfg.proto == VPPCOM_PROTO_TLS)
+ if (vsm->cfg.proto == VPPCOM_PROTO_TLS
+ || vsm->cfg.proto == VPPCOM_PROTO_QUIC)
{
vppcom_session_tls_add_cert (wrk->listen_fd, vcl_test_crt_rsa,
vcl_test_crt_rsa_len);
{
/* We could avoid the copy if the first segment is big enough but this
* just simplifies things */
- vppcom_data_segment_copy (conn->buf, conn->ds, sizeof (vcl_test_cfg_t));
+ vts_copy_ds (conn->buf, conn->ds, sizeof (vcl_test_cfg_t));
}
return (vcl_test_cfg_t *) conn->buf;
}
vcl_test_server_main_t *vsm = &vcl_server_main;
vcl_test_server_worker_t *wrk = arg;
vcl_test_server_conn_t *conn;
- int i, rx_bytes, num_ev;
+ int i, rx_bytes, num_ev, listener_fd;
vcl_test_cfg_t *rx_cfg;
if (wrk->wrk_index)
conn = &wrk->conn_pool[wrk->wait_events[i].data.u32];
if (wrk->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
{
+ vtinf ("Closing session %d on HUP", conn->fd);
+ listener_fd = vppcom_session_listener (conn->fd);
vppcom_session_close (conn->fd);
- wrk->nfds -= 1;
+ wrk->nfds--;
+ vts_clean_connected_listeners (wrk, listener_fd);
if (!wrk->nfds)
{
vtinf ("All client connections closed\n");
}
if (wrk->wait_events[i].data.u32 == ~0)
{
- vts_new_client (wrk);
+ vts_new_client (wrk, wrk->listen_fd);
+ continue;
+ }
+ else if (vppcom_session_is_connectable_listener (conn->fd))
+ {
+ vts_new_client (wrk, conn->fd);
continue;
}
if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC)
{
if (vsm->use_ds)
- vppcom_session_free_segments (conn->fd, conn->ds);
+ vppcom_session_free_segments (conn->fd, rx_bytes);
vts_handle_cfg (wrk, rx_cfg, conn, rx_bytes);
if (!wrk->nfds)
{