18 #include <sys/types.h> 19 #include <sys/socket.h> 27 #include <sys/epoll.h> 41 vppcom_data_segment_t ds[2];
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, rx_bytes);
252 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
258 uint32_t n_bytes = 0, ds_idx = 0, to_copy;
260 while (n_bytes < max_bytes)
262 to_copy =
clib_min (ds[ds_idx].
len, max_bytes - n_bytes);
273 int tx_bytes, nbytes, pos;
280 ((
char *) conn->
buf)[pos] = 0;
281 vtinf (
"(fd %d): RX (%d bytes) - '%s'", conn->
fd, rx_bytes, conn->
buf);
284 vtinf (
"(fd %d): Echoing back", conn->
fd);
286 nbytes = strlen ((
const char *) conn->
buf) + 1;
290 vtinf (
"(fd %d): TX (%d bytes) - '%s'", conn->
fd, tx_bytes, conn->
buf);
297 struct epoll_event ev;
303 vtwrn (
"No free connections!");
307 client_fd = vppcom_session_accept (listen_fd, &conn->
endpt, 0);
310 vterr (
"vppcom_session_accept()", client_fd);
313 conn->
fd = client_fd;
315 vtinf (
"Got a connection -- fd = %d (0x%08x) on listener fd = %d (0x%08x)",
316 client_fd, client_fd, listen_fd, listen_fd);
320 rv = vppcom_epoll_ctl (wrk->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
323 vterr (
"vppcom_epoll_ctl()", rv);
333 "vcl_test_server [OPTIONS] <port>\n" 335 " -h Print this message and exit.\n" 337 " -w <num> Number of workers\n" 338 " -p <PROTO> Use <PROTO> transport layer\n" 339 " -D Use UDP transport layer\n" 340 " -L Use TLS transport layer\n");
347 struct sockaddr_storage *servaddr = &vsm->
servaddr;
348 memset (servaddr, 0,
sizeof (*servaddr));
352 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) servaddr;
353 server_addr->sin6_family = AF_INET6;
354 server_addr->sin6_addr = in6addr_any;
355 server_addr->sin6_port = htons (vsm->
cfg.
port);
359 struct sockaddr_in *server_addr = (
struct sockaddr_in *) servaddr;
360 server_addr->sin_family = AF_INET;
361 server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
362 server_addr->sin_port = htons (vsm->
cfg.
port);
367 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) servaddr;
369 vsm->
cfg.
endpt.ip = (uint8_t *) & server_addr->sin6_addr;
370 vsm->
cfg.
endpt.port = (uint16_t) server_addr->sin6_port;
374 struct sockaddr_in *server_addr = (
struct sockaddr_in *) servaddr;
376 vsm->
cfg.
endpt.ip = (uint8_t *) & server_addr->sin_addr;
377 vsm->
cfg.
endpt.port = (uint16_t) server_addr->sin_port;
390 while ((c = getopt (argc, argv,
"6DLsw:hp:")) != -1)
398 if (vppcom_unformat_proto (&vsm->
cfg.
proto, optarg))
399 vtwrn (
"Invalid vppcom protocol %s, defaulting to TCP", optarg);
415 vtwrn (
"Invalid number of workers %d", v);
425 vtwrn (
"Option `-%c' requires an argument.", optopt);
428 if (isprint (optopt))
429 vtwrn (
"Unknown option `-%c'.", optopt);
431 vtwrn (
"Unknown option character `\\x%x'.", optopt);
439 if (argc < (optind + 1))
441 fprintf (stderr,
"SERVER: ERROR: Insufficient number of arguments!\n");
445 if (sscanf (argv[optind],
"%d", &v) == 1)
449 fprintf (stderr,
"SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
460 if ((vppcom_session_n_accepted (listener_fd) == 0) &
461 vppcom_session_is_connectable_listener (listener_fd))
463 vtinf (
"Connected Listener fd %x has no more sessions", listener_fd);
464 vppcom_session_close (listener_fd);
476 vtinf (
"(fd %d): Received a cfg msg!", conn->
fd);
480 if (rx_bytes !=
sizeof (*rx_cfg))
482 vtinf (
"(fd %d): Invalid cfg msg size %d expected %lu!", conn->
fd,
483 rx_bytes, sizeof (*rx_cfg));
488 vtinf (
"(fd %d): Replying to cfg msg", conn->
fd);
496 switch (rx_cfg->
test)
509 vtinf (
"Session fd %d closing!", conn->
fd);
510 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
511 listener_fd = vppcom_session_listener (conn->
fd);
512 vppcom_session_close (conn->
fd);
519 vtwrn (
"Unknown test type %d", rx_cfg->
test);
531 struct epoll_event listen_ev;
536 vtinf (
"Initializing worker ...");
540 if (vppcom_worker_register ())
541 vtfail (
"vppcom_worker_register()", 1);
548 if (vsm->
cfg.
proto == VPPCOM_PROTO_UDP)
550 vppcom_session_attr (wrk->
listen_fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
553 if (vsm->
cfg.
proto == VPPCOM_PROTO_TLS
554 || vsm->
cfg.
proto == VPPCOM_PROTO_QUIC)
564 vtfail (
"vppcom_session_bind()", rv);
566 if (!(vsm->
cfg.
proto == VPPCOM_PROTO_UDP))
568 rv = vppcom_session_listen (wrk->
listen_fd, 10);
570 vtfail (
"vppcom_session_listen()", rv);
573 wrk->
epfd = vppcom_epoll_create ();
577 listen_ev.events = EPOLLIN;
578 listen_ev.data.u32 = ~0;
579 rv = vppcom_epoll_ctl (wrk->
epfd, EPOLL_CTL_ADD, wrk->
listen_fd,
582 vtfail (
"vppcom_epoll_ctl", rv);
585 vtinf (
"Waiting for a client to connect on port %d ...", vsm->
cfg.
port);
628 return isascii (conn->
ds[0].data[0]);
630 return isascii (conn->
buf[0]);
639 int i, rx_bytes, num_ev, listener_fd;
651 vterr (
"vppcom_epoll_wait()", num_ev);
654 else if (num_ev == 0)
656 vtinf (
"vppcom_epoll_wait() timeout!");
659 for (i = 0; i < num_ev; i++)
662 if (wrk->
wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
664 vtinf (
"Closing session %d on HUP", conn->
fd);
665 listener_fd = vppcom_session_listener (conn->
fd);
666 vppcom_session_close (conn->
fd);
671 vtinf (
"All client connections closed\n");
681 else if (vppcom_session_is_connectable_listener (conn->
fd))
694 if (errno == ECONNRESET)
696 vtinf (
"Connection reset by remote peer.\n");
709 vppcom_session_free_segments (conn->
fd, rx_bytes);
713 vtinf (
"All client connections closed\n");
723 if (vppcom_session_attr (conn->
fd, VPPCOM_ATTR_GET_NREAD, 0,
734 vtwrn (
"FIFO not drained! extra bytes %d", rx_bytes);
739 vtwrn (
"Unhandled event");
768 rv = vppcom_app_create (
"vcl_test_server");
770 vtfail (
"vppcom_app_create()", rv);
785 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)
#define clib_memcpy_fast(a, b, c)
static int vcl_test_read_ds(int fd, vppcom_data_segment_t *ds, vcl_test_stats_t *stats)
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]
vppcom_data_segment_t ds[2]
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
#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)
void * realloc(void *p, size_t size)
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
static vcl_test_server_conn_t * conn_pool_alloc(vcl_test_server_worker_t *wrk)
void * calloc(size_t nmemb, size_t size)
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 vts_copy_ds(void *buf, vppcom_data_segment_t *ds, u32 max_bytes)
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)