X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvcl%2Fvcl_test_server.c;h=2913452ab1066ad95e03ad27f3a54c7e49236c97;hb=539663c401b087e4576e41af35144e73e1907c9d;hp=8b8b77fab2ce16c4d7490b370d4c82545e7cacbd;hpb=293aa059a0001d9def5fe2976ff5990595df3428;p=vpp.git diff --git a/src/vcl/vcl_test_server.c b/src/vcl/vcl_test_server.c index 8b8b77fab2c..2913452ab10 100644 --- a/src/vcl/vcl_test_server.c +++ b/src/vcl/vcl_test_server.c @@ -38,6 +38,7 @@ typedef struct sock_test_stats_t stats; vppcom_endpt_t endpt; uint8_t ip[16]; + vppcom_data_segments_t ds; } vcl_test_server_conn_t; typedef struct @@ -72,32 +73,13 @@ typedef struct struct sockaddr_storage servaddr; volatile int worker_fails; volatile int active_workers; + u8 use_ds; } vcl_test_server_main_t; static __thread int __wrk_index = 0; static vcl_test_server_main_t sock_server_main; -#define vtfail(_fn, _rv) \ -{ \ - errno = -_rv; \ - perror ("ERROR when calling " _fn); \ - fprintf (stderr, "\nSERVER ERROR: " _fn " failed (errno = %d)!\n", -_rv);\ - exit (1); \ -} - -#define vterr(_fn, _rv) \ -{ \ - errno = -_rv; \ - fprintf (stderr, "\nSERVER ERROR: " _fn " failed (errno = %d)!\n", -_rv);\ -} - -#define vtwrn(_fmt, _args...) \ - fprintf (stderr, "\nSERVER ERROR: " _fmt "\n", ##_args) \ - -#define vtinf(_fmt, _args...) \ - fprintf (stdout, "\nvts: " _fmt "\n", __wrk_index, ##_args) \ - static inline void conn_pool_expand (vcl_test_server_worker_t * wrk, size_t expand_size) { @@ -130,8 +112,9 @@ conn_pool_expand (vcl_test_server_worker_t * wrk, size_t expand_size) static inline vcl_test_server_conn_t * conn_pool_alloc (vcl_test_server_worker_t * wrk) { - int i; + int i, expand = 0; +again: for (i = 0; i < wrk->conn_pool_size; i++) { if (!wrk->conn_pool[i].is_alloc) @@ -142,6 +125,13 @@ conn_pool_alloc (vcl_test_server_worker_t * wrk) } } + if (expand == 0) + { + conn_pool_expand (wrk, 2 * wrk->conn_pool_size); + expand = 1; + goto again; + } + vtwrn ("Failed to allocate connection even after expand"); return 0; } @@ -171,67 +161,61 @@ sync_config_and_reply (vcl_test_server_conn_t * conn, } static void -stream_test_server_start_stop (vcl_test_server_worker_t * wrk, - vcl_test_server_conn_t * conn, - sock_test_cfg_t * rx_cfg) +vts_server_start_stop (vcl_test_server_worker_t * wrk, + vcl_test_server_conn_t * conn, + sock_test_cfg_t * rx_cfg) { - int client_fd = conn->fd; - sock_test_t test = rx_cfg->test; + u8 is_bi = rx_cfg->test == SOCK_TEST_TYPE_BI; + int client_fd = conn->fd, i; + vcl_test_server_conn_t *tc; + char buf[64]; if (rx_cfg->ctrl_handle == conn->fd) { - int i; clock_gettime (CLOCK_REALTIME, &conn->stats.stop); for (i = 0; i < wrk->conn_pool_size; i++) { - vcl_test_server_conn_t *tc = &wrk->conn_pool[i]; + tc = &wrk->conn_pool[i]; + if (tc->cfg.ctrl_handle != conn->fd) + continue; - if (tc->cfg.ctrl_handle == conn->fd) - { - sock_test_stats_accumulate (&conn->stats, &tc->stats); - - if (conn->cfg.verbose) - { - static char buf[64]; + sock_test_stats_accumulate (&conn->stats, &tc->stats); - sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd); - sock_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ , - test == SOCK_TEST_TYPE_BI - /* show tx */ , - conn->cfg.verbose); - } + if (conn->cfg.verbose) + { + sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd); + sock_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ , + is_bi /* show tx */ , conn->cfg.verbose); } } sock_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ , - (test == SOCK_TEST_TYPE_BI) /* show_tx */ , - conn->cfg.verbose); + is_bi /* show_tx */ , conn->cfg.verbose); sock_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); if (conn->cfg.verbose) { - printf (" sock server main\n" - SOCK_TEST_SEPARATOR_STRING - " buf: %p\n" - " buf size: %u (0x%08x)\n" - SOCK_TEST_SEPARATOR_STRING, - conn->buf, conn->buf_size, conn->buf_size); + vtinf (" sock server main\n" + SOCK_TEST_SEPARATOR_STRING + " buf: %p\n" + " buf size: %u (0x%08x)\n" + SOCK_TEST_SEPARATOR_STRING, + conn->buf, conn->buf_size, conn->buf_size); } sync_config_and_reply (conn, rx_cfg); - printf ("\nSERVER (fd %d): %s-directional Stream Test Complete!\n" - SOCK_TEST_BANNER_STRING "\n", conn->fd, - test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni"); + vtinf ("(fd %d): %s-directional Stream Test Complete!\n" + SOCK_TEST_BANNER_STRING "\n", conn->fd, is_bi ? "Bi" : "Uni"); + memset (&conn->stats, 0, sizeof (conn->stats)); } else { - printf ("\n" SOCK_TEST_BANNER_STRING - "SERVER (fd %d): %s-directional Stream Test!\n" - " Sending client the test cfg to start streaming data...\n", - client_fd, test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni"); + vtinf (SOCK_TEST_BANNER_STRING "(fd %d): %s-directional Stream Test!\n" + " Sending client the test cfg to start streaming data...\n", + client_fd, is_bi ? "Bi" : "Uni"); - rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd : - rx_cfg->ctrl_handle; + if (rx_cfg->ctrl_handle == ~0) + rx_cfg->ctrl_handle = conn->fd; sync_config_and_reply (conn, rx_cfg); @@ -241,31 +225,45 @@ stream_test_server_start_stop (vcl_test_server_worker_t * wrk, } } - static inline void -stream_test_server (vcl_test_server_conn_t * conn, int rx_bytes) +vts_server_rx (vcl_test_server_conn_t * conn, int rx_bytes) { + vcl_test_server_main_t *vts = &sock_server_main; int client_fd = conn->fd; - sock_test_t test = conn->cfg.test; - if (test == SOCK_TEST_TYPE_BI) - (void) vcl_test_write (client_fd, conn->buf, rx_bytes, &conn->stats, - conn->cfg.verbose); - - if (conn->stats.rx_bytes >= conn->cfg.total_bytes) + if (conn->cfg.test == SOCK_TEST_TYPE_BI) { - clock_gettime (CLOCK_REALTIME, &conn->stats.stop); + if (vts->use_ds) + { + (void) vcl_test_write (client_fd, conn->ds[0].data, conn->ds[0].len, + &conn->stats, conn->cfg.verbose); + if (conn->ds[1].len) + (void) vcl_test_write (client_fd, conn->ds[1].data, + conn->ds[1].len, &conn->stats, + conn->cfg.verbose); + } + else + (void) vcl_test_write (client_fd, conn->buf, rx_bytes, &conn->stats, + conn->cfg.verbose); } + + if (vts->use_ds) + vppcom_session_free_segments (conn->fd, conn->ds); + + if (conn->stats.rx_bytes >= conn->cfg.total_bytes) + clock_gettime (CLOCK_REALTIME, &conn->stats.stop); } static void -vcl_test_server_echo (vcl_test_server_conn_t * conn, int rx_bytes) +vts_server_echo (vcl_test_server_conn_t * conn, int rx_bytes) { + vcl_test_server_main_t *vts = &sock_server_main; int tx_bytes, nbytes, pos; - /* If it looks vaguely like a string, - * make sure it's terminated - */ + if (vts->use_ds) + vppcom_data_segment_copy (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; ((char *) conn->buf)[pos] = 0; vtinf ("(fd %d): RX (%d bytes) - '%s'", conn->fd, rx_bytes, conn->buf); @@ -281,7 +279,7 @@ vcl_test_server_echo (vcl_test_server_conn_t * conn, int rx_bytes) } static inline void -vcl_test_server_new_client (vcl_test_server_worker_t * wrk) +vts_new_client (vcl_test_server_worker_t * wrk) { int client_fd; vcl_test_server_conn_t *conn; @@ -370,7 +368,7 @@ vcl_test_init_endpoint_addr (vcl_test_server_main_t * ssm) } } -void +static void vcl_test_server_process_opts (vcl_test_server_main_t * ssm, int argc, char **argv) { @@ -379,7 +377,7 @@ vcl_test_server_process_opts (vcl_test_server_main_t * ssm, int argc, ssm->cfg.proto = VPPCOM_PROTO_TCP; opterr = 0; - while ((c = getopt (argc, argv, "6Dw:")) != -1) + while ((c = getopt (argc, argv, "6Dsw:")) != -1) switch (c) { case '6': @@ -397,17 +395,17 @@ vcl_test_server_process_opts (vcl_test_server_main_t * ssm, int argc, else vtwrn ("Invalid number of workers %d", v); break; - + case 's': + ssm->use_ds = 1; + break; case '?': switch (optopt) { default: if (isprint (optopt)) - fprintf (stderr, "SERVER: ERROR: Unknown " - "option `-%c'.\n", optopt); + vtwrn ("Unknown option `-%c'.", optopt); else - fprintf (stderr, "SERVER: ERROR: Unknown " - "option character `\\x%x'.\n", optopt); + vtwrn ("Unknown option character `\\x%x'.", optopt); } /* fall thru */ case 'h': @@ -433,9 +431,8 @@ vcl_test_server_process_opts (vcl_test_server_main_t * ssm, int argc, } int -vcl_test_server_handle_cfg (vcl_test_server_worker_t * wrk, - sock_test_cfg_t * rx_cfg, - vcl_test_server_conn_t * conn, int rx_bytes) +vts_handle_cfg (vcl_test_server_worker_t * wrk, sock_test_cfg_t * rx_cfg, + vcl_test_server_conn_t * conn, int rx_bytes) { if (rx_cfg->verbose) { @@ -468,14 +465,13 @@ vcl_test_server_handle_cfg (vcl_test_server_worker_t * wrk, case SOCK_TEST_TYPE_BI: case SOCK_TEST_TYPE_UNI: - stream_test_server_start_stop (wrk, conn, rx_cfg); + vts_server_start_stop (wrk, conn, rx_cfg); break; case SOCK_TEST_TYPE_EXIT: - vtinf ("Have a great day conn %d!", conn->fd); + vtinf ("Have a great day conn %d (closing)!", conn->fd); vppcom_session_close (conn->fd); conn_pool_free (conn); - vtinf ("Closed client fd %d", conn->fd); wrk->nfds--; break; @@ -489,7 +485,7 @@ vcl_test_server_handle_cfg (vcl_test_server_worker_t * wrk, } static void -vcl_test_server_worker_init (vcl_test_server_worker_t * wrk) +vts_worker_init (vcl_test_server_worker_t * wrk) { vcl_test_server_main_t *ssm = &sock_server_main; struct epoll_event listen_ev; @@ -501,7 +497,8 @@ vcl_test_server_worker_init (vcl_test_server_worker_t * wrk) conn_pool_expand (wrk, SOCK_SERVER_MAX_TEST_CONN + 1); if (wrk->wrk_index) - vppcom_worker_register (); + if (vppcom_worker_register ()) + vtfail ("vppcom_worker_register()", 1); wrk->listen_fd = vppcom_session_create (ssm->cfg.proto, 0 /* is_nonblocking */ ); @@ -530,11 +527,59 @@ vcl_test_server_worker_init (vcl_test_server_worker_t * wrk) if (rv < 0) vtfail ("vppcom_epoll_ctl", rv); + ssm->active_workers += 1; vtinf ("Waiting for a client to connect on port %d ...", ssm->cfg.port); } +static int +vts_conn_expect_config (vcl_test_server_conn_t * conn) +{ + if (conn->cfg.test == SOCK_TEST_TYPE_ECHO) + return 1; + + return (conn->stats.rx_bytes < 128 + || conn->stats.rx_bytes >= conn->cfg.total_bytes); +} + +static sock_test_cfg_t * +vts_conn_read_config (vcl_test_server_conn_t * conn) +{ + vcl_test_server_main_t *vts = &sock_server_main; + + if (vts->use_ds) + { + /* 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 (sock_test_cfg_t)); + vppcom_session_free_segments (conn->fd, conn->ds); + } + return (sock_test_cfg_t *) conn->buf; +} + +static inline int +vts_conn_read (vcl_test_server_conn_t * conn) +{ + vcl_test_server_main_t *vts = &sock_server_main; + if (vts->use_ds) + return vcl_test_read_ds (conn->fd, conn->ds, &conn->stats); + else + return vcl_test_read (conn->fd, conn->buf, conn->buf_size, &conn->stats); +} + +static inline int +vts_conn_has_ascii (vcl_test_server_conn_t * conn) +{ + vcl_test_server_main_t *vts = &sock_server_main; + + if (vts->use_ds) + return isascii (conn->ds[0].data[0]); + else + return isascii (conn->buf[0]); +} + static void * -vcl_test_server_worker_loop (void *arg) +vts_worker_loop (void *arg) { vcl_test_server_main_t *ssm = &sock_server_main; vcl_test_server_worker_t *wrk = arg; @@ -543,7 +588,7 @@ vcl_test_server_worker_loop (void *arg) sock_test_cfg_t *rx_cfg; if (wrk->wrk_index) - vcl_test_server_worker_init (wrk); + vts_worker_init (wrk); while (1) { @@ -565,18 +610,24 @@ vcl_test_server_worker_loop (void *arg) if (wrk->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP)) { vppcom_session_close (conn->fd); + wrk->nfds -= 1; + if (!wrk->nfds) + { + vtinf ("All client connections closed\n"); + goto done; + } continue; } if (wrk->wait_events[i].data.u32 == ~0) { - vcl_test_server_new_client (wrk); + vts_new_client (wrk); continue; } if (EPOLLIN & wrk->wait_events[i].events) { - rx_bytes = vcl_test_read (conn->fd, conn->buf, - conn->buf_size, &conn->stats); + read_again: + rx_bytes = vts_conn_read (conn); if (rx_bytes <= 0) { @@ -589,27 +640,32 @@ vcl_test_server_worker_loop (void *arg) continue; } - rx_cfg = (sock_test_cfg_t *) conn->buf; - if (rx_cfg->magic == SOCK_TEST_CFG_CTRL_MAGIC) + if (vts_conn_expect_config (conn)) { - vcl_test_server_handle_cfg (wrk, rx_cfg, conn, rx_bytes); - if (!wrk->nfds) + rx_cfg = vts_conn_read_config (conn); + if (rx_cfg->magic == SOCK_TEST_CFG_CTRL_MAGIC) { - vtinf ("All client connections closed\n"); - vtinf ("May the force be with you!\n"); - goto done; + vts_handle_cfg (wrk, rx_cfg, conn, rx_bytes); + if (!wrk->nfds) + { + vtinf ("All client connections closed\n"); + goto done; + } + continue; } - continue; } - else if ((conn->cfg.test == SOCK_TEST_TYPE_UNI) - || (conn->cfg.test == SOCK_TEST_TYPE_BI)) + if ((conn->cfg.test == SOCK_TEST_TYPE_UNI) + || (conn->cfg.test == SOCK_TEST_TYPE_BI)) { - stream_test_server (conn, rx_bytes); + vts_server_rx (conn, rx_bytes); + if (vppcom_session_attr (conn->fd, VPPCOM_ATTR_GET_NREAD, 0, + 0) > 0) + goto read_again; continue; } - else if (isascii (conn->buf[0])) + if (vts_conn_has_ascii (conn)) { - vcl_test_server_echo (conn, rx_bytes); + vts_server_echo (conn, rx_bytes); } else { @@ -638,36 +694,36 @@ done: int main (int argc, char **argv) { - vcl_test_server_main_t *ssm = &sock_server_main; + vcl_test_server_main_t *vsm = &sock_server_main; int rv, i; clib_mem_init_thread_safe (0, 64 << 20); - ssm->cfg.port = SOCK_TEST_SERVER_PORT; - ssm->cfg.workers = 1; - vcl_test_server_process_opts (ssm, argc, argv); + vsm->cfg.port = SOCK_TEST_SERVER_PORT; + vsm->cfg.workers = 1; + vsm->active_workers = 0; + vcl_test_server_process_opts (vsm, argc, argv); rv = vppcom_app_create ("vcl_test_server"); if (rv) vtfail ("vppcom_app_create()", rv); - ssm->workers = calloc (ssm->cfg.workers, sizeof (*ssm->workers)); - vcl_test_server_worker_init (&ssm->workers[0]); - for (i = 1; i < ssm->cfg.workers; i++) + vsm->workers = calloc (vsm->cfg.workers, sizeof (*vsm->workers)); + vts_worker_init (&vsm->workers[0]); + for (i = 1; i < vsm->cfg.workers; i++) { - ssm->workers[i].wrk_index = i; - rv = pthread_create (&ssm->workers[i].thread_handle, NULL, - vcl_test_server_worker_loop, - (void *) &ssm->workers[i]); + vsm->workers[i].wrk_index = i; + rv = pthread_create (&vsm->workers[i].thread_handle, NULL, + vts_worker_loop, (void *) &vsm->workers[i]); } - vcl_test_server_worker_loop (&ssm->workers[0]); + vts_worker_loop (&vsm->workers[0]); - while (ssm->active_workers) + while (vsm->active_workers > 0) ; vppcom_app_destroy (); - free (ssm->workers); + free (vsm->workers); - return ssm->worker_fails; + return vsm->worker_fails; } /*