volatile int worker_fails;
volatile int active_workers;
u8 use_ds;
+ u8 incremental_stats;
} vcl_test_server_main_t;
vcl_test_main_t vcl_test_main;
if (!wrk->conn_pool[i].is_alloc)
{
conn = &wrk->conn_pool[i];
+ memset (conn, 0, sizeof (*conn));
conn->endpt.ip = wrk->conn_pool[i].ip;
conn->is_alloc = 1;
conn->session_index = i;
- memset (&conn->stats, 0, sizeof (vcl_test_stats_t));
vcl_test_cfg_init (&conn->cfg);
return (&wrk->conn_pool[i]);
}
vtinf ("(fd %d): TX (%d bytes) - '%s'", conn->fd, tx_bytes, conn->rxbuf);
}
+static vcl_test_session_t *
+vts_accept_ctrl (vcl_test_server_worker_t *wrk, int listen_fd)
+{
+ vcl_test_server_main_t *vsm = &vcl_server_main;
+ const vcl_test_proto_vft_t *tp;
+ vcl_test_session_t *conn;
+ struct epoll_event ev;
+ int rv;
+
+ conn = conn_pool_alloc (wrk);
+ if (!conn)
+ {
+ vtwrn ("No free connections!");
+ return 0;
+ }
+
+ if (vsm->ctrl)
+ conn->cfg = vsm->ctrl->cfg;
+ vcl_test_session_buf_alloc (conn);
+ clock_gettime (CLOCK_REALTIME, &conn->old_stats.stop);
+
+ tp = vcl_test_main.protos[VPPCOM_PROTO_TCP];
+ if (tp->accept (listen_fd, conn))
+ return 0;
+
+ vtinf ("CTRL accepted fd = %d (0x%08x) on listener fd = %d (0x%08x)",
+ conn->fd, conn->fd, listen_fd, listen_fd);
+
+ ev.events = EPOLLET | EPOLLIN;
+ ev.data.u64 = conn - wrk->conn_pool;
+ rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, conn->fd, &ev);
+ if (rv < 0)
+ {
+ vterr ("vppcom_epoll_ctl()", rv);
+ return 0;
+ }
+
+ wrk->nfds++;
+
+ return conn;
+}
+
static vcl_test_session_t *
vts_accept_client (vcl_test_server_worker_t *wrk, int listen_fd)
{
if (vsm->ctrl)
conn->cfg = vsm->ctrl->cfg;
vcl_test_session_buf_alloc (conn);
+ clock_gettime (CLOCK_REALTIME, &conn->old_stats.stop);
tp = vcl_test_main.protos[vsm->server_cfg.proto];
if (tp->accept (listen_fd, conn))
vtinf ("Got a connection -- fd = %d (0x%08x) on listener fd = %d (0x%08x)",
conn->fd, conn->fd, listen_fd, listen_fd);
- ev.events = EPOLLIN;
+ ev.events = EPOLLET | EPOLLIN;
ev.data.u64 = conn - wrk->conn_pool;
rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, conn->fd, &ev);
if (rv < 0)
static void
print_usage_and_exit (void)
{
- fprintf (stderr,
- "vcl_test_server [OPTIONS] <port>\n"
- " OPTIONS\n"
- " -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");
+ fprintf (stderr, "vcl_test_server [OPTIONS] <port>\n"
+ " OPTIONS\n"
+ " -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"
+ " -S Incremental stats\n");
exit (1);
}
vsm->server_cfg.proto = VPPCOM_PROTO_TCP;
opterr = 0;
- while ((c = getopt (argc, argv, "6DLsw:hp:")) != -1)
+ while ((c = getopt (argc, argv, "6DLsw:hp:S")) != -1)
switch (c)
{
case '6':
case 's':
vsm->use_ds = 1;
break;
+ case 'S':
+ vsm->incremental_stats = 1;
+ break;
case '?':
switch (optopt)
{
print_usage_and_exit ();
}
- if (argc < (optind + 1))
+ if (argc > (optind + 1))
{
- fprintf (stderr, "SERVER: ERROR: Insufficient number of arguments!\n");
+ fprintf (stderr, "Incorrect number of arguments!\n");
print_usage_and_exit ();
}
-
- if (sscanf (argv[optind], "%d", &v) == 1)
- vsm->server_cfg.port = (uint16_t) v;
- else
+ else if (argc > 1 && argc == (optind + 1))
{
- fprintf (stderr, "SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
- print_usage_and_exit ();
+ if (sscanf (argv[optind], "%d", &v) == 1)
+ vsm->server_cfg.port = (uint16_t) v;
+ else
+ {
+ fprintf (stderr, "Invalid port (%s)!\n", argv[optind]);
+ print_usage_and_exit ();
+ }
}
vcl_test_init_endpoint_addr (vsm);
wrk->nfds--;
if (wrk->nfds)
vts_wrk_cleanup_all (wrk);
+ vcl_server_main.ctrl = 0;
break;
default:
vtfail ("vppcom_epoll_create()", wrk->epfd);
}
- listen_ev.events = EPOLLIN;
+ listen_ev.events = EPOLLET | EPOLLIN;
listen_ev.data.u32 = VCL_TEST_DATA_LISTENER;
rv =
vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, wrk->listener.fd, &listen_ev);
return conn->read (conn, conn->rxbuf, conn->rxbuf_size);
}
+static void
+vts_inc_stats_check (vcl_test_session_t *ts)
+{
+ /* Avoid checking time too often because of syscall cost */
+ if (ts->stats.rx_bytes - ts->old_stats.rx_bytes < 1 << 20)
+ return;
+
+ clock_gettime (CLOCK_REALTIME, &ts->stats.stop);
+ if (vcl_test_time_diff (&ts->old_stats.stop, &ts->stats.stop) > 1)
+ {
+ vcl_test_stats_dump_inc (ts, 1 /* is_rx */);
+ ts->old_stats = ts->stats;
+ }
+}
+
static void *
vts_worker_loop (void *arg)
{
*/
if (ep_evts[i].events & (EPOLLHUP | EPOLLRDHUP))
{
- vts_session_cleanup (conn);
- wrk->nfds--;
- if (!wrk->nfds)
+ if (conn == vsm->ctrl)
{
- vtinf ("All client connections closed\n");
- goto done;
+ vtinf ("ctrl session went away");
+ vsm->ctrl = 0;
}
+ vts_session_cleanup (conn);
+ wrk->nfds--;
continue;
}
vtwrn ("ctrl already exists");
continue;
}
- vsm->ctrl = vts_accept_client (wrk, vsm->ctrl_listen_fd);
+ vsm->ctrl = vts_accept_ctrl (wrk, vsm->ctrl_listen_fd);
continue;
}
if (ep_evts[i].data.u32 == VCL_TEST_DATA_LISTENER)
if (vppcom_session_attr (conn->fd, VPPCOM_ATTR_GET_NREAD, 0, 0) >
0)
goto read_again;
+ if (vsm->incremental_stats)
+ vts_inc_stats_check (conn);
continue;
}
else
if (wrk->epfd < 0)
vtfail ("vppcom_epoll_create()", wrk->epfd);
- listen_ev.events = EPOLLIN;
+ listen_ev.events = EPOLLET | EPOLLIN;
listen_ev.data.u32 = VCL_TEST_CTRL_LISTENER;
rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, vsm->ctrl_listen_fd,
&listen_ev);