diff options
Diffstat (limited to 'src/vcl')
-rw-r--r-- | src/vcl/CMakeLists.txt | 21 | ||||
-rw-r--r-- | src/vcl/sock_test.h | 122 | ||||
-rw-r--r-- | src/vcl/sock_test_client.c | 1277 | ||||
-rw-r--r-- | src/vcl/sock_test_server.c | 1015 | ||||
-rw-r--r-- | src/vcl/vcl_test.h | 538 | ||||
-rw-r--r-- | src/vcl/vcl_test_client.c | 1097 | ||||
-rw-r--r-- | src/vcl/vcl_test_server.c | 743 |
7 files changed, 1 insertions, 4812 deletions
diff --git a/src/vcl/CMakeLists.txt b/src/vcl/CMakeLists.txt index 2578a37bf42..ab0a6ad6a2d 100644 --- a/src/vcl/CMakeLists.txt +++ b/src/vcl/CMakeLists.txt @@ -40,27 +40,8 @@ add_vpp_library(vcl_ldpreload add_vpp_headers(vcl ldp.h - sock_test.h ldp_glibc_socket.h - vcl_test.h vppcom.h vcl_locked.h ldp_socket_wrapper.h -) - -############################################################################## -# vcl tests -############################################################################## -option(VPP_BUILD_VCL_TESTS "Build vcl tests." ON) -if(VPP_BUILD_VCL_TESTS) - foreach(test - vcl_test_server - vcl_test_client - sock_test_server - sock_test_client - ) - add_vpp_executable(${test} SOURCES ${test}.c LINK_LIBRARIES vppcom pthread - NO_INSTALL) - endforeach() -endif(VPP_BUILD_VCL_TESTS) - +)
\ No newline at end of file diff --git a/src/vcl/sock_test.h b/src/vcl/sock_test.h deleted file mode 100644 index 082c72e38f5..00000000000 --- a/src/vcl/sock_test.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __sock_test_h__ -#define __sock_test_h__ - -#include <netdb.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <vcl/vcl_test.h> - -#define SOCK_TEST_AF_UNIX_FILENAME "/tmp/ldp_server_af_unix_socket" -#define SOCK_TEST_MIXED_EPOLL_DATA "Hello, world! (over an AF_UNIX socket)" -#define SOCK_TEST_AF_UNIX_ACCEPT_DATA 0xaf0000af -#define SOCK_TEST_AF_UNIX_FD_MASK 0x00af0000 -#define SOCK_TEST_BANNER_STRING \ - "============================================\n" - -static inline int -sock_test_read (int fd, uint8_t *buf, uint32_t nbytes, - vcl_test_stats_t *stats) -{ - int rx_bytes, errno_val; - - do - { - if (stats) - stats->rx_xacts++; - rx_bytes = read (fd, buf, nbytes); - if (stats) - { - if ((rx_bytes == 0) || - ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))) - stats->rx_eagain++; - else if (rx_bytes < nbytes) - stats->rx_incomp++; - } - } - while ((rx_bytes == 0) || - ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))); - - if (rx_bytes < 0) - { - errno_val = errno; - perror ("ERROR in sock_test_read()"); - fprintf (stderr, "SOCK_TEST: ERROR: socket read " - "failed (errno = %d)!\n", errno_val); - errno = errno_val; - } - else if (stats) - stats->rx_bytes += rx_bytes; - - return (rx_bytes); -} - -static inline int -sock_test_write (int fd, uint8_t *buf, uint32_t nbytes, - vcl_test_stats_t *stats, uint32_t verbose) -{ - int tx_bytes = 0; - int nbytes_left = nbytes; - int rv, errno_val; - - do - { - if (stats) - stats->tx_xacts++; - rv = write (fd, buf, nbytes_left); - if (rv < 0) - { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) - { - if (stats) - stats->tx_eagain++; - continue; - } - else - break; - } - tx_bytes += rv; - - if (tx_bytes != nbytes) - { - nbytes_left = nbytes_left - rv; - if (stats) - stats->tx_incomp++; - if (verbose) - { - printf ("SOCK_TEST: WARNING: bytes written (%d) " - "!= bytes to write (%d)!\n", tx_bytes, nbytes); - } - } - - } while (tx_bytes != nbytes); - - if (tx_bytes < 0) - { - errno_val = errno; - perror ("ERROR in sock_test_write()"); - fprintf (stderr, "SOCK_TEST: ERROR: socket write failed " - "(errno = %d)!\n", errno_val); - } - else if (stats) - stats->tx_bytes += tx_bytes; - - return (tx_bytes); -} - -#endif /* __sock_test_h__ */ diff --git a/src/vcl/sock_test_client.c b/src/vcl/sock_test_client.c deleted file mode 100644 index a28feee674f..00000000000 --- a/src/vcl/sock_test_client.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <unistd.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <time.h> -#include <arpa/inet.h> -#include <vcl/sock_test.h> -#include <fcntl.h> -#ifndef VCL_TEST -#include <sys/un.h> -#endif - -typedef struct -{ -#ifdef VCL_TEST - vppcom_endpt_t server_endpt; -#else - int af_unix_echo_tx; - int af_unix_echo_rx; -#endif - struct sockaddr_storage server_addr; - uint32_t server_addr_size; - uint32_t cfg_seq_num; - vcl_test_session_t ctrl_socket; - vcl_test_session_t *test_socket; - uint32_t num_test_sockets; - uint8_t dump_cfg; -} sock_client_main_t; - -sock_client_main_t vcl_client_main; - - -static int -sock_test_cfg_sync (vcl_test_session_t * socket) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_cfg_t *rl_cfg = (vcl_test_cfg_t *) socket->rxbuf; - int rx_bytes, tx_bytes; - - if (socket->cfg.verbose) - vcl_test_cfg_dump (&socket->cfg, 1 /* is_client */ ); - - ctrl->cfg.seq_num = ++scm->cfg_seq_num; - if (socket->cfg.verbose) - { - printf ("CLIENT (fd %d): Sending config sent to server.\n", socket->fd); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - tx_bytes = sock_test_write (socket->fd, (uint8_t *) & ctrl->cfg, - sizeof (ctrl->cfg), NULL, ctrl->cfg.verbose); - if (tx_bytes < 0) - { - fprintf (stderr, "CLIENT (fd %d): ERROR: write test cfg failed (%d)!\n", - socket->fd, tx_bytes); - return tx_bytes; - } - - rx_bytes = sock_test_read (socket->fd, (uint8_t *) socket->rxbuf, - sizeof (vcl_test_cfg_t), NULL); - if (rx_bytes < 0) - return rx_bytes; - - if (rl_cfg->magic != VCL_TEST_CFG_CTRL_MAGIC) - { - fprintf (stderr, "CLIENT (fd %d): ERROR: Bad server reply cfg " - "-- aborting!\n", socket->fd); - return -1; - } - if ((rx_bytes != sizeof (vcl_test_cfg_t)) - || !vcl_test_cfg_verify (rl_cfg, &ctrl->cfg)) - { - fprintf (stderr, "CLIENT (fd %d): ERROR: Invalid config received " - "from server!\n", socket->fd); - if (rx_bytes != sizeof (vcl_test_cfg_t)) - { - fprintf (stderr, "\tRx bytes %d != cfg size %lu\n", - rx_bytes, sizeof (vcl_test_cfg_t)); - } - else - { - vcl_test_cfg_dump (rl_cfg, 1 /* is_client */ ); - fprintf (stderr, "CLIENT (fd %d): Valid config sent to server.\n", - socket->fd); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - return -1; - } - else if (socket->cfg.verbose) - { - printf ("CLIENT (fd %d): Got config back from server.\n", socket->fd); - vcl_test_cfg_dump (rl_cfg, 1 /* is_client */ ); - } - ctrl->cfg.ctrl_handle = ((ctrl->cfg.ctrl_handle == ~0) ? - rl_cfg->ctrl_handle : ctrl->cfg.ctrl_handle); - - return 0; -} - -static void -echo_test_client () -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_session_t *tsock; - int rx_bytes, tx_bytes, nbytes; - uint32_t i, n; - int rv; - int nfds = 0; - fd_set wr_fdset, rd_fdset; - fd_set _wfdset, *wfdset = &_wfdset; - fd_set _rfdset, *rfdset = &_rfdset; - - FD_ZERO (&wr_fdset); - FD_ZERO (&rd_fdset); - memset (&ctrl->stats, 0, sizeof (ctrl->stats)); - ctrl->cfg.total_bytes = nbytes = strlen (ctrl->txbuf) + 1; - for (n = 0; n != ctrl->cfg.num_test_sessions; n++) - { - tsock = &scm->test_socket[n]; - tsock->cfg = ctrl->cfg; - vcl_test_session_buf_alloc (tsock); - if (sock_test_cfg_sync (tsock)) - return; - - memcpy (tsock->txbuf, ctrl->txbuf, nbytes); - memset (&tsock->stats, 0, sizeof (tsock->stats)); - - FD_SET (tsock->fd, &wr_fdset); - FD_SET (tsock->fd, &rd_fdset); - nfds = ((tsock->fd + 1) > nfds) ? (tsock->fd + 1) : nfds; - } - - nfds++; - clock_gettime (CLOCK_REALTIME, &ctrl->stats.start); - while (n) - { - _wfdset = wr_fdset; - _rfdset = rd_fdset; - -#ifdef VCL_TEST - rv = - vppcom_select (nfds, (unsigned long *) rfdset, - (unsigned long *) wfdset, NULL, 0); -#else - { - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - rv = select (nfds, rfdset, wfdset, NULL, &timeout); - } -#endif - if (rv < 0) - { - perror ("select()"); - fprintf (stderr, "\nCLIENT: ERROR: select() failed -- " - "aborting test!\n"); - return; - } - else if (rv == 0) - continue; - - for (i = 0; i < ctrl->cfg.num_test_sessions; i++) - { - tsock = &scm->test_socket[i]; - if (!((tsock->stats.stop.tv_sec == 0) && - (tsock->stats.stop.tv_nsec == 0))) - continue; - - if (FD_ISSET (tsock->fd, wfdset) && - (tsock->stats.tx_bytes < ctrl->cfg.total_bytes)) - - { - tx_bytes = - sock_test_write (tsock->fd, (uint8_t *) tsock->txbuf, nbytes, - &tsock->stats, ctrl->cfg.verbose); - if (tx_bytes < 0) - { - fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) " - "failed -- aborting test!\n", tsock->fd); - return; - } - - printf ("CLIENT (fd %d): TX (%d bytes) - '%s'\n", - tsock->fd, tx_bytes, tsock->txbuf); - } - - if ((FD_ISSET (tsock->fd, rfdset)) && - (tsock->stats.rx_bytes < ctrl->cfg.total_bytes)) - { - rx_bytes = - sock_test_read (tsock->fd, (uint8_t *) tsock->rxbuf, - nbytes, &tsock->stats); - if (rx_bytes > 0) - { - printf ("CLIENT (fd %d): RX (%d bytes) - '%s'\n", - tsock->fd, rx_bytes, tsock->rxbuf); - - if (tsock->stats.rx_bytes != tsock->stats.tx_bytes) - printf ("CLIENT: WARNING: bytes read (%lu) " - "!= bytes written (%lu)!\n", - tsock->stats.rx_bytes, tsock->stats.tx_bytes); - } - } - - if (tsock->stats.rx_bytes >= ctrl->cfg.total_bytes) - { - clock_gettime (CLOCK_REALTIME, &tsock->stats.stop); - n--; - } - } - } - clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop); - -#ifndef VCL_TEST - { - int fd, errno_val; - struct sockaddr_un serveraddr; - uint8_t buffer[256]; - size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1; - struct timeval timeout; - - /* Open AF_UNIX socket and send an echo to test mixed epoll on server. - */ - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - { - errno_val = errno; - perror ("ERROR in echo_test_client(): socket(AF_UNIX) failed"); - fprintf (stderr, - "CLIENT: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed " - "(errno = %d)!\n", errno_val); - goto out; - } - memset (&serveraddr, 0, sizeof (serveraddr)); - serveraddr.sun_family = AF_UNIX; - strcpy (serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME); - rv = connect (fd, (struct sockaddr *) &serveraddr, SUN_LEN (&serveraddr)); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in echo_test_client(): connect() failed"); - fprintf (stderr, "CLIENT: ERROR: connect(fd %d, \"%s\", %lu) " - "failed (errno = %d)!\n", fd, SOCK_TEST_AF_UNIX_FILENAME, - SUN_LEN (&serveraddr), errno_val); - goto done; - } - - scm->af_unix_echo_tx++; - strcpy ((char *) buffer, SOCK_TEST_MIXED_EPOLL_DATA); - timeout.tv_sec = 0; - timeout.tv_usec = 250000; - select (0, NULL, NULL, NULL, &timeout); /* delay .25 secs */ - rv = write (fd, buffer, nbytes); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in echo_test_client(): write() failed"); - fprintf (stderr, "CLIENT: ERROR: write(fd %d, \"%s\", %lu) " - "failed (errno = %d)!\n", fd, buffer, nbytes, errno_val); - goto done; - } - else if (rv < nbytes) - { - fprintf (stderr, "CLIENT: ERROR: write(fd %d, \"%s\", %lu) " - "returned %d!\n", fd, buffer, nbytes, rv); - goto done; - } - - printf ("CLIENT (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer); - memset (buffer, 0, sizeof (buffer)); - rv = read (fd, buffer, nbytes); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in echo_test_client(): read() failed"); - fprintf (stderr, "CLIENT: ERROR: read(fd %d, %p, %lu) " - "failed (errno = %d)!\n", fd, buffer, nbytes, errno_val); - goto done; - } - else if (rv < nbytes) - { - fprintf (stderr, "CLIENT: ERROR: read(fd %d, %p, %lu) " - "returned %d!\n", fd, buffer, nbytes, rv); - goto done; - } - - if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes)) - { - printf ("CLIENT (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer); - scm->af_unix_echo_rx++; - } - else - printf ("CLIENT (AF_UNIX): ERROR: RX (%d bytes) - '%s'\n", rv, buffer); - - done: - close (fd); - out: - ; - } -#endif - - for (i = 0; i < ctrl->cfg.num_test_sessions; i++) - { - tsock = &scm->test_socket[i]; - tsock->stats.start = ctrl->stats.start; - - if (ctrl->cfg.verbose) - { - static char buf[64]; - - sprintf (buf, "CLIENT (fd %d) RESULTS", tsock->fd); - vcl_test_stats_dump (buf, &tsock->stats, - 1 /* show_rx */ , 1 /* show tx */ , - ctrl->cfg.verbose); - } - - vcl_test_stats_accumulate (&ctrl->stats, &tsock->stats); - } - - if (ctrl->cfg.verbose) - { - vcl_test_stats_dump ("CLIENT RESULTS", &ctrl->stats, - 1 /* show_rx */ , 1 /* show tx */ , - ctrl->cfg.verbose); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - - if (ctrl->cfg.verbose > 1) - { - printf (" ctrl socket info\n" - VCL_TEST_SEPARATOR_STRING - " fd: %d (0x%08x)\n" - " rxbuf: %p\n" - " rxbuf size: %u (0x%08x)\n" - " txbuf: %p\n" - " txbuf size: %u (0x%08x)\n" - VCL_TEST_SEPARATOR_STRING, - ctrl->fd, (uint32_t) ctrl->fd, - ctrl->rxbuf, ctrl->rxbuf_size, ctrl->rxbuf_size, - ctrl->txbuf, ctrl->txbuf_size, ctrl->txbuf_size); - } - } -} - -static void -stream_test_client (vcl_test_t test) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_session_t *tsock; - int tx_bytes; - uint32_t i, n; - int rv; - int nfds = 0; - fd_set wr_fdset, rd_fdset; - fd_set _wfdset, *wfdset = &_wfdset; - fd_set _rfdset, *rfdset = (test == VCL_TEST_TYPE_BI) ? &_rfdset : 0; - - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - ctrl->cfg.ctrl_handle = ~0; - - printf ("\n" SOCK_TEST_BANNER_STRING - "CLIENT (fd %d): %s-directional Stream Test!\n\n" - "CLIENT (fd %d): Sending config to server on ctrl socket...\n", - ctrl->fd, test == VCL_TEST_TYPE_BI ? "Bi" : "Uni", ctrl->fd); - - if (sock_test_cfg_sync (ctrl)) - { - fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!"); - return; - } - - FD_ZERO (&wr_fdset); - FD_ZERO (&rd_fdset); - memset (&ctrl->stats, 0, sizeof (ctrl->stats)); - for (n = 0; n != ctrl->cfg.num_test_sessions; n++) - { - tsock = &scm->test_socket[n]; - tsock->cfg = ctrl->cfg; - vcl_test_session_buf_alloc (tsock); - printf ("CLIENT (fd %d): Sending config to server on " - "test socket %d...\n", tsock->fd, n); - sock_test_cfg_sync (tsock); - - /* Fill payload with incrementing uint32's */ - for (i = 0; i < tsock->txbuf_size; i++) - tsock->txbuf[i] = i & 0xff; - - memset (&tsock->stats, 0, sizeof (tsock->stats)); - FD_SET (tsock->fd, &wr_fdset); - FD_SET (tsock->fd, &rd_fdset); - nfds = ((tsock->fd + 1) > nfds) ? (tsock->fd + 1) : nfds; - } - - nfds++; - clock_gettime (CLOCK_REALTIME, &ctrl->stats.start); - while (n) - { - _wfdset = wr_fdset; - _rfdset = rd_fdset; - -#ifdef VCL_TEST - rv = - vppcom_select (nfds, (unsigned long *) rfdset, - (unsigned long *) wfdset, NULL, 0); -#else - { - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - rv = select (nfds, rfdset, wfdset, NULL, &timeout); - } -#endif - if (rv < 0) - { - perror ("select()"); - fprintf (stderr, "\nCLIENT: ERROR: select() failed -- " - "aborting test!\n"); - return; - } - else if (rv == 0) - continue; - - for (i = 0; i < ctrl->cfg.num_test_sessions; i++) - { - tsock = &scm->test_socket[i]; - if (!((tsock->stats.stop.tv_sec == 0) && - (tsock->stats.stop.tv_nsec == 0))) - continue; - - if ((test == VCL_TEST_TYPE_BI) && - FD_ISSET (tsock->fd, rfdset) && - (tsock->stats.rx_bytes < ctrl->cfg.total_bytes)) - { - (void) sock_test_read (tsock->fd, - (uint8_t *) tsock->rxbuf, - tsock->rxbuf_size, &tsock->stats); - } - - if (FD_ISSET (tsock->fd, wfdset) && - (tsock->stats.tx_bytes < ctrl->cfg.total_bytes)) - { - tx_bytes = sock_test_write (tsock->fd, (uint8_t *) tsock->txbuf, - ctrl->cfg.txbuf_size, &tsock->stats, - ctrl->cfg.verbose); - if (tx_bytes < 0) - { - fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) " - "failed -- aborting test!\n", tsock->fd); - return; - } - } - - if (((test == VCL_TEST_TYPE_UNI) && - (tsock->stats.tx_bytes >= ctrl->cfg.total_bytes)) || - ((test == VCL_TEST_TYPE_BI) && - (tsock->stats.rx_bytes >= ctrl->cfg.total_bytes))) - { - clock_gettime (CLOCK_REALTIME, &tsock->stats.stop); - n--; - } - } - } - clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop); - - printf ("CLIENT (fd %d): Sending config to server on ctrl socket...\n", - ctrl->fd); - - if (sock_test_cfg_sync (ctrl)) - { - fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!"); - return; - } - - for (i = 0; i < ctrl->cfg.num_test_sessions; i++) - { - tsock = &scm->test_socket[i]; - - if (ctrl->cfg.verbose) - { - static char buf[64]; - - sprintf (buf, "CLIENT (fd %d) RESULTS", tsock->fd); - vcl_test_stats_dump (buf, &tsock->stats, - test == VCL_TEST_TYPE_BI /* show_rx */ , - 1 /* show tx */ , ctrl->cfg.verbose); - } - - vcl_test_stats_accumulate (&ctrl->stats, &tsock->stats); - } - - vcl_test_stats_dump ("CLIENT RESULTS", &ctrl->stats, - test == VCL_TEST_TYPE_BI /* show_rx */ , - 1 /* show tx */ , ctrl->cfg.verbose); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - - if (ctrl->cfg.verbose) - { - printf (" ctrl socket info\n" - VCL_TEST_SEPARATOR_STRING - " fd: %d (0x%08x)\n" - " rxbuf: %p\n" - " rxbuf size: %u (0x%08x)\n" - " txbuf: %p\n" - " txbuf size: %u (0x%08x)\n" - VCL_TEST_SEPARATOR_STRING, - ctrl->fd, (uint32_t) ctrl->fd, - ctrl->rxbuf, ctrl->rxbuf_size, ctrl->rxbuf_size, - ctrl->txbuf, ctrl->txbuf_size, ctrl->txbuf_size); - } - - ctrl->cfg.test = VCL_TEST_TYPE_ECHO; - if (sock_test_cfg_sync (ctrl)) - fprintf (stderr, "CLIENT: ERROR: post-test cfg sync failed!"); - - printf ("CLIENT (fd %d): %s-directional Stream Test Complete!\n" - SOCK_TEST_BANNER_STRING "\n", ctrl->fd, - test == VCL_TEST_TYPE_BI ? "Bi" : "Uni"); -} - -static void -exit_client (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_session_t *tsock; - int i; - -#ifndef VCL_TEST - printf ("CLIENT: af_unix_echo_tx %d, af_unix_echo_rx %d\n", - scm->af_unix_echo_tx, scm->af_unix_echo_rx); -#endif - for (i = 0; i < ctrl->cfg.num_test_sessions; i++) - { - tsock = &scm->test_socket[i]; - tsock->cfg.test = VCL_TEST_TYPE_EXIT; - - /* coverity[COPY_PASTE_ERROR] */ - if (ctrl->cfg.verbose) - { - printf ("\nCLIENT (fd %d): Sending exit cfg to server...\n", - tsock->fd); - vcl_test_cfg_dump (&tsock->cfg, 1 /* is_client */ ); - } - (void) sock_test_write (tsock->fd, (uint8_t *) & tsock->cfg, - sizeof (tsock->cfg), &tsock->stats, - ctrl->cfg.verbose); - } - - ctrl->cfg.test = VCL_TEST_TYPE_EXIT; - if (ctrl->cfg.verbose) - { - printf ("\nCLIENT (fd %d): Sending exit cfg to server...\n", ctrl->fd); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - (void) sock_test_write (ctrl->fd, (uint8_t *) & ctrl->cfg, - sizeof (ctrl->cfg), &ctrl->stats, - ctrl->cfg.verbose); - printf ("\nCLIENT: So long and thanks for all the fish!\n\n"); - sleep (1); -} - -static int -sock_test_connect_test_sockets (uint32_t num_test_sockets) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_session_t *tsock; - int i, rv, errno_val; - - if (num_test_sockets < 1) - { - errno = EINVAL; - return -1; - } - - if (num_test_sockets < scm->num_test_sockets) - { - for (i = scm->num_test_sockets - 1; i >= num_test_sockets; i--) - { - tsock = &scm->test_socket[i]; -#ifdef VCL_TEST - vppcom_session_close (tsock->fd); -#else - close (tsock->fd); -#endif - free (tsock->txbuf); - free (tsock->rxbuf); - } - } - - else if (num_test_sockets > scm->num_test_sockets) - { - tsock = realloc (scm->test_socket, - sizeof (vcl_test_session_t) * num_test_sockets); - if (!tsock) - { - errno_val = errno; - perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n", - errno_val); - return -1; - } - - if (!scm->test_socket) - memset (tsock, 0, sizeof (*tsock)); - - scm->test_socket = tsock; - for (i = scm->num_test_sockets; i < num_test_sockets; i++) - { - tsock = &scm->test_socket[i]; -#ifdef VCL_TEST - tsock->fd = vppcom_session_create (ctrl->cfg.transport_udp ? - VPPCOM_PROTO_UDP : - VPPCOM_PROTO_TCP, - 1 /* is_nonblocking */ ); - if (tsock->fd < 0) - { - errno = -tsock->fd; - tsock->fd = -1; - } -#else - tsock->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET, - ctrl->cfg.transport_udp ? - SOCK_DGRAM : SOCK_STREAM, 0); -#endif - if (tsock->fd < 0) - { - errno_val = errno; - perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n", - errno_val); - return tsock->fd; - } - if (fcntl (tsock->fd, F_SETFL, O_NONBLOCK) < 0) - { - errno_val = errno; - perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "CLIENT: ERROR: fcntl failed (errno = %d)!\n", - errno_val); - return -1; - } - -#ifdef VCL_TEST - rv = vppcom_session_connect (tsock->fd, &scm->server_endpt); - if (rv) - { - errno = -rv; - rv = -1; - } -#else - rv = - connect (tsock->fd, (struct sockaddr *) &scm->server_addr, - scm->server_addr_size); -#endif - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "CLIENT: ERROR: connect failed " - "(errno = %d)!\n", errno_val); - return -1; - } - tsock->cfg = ctrl->cfg; - vcl_test_session_buf_alloc (tsock); - sock_test_cfg_sync (tsock); - - printf ("CLIENT (fd %d): Test socket %d connected.\n", - tsock->fd, i); - } - } - - scm->num_test_sockets = num_test_sockets; - printf ("CLIENT: All sockets (%d) connected!\n", scm->num_test_sockets + 1); - return 0; -} - -static void -dump_help (void) -{ -#define INDENT "\n " - - printf ("CLIENT: Test configuration commands:" - INDENT VCL_TEST_TOKEN_HELP - "\t\t\tDisplay help." - INDENT VCL_TEST_TOKEN_EXIT - "\t\t\tExit test client & server." - INDENT VCL_TEST_TOKEN_SHOW_CFG - "\t\t\tShow the current test cfg." - INDENT VCL_TEST_TOKEN_RUN_UNI - "\t\t\tRun the Uni-directional test." - INDENT VCL_TEST_TOKEN_RUN_BI - "\t\t\tRun the Bi-directional test." - INDENT VCL_TEST_TOKEN_VERBOSE - "\t\t\tToggle verbose setting." - INDENT VCL_TEST_TOKEN_RXBUF_SIZE - "<rxbuf size>\tRx buffer size (bytes)." - INDENT VCL_TEST_TOKEN_TXBUF_SIZE - "<txbuf size>\tTx buffer size (bytes)." - INDENT VCL_TEST_TOKEN_NUM_WRITES - "<# of writes>\tNumber of txbuf writes to server." "\n"); -} - -static void -cfg_txbuf_size_set (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_TXBUF_SIZE); - uint64_t txbuf_size = strtoull ((const char *) p, NULL, 10); - - if (txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->cfg.txbuf_size = txbuf_size; - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ , - (uint8_t **) & ctrl->txbuf, &ctrl->txbuf_size); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - fprintf (stderr, "CLIENT: ERROR: Invalid txbuf size (%lu) < " - "minimum buf size (%u)!\n", - txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); -} - -static void -cfg_num_writes_set (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_WRITES); - uint32_t num_writes = strtoul ((const char *) p, NULL, 10); - - if (num_writes > 0) - { - ctrl->cfg.num_writes = num_writes; - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - { - fprintf (stderr, "CLIENT: ERROR: invalid num writes: %u\n", num_writes); - } -} - -static void -cfg_num_test_sockets_set (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_TEST_SESS); - uint32_t num_test_sockets = strtoul ((const char *) p, NULL, 10); - - if ((num_test_sockets > 0) && - (num_test_sockets <= VCL_TEST_CFG_MAX_TEST_SESS)) - { - ctrl->cfg.num_test_sessions = num_test_sockets; - sock_test_connect_test_sockets (num_test_sockets); - - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - { - fprintf (stderr, "CLIENT: ERROR: invalid num test sockets: " - "%u, (%d max)\n", - num_test_sockets, VCL_TEST_CFG_MAX_TEST_SESS); - } -} - -static void -cfg_rxbuf_size_set (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_RXBUF_SIZE); - uint64_t rxbuf_size = strtoull ((const char *) p, NULL, 10); - - if (rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->cfg.rxbuf_size = rxbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ , - (uint8_t **) & ctrl->rxbuf, &ctrl->rxbuf_size); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - fprintf (stderr, "CLIENT: ERROR: Invalid rxbuf size (%lu) < " - "minimum buf size (%u)!\n", - rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); -} - -static void -cfg_verbose_toggle (void) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - - ctrl->cfg.verbose = ctrl->cfg.verbose ? 0 : 1; - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - -} - -static vcl_test_t -parse_input () -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - vcl_test_t rv = VCL_TEST_TYPE_NONE; - - if (!strncmp (VCL_TEST_TOKEN_EXIT, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_EXIT))) - rv = VCL_TEST_TYPE_EXIT; - - else if (!strncmp (VCL_TEST_TOKEN_HELP, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_HELP))) - dump_help (); - - else if (!strncmp (VCL_TEST_TOKEN_SHOW_CFG, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_SHOW_CFG))) - scm->dump_cfg = 1; - - else if (!strncmp (VCL_TEST_TOKEN_VERBOSE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_VERBOSE))) - cfg_verbose_toggle (); - - else if (!strncmp (VCL_TEST_TOKEN_TXBUF_SIZE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_TXBUF_SIZE))) - cfg_txbuf_size_set (); - - else if (!strncmp (VCL_TEST_TOKEN_NUM_TEST_SESS, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_NUM_TEST_SESS))) - cfg_num_test_sockets_set (); - - else if (!strncmp (VCL_TEST_TOKEN_NUM_WRITES, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_NUM_WRITES))) - cfg_num_writes_set (); - - else if (!strncmp (VCL_TEST_TOKEN_RXBUF_SIZE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RXBUF_SIZE))) - cfg_rxbuf_size_set (); - - else if (!strncmp (VCL_TEST_TOKEN_RUN_UNI, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RUN_UNI))) - rv = ctrl->cfg.test = VCL_TEST_TYPE_UNI; - - else if (!strncmp (VCL_TEST_TOKEN_RUN_BI, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RUN_BI))) - rv = ctrl->cfg.test = VCL_TEST_TYPE_BI; - - else - rv = VCL_TEST_TYPE_ECHO; - - return rv; -} - -void -print_usage_and_exit (void) -{ - fprintf (stderr, - "sock_test_client [OPTIONS] <ipaddr> <port>\n" - " OPTIONS\n" - " -h Print this message and exit.\n" - " -6 Use IPv6\n" - " -u Use UDP transport layer\n" - " -c Print test config before test.\n" - " -w <dir> Write test results to <dir>.\n" - " -X Exit after running test.\n" - " -E Run Echo test.\n" - " -N <num-writes> Test Cfg: number of writes.\n" - " -R <rxbuf-size> Test Cfg: rx buffer size.\n" - " -T <txbuf-size> Test Cfg: tx buffer size.\n" - " -U Run Uni-directional test.\n" - " -B Run Bi-directional test.\n" - " -V Verbose mode.\n"); - exit (1); -} - -int -main (int argc, char **argv) -{ - sock_client_main_t *scm = &vcl_client_main; - vcl_test_session_t *ctrl = &scm->ctrl_socket; - int c, rv, errno_val; - vcl_test_t post_test = VCL_TEST_TYPE_NONE; - - vcl_test_cfg_init (&ctrl->cfg); - vcl_test_session_buf_alloc (ctrl); - - opterr = 0; - while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6D")) != -1) - switch (c) - { - case 'c': - scm->dump_cfg = 1; - break; - - case 's': - if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1) - if (sscanf (optarg, "%u", &ctrl->cfg.num_test_sessions) != 1) - { - fprintf (stderr, "CLIENT: ERROR: Invalid value for " - "option -%c!\n", c); - print_usage_and_exit (); - } - if (!ctrl->cfg.num_test_sessions || - (ctrl->cfg.num_test_sessions > FD_SETSIZE)) - { - fprintf (stderr, "CLIENT: ERROR: Invalid number of " - "sockets (%d) specified for option -%c!\n" - " Valid range is 1 - %d\n", - ctrl->cfg.num_test_sessions, c, FD_SETSIZE); - print_usage_and_exit (); - } - break; - - case 'w': - fprintf (stderr, "CLIENT: Writing test results to files is TBD.\n"); - break; - - case 'X': - post_test = VCL_TEST_TYPE_EXIT; - break; - - case 'E': - if (strlen (optarg) > ctrl->txbuf_size) - { - fprintf (stderr, "CLIENT: ERROR: Option -%c value " - "larger than txbuf size (%d)!\n", - optopt, ctrl->txbuf_size); - print_usage_and_exit (); - } - strcpy (ctrl->txbuf, optarg); - ctrl->cfg.test = VCL_TEST_TYPE_ECHO; - break; - - case 'I': - if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1) - if (sscanf (optarg, "%d", &ctrl->cfg.num_test_sessions) != 1) - { - fprintf (stderr, "CLIENT: ERROR: Invalid value for " - "option -%c!\n", c); - print_usage_and_exit (); - } - if (ctrl->cfg.num_test_sessions > VCL_TEST_CFG_MAX_TEST_SESS) - { - fprintf (stderr, "CLIENT: ERROR: value greater than max " - "number test sockets (%d)!", VCL_TEST_CFG_MAX_TEST_SESS); - print_usage_and_exit (); - } - break; - - case 'N': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.num_writes) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.num_writes) != 1) - { - fprintf (stderr, "CLIENT: ERROR: Invalid value for " - "option -%c!\n", c); - print_usage_and_exit (); - } - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - break; - - case 'R': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.rxbuf_size) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.rxbuf_size) != 1) - { - fprintf (stderr, "CLIENT: ERROR: Invalid value for " - "option -%c!\n", c); - print_usage_and_exit (); - } - if (ctrl->cfg.rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->rxbuf_size = ctrl->cfg.rxbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ , - (uint8_t **) & ctrl->rxbuf, - &ctrl->rxbuf_size); - } - else - { - fprintf (stderr, "CLIENT: ERROR: rxbuf size (%lu) " - "less than minumum (%u)\n", - ctrl->cfg.rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); - print_usage_and_exit (); - } - - break; - - case 'T': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.txbuf_size) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.txbuf_size) != 1) - { - fprintf (stderr, "CLIENT: ERROR: Invalid value " - "for option -%c!\n", c); - print_usage_and_exit (); - } - if (ctrl->cfg.txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->txbuf_size = ctrl->cfg.txbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ , - (uint8_t **) & ctrl->txbuf, - &ctrl->txbuf_size); - ctrl->cfg.total_bytes = - ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - } - else - { - fprintf (stderr, "CLIENT: ERROR: txbuf size (%lu) " - "less than minumum (%u)!\n", - ctrl->cfg.txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); - print_usage_and_exit (); - } - break; - - case 'U': - ctrl->cfg.test = VCL_TEST_TYPE_UNI; - break; - - case 'B': - ctrl->cfg.test = VCL_TEST_TYPE_BI; - break; - - case 'V': - ctrl->cfg.verbose = 1; - break; - - case '6': - ctrl->cfg.address_ip6 = 1; - break; - - case 'D': - ctrl->cfg.transport_udp = 1; - break; - - case '?': - switch (optopt) - { - case 'E': - case 'I': - case 'N': - case 'R': - case 'T': - case 'w': - fprintf (stderr, "CLIENT: ERROR: Option -%c " - "requires an argument.\n", optopt); - break; - - default: - if (isprint (optopt)) - fprintf (stderr, "CLIENT: ERROR: Unknown " - "option `-%c'.\n", optopt); - else - fprintf (stderr, "CLIENT: ERROR: Unknown " - "option character `\\x%x'.\n", optopt); - } - /* fall thru */ - case 'h': - default: - print_usage_and_exit (); - } - - if (argc < (optind + 2)) - { - fprintf (stderr, "CLIENT: ERROR: Insufficient number of arguments!\n"); - print_usage_and_exit (); - } - -#ifdef VCL_TEST - ctrl->fd = vppcom_app_create ("vcl_test_client"); - if (ctrl->fd < 0) - { - errno = -ctrl->fd; - ctrl->fd = -1; - } - else - { - ctrl->fd = vppcom_session_create (ctrl->cfg.transport_udp ? - VPPCOM_PROTO_UDP : - VPPCOM_PROTO_TCP, - 0 /* is_nonblocking */ ); - if (ctrl->fd < 0) - { - errno = -ctrl->fd; - ctrl->fd = -1; - } - } -#else - ctrl->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET, - ctrl->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM, 0); -#endif - - if (ctrl->fd < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "CLIENT: ERROR: socket " - "failed (errno = %d)!\n", errno_val); - return ctrl->fd; - } - - memset (&scm->server_addr, 0, sizeof (scm->server_addr)); - if (ctrl->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = - (struct sockaddr_in6 *) &scm->server_addr; - scm->server_addr_size = sizeof (*server_addr); - server_addr->sin6_family = AF_INET6; - inet_pton (AF_INET6, argv[optind++], &(server_addr->sin6_addr)); - server_addr->sin6_port = htons (atoi (argv[optind])); - } - else - { - struct sockaddr_in *server_addr = - (struct sockaddr_in *) &scm->server_addr; - scm->server_addr_size = sizeof (*server_addr); - server_addr->sin_family = AF_INET; - inet_pton (AF_INET, argv[optind++], &(server_addr->sin_addr)); - server_addr->sin_port = htons (atoi (argv[optind])); - } - -#ifdef VCL_TEST - if (ctrl->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = - (struct sockaddr_in6 *) &scm->server_addr; - scm->server_endpt.is_ip4 = 0; - scm->server_endpt.ip = (uint8_t *) & server_addr->sin6_addr; - scm->server_endpt.port = (uint16_t) server_addr->sin6_port; - } - else - { - struct sockaddr_in *server_addr = - (struct sockaddr_in *) &scm->server_addr; - scm->server_endpt.is_ip4 = 1; - scm->server_endpt.ip = (uint8_t *) & server_addr->sin_addr; - scm->server_endpt.port = (uint16_t) server_addr->sin_port; - } -#endif - - do - { - printf ("\nCLIENT: Connecting to server...\n"); - -#ifdef VCL_TEST - rv = vppcom_session_connect (ctrl->fd, &scm->server_endpt); - if (rv) - { - errno = -rv; - rv = -1; - } -#else - rv = - connect (ctrl->fd, (struct sockaddr *) &scm->server_addr, - scm->server_addr_size); -#endif - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "CLIENT: ERROR: connect failed (errno = %d)!\n", - errno_val); - return -1; - } - - sock_test_cfg_sync (ctrl); - printf ("CLIENT (fd %d): Control socket connected.\n", ctrl->fd); - } - while (rv < 0); - - sock_test_connect_test_sockets (ctrl->cfg.num_test_sessions); - - while (ctrl->cfg.test != VCL_TEST_TYPE_EXIT) - { - if (scm->dump_cfg) - { - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - scm->dump_cfg = 0; - } - - switch (ctrl->cfg.test) - { - case VCL_TEST_TYPE_ECHO: - echo_test_client (); - break; - - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - stream_test_client (ctrl->cfg.test); - break; - - case VCL_TEST_TYPE_EXIT: - continue; - - case VCL_TEST_TYPE_NONE: - default: - break; - } - switch (post_test) - { - case VCL_TEST_TYPE_EXIT: - switch (ctrl->cfg.test) - { - case VCL_TEST_TYPE_EXIT: - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - case VCL_TEST_TYPE_ECHO: - ctrl->cfg.test = VCL_TEST_TYPE_EXIT; - continue; - - case VCL_TEST_TYPE_NONE: - default: - break; - } - break; - - case VCL_TEST_TYPE_NONE: - case VCL_TEST_TYPE_ECHO: - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - default: - break; - } - - memset (ctrl->txbuf, 0, ctrl->txbuf_size); - memset (ctrl->rxbuf, 0, ctrl->rxbuf_size); - - printf ("\nCLIENT: Type some characters and hit <return>\n" - "('" VCL_TEST_TOKEN_HELP "' for help): "); - - if (fgets (ctrl->txbuf, ctrl->txbuf_size, stdin) != NULL) - { - if (strlen (ctrl->txbuf) == 1) - { - printf ("\nCLIENT: Nothing to send! Please try again...\n"); - continue; - } - ctrl->txbuf[strlen (ctrl->txbuf) - 1] = 0; // chomp the newline. - - /* Parse input for keywords */ - ctrl->cfg.test = parse_input (); - } - } - - exit_client (); -#ifdef VCL_TEST - vppcom_session_close (ctrl->fd); - vppcom_app_destroy (); - return 0; -#else - close (ctrl->fd); - return (scm->af_unix_echo_tx == scm->af_unix_echo_rx) ? 0 : -1; -#endif -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/sock_test_server.c b/src/vcl/sock_test_server.c deleted file mode 100644 index 2e678c3899a..00000000000 --- a/src/vcl/sock_test_server.c +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <ctype.h> -#include <vcl/sock_test.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#define SOCK_SERVER_USE_EPOLL 1 -#define VPPCOM_SESSION_ATTR_UNIT_TEST 0 - -#if SOCK_SERVER_USE_EPOLL -#include <sys/epoll.h> -#if !defined(VCL_TEST) -#include <sys/un.h> -#endif -#endif - -#ifdef VCL_TEST -#if VPPCOM_SESSION_ATTR_UNIT_TEST -#define BUFLEN sizeof (uint64_t) * 16 -uint64_t buffer[16]; -uint32_t buflen = BUFLEN; -uint32_t *flags = (uint32_t *) buffer; -#endif -#endif - -typedef struct -{ - uint8_t is_alloc; - int fd; - uint8_t *buf; - uint32_t buf_size; - vcl_test_cfg_t cfg; - vcl_test_stats_t stats; -#ifdef VCL_TEST - vppcom_endpt_t endpt; - uint8_t ip[16]; -#endif -} sock_server_conn_t; - -typedef struct -{ - uint32_t port; - uint32_t address_ip6; - uint32_t transport_udp; -} sock_server_cfg_t; - -#define SOCK_SERVER_MAX_TEST_CONN 10 -#define SOCK_SERVER_MAX_EPOLL_EVENTS 10 -typedef struct -{ - int listen_fd; - sock_server_cfg_t cfg; -#if SOCK_SERVER_USE_EPOLL - int epfd; - struct epoll_event listen_ev; - struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS]; -#if !defined (VCL_TEST) - int af_unix_listen_fd; - int af_unix_fd; - struct epoll_event af_unix_listen_ev; - struct sockaddr_un serveraddr; - uint32_t af_unix_xacts; -#endif -#endif - size_t num_conn; - size_t conn_pool_size; - sock_server_conn_t *conn_pool; - int nfds; - fd_set rd_fdset; - fd_set wr_fdset; - struct timeval timeout; -} sock_server_main_t; - -sock_server_main_t sock_server_main; - -#if ! SOCK_SERVER_USE_EPOLL -static inline int -get_nfds (void) -{ - sock_server_main_t *ssm = &sock_server_main; - int i, nfds; - - for (nfds = i = 0; i < FD_SETSIZE; i++) - { - if (FD_ISSET (i, &ssm->rd_fdset) || FD_ISSET (i, &ssm->wr_fdset)) - nfds = i + 1; - } - return nfds; -} - -static inline void -conn_fdset_set (sock_server_conn_t * conn, fd_set * fdset) -{ - sock_server_main_t *ssm = &sock_server_main; - - FD_SET (conn->fd, fdset); - ssm->nfds = get_nfds (); -} - -static inline void -conn_fdset_clr (sock_server_conn_t * conn, fd_set * fdset) -{ - sock_server_main_t *ssm = &sock_server_main; - - FD_CLR (conn->fd, fdset); - ssm->nfds = get_nfds (); -} -#endif - -static inline void -conn_pool_expand (size_t expand_size) -{ - sock_server_main_t *ssm = &sock_server_main; - sock_server_conn_t *conn_pool; - size_t new_size = ssm->conn_pool_size + expand_size; - int i; - - conn_pool = realloc (ssm->conn_pool, new_size * sizeof (*ssm->conn_pool)); - if (conn_pool) - { - for (i = ssm->conn_pool_size; i < new_size; i++) - { - sock_server_conn_t *conn = &conn_pool[i]; - memset (conn, 0, sizeof (*conn)); - vcl_test_cfg_init (&conn->cfg); - vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , - &conn->buf, &conn->buf_size); - conn->cfg.txbuf_size = conn->cfg.rxbuf_size; - } - - ssm->conn_pool = conn_pool; - ssm->conn_pool_size = new_size; - } - else - { - int errno_val = errno; - perror ("ERROR in conn_pool_expand()"); - fprintf (stderr, "SERVER: ERROR: Memory allocation " - "failed (errno = %d)!\n", errno_val); - } -} - -static inline sock_server_conn_t * -conn_pool_alloc (void) -{ - sock_server_main_t *ssm = &sock_server_main; - int i; - - for (i = 0; i < ssm->conn_pool_size; i++) - { - if (!ssm->conn_pool[i].is_alloc) - { -#ifdef VCL_TEST - ssm->conn_pool[i].endpt.ip = ssm->conn_pool[i].ip; -#endif - ssm->conn_pool[i].is_alloc = 1; - return (&ssm->conn_pool[i]); - } - } - - return 0; -} - -static inline void -conn_pool_free (sock_server_conn_t * conn) -{ -#if ! SOCK_SERVER_USE_EPOLL - sock_server_main_t *ssm = &sock_server_main; - - conn_fdset_clr (conn, &ssm->rd_fdset); - conn_fdset_clr (conn, &ssm->wr_fdset); -#endif - conn->fd = 0; - conn->is_alloc = 0; -} - -static inline void -sync_config_and_reply (sock_server_conn_t * conn, vcl_test_cfg_t * rx_cfg) -{ - conn->cfg = *rx_cfg; - vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , - &conn->buf, &conn->buf_size); - conn->cfg.txbuf_size = conn->cfg.rxbuf_size; - - if (conn->cfg.verbose) - { - printf ("\nSERVER (fd %d): Replying to cfg message!\n", conn->fd); - vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); - } - (void) sock_test_write (conn->fd, (uint8_t *) & conn->cfg, - sizeof (conn->cfg), NULL, conn->cfg.verbose); -} - -static void -stream_test_server_start_stop (sock_server_conn_t * conn, - vcl_test_cfg_t * rx_cfg) -{ - sock_server_main_t *ssm = &sock_server_main; - int client_fd = conn->fd; - vcl_test_t test = rx_cfg->test; - - if (rx_cfg->ctrl_handle == conn->fd) - { - int i; - clock_gettime (CLOCK_REALTIME, &conn->stats.stop); - - for (i = 0; i < ssm->conn_pool_size; i++) - { - sock_server_conn_t *tc = &ssm->conn_pool[i]; - - if (tc->cfg.ctrl_handle == conn->fd) - { - vcl_test_stats_accumulate (&conn->stats, &tc->stats); - - if (conn->cfg.verbose) - { - static char buf[64]; - - sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd); - vcl_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ , - test == VCL_TEST_TYPE_BI - /* show tx */ , - conn->cfg.verbose); - } - } - } - - vcl_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ , - (test == VCL_TEST_TYPE_BI) /* show_tx */ , - conn->cfg.verbose); - vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); - if (conn->cfg.verbose) - { - printf (" sock server main\n" - VCL_TEST_SEPARATOR_STRING - " buf: %p\n" - " buf size: %u (0x%08x)\n" - VCL_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 == VCL_TEST_TYPE_BI ? "Bi" : "Uni"); - } - 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 == VCL_TEST_TYPE_BI ? "Bi" : "Uni"); - - rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd : - rx_cfg->ctrl_handle; - - sync_config_and_reply (conn, rx_cfg); - - /* read the 1st chunk, record start time */ - memset (&conn->stats, 0, sizeof (conn->stats)); - clock_gettime (CLOCK_REALTIME, &conn->stats.start); - } -} - - -static inline void -stream_test_server (sock_server_conn_t * conn, int rx_bytes) -{ - int client_fd = conn->fd; - vcl_test_t test = conn->cfg.test; - - if (test == VCL_TEST_TYPE_BI) - (void) sock_test_write (client_fd, conn->buf, rx_bytes, &conn->stats, - conn->cfg.verbose); - - if (conn->stats.rx_bytes >= conn->cfg.total_bytes) - { - clock_gettime (CLOCK_REALTIME, &conn->stats.stop); - } -} - -#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) -static inline void -af_unix_echo (void) -{ - sock_server_main_t *ssm = &sock_server_main; - int af_unix_client_fd; - int rv; - int errno_val; - uint8_t buffer[256]; - size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1; - -#if HAVE_ACCEPT4 - af_unix_client_fd = accept4 (ssm->af_unix_listen_fd, - (struct sockaddr *) NULL, NULL, NULL); -#else - af_unix_client_fd = accept (ssm->af_unix_listen_fd, - (struct sockaddr *) NULL, NULL); -#endif - if (af_unix_client_fd < 0) - { - errno_val = errno; - perror ("ERROR in af_unix_accept()"); - fprintf (stderr, "SERVER: ERROR: accept failed " - "(errno = %d)!\n", errno_val); - return; - } - - printf ("SERVER: Got an AF_UNIX connection -- fd = %d (0x%08x)!\n", - af_unix_client_fd, af_unix_client_fd); - - memset (buffer, 0, sizeof (buffer)); - - rv = read (af_unix_client_fd, buffer, nbytes); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in af_unix_echo(): read() failed"); - fprintf (stderr, "SERVER: ERROR: read(af_unix_client_fd %d (0x%x), " - "\"%s\", nbytes %lu) failed (errno = %d)!\n", - af_unix_client_fd, af_unix_client_fd, buffer, nbytes, - errno_val); - goto done; - } - - printf ("SERVER (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer); - - if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes)) - { - rv = write (af_unix_client_fd, buffer, nbytes); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in af_unix_echo(): write() failed"); - fprintf (stderr, - "SERVER: ERROR: write(af_unix_client_fd %d (0x%x), " - "\"%s\", nbytes %ld) failed (errno = %d)!\n", - af_unix_client_fd, af_unix_client_fd, buffer, nbytes, - errno_val); - goto done; - } - printf ("SERVER (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer); - ssm->af_unix_xacts++; - } -done: - close (af_unix_client_fd); -} - -#endif - -static inline void -new_client (void) -{ - sock_server_main_t *ssm = &sock_server_main; - int client_fd; - sock_server_conn_t *conn; - - if (ssm->conn_pool_size < (ssm->num_conn + SOCK_SERVER_MAX_TEST_CONN + 1)) - conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1); - - conn = conn_pool_alloc (); - if (!conn) - { - fprintf (stderr, "\nSERVER: ERROR: No free connections!\n"); - return; - } - -#ifdef VCL_TEST - client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, 0); - if (client_fd < 0) - errno = -client_fd; -#elif HAVE_ACCEPT4 - client_fd = accept4 (ssm->listen_fd, (struct sockaddr *) NULL, NULL, NULL); -#else - client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL); -#endif - if (client_fd < 0) - { - int errno_val; - errno_val = errno; - perror ("ERROR in new_client()"); - fprintf (stderr, "SERVER: ERROR: accept failed " - "(errno = %d)!\n", errno_val); - return; - } - - printf ("SERVER: Got a connection -- fd = %d (0x%08x)!\n", - client_fd, client_fd); - - conn->fd = client_fd; - -#if ! SOCK_SERVER_USE_EPOLL - conn_fdset_set (conn, &ssm->rd_fdset); - ssm->nfds++; -#else - { - struct epoll_event ev; - int rv; - - ev.events = EPOLLIN; - ev.data.u64 = conn - ssm->conn_pool; -#ifdef VCL_TEST - rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev); - if (rv) - errno = -rv; -#else - rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev); -#endif - if (rv < 0) - { - int errno_val; - errno_val = errno; - perror ("ERROR in new_client()"); - fprintf (stderr, "SERVER: ERROR: epoll_ctl failed (errno = %d)!\n", - errno_val); - } - else - ssm->nfds++; - } -#endif -} - -void -print_usage_and_exit (void) -{ - fprintf (stderr, - "sock_test_server [OPTIONS] <port>\n" - " OPTIONS\n" - " -h Print this message and exit.\n" - " -6 Use IPv6\n" - " -u Use UDP transport layer\n"); - exit (1); -} - -int -main (int argc, char **argv) -{ - sock_server_main_t *ssm = &sock_server_main; - int client_fd, rv, main_rv = 0; - int tx_bytes, rx_bytes, nbytes; - sock_server_conn_t *conn; - vcl_test_cfg_t *rx_cfg; - uint32_t xtra = 0; - uint64_t xtra_bytes = 0; - struct sockaddr_storage servaddr; - int errno_val; - int c, v, i; - uint16_t port = VCL_TEST_SERVER_PORT; -#if ! SOCK_SERVER_USE_EPOLL - fd_set _rfdset, *rfdset = &_rfdset; -#endif -#ifdef VCL_TEST - vppcom_endpt_t endpt; -#else - uint32_t servaddr_size; -#if ! SOCK_SERVER_USE_EPOLL - fd_set _wfdset, *wfdset = &_wfdset; -#endif -#endif - - opterr = 0; - while ((c = getopt (argc, argv, "6D")) != -1) - switch (c) - { - case '6': - ssm->cfg.address_ip6 = 1; - break; - - case 'D': - ssm->cfg.transport_udp = 1; - break; - - case '?': - switch (optopt) - { - default: - if (isprint (optopt)) - fprintf (stderr, "SERVER: ERROR: Unknown " - "option `-%c'.\n", optopt); - else - fprintf (stderr, "SERVER: ERROR: Unknown " - "option character `\\x%x'.\n", optopt); - } - /* fall thru */ - case 'h': - default: - print_usage_and_exit (); - } - - if (argc < (optind + 1)) - { - fprintf (stderr, "SERVER: ERROR: Insufficient number of arguments!\n"); - print_usage_and_exit (); - } - - if (sscanf (argv[optind], "%d", &v) == 1) - port = (uint16_t) v; - else - { - fprintf (stderr, "SERVER: ERROR: Invalid port (%s)!\n", argv[optind]); - print_usage_and_exit (); - } - - conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1); - -#ifdef VCL_TEST - rv = vppcom_app_create ("vcl_test_server"); - if (rv) - { - errno = -rv; - ssm->listen_fd = -1; - } - else - { - ssm->listen_fd = vppcom_session_create (ssm->cfg.transport_udp ? - VPPCOM_PROTO_UDP : - VPPCOM_PROTO_TCP, - 0 /* is_nonblocking */ ); - } -#else - ssm->listen_fd = socket (ssm->cfg.address_ip6 ? AF_INET6 : AF_INET, - ssm->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM, - 0); -#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) - unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME); - ssm->af_unix_listen_fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (ssm->af_unix_listen_fd < 0) - { - errno_val = errno; - perror ("ERROR in main(): socket(AF_UNIX) failed"); - fprintf (stderr, - "SERVER: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed " - "(errno = %d)!\n", errno_val); - return ssm->af_unix_listen_fd; - } - - memset (&ssm->serveraddr, 0, sizeof (ssm->serveraddr)); - ssm->serveraddr.sun_family = AF_UNIX; - strcpy (ssm->serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME); - - rv = bind (ssm->af_unix_listen_fd, (struct sockaddr *) &ssm->serveraddr, - SUN_LEN (&ssm->serveraddr)); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main(): bind(SOCK_TEST_AF_UNIX_FILENAME) failed"); - fprintf (stderr, "SERVER: ERROR: bind() fd %d, \"%s\": " - "failed (errno = %d)!\n", ssm->af_unix_listen_fd, - SOCK_TEST_AF_UNIX_FILENAME, errno_val); - close (ssm->af_unix_listen_fd); - unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME); - return rv; - } - - rv = listen (ssm->af_unix_listen_fd, 10); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main(): listen(AF_UNIX) failed"); - fprintf (stderr, "SERVER: ERROR: listen() fd %d, \"%s\": " - "failed (errno = %d)!\n", ssm->af_unix_listen_fd, - SOCK_TEST_AF_UNIX_FILENAME, errno_val); - close (ssm->af_unix_listen_fd); - unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME); - return rv; - } -#endif /* SOCK_SERVER_USE_EPOLL */ -#endif - if (ssm->listen_fd < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: socket() failed " - "(errno = %d)!\n", errno_val); - return ssm->listen_fd; - } - - memset (&servaddr, 0, sizeof (servaddr)); - - if (ssm->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) &servaddr; -#ifndef VCL_TEST - servaddr_size = sizeof (*server_addr); -#endif - server_addr->sin6_family = AF_INET6; - server_addr->sin6_addr = in6addr_any; - server_addr->sin6_port = htons (port); - } - else - { - struct sockaddr_in *server_addr = (struct sockaddr_in *) &servaddr; -#ifndef VCL_TEST - servaddr_size = sizeof (*server_addr); -#endif - server_addr->sin_family = AF_INET; - server_addr->sin_addr.s_addr = htonl (INADDR_ANY); - server_addr->sin_port = htons (port); - } - -#ifdef VCL_TEST - if (ssm->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) &servaddr; - endpt.is_ip4 = 0; - endpt.ip = (uint8_t *) & server_addr->sin6_addr; - endpt.port = (uint16_t) server_addr->sin6_port; - } - else - { - struct sockaddr_in *server_addr = (struct sockaddr_in *) &servaddr; - endpt.is_ip4 = 1; - endpt.ip = (uint8_t *) & server_addr->sin_addr; - endpt.port = (uint16_t) server_addr->sin_port; - } - - rv = vppcom_session_bind (ssm->listen_fd, &endpt); - if (rv) - { - errno = -rv; - rv = -1; - } -#else - rv = bind (ssm->listen_fd, (struct sockaddr *) &servaddr, servaddr_size); -#endif - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: bind failed (errno = %d)!\n", - errno_val); - return rv; - } - if (fcntl (ssm->listen_fd, F_SETFL, O_NONBLOCK) < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: fcntl failed (errno = %d)!\n", - errno_val); - return rv; - } - -#ifdef VCL_TEST - rv = vppcom_session_listen (ssm->listen_fd, 10); - if (rv) - { - errno = -rv; - rv = -1; - } -#else - rv = listen (ssm->listen_fd, 10); -#endif - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: listen failed " - "(errno = %d)!\n", errno_val); - return rv; - } - -#if ! SOCK_SERVER_USE_EPOLL - - FD_ZERO (&ssm->wr_fdset); - FD_ZERO (&ssm->rd_fdset); - - FD_SET (ssm->listen_fd, &ssm->rd_fdset); - ssm->nfds = ssm->listen_fd + 1; - -#else -#ifdef VCL_TEST - ssm->epfd = vppcom_epoll_create (); - if (ssm->epfd < 0) - errno = -ssm->epfd; -#else - ssm->epfd = epoll_create (1); -#endif - if (ssm->epfd < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: epoll_create failed (errno = %d)!\n", - errno_val); - return ssm->epfd; - } - - ssm->listen_ev.events = EPOLLIN; - ssm->listen_ev.data.u32 = ~0; -#ifdef VCL_TEST - rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, - &ssm->listen_ev); - if (rv < 0) - errno = -rv; -#else - ssm->af_unix_listen_ev.events = EPOLLIN; - ssm->af_unix_listen_ev.data.u32 = SOCK_TEST_AF_UNIX_ACCEPT_DATA; - rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->af_unix_listen_fd, - &ssm->af_unix_listen_ev); - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main(): mixed epoll_ctl(EPOLL_CTL_ADD)"); - fprintf (stderr, "SERVER: ERROR: mixed epoll_ctl(epfd %d (0x%x), " - "EPOLL_CTL_ADD, af_unix_listen_fd %d (0x%x), EPOLLIN) failed " - "(errno = %d)!\n", ssm->epfd, ssm->epfd, - ssm->af_unix_listen_fd, ssm->af_unix_listen_fd, errno_val); - close (ssm->af_unix_listen_fd); - unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME); - return rv; - } - - rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, &ssm->listen_ev); -#endif - if (rv < 0) - { - errno_val = errno; - perror ("ERROR in main()"); - fprintf (stderr, "SERVER: ERROR: epoll_ctl failed " - "(errno = %d)!\n", errno_val); - return rv; - } -#endif - - printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port); - - while (1) - { -#if ! SOCK_SERVER_USE_EPOLL - _rfdset = ssm->rd_fdset; - -#ifdef VCL_TEST - rv = vppcom_select (ssm->nfds, (unsigned long *) rfdset, NULL, NULL, 0); -#else - { - struct timeval timeout; - timeout = ssm->timeout; - _wfdset = ssm->wr_fdset; - rv = select (ssm->nfds, rfdset, wfdset, NULL, &timeout); - } -#endif - if (rv < 0) - { - perror ("select()"); - fprintf (stderr, "\nSERVER: ERROR: select() failed -- aborting!\n"); - main_rv = -1; - goto done; - } - else if (rv == 0) - continue; - - if (FD_ISSET (ssm->listen_fd, rfdset)) - new_client (); - - for (i = 0; i < ssm->conn_pool_size; i++) - { - if (!ssm->conn_pool[i].is_alloc) - continue; - - conn = &ssm->conn_pool[i]; -#else - int num_ev; -#ifdef VCL_TEST - num_ev = vppcom_epoll_wait (ssm->epfd, ssm->wait_events, - SOCK_SERVER_MAX_EPOLL_EVENTS, 60.0); - if (num_ev < 0) - errno = -num_ev; -#else - num_ev = epoll_wait (ssm->epfd, ssm->wait_events, - SOCK_SERVER_MAX_EPOLL_EVENTS, 60000); -#endif - if (num_ev < 0) - { - perror ("epoll_wait()"); - fprintf (stderr, "\nSERVER: ERROR: epoll_wait() " - "failed -- aborting!\n"); - main_rv = -1; - goto done; - } - if (num_ev == 0) - { - fprintf (stderr, "\nSERVER: epoll_wait() timeout!\n"); - continue; - } - for (i = 0; i < num_ev; i++) - { - conn = &ssm->conn_pool[ssm->wait_events[i].data.u32]; - if (ssm->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP)) - { -#ifdef VCL_TEST - vppcom_session_close (conn->fd); -#else - close (conn->fd); -#endif - continue; - } - if (ssm->wait_events[i].data.u32 == ~0) - { - new_client (); - continue; - } -#if !defined (VCL_TEST) - else if (ssm->wait_events[i].data.u32 == - SOCK_TEST_AF_UNIX_ACCEPT_DATA) - { - af_unix_echo (); - continue; - } -#endif -#endif - client_fd = conn->fd; - -#if ! SOCK_SERVER_USE_EPOLL - if (FD_ISSET (client_fd, rfdset)) -#else - if (EPOLLIN & ssm->wait_events[i].events) -#endif - { - read_again: - rx_bytes = sock_test_read (client_fd, conn->buf, - conn->buf_size, &conn->stats); - if (rx_bytes > 0) - { - rx_cfg = (vcl_test_cfg_t *) conn->buf; - if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC) - { - if (rx_cfg->verbose) - { - printf ("SERVER (fd %d): Received a cfg message!\n", - client_fd); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - } - - if (rx_bytes != sizeof (*rx_cfg)) - { - printf ("SERVER (fd %d): Invalid cfg message " - "size (%d)!\n Should be %lu bytes.\n", - client_fd, rx_bytes, sizeof (*rx_cfg)); - conn->cfg.rxbuf_size = 0; - conn->cfg.num_writes = 0; - if (conn->cfg.verbose) - { - printf ("SERVER (fd %d): Replying to " - "cfg message!\n", client_fd); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - } - sock_test_write (client_fd, (uint8_t *) & conn->cfg, - sizeof (conn->cfg), NULL, - conn->cfg.verbose); - continue; - } - - switch (rx_cfg->test) - { - case VCL_TEST_TYPE_NONE: - case VCL_TEST_TYPE_ECHO: - sync_config_and_reply (conn, rx_cfg); - break; - - case VCL_TEST_TYPE_BI: - case VCL_TEST_TYPE_UNI: - stream_test_server_start_stop (conn, rx_cfg); - break; - - case VCL_TEST_TYPE_EXIT: - printf ("SERVER: Have a great day, " - "connection %d!\n", client_fd); -#ifdef VCL_TEST - vppcom_session_close (client_fd); -#else - close (client_fd); -#endif - conn_pool_free (conn); - printf ("SERVER: Closed client fd %d\n", client_fd); -#if ! SOCK_SERVER_USE_EPOLL - if (ssm->nfds == (ssm->listen_fd + 1)) -#else - ssm->nfds--; - if (!ssm->nfds) -#endif - { - printf ("SERVER: All client connections " - "closed.\n\nSERVER: " - "May the force be with you!\n\n"); - goto done; - } - break; - - default: - fprintf (stderr, - "SERVER: ERROR: Unknown test type!\n"); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - break; - } - continue; - } - - else if ((conn->cfg.test == VCL_TEST_TYPE_UNI) || - (conn->cfg.test == VCL_TEST_TYPE_BI)) - { - stream_test_server (conn, rx_bytes); - if (ioctl (conn->fd, FIONREAD)) - goto read_again; - continue; - } - - else if (isascii (conn->buf[0])) - { - // If it looks vaguely like a string, make sure it's terminated - ((char *) conn->buf)[rx_bytes < - conn->buf_size ? rx_bytes : - conn->buf_size - 1] = 0; - printf ("SERVER (fd %d): RX (%d bytes) - '%s'\n", - conn->fd, rx_bytes, conn->buf); - } - } - else // rx_bytes < 0 - { - if (errno == ECONNRESET) - { - printf ("\nSERVER: Connection reset by remote peer.\n" - " Y'all have a great day now!\n\n"); - break; - } - else - continue; - } - - if (isascii (conn->buf[0])) - { - /* If it looks vaguely like a string, - * make sure it's terminated - */ - ((char *) conn->buf)[rx_bytes < - conn->buf_size ? rx_bytes : - conn->buf_size - 1] = 0; - if (xtra) - fprintf (stderr, "SERVER: ERROR: " - "FIFO not drained in previous test!\n" - " extra chunks %u (0x%x)\n" - " extra bytes %lu (0x%lx)\n", - xtra, xtra, xtra_bytes, xtra_bytes); - - xtra = 0; - xtra_bytes = 0; - - if (conn->cfg.verbose) - printf ("SERVER (fd %d): Echoing back\n", client_fd); - - nbytes = strlen ((const char *) conn->buf) + 1; - - tx_bytes = sock_test_write (client_fd, conn->buf, - nbytes, &conn->stats, - conn->cfg.verbose); - if (tx_bytes >= 0) - printf ("SERVER (fd %d): TX (%d bytes) - '%s'\n", - conn->fd, tx_bytes, conn->buf); - } - - else // Extraneous read data from non-echo tests??? - { - xtra++; - xtra_bytes += rx_bytes; - } - } - } - } - -done: -#ifdef VCL_TEST - vppcom_session_close (ssm->listen_fd); - vppcom_app_destroy (); -#else - close (ssm->listen_fd); - -#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) - close (ssm->af_unix_listen_fd); - unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME); -#endif /* SOCK_SERVER_USE_EPOLL */ - -#endif - if (ssm->conn_pool) - free (ssm->conn_pool); - - return main_rv; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcl_test.h b/src/vcl/vcl_test.h deleted file mode 100644 index ab05f7ae9cf..00000000000 --- a/src/vcl/vcl_test.h +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __vcl_test_h__ -#define __vcl_test_h__ - -#include <netdb.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <vcl/vppcom.h> - -#define vtfail(_fn, _rv) \ -{ \ - errno = -_rv; \ - perror ("ERROR when calling " _fn); \ - fprintf (stderr, "\nERROR: " _fn " failed (errno = %d)!\n", -_rv); \ - exit (1); \ -} - -#define vterr(_fn, _rv) \ -{ \ - errno = -_rv; \ - fprintf (stderr, "\nERROR: " _fn " failed (errno = %d)!\n", -_rv); \ -} - -#define vtwrn(_fmt, _args...) \ - fprintf (stderr, "\nERROR: " _fmt "\n", ##_args) \ - -#define vtinf(_fmt, _args...) \ - fprintf (stdout, "vt<w%u>: " _fmt "\n", __wrk_index, ##_args) - -#define vt_atomic_add(_ptr, _val) \ - __atomic_fetch_add (_ptr, _val, __ATOMIC_RELEASE) - -#define VCL_TEST_TOKEN_HELP "#H" -#define VCL_TEST_TOKEN_EXIT "#X" -#define VCL_TEST_TOKEN_VERBOSE "#V" -#define VCL_TEST_TOKEN_TXBUF_SIZE "#T:" -#define VCL_TEST_TOKEN_NUM_TEST_SESS "#I:" -#define VCL_TEST_TOKEN_NUM_WRITES "#N:" -#define VCL_TEST_TOKEN_RXBUF_SIZE "#R:" -#define VCL_TEST_TOKEN_SHOW_CFG "#C" -#define VCL_TEST_TOKEN_RUN_UNI "#U" -#define VCL_TEST_TOKEN_RUN_BI "#B" - -#define VCL_TEST_SERVER_PORT 22000 -#define VCL_TEST_LOCALHOST_IPADDR "127.0.0.1" - -#define VCL_TEST_CFG_CTRL_MAGIC 0xfeedface -#define VCL_TEST_CFG_NUM_WRITES_DEF 1000000 -#define VCL_TEST_CFG_TXBUF_SIZE_DEF 8192 -#define VCL_TEST_CFG_RXBUF_SIZE_DEF (64*VCL_TEST_CFG_TXBUF_SIZE_DEF) -#define VCL_TEST_CFG_BUF_SIZE_MIN 128 -#define VCL_TEST_CFG_MAX_TEST_SESS 32 -#define VCL_TEST_CFG_MAX_EPOLL_EVENTS 16 - -#define VCL_TEST_DELAY_DISCONNECT 1 -#define VCL_TEST_SEPARATOR_STRING \ - " -----------------------------\n" -typedef enum -{ - VCL_TEST_TYPE_NONE, - VCL_TEST_TYPE_ECHO, - VCL_TEST_TYPE_UNI, - VCL_TEST_TYPE_BI, - VCL_TEST_TYPE_EXIT, -} vcl_test_t; - -typedef struct __attribute__ ((packed)) -{ - uint32_t magic; - uint32_t seq_num; - uint32_t test; - uint32_t ctrl_handle; - uint32_t num_test_sessions; - uint32_t verbose; - uint32_t address_ip6; - uint32_t transport_udp; - uint32_t transport_tls; - uint64_t rxbuf_size; - uint64_t txbuf_size; - uint64_t num_writes; - uint64_t total_bytes; -} vcl_test_cfg_t; - -typedef struct -{ - uint64_t rx_xacts; - uint64_t rx_bytes; - uint32_t rx_eagain; - uint32_t rx_incomp; - uint64_t tx_xacts; - uint64_t tx_bytes; - uint32_t tx_eagain; - uint32_t tx_incomp; - struct timespec start; - struct timespec stop; -} vcl_test_stats_t; - -typedef struct -{ - int fd; - uint32_t txbuf_size; - char *txbuf; - uint32_t rxbuf_size; - char *rxbuf; - vcl_test_cfg_t cfg; - vcl_test_stats_t stats; -} vcl_test_session_t; - - -/* - * TLS server cert and keys to be used for testing only - */ -char vcl_test_crt_rsa[] = - "-----BEGIN CERTIFICATE-----\r\n" - "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n" - "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n" - "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n" - "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n" - "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n" - "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n" - "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n" - "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n" - "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n" - "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n" - "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n" - "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n" - "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n" - "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n" - "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n" - "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n" - "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n" - "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n" - "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n" - "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n" - "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n" - "-----END CERTIFICATE-----\r\n"; -uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa); - -char vcl_test_key_rsa[] = - "-----BEGIN PRIVATE KEY-----\r\n" - "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n" - "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n" - "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n" - "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n" - "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n" - "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n" - "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n" - "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n" - "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n" - "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n" - "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n" - "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n" - "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n" - "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n" - "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n" - "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n" - "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n" - "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n" - "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n" - "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n" - "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n" - "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n" - "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n" - "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n" - "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n" - "oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n"; -uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa); - -static inline void -vcl_test_stats_accumulate (vcl_test_stats_t * accum, vcl_test_stats_t * incr) -{ - accum->rx_xacts += incr->rx_xacts; - accum->rx_bytes += incr->rx_bytes; - accum->rx_eagain += incr->rx_eagain; - accum->rx_incomp += incr->rx_incomp; - accum->tx_xacts += incr->tx_xacts; - accum->tx_bytes += incr->tx_bytes; - accum->tx_eagain += incr->tx_eagain; - accum->tx_incomp += incr->tx_incomp; -} - -static inline void -vcl_test_cfg_init (vcl_test_cfg_t * cfg) -{ - cfg->magic = VCL_TEST_CFG_CTRL_MAGIC; - cfg->test = VCL_TEST_TYPE_NONE; - cfg->ctrl_handle = ~0; - cfg->num_test_sessions = 1; - cfg->verbose = 0; - cfg->rxbuf_size = VCL_TEST_CFG_RXBUF_SIZE_DEF; - cfg->num_writes = VCL_TEST_CFG_NUM_WRITES_DEF; - cfg->txbuf_size = VCL_TEST_CFG_TXBUF_SIZE_DEF; - cfg->total_bytes = cfg->num_writes * cfg->txbuf_size; -} - -static inline int -vcl_test_cfg_verify (vcl_test_cfg_t * cfg, vcl_test_cfg_t * valid_cfg) -{ - /* Note: txbuf & rxbuf on server are the same buffer, - * so txbuf_size is not included in this check. - */ - return ((cfg->magic == valid_cfg->magic) - && (cfg->test == valid_cfg->test) - && (cfg->verbose == valid_cfg->verbose) - && (cfg->rxbuf_size == valid_cfg->rxbuf_size) - && (cfg->num_writes == valid_cfg->num_writes) - && (cfg->total_bytes == valid_cfg->total_bytes)); -} - -static inline void -vcl_test_buf_alloc (vcl_test_cfg_t * cfg, uint8_t is_rxbuf, uint8_t ** buf, - uint32_t * bufsize) -{ - uint32_t alloc_size = is_rxbuf ? cfg->rxbuf_size : cfg->txbuf_size; - uint8_t *lb = realloc (*buf, (size_t) alloc_size); - - if (lb) - { - if (is_rxbuf) - cfg->rxbuf_size = *bufsize = alloc_size; - else - cfg->txbuf_size = *bufsize = alloc_size; - - *buf = lb; - } - else - { - vtwrn ("realloc failed. using buffer size %d instead of %u", - *bufsize, alloc_size); - } -} - -static inline void -vcl_test_session_buf_alloc (vcl_test_session_t * socket) -{ - socket->rxbuf_size = socket->cfg.rxbuf_size; - socket->txbuf_size = socket->cfg.txbuf_size; - vcl_test_buf_alloc (&socket->cfg, 0 /* is_rxbuf */ , - (uint8_t **) & socket->txbuf, &socket->txbuf_size); - vcl_test_buf_alloc (&socket->cfg, 1 /* is_rxbuf */ , - (uint8_t **) & socket->rxbuf, &socket->rxbuf_size); -} - -static inline char * -vcl_test_type_str (vcl_test_t t) -{ - switch (t) - { - case VCL_TEST_TYPE_NONE: - return "NONE"; - - case VCL_TEST_TYPE_ECHO: - return "ECHO"; - - case VCL_TEST_TYPE_UNI: - return "UNI"; - - case VCL_TEST_TYPE_BI: - return "BI"; - - case VCL_TEST_TYPE_EXIT: - return "EXIT"; - - default: - return "Unknown"; - } -} - -static inline void -vcl_test_cfg_dump (vcl_test_cfg_t * cfg, uint8_t is_client) -{ - char *spc = " "; - - printf (" test config (%p):\n" - VCL_TEST_SEPARATOR_STRING - " magic: 0x%08x\n" - " seq_num: 0x%08x\n" - "%-5s test: %s (%d)\n" - " ctrl handle: %d (0x%x)\n" - "%-5s num test sockets: %u (0x%08x)\n" - "%-5s verbose: %s (%d)\n" - "%-5s rxbuf size: %lu (0x%08lx)\n" - "%-5s txbuf size: %lu (0x%08lx)\n" - "%-5s num writes: %lu (0x%08lx)\n" - " client tx bytes: %lu (0x%08lx)\n" - VCL_TEST_SEPARATOR_STRING, - (void *) cfg, cfg->magic, cfg->seq_num, - is_client && (cfg->test == VCL_TEST_TYPE_UNI) ? - "'" VCL_TEST_TOKEN_RUN_UNI "'" : - is_client && (cfg->test == VCL_TEST_TYPE_BI) ? - "'" VCL_TEST_TOKEN_RUN_BI "'" : spc, - vcl_test_type_str (cfg->test), cfg->test, - cfg->ctrl_handle, cfg->ctrl_handle, - is_client ? "'" VCL_TEST_TOKEN_NUM_TEST_SESS "'" : spc, - cfg->num_test_sessions, cfg->num_test_sessions, - is_client ? "'" VCL_TEST_TOKEN_VERBOSE "'" : spc, - cfg->verbose ? "on" : "off", cfg->verbose, - is_client ? "'" VCL_TEST_TOKEN_RXBUF_SIZE "'" : spc, - cfg->rxbuf_size, cfg->rxbuf_size, - is_client ? "'" VCL_TEST_TOKEN_TXBUF_SIZE "'" : spc, - cfg->txbuf_size, cfg->txbuf_size, - is_client ? "'" VCL_TEST_TOKEN_NUM_WRITES "'" : spc, - cfg->num_writes, cfg->num_writes, - cfg->total_bytes, cfg->total_bytes); -} - -static inline void -vcl_test_stats_dump (char *header, vcl_test_stats_t * stats, - uint8_t show_rx, uint8_t show_tx, uint8_t verbose) -{ - struct timespec diff; - double duration, rate; - uint64_t total_bytes; - - if ((stats->stop.tv_nsec - stats->start.tv_nsec) < 0) - { - diff.tv_sec = stats->stop.tv_sec - stats->start.tv_sec - 1; - diff.tv_nsec = stats->stop.tv_nsec - stats->start.tv_nsec + 1e9; - } - else - { - diff.tv_sec = stats->stop.tv_sec - stats->start.tv_sec; - diff.tv_nsec = stats->stop.tv_nsec - stats->start.tv_nsec; - } - duration = (double) diff.tv_sec + (1e-9 * diff.tv_nsec); - - total_bytes = stats->tx_bytes + stats->rx_bytes; - rate = (double) total_bytes *8 / duration / 1e9; - printf ("\n%s: Streamed %lu bytes\n" - " in %lf seconds (%lf Gbps %s-duplex)!\n", - header, total_bytes, duration, rate, - (show_rx && show_tx) ? "full" : "half"); - - if (show_tx) - { - printf (VCL_TEST_SEPARATOR_STRING - " tx stats (0x%p):\n" - VCL_TEST_SEPARATOR_STRING - " writes: %lu (0x%08lx)\n" - " tx bytes: %lu (0x%08lx)\n" - " tx eagain: %u (0x%08x)\n" - " tx incomplete: %u (0x%08x)\n", - (void *) stats, stats->tx_xacts, stats->tx_xacts, - stats->tx_bytes, stats->tx_bytes, - stats->tx_eagain, stats->tx_eagain, - stats->tx_incomp, stats->tx_incomp); - } - if (show_rx) - { - printf (VCL_TEST_SEPARATOR_STRING - " rx stats (0x%p):\n" - VCL_TEST_SEPARATOR_STRING - " reads: %lu (0x%08lx)\n" - " rx bytes: %lu (0x%08lx)\n" - " rx eagain: %u (0x%08x)\n" - " rx incomplete: %u (0x%08x)\n", - (void *) stats, stats->rx_xacts, stats->rx_xacts, - stats->rx_bytes, stats->rx_bytes, - stats->rx_eagain, stats->rx_eagain, - stats->rx_incomp, stats->rx_incomp); - } - if (verbose) - printf (" start.tv_sec: %ld\n" - " start.tv_nsec: %ld\n" - " stop.tv_sec: %ld\n" - " stop.tv_nsec: %ld\n", - stats->start.tv_sec, stats->start.tv_nsec, - stats->stop.tv_sec, stats->stop.tv_nsec); - - printf (VCL_TEST_SEPARATOR_STRING); -} - -static inline int -vcl_comp_tspec (struct timespec *a, struct timespec *b) -{ - if (a->tv_sec < b->tv_sec) - return -1; - else if (a->tv_sec > b->tv_sec) - return 1; - else if (a->tv_nsec < b->tv_nsec) - return -1; - else if (a->tv_nsec > b->tv_nsec) - return 1; - else - return 0; -} - -static inline int -vcl_test_read (int fd, uint8_t * buf, uint32_t nbytes, - vcl_test_stats_t * stats) -{ - int rx_bytes; - - do - { - if (stats) - stats->rx_xacts++; - rx_bytes = vppcom_session_read (fd, buf, nbytes); - - if (rx_bytes < 0) - { - errno = -rx_bytes; - rx_bytes = -1; - } - if (stats) - { - if ((rx_bytes == 0) || - ((rx_bytes < 0) - && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))) - stats->rx_eagain++; - else if (rx_bytes < nbytes) - stats->rx_incomp++; - } - } - while ((rx_bytes == 0) || - ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))); - - if (rx_bytes < 0) - { - vterr ("vppcom_session_read()", -errno); - } - else if (stats) - stats->rx_bytes += rx_bytes; - - return (rx_bytes); -} - -static inline int -vcl_test_read_ds (int fd, vppcom_data_segments_t ds, vcl_test_stats_t * stats) -{ - int rx_bytes; - - do - { - if (stats) - stats->rx_xacts++; - rx_bytes = vppcom_session_read_segments (fd, ds); - - if (rx_bytes < 0) - { - errno = -rx_bytes; - rx_bytes = -1; - } - if (stats) - { - if ((rx_bytes == 0) || - ((rx_bytes < 0) - && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))) - stats->rx_eagain++; - } - } - while ((rx_bytes == 0) || - ((rx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))); - - if (rx_bytes < 0) - { - vterr ("vppcom_session_read()", -errno); - } - else if (stats) - stats->rx_bytes += rx_bytes; - - return (rx_bytes); -} - -static inline int -vcl_test_write (int fd, uint8_t * buf, uint32_t nbytes, - vcl_test_stats_t * stats, uint32_t verbose) -{ - int tx_bytes = 0, nbytes_left = nbytes, rv; - - do - { - if (stats) - stats->tx_xacts++; - rv = vppcom_session_write (fd, buf, nbytes_left); - if (rv < 0) - { - errno = -rv; - rv = -1; - } - if (rv < 0) - { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) - { - if (stats) - stats->tx_eagain++; - break; - } - else - break; - } - tx_bytes += rv; - - if (tx_bytes != nbytes) - { - nbytes_left = nbytes_left - rv; - buf += rv; - if (stats) - stats->tx_incomp++; - } - - } - while (tx_bytes != nbytes); - - if (tx_bytes < 0) - { - vterr ("vpcom_session_write", -errno); - } - else if (stats) - stats->tx_bytes += tx_bytes; - - return (tx_bytes); -} - -#endif /* __vcl_test_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcl_test_client.c b/src/vcl/vcl_test_client.c deleted file mode 100644 index 42476ffbe01..00000000000 --- a/src/vcl/vcl_test_client.c +++ /dev/null @@ -1,1097 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <unistd.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <time.h> -#include <arpa/inet.h> -#include <vcl/vcl_test.h> -#include <pthread.h> - -typedef struct -{ - vcl_test_session_t *sessions; - uint32_t n_sessions; - uint32_t wrk_index; - fd_set wr_fdset; - fd_set rd_fdset; - int max_fd_index; - pthread_t thread_handle; - vcl_test_cfg_t cfg; -} vcl_test_client_worker_t; - -typedef struct -{ - vcl_test_client_worker_t *workers; - vppcom_endpt_t server_endpt; - uint32_t cfg_seq_num; - vcl_test_session_t ctrl_session; - vcl_test_session_t *sessions; - uint8_t dump_cfg; - vcl_test_t post_test; - uint32_t proto; - uint32_t n_workers; - volatile int active_workers; - struct sockaddr_storage server_addr; -} vcl_test_client_main_t; - -static __thread int __wrk_index = 0; - -vcl_test_client_main_t vcl_client_main; - -#define vtc_min(a, b) (a < b ? a : b) -#define vtc_max(a, b) (a > b ? a : b) - -static int -vtc_cfg_sync (vcl_test_session_t * ts) -{ - vcl_test_cfg_t *rx_cfg = (vcl_test_cfg_t *) ts->rxbuf; - int rx_bytes, tx_bytes; - - vt_atomic_add (&ts->cfg.seq_num, 1); - if (ts->cfg.verbose) - { - vtinf ("(fd %d): Sending config to server.", ts->fd); - vcl_test_cfg_dump (&ts->cfg, 1 /* is_client */ ); - } - tx_bytes = vcl_test_write (ts->fd, (uint8_t *) & ts->cfg, - sizeof (ts->cfg), NULL, ts->cfg.verbose); - if (tx_bytes < 0) - { - vtwrn ("(fd %d): write test cfg failed (%d)!", ts->fd, tx_bytes); - return tx_bytes; - } - - rx_bytes = vcl_test_read (ts->fd, (uint8_t *) ts->rxbuf, - sizeof (vcl_test_cfg_t), NULL); - if (rx_bytes < 0) - return rx_bytes; - - if (rx_cfg->magic != VCL_TEST_CFG_CTRL_MAGIC) - { - vtwrn ("(fd %d): Bad server reply cfg -- aborting!", ts->fd); - return -1; - } - if ((rx_bytes != sizeof (vcl_test_cfg_t)) - || !vcl_test_cfg_verify (rx_cfg, &ts->cfg)) - { - vtwrn ("(fd %d): Invalid config received from server!", ts->fd); - if (rx_bytes != sizeof (vcl_test_cfg_t)) - { - vtinf ("\tRx bytes %d != cfg size %lu", rx_bytes, - sizeof (vcl_test_cfg_t)); - } - else - { - vcl_test_cfg_dump (rx_cfg, 1 /* is_client */ ); - vtinf ("(fd %d): Valid config sent to server.", ts->fd); - vcl_test_cfg_dump (&ts->cfg, 1 /* is_client */ ); - } - return -1; - } - if (ts->cfg.verbose) - { - vtinf ("(fd %d): Got config back from server.", ts->fd); - vcl_test_cfg_dump (rx_cfg, 1 /* is_client */ ); - } - - return 0; -} - -static int -vtc_connect_test_sessions (vcl_test_client_worker_t * wrk) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ts; - uint32_t n_test_sessions; - int i, rv; - - n_test_sessions = wrk->cfg.num_test_sessions; - if (n_test_sessions < 1) - { - errno = EINVAL; - return -1; - } - - if (wrk->n_sessions >= n_test_sessions) - goto done; - - if (wrk->n_sessions) - wrk->sessions = realloc (wrk->sessions, - n_test_sessions * sizeof (vcl_test_session_t)); - else - wrk->sessions = calloc (n_test_sessions, sizeof (vcl_test_session_t)); - - if (!wrk->sessions) - { - vterr ("failed to alloc sessions", -errno); - return errno; - } - - for (i = 0; i < n_test_sessions; i++) - { - ts = &wrk->sessions[i]; - ts->fd = vppcom_session_create (vcm->proto, 1 /* is_nonblocking */ ); - if (ts->fd < 0) - { - vterr ("vppcom_session_create()", ts->fd); - return ts->fd; - } - - rv = vppcom_session_connect (ts->fd, &vcm->server_endpt); - if (rv < 0) - { - vterr ("vppcom_session_connect()", rv); - return rv; - } - vtinf ("Test session %d (fd %d) connected.", i, ts->fd); - } - wrk->n_sessions = n_test_sessions; - -done: - vtinf ("All test sessions (%d) connected!", n_test_sessions); - return 0; -} - -static int -vtc_worker_test_setup (vcl_test_client_worker_t * wrk) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_cfg_t *cfg = &wrk->cfg; - vcl_test_session_t *ts; - uint32_t sidx; - int i, j; - - FD_ZERO (&wrk->wr_fdset); - FD_ZERO (&wrk->rd_fdset); - - for (i = 0; i < cfg->num_test_sessions; i++) - { - ts = &wrk->sessions[i]; - ts->cfg = wrk->cfg; - vcl_test_session_buf_alloc (ts); - - switch (cfg->test) - { - case VCL_TEST_TYPE_ECHO: - memcpy (ts->txbuf, ctrl->txbuf, cfg->total_bytes); - break; - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - for (j = 0; j < ts->txbuf_size; j++) - ts->txbuf[j] = j & 0xff; - break; - } - - FD_SET (vppcom_session_index (ts->fd), &wrk->wr_fdset); - FD_SET (vppcom_session_index (ts->fd), &wrk->rd_fdset); - sidx = vppcom_session_index (ts->fd); - wrk->max_fd_index = vtc_max (sidx, wrk->max_fd_index); - } - wrk->max_fd_index += 1; - - return 0; -} - -static int -vtc_worker_init (vcl_test_client_worker_t * wrk) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_cfg_t *cfg = &wrk->cfg; - vcl_test_session_t *ts; - uint32_t n; - int rv; - - __wrk_index = wrk->wrk_index; - - vtinf ("Initializing worker %u ...", wrk->wrk_index); - - if (wrk->wrk_index) - { - if (vppcom_worker_register ()) - { - vtwrn ("failed to register worker"); - return -1; - } - vt_atomic_add (&vcm->active_workers, 1); - } - rv = vtc_connect_test_sessions (wrk); - if (rv) - { - vterr ("vtc_connect_test_sessions ()", rv); - return rv; - } - - if (vtc_worker_test_setup (wrk)) - return -1; - - vtinf ("Sending config to server on all sessions ..."); - - for (n = 0; n < cfg->num_test_sessions; n++) - { - ts = &wrk->sessions[n]; - if (vtc_cfg_sync (ts)) - return -1; - memset (&ts->stats, 0, sizeof (ts->stats)); - } - - return 0; -} - -static int stats_lock = 0; - -static void -vtc_accumulate_stats (vcl_test_client_worker_t * wrk, - vcl_test_session_t * ctrl) -{ - vcl_test_session_t *ts; - static char buf[64]; - int i, show_rx = 0; - - while (__sync_lock_test_and_set (&stats_lock, 1)) - ; - - if (ctrl->cfg.test == VCL_TEST_TYPE_BI - || ctrl->cfg.test == VCL_TEST_TYPE_ECHO) - show_rx = 1; - - for (i = 0; i < wrk->cfg.num_test_sessions; i++) - { - ts = &wrk->sessions[i]; - ts->stats.start = ctrl->stats.start; - - if (ctrl->cfg.verbose > 1) - { - sprintf (buf, "CLIENT (fd %d) RESULTS", ts->fd); - vcl_test_stats_dump (buf, &ts->stats, show_rx, 1 /* show tx */ , - ctrl->cfg.verbose); - } - - vcl_test_stats_accumulate (&ctrl->stats, &ts->stats); - if (vcl_comp_tspec (&ctrl->stats.stop, &ts->stats.stop) < 0) - ctrl->stats.stop = ts->stats.stop; - } - - __sync_lock_release (&stats_lock); -} - -static void -vtc_worker_sessions_exit (vcl_test_client_worker_t * wrk) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_session_t *ts; - int i, verbose = ctrl->cfg.verbose; - - for (i = 0; i < wrk->cfg.num_test_sessions; i++) - { - ts = &wrk->sessions[i]; - ts->cfg.test = VCL_TEST_TYPE_EXIT; - - if (verbose) - { - vtinf ("(fd %d): Sending exit cfg to server...", ts->fd); - vcl_test_cfg_dump (&ts->cfg, 1 /* is_client */ ); - } - (void) vcl_test_write (ts->fd, (uint8_t *) & ts->cfg, - sizeof (ts->cfg), &ts->stats, verbose); - } - wrk->n_sessions = 0; -} - -static void * -vtc_worker_loop (void *arg) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_client_worker_t *wrk = arg; - uint32_t n_active_sessions, n_bytes; - fd_set _wfdset, *wfdset = &_wfdset; - fd_set _rfdset, *rfdset = &_rfdset; - vcl_test_session_t *ts; - int i, rv, check_rx = 0; - - rv = vtc_worker_init (wrk); - if (rv) - { - vterr ("vtc_worker_init()", rv); - return 0; - } - - vtinf ("Starting test ..."); - - if (wrk->wrk_index == 0) - clock_gettime (CLOCK_REALTIME, &ctrl->stats.start); - - check_rx = wrk->cfg.test != VCL_TEST_TYPE_UNI; - n_active_sessions = wrk->cfg.num_test_sessions; - while (n_active_sessions) - { - _wfdset = wrk->wr_fdset; - _rfdset = wrk->rd_fdset; - - rv = vppcom_select (wrk->max_fd_index, (unsigned long *) rfdset, - (unsigned long *) wfdset, NULL, 0); - if (rv < 0) - { - vterr ("vppcom_select()", rv); - goto exit; - } - else if (rv == 0) - continue; - - for (i = 0; i < wrk->cfg.num_test_sessions; i++) - { - ts = &wrk->sessions[i]; - if (!((ts->stats.stop.tv_sec == 0) && - (ts->stats.stop.tv_nsec == 0))) - continue; - - if (FD_ISSET (vppcom_session_index (ts->fd), rfdset) - && ts->stats.rx_bytes < ts->cfg.total_bytes) - { - (void) vcl_test_read (ts->fd, (uint8_t *) ts->rxbuf, - ts->rxbuf_size, &ts->stats); - } - - if (FD_ISSET (vppcom_session_index (ts->fd), wfdset) - && ts->stats.tx_bytes < ts->cfg.total_bytes) - { - n_bytes = ts->cfg.txbuf_size; - if (ts->cfg.test == VCL_TEST_TYPE_ECHO) - n_bytes = strlen (ctrl->txbuf) + 1; - rv = vcl_test_write (ts->fd, (uint8_t *) ts->txbuf, - n_bytes, &ts->stats, ts->cfg.verbose); - if (rv < 0) - { - vtwrn ("vppcom_test_write (%d) failed -- aborting test", - ts->fd); - goto exit; - } - } - - if ((!check_rx && ts->stats.tx_bytes >= ts->cfg.total_bytes) - || (check_rx && ts->stats.rx_bytes >= ts->cfg.total_bytes)) - { - clock_gettime (CLOCK_REALTIME, &ts->stats.stop); - n_active_sessions--; - } - } - } -exit: - vtinf ("Worker %d done ...", wrk->wrk_index); - if (wrk->cfg.test != VCL_TEST_TYPE_ECHO) - vtc_accumulate_stats (wrk, ctrl); - sleep (VCL_TEST_DELAY_DISCONNECT); - vtc_worker_sessions_exit (wrk); - if (wrk->wrk_index) - vt_atomic_add (&vcm->active_workers, -1); - return 0; -} - -static void -vtc_print_stats (vcl_test_session_t * ctrl) -{ - int is_echo = ctrl->cfg.test == VCL_TEST_TYPE_ECHO; - int show_rx = 0; - char buf[64]; - - if (ctrl->cfg.test == VCL_TEST_TYPE_BI - || ctrl->cfg.test == VCL_TEST_TYPE_ECHO) - show_rx = 1; - - vcl_test_stats_dump ("CLIENT RESULTS", &ctrl->stats, - show_rx, 1 /* show tx */ , - ctrl->cfg.verbose); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - - if (ctrl->cfg.verbose) - { - vtinf (" ctrl session info\n" - VCL_TEST_SEPARATOR_STRING - " fd: %d (0x%08x)\n" - " rxbuf: %p\n" - " rxbuf size: %u (0x%08x)\n" - " txbuf: %p\n" - " txbuf size: %u (0x%08x)\n" - VCL_TEST_SEPARATOR_STRING, - ctrl->fd, (uint32_t) ctrl->fd, - ctrl->rxbuf, ctrl->rxbuf_size, ctrl->rxbuf_size, - ctrl->txbuf, ctrl->txbuf_size, ctrl->txbuf_size); - } - - if (is_echo) - sprintf (buf, "Echo"); - else - sprintf (buf, "%s-directional Stream", - ctrl->cfg.test == VCL_TEST_TYPE_BI ? "Bi" : "Uni"); -} - -static void -vtc_echo_client (vcl_test_client_main_t * vcm) -{ - vcl_test_client_worker_t *wrk; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_cfg_t *cfg = &ctrl->cfg; - - cfg->total_bytes = strlen (ctrl->txbuf) + 1; - memset (&ctrl->stats, 0, sizeof (ctrl->stats)); - - /* Echo works with only one worker */ - wrk = vcm->workers; - wrk->wrk_index = 0; - wrk->cfg = *cfg; - - vtc_worker_loop (wrk); - - /* Not relevant for echo test - clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop); - vtc_accumulate_stats (wrk, ctrl); - vtc_print_stats (ctrl); - */ -} - -static void -vtc_stream_client (vcl_test_client_main_t * vcm) -{ - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_cfg_t *cfg = &ctrl->cfg; - vcl_test_client_worker_t *wrk; - uint32_t i, n_conn, n_conn_per_wrk; - - vtinf ("%s-directional Stream Test Starting!", - ctrl->cfg.test == VCL_TEST_TYPE_BI ? "Bi" : "Uni"); - - cfg->total_bytes = cfg->num_writes * cfg->txbuf_size; - cfg->ctrl_handle = ~0; - if (vtc_cfg_sync (ctrl)) - { - vtwrn ("test cfg sync failed -- aborting!"); - return; - } - cfg->ctrl_handle = ((vcl_test_cfg_t *) ctrl->rxbuf)->ctrl_handle; - memset (&ctrl->stats, 0, sizeof (ctrl->stats)); - - n_conn = cfg->num_test_sessions; - n_conn_per_wrk = n_conn / vcm->n_workers; - for (i = 0; i < vcm->n_workers; i++) - { - wrk = &vcm->workers[i]; - wrk->wrk_index = i; - wrk->cfg = ctrl->cfg; - wrk->cfg.num_test_sessions = vtc_min (n_conn_per_wrk, n_conn); - n_conn -= wrk->cfg.num_test_sessions; - } - - for (i = 1; i < vcm->n_workers; i++) - { - wrk = &vcm->workers[i]; - pthread_create (&wrk->thread_handle, NULL, vtc_worker_loop, - (void *) wrk); - } - vtc_worker_loop (&vcm->workers[0]); - - while (vcm->active_workers > 0) - ; - - vtinf ("Sending config on ctrl session (fd %d) for stats...", ctrl->fd); - if (vtc_cfg_sync (ctrl)) - { - vtwrn ("test cfg sync failed -- aborting!"); - return; - } - - vtc_print_stats (ctrl); - - ctrl->cfg.test = VCL_TEST_TYPE_ECHO; - ctrl->cfg.total_bytes = 0; - if (vtc_cfg_sync (ctrl)) - vtwrn ("post-test cfg sync failed!"); -} - -static void -dump_help (void) -{ -#define INDENT "\n " - - printf ("CLIENT: Test configuration commands:" - INDENT VCL_TEST_TOKEN_HELP - "\t\t\tDisplay help." - INDENT VCL_TEST_TOKEN_EXIT - "\t\t\tExit test client & server." - INDENT VCL_TEST_TOKEN_SHOW_CFG - "\t\t\tShow the current test cfg." - INDENT VCL_TEST_TOKEN_RUN_UNI - "\t\t\tRun the Uni-directional test." - INDENT VCL_TEST_TOKEN_RUN_BI - "\t\t\tRun the Bi-directional test." - INDENT VCL_TEST_TOKEN_VERBOSE - "\t\t\tToggle verbose setting." - INDENT VCL_TEST_TOKEN_RXBUF_SIZE - "<rxbuf size>\tRx buffer size (bytes)." - INDENT VCL_TEST_TOKEN_TXBUF_SIZE - "<txbuf size>\tTx buffer size (bytes)." - INDENT VCL_TEST_TOKEN_NUM_WRITES - "<# of writes>\tNumber of txbuf writes to server." "\n"); -} - -static void -cfg_txbuf_size_set (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_TXBUF_SIZE); - uint64_t txbuf_size = strtoull ((const char *) p, NULL, 10); - - if (txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->cfg.txbuf_size = txbuf_size; - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ , - (uint8_t **) & ctrl->txbuf, &ctrl->txbuf_size); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - vtwrn ("Invalid txbuf size (%lu) < minimum buf size (%u)!", - txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); -} - -static void -cfg_num_writes_set (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_WRITES); - uint32_t num_writes = strtoul ((const char *) p, NULL, 10); - - if (num_writes > 0) - { - ctrl->cfg.num_writes = num_writes; - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - { - vtwrn ("invalid num writes: %u", num_writes); - } -} - -static void -cfg_num_test_sessions_set (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_TEST_SESS); - uint32_t num_test_sessions = strtoul ((const char *) p, NULL, 10); - - if ((num_test_sessions > 0) && - (num_test_sessions <= VCL_TEST_CFG_MAX_TEST_SESS)) - { - ctrl->cfg.num_test_sessions = num_test_sessions; - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - { - vtwrn ("invalid num test sessions: %u, (%d max)", - num_test_sessions, VCL_TEST_CFG_MAX_TEST_SESS); - } -} - -static void -cfg_rxbuf_size_set (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_RXBUF_SIZE); - uint64_t rxbuf_size = strtoull ((const char *) p, NULL, 10); - - if (rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->cfg.rxbuf_size = rxbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ , - (uint8_t **) & ctrl->rxbuf, &ctrl->rxbuf_size); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - else - vtwrn ("Invalid rxbuf size (%lu) < minimum buf size (%u)!", - rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); -} - -static void -cfg_verbose_toggle (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - - ctrl->cfg.verbose = ctrl->cfg.verbose ? 0 : 1; - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - -} - -static vcl_test_t -parse_input () -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - vcl_test_t rv = VCL_TEST_TYPE_NONE; - - if (!strncmp (VCL_TEST_TOKEN_EXIT, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_EXIT))) - rv = VCL_TEST_TYPE_EXIT; - - else if (!strncmp (VCL_TEST_TOKEN_HELP, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_HELP))) - dump_help (); - - else if (!strncmp (VCL_TEST_TOKEN_SHOW_CFG, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_SHOW_CFG))) - vcm->dump_cfg = 1; - - else if (!strncmp (VCL_TEST_TOKEN_VERBOSE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_VERBOSE))) - cfg_verbose_toggle (); - - else if (!strncmp (VCL_TEST_TOKEN_TXBUF_SIZE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_TXBUF_SIZE))) - cfg_txbuf_size_set (); - - else if (!strncmp (VCL_TEST_TOKEN_NUM_TEST_SESS, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_NUM_TEST_SESS))) - cfg_num_test_sessions_set (); - - else if (!strncmp (VCL_TEST_TOKEN_NUM_WRITES, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_NUM_WRITES))) - cfg_num_writes_set (); - - else if (!strncmp (VCL_TEST_TOKEN_RXBUF_SIZE, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RXBUF_SIZE))) - cfg_rxbuf_size_set (); - - else if (!strncmp (VCL_TEST_TOKEN_RUN_UNI, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RUN_UNI))) - rv = ctrl->cfg.test = VCL_TEST_TYPE_UNI; - - else if (!strncmp (VCL_TEST_TOKEN_RUN_BI, ctrl->txbuf, - strlen (VCL_TEST_TOKEN_RUN_BI))) - rv = ctrl->cfg.test = VCL_TEST_TYPE_BI; - - else - rv = VCL_TEST_TYPE_ECHO; - - return rv; -} - -void -print_usage_and_exit (void) -{ - fprintf (stderr, - "vcl_test_client [OPTIONS] <ipaddr> <port>\n" - " OPTIONS\n" - " -h Print this message and exit.\n" - " -6 Use IPv6\n" - " -c Print test config before test.\n" - " -w <dir> Write test results to <dir>.\n" - " -X Exit after running test.\n" - " -D Use UDP transport layer\n" - " -L Use TLS transport layer\n" - " -E Run Echo test.\n" - " -N <num-writes> Test Cfg: number of writes.\n" - " -R <rxbuf-size> Test Cfg: rx buffer size.\n" - " -T <txbuf-size> Test Cfg: tx buffer size.\n" - " -U Run Uni-directional test.\n" - " -B Run Bi-directional test.\n" - " -V Verbose mode.\n"); - exit (1); -} - -static void -vtc_process_opts (vcl_test_client_main_t * vcm, int argc, char **argv) -{ - vcl_test_session_t *ctrl = &vcm->ctrl_session; - int c, v; - - opterr = 0; - while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6DL")) != -1) - switch (c) - { - case 'c': - vcm->dump_cfg = 1; - break; - - case 's': - if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1) - if (sscanf (optarg, "%u", &ctrl->cfg.num_test_sessions) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - if (!ctrl->cfg.num_test_sessions || - (ctrl->cfg.num_test_sessions > FD_SETSIZE)) - { - vtwrn ("Invalid number of sessions (%d) specified for option -%c!" - "\n Valid range is 1 - %d", - ctrl->cfg.num_test_sessions, c, FD_SETSIZE); - print_usage_and_exit (); - } - break; - - case 'w': - if (sscanf (optarg, "%d", &v) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - if (v > 1) - vcm->n_workers = v; - break; - - case 'X': - vcm->post_test = VCL_TEST_TYPE_EXIT; - break; - - case 'E': - if (strlen (optarg) > ctrl->txbuf_size) - { - vtwrn ("Option -%c value larger than txbuf size (%d)!", - optopt, ctrl->txbuf_size); - print_usage_and_exit (); - } - strcpy (ctrl->txbuf, optarg); - ctrl->cfg.test = VCL_TEST_TYPE_ECHO; - break; - - case 'I': - if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1) - if (sscanf (optarg, "%d", &ctrl->cfg.num_test_sessions) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - if (ctrl->cfg.num_test_sessions > VCL_TEST_CFG_MAX_TEST_SESS) - { - vtwrn ("value greater than max number test sessions (%d)!", - VCL_TEST_CFG_MAX_TEST_SESS); - print_usage_and_exit (); - } - break; - - case 'N': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.num_writes) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.num_writes) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - break; - - case 'R': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.rxbuf_size) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.rxbuf_size) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - if (ctrl->cfg.rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->rxbuf_size = ctrl->cfg.rxbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ , - (uint8_t **) & ctrl->rxbuf, - &ctrl->rxbuf_size); - } - else - { - vtwrn ("rxbuf size (%lu) less than minumum (%u)", - ctrl->cfg.rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); - print_usage_and_exit (); - } - - break; - - case 'T': - if (sscanf (optarg, "0x%lx", &ctrl->cfg.txbuf_size) != 1) - if (sscanf (optarg, "%ld", &ctrl->cfg.txbuf_size) != 1) - { - vtwrn ("Invalid value for option -%c!", c); - print_usage_and_exit (); - } - if (ctrl->cfg.txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN) - { - ctrl->txbuf_size = ctrl->cfg.txbuf_size; - vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ , - (uint8_t **) & ctrl->txbuf, - &ctrl->txbuf_size); - ctrl->cfg.total_bytes = - ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; - } - else - { - vtwrn ("txbuf size (%lu) less than minumum (%u)!", - ctrl->cfg.txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN); - print_usage_and_exit (); - } - break; - - case 'U': - ctrl->cfg.test = VCL_TEST_TYPE_UNI; - break; - - case 'B': - ctrl->cfg.test = VCL_TEST_TYPE_BI; - break; - - case 'V': - ctrl->cfg.verbose = 1; - break; - - case '6': - ctrl->cfg.address_ip6 = 1; - break; - - case 'D': - ctrl->cfg.transport_udp = 1; - break; - - case 'L': - ctrl->cfg.transport_tls = 1; - break; - - case '?': - switch (optopt) - { - case 'E': - case 'I': - case 'N': - case 'R': - case 'T': - case 'w': - vtwrn ("Option -%c requires an argument.", optopt); - break; - - default: - if (isprint (optopt)) - vtwrn ("Unknown option `-%c'.", optopt); - else - vtwrn ("Unknown option character `\\x%x'.", optopt); - } - /* fall thru */ - case 'h': - default: - print_usage_and_exit (); - } - - if (argc < (optind + 2)) - { - vtwrn ("Insufficient number of arguments!"); - print_usage_and_exit (); - } - - if (ctrl->cfg.transport_udp) - { - vcm->proto = VPPCOM_PROTO_UDP; - } - else if (ctrl->cfg.transport_tls) - { - vcm->proto = VPPCOM_PROTO_TLS; - } - else - { - vcm->proto = VPPCOM_PROTO_TCP; - } - - memset (&vcm->server_addr, 0, sizeof (vcm->server_addr)); - if (ctrl->cfg.address_ip6) - { - struct sockaddr_in6 *sddr6 = (struct sockaddr_in6 *) &vcm->server_addr; - sddr6->sin6_family = AF_INET6; - inet_pton (AF_INET6, argv[optind++], &(sddr6->sin6_addr)); - sddr6->sin6_port = htons (atoi (argv[optind])); - - vcm->server_endpt.is_ip4 = 0; - vcm->server_endpt.ip = (uint8_t *) & sddr6->sin6_addr; - vcm->server_endpt.port = (uint16_t) sddr6->sin6_port; - } - else - { - struct sockaddr_in *saddr4 = (struct sockaddr_in *) &vcm->server_addr; - saddr4->sin_family = AF_INET; - inet_pton (AF_INET, argv[optind++], &(saddr4->sin_addr)); - saddr4->sin_port = htons (atoi (argv[optind])); - - vcm->server_endpt.is_ip4 = 1; - vcm->server_endpt.ip = (uint8_t *) & saddr4->sin_addr; - vcm->server_endpt.port = (uint16_t) saddr4->sin_port; - } -} - -static void -vtc_read_user_input (vcl_test_session_t * ctrl) -{ - printf ("\nType some characters and hit <return>\n" - "('" VCL_TEST_TOKEN_HELP "' for help): "); - - if (fgets (ctrl->txbuf, ctrl->txbuf_size, stdin) != NULL) - { - if (strlen (ctrl->txbuf) == 1) - { - printf ("\nNothing to send! Please try again...\n"); - return; - } - ctrl->txbuf[strlen (ctrl->txbuf) - 1] = 0; // chomp the newline. - - /* Parse input for keywords */ - ctrl->cfg.test = parse_input (); - } -} - -static void -vtc_ctrl_session_exit (void) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - int verbose = ctrl->cfg.verbose; - - ctrl->cfg.test = VCL_TEST_TYPE_EXIT; - if (verbose) - { - vtinf ("(fd %d): Sending exit cfg to server...", ctrl->fd); - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - } - (void) vcl_test_write (ctrl->fd, (uint8_t *) & ctrl->cfg, - sizeof (ctrl->cfg), &ctrl->stats, verbose); - sleep (1); -} - -int -main (int argc, char **argv) -{ - vcl_test_client_main_t *vcm = &vcl_client_main; - vcl_test_session_t *ctrl = &vcm->ctrl_session; - int rv; - - vcm->n_workers = 1; - vcl_test_cfg_init (&ctrl->cfg); - vcl_test_session_buf_alloc (ctrl); - vtc_process_opts (vcm, argc, argv); - - vcm->workers = calloc (vcm->n_workers, sizeof (vcl_test_client_worker_t)); - rv = vppcom_app_create ("vcl_test_client"); - if (rv < 0) - vtfail ("vppcom_app_create()", rv); - - ctrl->fd = vppcom_session_create (vcm->proto, 0 /* is_nonblocking */ ); - if (ctrl->fd < 0) - vtfail ("vppcom_session_create()", ctrl->fd); - - if (vcm->proto == VPPCOM_PROTO_TLS) - { - vtinf ("Adding tls certs ..."); - vppcom_session_tls_add_cert (ctrl->fd, vcl_test_crt_rsa, - vcl_test_crt_rsa_len); - vppcom_session_tls_add_key (ctrl->fd, vcl_test_key_rsa, - vcl_test_key_rsa_len); - } - - vtinf ("Connecting to server..."); - rv = vppcom_session_connect (ctrl->fd, &vcm->server_endpt); - if (rv) - vtfail ("vppcom_session_connect()", rv); - vtinf ("Control session (fd %d) connected.", ctrl->fd); - - rv = vtc_cfg_sync (ctrl); - if (rv) - vtfail ("vtc_cfg_sync()", rv); - - ctrl->cfg.ctrl_handle = ((vcl_test_cfg_t *) ctrl->rxbuf)->ctrl_handle; - memset (&ctrl->stats, 0, sizeof (ctrl->stats)); - - while (ctrl->cfg.test != VCL_TEST_TYPE_EXIT) - { - if (vcm->dump_cfg) - { - vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); - vcm->dump_cfg = 0; - } - - switch (ctrl->cfg.test) - { - case VCL_TEST_TYPE_ECHO: - vtc_echo_client (vcm); - break; - - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - vtc_stream_client (vcm); - break; - - case VCL_TEST_TYPE_EXIT: - continue; - - case VCL_TEST_TYPE_NONE: - default: - break; - } - switch (vcm->post_test) - { - case VCL_TEST_TYPE_EXIT: - switch (ctrl->cfg.test) - { - case VCL_TEST_TYPE_EXIT: - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - case VCL_TEST_TYPE_ECHO: - ctrl->cfg.test = VCL_TEST_TYPE_EXIT; - continue; - - case VCL_TEST_TYPE_NONE: - default: - break; - } - break; - - case VCL_TEST_TYPE_NONE: - case VCL_TEST_TYPE_ECHO: - case VCL_TEST_TYPE_UNI: - case VCL_TEST_TYPE_BI: - default: - break; - } - - memset (ctrl->txbuf, 0, ctrl->txbuf_size); - memset (ctrl->rxbuf, 0, ctrl->rxbuf_size); - - vtc_read_user_input (ctrl); - } - - vtc_ctrl_session_exit (); - vppcom_session_close (ctrl->fd); - vppcom_app_destroy (); - free (vcm->workers); - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcl_test_server.c b/src/vcl/vcl_test_server.c deleted file mode 100644 index 173bada2315..00000000000 --- a/src/vcl/vcl_test_server.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <unistd.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <ctype.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <vcl/vcl_test.h> -#include <sys/epoll.h> -#include <vppinfra/mem.h> -#include <pthread.h> - -typedef struct -{ - uint8_t is_alloc; - int fd; - uint8_t *buf; - uint32_t buf_size; - vcl_test_cfg_t cfg; - vcl_test_stats_t stats; - vppcom_endpt_t endpt; - uint8_t ip[16]; - vppcom_data_segments_t ds; -} vcl_test_server_conn_t; - -typedef struct -{ - uint16_t port; - uint32_t address_ip6; - u8 proto; - u8 workers; - vppcom_endpt_t endpt; -} vcl_test_server_cfg_t; - -typedef struct -{ - uint32_t wrk_index; - int listen_fd; - int epfd; - struct epoll_event wait_events[VCL_TEST_CFG_MAX_EPOLL_EVENTS]; - size_t conn_pool_size; - vcl_test_server_conn_t *conn_pool; - int nfds; - pthread_t thread_handle; -} vcl_test_server_worker_t; - -typedef struct -{ - vcl_test_server_cfg_t cfg; - vcl_test_server_worker_t *workers; - - 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 vcl_server_main; - -static inline void -conn_pool_expand (vcl_test_server_worker_t * wrk, size_t expand_size) -{ - vcl_test_server_conn_t *conn_pool; - size_t new_size = wrk->conn_pool_size + expand_size; - int i; - - conn_pool = realloc (wrk->conn_pool, new_size * sizeof (*wrk->conn_pool)); - if (conn_pool) - { - for (i = wrk->conn_pool_size; i < new_size; i++) - { - vcl_test_server_conn_t *conn = &conn_pool[i]; - memset (conn, 0, sizeof (*conn)); - vcl_test_cfg_init (&conn->cfg); - vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , - &conn->buf, &conn->buf_size); - conn->cfg.txbuf_size = conn->cfg.rxbuf_size; - } - - wrk->conn_pool = conn_pool; - wrk->conn_pool_size = new_size; - } - else - { - vterr ("conn_pool_expand()", -errno); - } -} - -static inline vcl_test_server_conn_t * -conn_pool_alloc (vcl_test_server_worker_t * wrk) -{ - int i, expand = 0; - -again: - for (i = 0; i < wrk->conn_pool_size; i++) - { - if (!wrk->conn_pool[i].is_alloc) - { - wrk->conn_pool[i].endpt.ip = wrk->conn_pool[i].ip; - wrk->conn_pool[i].is_alloc = 1; - return (&wrk->conn_pool[i]); - } - } - - 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; -} - -static inline void -conn_pool_free (vcl_test_server_conn_t * conn) -{ - conn->fd = 0; - conn->is_alloc = 0; -} - -static inline void -sync_config_and_reply (vcl_test_server_conn_t * conn, vcl_test_cfg_t * rx_cfg) -{ - conn->cfg = *rx_cfg; - vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , - &conn->buf, &conn->buf_size); - conn->cfg.txbuf_size = conn->cfg.rxbuf_size; - - if (conn->cfg.verbose) - { - vtinf ("(fd %d): Replying to cfg message!\n", conn->fd); - vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); - } - (void) vcl_test_write (conn->fd, (uint8_t *) & conn->cfg, - sizeof (conn->cfg), NULL, conn->cfg.verbose); -} - -static void -vts_server_start_stop (vcl_test_server_worker_t * wrk, - vcl_test_server_conn_t * conn, vcl_test_cfg_t * rx_cfg) -{ - u8 is_bi = rx_cfg->test == VCL_TEST_TYPE_BI; - vcl_test_server_conn_t *tc; - char buf[64]; - int i; - - if (rx_cfg->ctrl_handle == conn->fd) - { - for (i = 0; i < wrk->conn_pool_size; i++) - { - tc = &wrk->conn_pool[i]; - if (tc->cfg.ctrl_handle != conn->fd) - continue; - - vcl_test_stats_accumulate (&conn->stats, &tc->stats); - if (vcl_comp_tspec (&conn->stats.stop, &tc->stats.stop) < 0) - conn->stats.stop = tc->stats.stop; - /* Client delays sending of disconnect */ - conn->stats.stop.tv_sec -= VCL_TEST_DELAY_DISCONNECT; - if (conn->cfg.verbose) - { - sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd); - vcl_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ , - is_bi /* show tx */ , conn->cfg.verbose); - } - } - - vcl_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ , - is_bi /* show_tx */ , conn->cfg.verbose); - vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); - if (conn->cfg.verbose) - { - vtinf (" vcl server main\n" - VCL_TEST_SEPARATOR_STRING - " buf: %p\n" - " buf size: %u (0x%08x)\n" - VCL_TEST_SEPARATOR_STRING, - conn->buf, conn->buf_size, conn->buf_size); - } - - sync_config_and_reply (conn, rx_cfg); - memset (&conn->stats, 0, sizeof (conn->stats)); - } - else - { - if (rx_cfg->ctrl_handle == ~0) - { - rx_cfg->ctrl_handle = conn->fd; - vtinf ("Set control fd %d for test!", conn->fd); - } - else - { - vtinf ("Starting %s-directional Stream Test (fd %d)!", - is_bi ? "Bi" : "Uni", conn->fd); - } - - sync_config_and_reply (conn, rx_cfg); - - /* read the 1st chunk, record start time */ - memset (&conn->stats, 0, sizeof (conn->stats)); - clock_gettime (CLOCK_REALTIME, &conn->stats.start); - } -} - -static inline void -vts_server_rx (vcl_test_server_conn_t * conn, int rx_bytes) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - int client_fd = conn->fd; - - if (conn->cfg.test == VCL_TEST_TYPE_BI) - { - if (vsm->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 (vsm->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 -vts_server_echo (vcl_test_server_conn_t * conn, int rx_bytes) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - int tx_bytes, nbytes, pos; - - if (vsm->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); - - if (conn->cfg.verbose) - vtinf ("(fd %d): Echoing back", conn->fd); - - nbytes = strlen ((const char *) conn->buf) + 1; - tx_bytes = vcl_test_write (conn->fd, conn->buf, nbytes, &conn->stats, - conn->cfg.verbose); - if (tx_bytes >= 0) - vtinf ("(fd %d): TX (%d bytes) - '%s'", conn->fd, tx_bytes, conn->buf); -} - -static void -vts_new_client (vcl_test_server_worker_t * wrk) -{ - vcl_test_server_conn_t *conn; - struct epoll_event ev; - int rv, client_fd; - - conn = conn_pool_alloc (wrk); - if (!conn) - { - vtwrn ("No free connections!"); - return; - } - - client_fd = vppcom_session_accept (wrk->listen_fd, &conn->endpt, 0); - if (client_fd < 0) - { - vterr ("vppcom_session_accept()", client_fd); - return; - } - conn->fd = client_fd; - - vtinf ("Got a connection -- fd = %d (0x%08x)!", client_fd, client_fd); - - ev.events = EPOLLIN; - ev.data.u64 = conn - wrk->conn_pool; - rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, client_fd, &ev); - if (rv < 0) - { - vterr ("vppcom_epoll_ctl()", rv); - return; - } - wrk->nfds++; -} - -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" - " -D Use UDP transport layer\n" - " -L Use TLS transport layer\n"); - exit (1); -} - -static void -vcl_test_init_endpoint_addr (vcl_test_server_main_t * vsm) -{ - struct sockaddr_storage *servaddr = &vsm->servaddr; - memset (servaddr, 0, sizeof (*servaddr)); - - if (vsm->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) servaddr; - server_addr->sin6_family = AF_INET6; - server_addr->sin6_addr = in6addr_any; - server_addr->sin6_port = htons (vsm->cfg.port); - } - else - { - struct sockaddr_in *server_addr = (struct sockaddr_in *) servaddr; - server_addr->sin_family = AF_INET; - server_addr->sin_addr.s_addr = htonl (INADDR_ANY); - server_addr->sin_port = htons (vsm->cfg.port); - } - - if (vsm->cfg.address_ip6) - { - struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) servaddr; - vsm->cfg.endpt.is_ip4 = 0; - vsm->cfg.endpt.ip = (uint8_t *) & server_addr->sin6_addr; - vsm->cfg.endpt.port = (uint16_t) server_addr->sin6_port; - } - else - { - struct sockaddr_in *server_addr = (struct sockaddr_in *) servaddr; - vsm->cfg.endpt.is_ip4 = 1; - vsm->cfg.endpt.ip = (uint8_t *) & server_addr->sin_addr; - vsm->cfg.endpt.port = (uint16_t) server_addr->sin_port; - } -} - -static void -vcl_test_server_process_opts (vcl_test_server_main_t * vsm, int argc, - char **argv) -{ - int v, c; - - vsm->cfg.proto = VPPCOM_PROTO_TCP; - - opterr = 0; - while ((c = getopt (argc, argv, "6DLsw:")) != -1) - switch (c) - { - case '6': - vsm->cfg.address_ip6 = 1; - break; - - case 'D': - vsm->cfg.proto = VPPCOM_PROTO_UDP; - break; - - case 'L': - vsm->cfg.proto = VPPCOM_PROTO_TLS; - break; - - case 'w': - v = atoi (optarg); - if (v > 1) - vsm->cfg.workers = v; - else - vtwrn ("Invalid number of workers %d", v); - break; - case 's': - vsm->use_ds = 1; - break; - case '?': - switch (optopt) - { - default: - if (isprint (optopt)) - vtwrn ("Unknown option `-%c'.", optopt); - else - vtwrn ("Unknown option character `\\x%x'.", optopt); - } - /* fall thru */ - case 'h': - default: - print_usage_and_exit (); - } - - if (argc < (optind + 1)) - { - fprintf (stderr, "SERVER: ERROR: Insufficient number of arguments!\n"); - print_usage_and_exit (); - } - - if (sscanf (argv[optind], "%d", &v) == 1) - vsm->cfg.port = (uint16_t) v; - else - { - fprintf (stderr, "SERVER: ERROR: Invalid port (%s)!\n", argv[optind]); - print_usage_and_exit (); - } - - vcl_test_init_endpoint_addr (vsm); -} - -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) -{ - if (rx_cfg->verbose) - { - vtinf ("(fd %d): Received a cfg msg!", conn->fd); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - } - - if (rx_bytes != sizeof (*rx_cfg)) - { - vtinf ("(fd %d): Invalid cfg msg size %d expected %lu!", conn->fd, - rx_bytes, sizeof (*rx_cfg)); - conn->cfg.rxbuf_size = 0; - conn->cfg.num_writes = 0; - if (conn->cfg.verbose) - { - vtinf ("(fd %d): Replying to cfg msg", conn->fd); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - } - vcl_test_write (conn->fd, (uint8_t *) & conn->cfg, - sizeof (conn->cfg), NULL, conn->cfg.verbose); - return -1; - } - - switch (rx_cfg->test) - { - case VCL_TEST_TYPE_NONE: - case VCL_TEST_TYPE_ECHO: - sync_config_and_reply (conn, rx_cfg); - break; - - case VCL_TEST_TYPE_BI: - case VCL_TEST_TYPE_UNI: - vts_server_start_stop (wrk, conn, rx_cfg); - break; - - case VCL_TEST_TYPE_EXIT: - vtinf ("Session fd %d closing!", conn->fd); - clock_gettime (CLOCK_REALTIME, &conn->stats.stop); - vppcom_session_close (conn->fd); - conn_pool_free (conn); - wrk->nfds--; - break; - - default: - vtwrn ("Unknown test type %d", rx_cfg->test); - vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ ); - break; - } - - return 0; -} - -static void -vts_worker_init (vcl_test_server_worker_t * wrk) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - struct epoll_event listen_ev; - int rv; - - __wrk_index = wrk->wrk_index; - - vtinf ("Initializing worker ..."); - - conn_pool_expand (wrk, VCL_TEST_CFG_MAX_TEST_SESS + 1); - if (wrk->wrk_index) - if (vppcom_worker_register ()) - vtfail ("vppcom_worker_register()", 1); - - wrk->listen_fd = vppcom_session_create (vsm->cfg.proto, - 0 /* is_nonblocking */ ); - if (wrk->listen_fd < 0) - vtfail ("vppcom_session_create()", wrk->listen_fd); - - - if (vsm->cfg.proto == VPPCOM_PROTO_TLS) - { - vppcom_session_tls_add_cert (wrk->listen_fd, vcl_test_crt_rsa, - vcl_test_crt_rsa_len); - vppcom_session_tls_add_key (wrk->listen_fd, vcl_test_key_rsa, - vcl_test_key_rsa_len); - } - - rv = vppcom_session_bind (wrk->listen_fd, &vsm->cfg.endpt); - if (rv < 0) - vtfail ("vppcom_session_bind()", rv); - - if (!(vsm->cfg.proto == VPPCOM_PROTO_UDP)) - { - rv = vppcom_session_listen (wrk->listen_fd, 10); - if (rv < 0) - vtfail ("vppcom_session_listen()", rv); - } - - wrk->epfd = vppcom_epoll_create (); - if (wrk->epfd < 0) - vtfail ("vppcom_epoll_create()", wrk->epfd); - - listen_ev.events = EPOLLIN; - listen_ev.data.u32 = ~0; - rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, wrk->listen_fd, - &listen_ev); - if (rv < 0) - vtfail ("vppcom_epoll_ctl", rv); - - vsm->active_workers += 1; - vtinf ("Waiting for a client to connect on port %d ...", vsm->cfg.port); -} - -static int -vts_conn_expect_config (vcl_test_server_conn_t * conn) -{ - if (conn->cfg.test == VCL_TEST_TYPE_ECHO) - return 1; - - return (conn->stats.rx_bytes < 128 - || conn->stats.rx_bytes > conn->cfg.total_bytes); -} - -static vcl_test_cfg_t * -vts_conn_read_config (vcl_test_server_conn_t * conn) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - - if (vsm->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 (vcl_test_cfg_t)); - } - return (vcl_test_cfg_t *) conn->buf; -} - -static inline int -vts_conn_read (vcl_test_server_conn_t * conn) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - if (vsm->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 *vsm = &vcl_server_main; - - if (vsm->use_ds) - return isascii (conn->ds[0].data[0]); - else - return isascii (conn->buf[0]); -} - -static void * -vts_worker_loop (void *arg) -{ - 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; - vcl_test_cfg_t *rx_cfg; - - if (wrk->wrk_index) - vts_worker_init (wrk); - - while (1) - { - num_ev = vppcom_epoll_wait (wrk->epfd, wrk->wait_events, - VCL_TEST_CFG_MAX_EPOLL_EVENTS, 60000.0); - if (num_ev < 0) - { - vterr ("vppcom_epoll_wait()", num_ev); - goto fail; - } - else if (num_ev == 0) - { - vtinf ("vppcom_epoll_wait() timeout!"); - continue; - } - for (i = 0; i < num_ev; i++) - { - conn = &wrk->conn_pool[wrk->wait_events[i].data.u32]; - 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) - { - vts_new_client (wrk); - continue; - } - - if (EPOLLIN & wrk->wait_events[i].events) - { - read_again: - rx_bytes = vts_conn_read (conn); - - if (rx_bytes <= 0) - { - if (errno == ECONNRESET) - { - vtinf ("Connection reset by remote peer.\n"); - goto fail; - } - else - continue; - } - - if (vts_conn_expect_config (conn)) - { - rx_cfg = vts_conn_read_config (conn); - if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC) - { - if (vsm->use_ds) - vppcom_session_free_segments (conn->fd, conn->ds); - vts_handle_cfg (wrk, rx_cfg, conn, rx_bytes); - if (!wrk->nfds) - { - vtinf ("All client connections closed\n"); - goto done; - } - continue; - } - } - if ((conn->cfg.test == VCL_TEST_TYPE_UNI) - || (conn->cfg.test == VCL_TEST_TYPE_BI)) - { - vts_server_rx (conn, rx_bytes); - if (vppcom_session_attr (conn->fd, VPPCOM_ATTR_GET_NREAD, 0, - 0) > 0) - goto read_again; - continue; - } - if (vts_conn_has_ascii (conn)) - { - vts_server_echo (conn, rx_bytes); - } - else - { - vtwrn ("FIFO not drained! extra bytes %d", rx_bytes); - } - } - else - { - vtwrn ("Unhandled event"); - goto fail; - } - } - } - -fail: - vsm->worker_fails -= 1; - -done: - vppcom_session_close (wrk->listen_fd); - if (wrk->conn_pool) - free (wrk->conn_pool); - vsm->active_workers -= 1; - return 0; -} - -int -main (int argc, char **argv) -{ - vcl_test_server_main_t *vsm = &vcl_server_main; - int rv, i; - - clib_mem_init_thread_safe (0, 64 << 20); - vsm->cfg.port = VCL_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); - - vsm->workers = calloc (vsm->cfg.workers, sizeof (*vsm->workers)); - vts_worker_init (&vsm->workers[0]); - for (i = 1; i < vsm->cfg.workers; i++) - { - vsm->workers[i].wrk_index = i; - rv = pthread_create (&vsm->workers[i].thread_handle, NULL, - vts_worker_loop, (void *) &vsm->workers[i]); - } - vts_worker_loop (&vsm->workers[0]); - - while (vsm->active_workers > 0) - ; - - vppcom_app_destroy (); - free (vsm->workers); - - return vsm->worker_fails; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |