18 #include <sys/types.h> 19 #include <sys/socket.h> 27 #include <sys/epoll.h> 41 vppcom_data_segments_t
ds;
70 struct sockaddr_storage servaddr;
76 static __thread
int __wrk_index = 0;
93 memset (conn, 0,
sizeof (*conn));
105 vterr (
"conn_pool_expand()", -errno);
131 vtwrn (
"Failed to allocate connection even after expand");
152 vtinf (
"(fd %d): Replying to cfg message!\n", conn->
fd);
183 snprintf (buf,
sizeof (buf),
"SERVER (fd %d) RESULTS", tc->
fd);
194 vtinf (
" vcl server main\n" 197 " buf size: %u (0x%08x)\n" 203 memset (&conn->
stats, 0, sizeof (conn->
stats));
210 vtinf (
"Set control fd %d for test!", conn->
fd);
214 vtinf (
"Starting %s-directional Stream Test (fd %d)!",
215 is_bi ?
"Bi" :
"Uni", conn->
fd);
221 memset (&conn->
stats, 0, sizeof (conn->
stats));
222 clock_gettime (CLOCK_REALTIME, &conn->
stats.
start);
230 int client_fd = conn->
fd;
249 vppcom_session_free_segments (conn->
fd, conn->
ds);
252 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
259 int tx_bytes, nbytes, pos;
262 vppcom_data_segment_copy (conn->
buf, conn->
ds, rx_bytes);
266 ((
char *) conn->
buf)[pos] = 0;
267 vtinf (
"(fd %d): RX (%d bytes) - '%s'", conn->
fd, rx_bytes, conn->
buf);
270 vtinf (
"(fd %d): Echoing back", conn->
fd);
272 nbytes = strlen ((
const char *) conn->
buf) + 1;
276 vtinf (
"(fd %d): TX (%d bytes) - '%s'", conn->
fd, tx_bytes, conn->
buf);
283 struct epoll_event ev;
289 vtwrn (
"No free connections!");
293 client_fd = vppcom_session_accept (listen_fd, &conn->
endpt, 0);
296 vterr (
"vppcom_session_accept()", client_fd);
299 conn->
fd = client_fd;
301 vtinf (
"Got a connection -- fd = %d (0x%08x) on listener fd = %d (0x%08x)",
302 client_fd, client_fd, listen_fd, listen_fd);
306 rv = vppcom_epoll_ctl (wrk->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
309 vterr (
"vppcom_epoll_ctl()", rv);
319 "vcl_test_server [OPTIONS] <port>\n" 321 " -h Print this message and exit.\n" 323 " -w <num> Number of workers\n" 324 " -p <PROTO> Use <PROTO> transport layer\n" 325 " -D Use UDP transport layer\n" 326 " -L Use TLS transport layer\n");
333 struct sockaddr_storage *servaddr = &vsm->
servaddr;
334 memset (servaddr, 0,
sizeof (*servaddr));
338 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) servaddr;
339 server_addr->sin6_family = AF_INET6;
340 server_addr->sin6_addr = in6addr_any;
341 server_addr->sin6_port = htons (vsm->
cfg.
port);
345 struct sockaddr_in *server_addr = (
struct sockaddr_in *) servaddr;
346 server_addr->sin_family = AF_INET;
347 server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
348 server_addr->sin_port = htons (vsm->
cfg.
port);
353 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) servaddr;
355 vsm->
cfg.
endpt.ip = (uint8_t *) & server_addr->sin6_addr;
356 vsm->
cfg.
endpt.port = (uint16_t) server_addr->sin6_port;
360 struct sockaddr_in *server_addr = (
struct sockaddr_in *) servaddr;
362 vsm->
cfg.
endpt.ip = (uint8_t *) & server_addr->sin_addr;
363 vsm->
cfg.
endpt.port = (uint16_t) server_addr->sin_port;
376 while ((c = getopt (argc, argv,
"6DLsw:p:")) != -1)
384 if (vppcom_unformat_proto (&vsm->
cfg.
proto, optarg))
385 vtwrn (
"Invalid vppcom protocol %s, defaulting to TCP", optarg);
401 vtwrn (
"Invalid number of workers %d", v);
411 vtwrn (
"Option `-%c' requires an argument.", optopt);
414 if (isprint (optopt))
415 vtwrn (
"Unknown option `-%c'.", optopt);
417 vtwrn (
"Unknown option character `\\x%x'.", optopt);
425 if (argc < (optind + 1))
427 fprintf (stderr,
"SERVER: ERROR: Insufficient number of arguments!\n");
431 if (sscanf (argv[optind],
"%d", &v) == 1)
435 fprintf (stderr,
"SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
446 if ((vppcom_session_n_accepted (listener_fd) == 0) &
447 vppcom_session_is_connectable_listener (listener_fd))
449 vtinf (
"Connected Listener fd %x has no more sessions", listener_fd);
450 vppcom_session_close (listener_fd);
462 vtinf (
"(fd %d): Received a cfg msg!", conn->
fd);
466 if (rx_bytes !=
sizeof (*rx_cfg))
468 vtinf (
"(fd %d): Invalid cfg msg size %d expected %lu!", conn->
fd,
469 rx_bytes, sizeof (*rx_cfg));
474 vtinf (
"(fd %d): Replying to cfg msg", conn->
fd);
482 switch (rx_cfg->
test)
495 vtinf (
"Session fd %d closing!", conn->
fd);
496 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
497 listener_fd = vppcom_session_listener (conn->
fd);
498 vppcom_session_close (conn->
fd);
505 vtwrn (
"Unknown test type %d", rx_cfg->
test);
517 struct epoll_event listen_ev;
522 vtinf (
"Initializing worker ...");
526 if (vppcom_worker_register ())
527 vtfail (
"vppcom_worker_register()", 1);
534 if (vsm->
cfg.
proto == VPPCOM_PROTO_UDP)
536 vppcom_session_attr (wrk->
listen_fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
539 if (vsm->
cfg.
proto == VPPCOM_PROTO_TLS
540 || vsm->
cfg.
proto == VPPCOM_PROTO_QUIC)
550 vtfail (
"vppcom_session_bind()", rv);
552 if (!(vsm->
cfg.
proto == VPPCOM_PROTO_UDP))
554 rv = vppcom_session_listen (wrk->
listen_fd, 10);
556 vtfail (
"vppcom_session_listen()", rv);
559 wrk->
epfd = vppcom_epoll_create ();
563 listen_ev.events = EPOLLIN;
564 listen_ev.data.u32 = ~0;
565 rv = vppcom_epoll_ctl (wrk->
epfd, EPOLL_CTL_ADD, wrk->
listen_fd,
568 vtfail (
"vppcom_epoll_ctl", rv);
571 vtinf (
"Waiting for a client to connect on port %d ...", vsm->
cfg.
port);
614 return isascii (conn->
ds[0].data[0]);
616 return isascii (conn->
buf[0]);
625 int i, rx_bytes, num_ev, listener_fd;
637 vterr (
"vppcom_epoll_wait()", num_ev);
640 else if (num_ev == 0)
642 vtinf (
"vppcom_epoll_wait() timeout!");
645 for (i = 0; i < num_ev; i++)
648 if (wrk->
wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
650 vtinf (
"Closing session %d on HUP", conn->
fd);
651 listener_fd = vppcom_session_listener (conn->
fd);
652 vppcom_session_close (conn->
fd);
657 vtinf (
"All client connections closed\n");
667 else if (vppcom_session_is_connectable_listener (conn->
fd))
680 if (errno == ECONNRESET)
682 vtinf (
"Connection reset by remote peer.\n");
695 vppcom_session_free_segments (conn->
fd, conn->
ds);
699 vtinf (
"All client connections closed\n");
709 if (vppcom_session_attr (conn->
fd, VPPCOM_ATTR_GET_NREAD, 0,
720 vtwrn (
"FIFO not drained! extra bytes %d", rx_bytes);
725 vtwrn (
"Unhandled event");
754 rv = vppcom_app_create (
"vcl_test_server");
756 vtfail (
"vppcom_app_create()", rv);
771 vppcom_app_destroy ();
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)
static void conn_pool_free(vcl_test_server_conn_t *conn)
static int vts_conn_has_ascii(vcl_test_server_conn_t *conn)
struct sockaddr_storage servaddr
uint32_t vcl_test_crt_rsa_len
Optimized string handling code, including c11-compliant "safe C library" variants.
static void sync_config_and_reply(vcl_test_server_conn_t *conn, vcl_test_cfg_t *rx_cfg)
static void vcl_test_server_process_opts(vcl_test_server_main_t *vsm, int argc, char **argv)
struct epoll_event wait_events[VCL_TEST_CFG_MAX_EPOLL_EVENTS]
static int vts_conn_read(vcl_test_server_conn_t *conn)
static void conn_pool_expand(vcl_test_server_worker_t *wrk, size_t expand_size)
#define VCL_TEST_DELAY_DISCONNECT
#define VCL_TEST_SERVER_PORT
static void print_usage_and_exit(void)
static void vts_server_echo(vcl_test_server_conn_t *conn, int rx_bytes)
static void vcl_test_stats_dump(char *header, vcl_test_stats_t *stats, uint8_t show_rx, uint8_t show_tx, uint8_t verbose)
volatile int worker_fails
static vcl_test_server_main_t vcl_server_main
static void * vts_worker_loop(void *arg)
#define VCL_TEST_CFG_MAX_EPOLL_EVENTS
static int vcl_test_read_ds(int fd, vppcom_data_segments_t ds, vcl_test_stats_t *stats)
#define VCL_TEST_SEPARATOR_STRING
static void vcl_test_cfg_dump(vcl_test_cfg_t *cfg, uint8_t is_client)
static void vts_server_rx(vcl_test_server_conn_t *conn, int rx_bytes)
#define VCL_TEST_CFG_CTRL_MAGIC
static void vts_new_client(vcl_test_server_worker_t *wrk, int listen_fd)
static void vts_server_start_stop(vcl_test_server_worker_t *wrk, vcl_test_server_conn_t *conn, vcl_test_cfg_t *rx_cfg)
static void vts_worker_init(vcl_test_server_worker_t *wrk)
sll srl srl sll sra u16x4 i
vcl_test_server_cfg_t cfg
static void vcl_test_cfg_init(vcl_test_cfg_t *cfg)
vcl_test_server_conn_t * conn_pool
#define vtinf(_fmt, _args...)
static void vcl_test_buf_alloc(vcl_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf, uint32_t *bufsize)
static vcl_test_cfg_t * vts_conn_read_config(vcl_test_server_conn_t *conn)
static int vcl_test_read(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats)
int main(int argc, char **argv)
static int vcl_test_write(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats, uint32_t verbose)
uint32_t vcl_test_key_rsa_len
vppcom_data_segments_t ds
static vcl_test_server_conn_t * conn_pool_alloc(vcl_test_server_worker_t *wrk)
static void vts_clean_connected_listeners(vcl_test_server_worker_t *wrk, int listener_fd)
static int vcl_comp_tspec(struct timespec *a, struct timespec *b)
static void vcl_test_stats_accumulate(vcl_test_stats_t *accum, vcl_test_stats_t *incr)
vcl_test_server_worker_t * workers
static void vcl_test_init_endpoint_addr(vcl_test_server_main_t *vsm)
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
volatile int active_workers
#define VCL_TEST_CFG_MAX_TEST_SESS
#define vtwrn(_fmt, _args...)
static int vts_conn_expect_config(vcl_test_server_conn_t *conn)