20 #include <sys/types.h> 21 #include <sys/socket.h> 24 #include <arpa/inet.h> 55 struct sockaddr_storage server_addr;
58 static __thread
int __wrk_index = 0;
62 #define vtc_min(a, b) (a < b ? a : b) 63 #define vtc_max(a, b) (a > b ? a : b) 69 int rx_bytes, tx_bytes;
74 vtinf (
"(fd %d): Sending config to server.", ts->
fd);
81 vtwrn (
"(fd %d): write test cfg failed (%d)!", ts->
fd, tx_bytes);
92 vtwrn (
"(fd %d): Bad server reply cfg -- aborting!", ts->
fd);
98 vtwrn (
"(fd %d): Invalid config received from server!", ts->
fd);
101 vtinf (
"\tRx bytes %d != cfg size %lu", rx_bytes,
107 vtinf (
"(fd %d): Valid config sent to server.", ts->
fd);
114 vtinf (
"(fd %d): Got config back from server.", ts->
fd);
150 vterr (
"failed to alloc Qsessions", -errno);
158 tq->
fd = vppcom_session_create (vcm->
proto, 0 );
162 vterr (
"vppcom_session_create()", tq->
fd);
170 vterr (
"vppcom_session_connect()", rv);
174 flen =
sizeof (
flags);
175 vppcom_session_attr (tq->
fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
176 vtinf (
"Test Qsession %d (fd %d) connected.", i, tq->
fd);
192 vterr (
"failed to alloc sessions", -errno);
200 ts->
fd = vppcom_session_create (vcm->
proto, 1 );
204 vterr (
"vppcom_session_create()", ts->
fd);
208 rv = vppcom_session_stream_connect (ts->
fd, tq->
fd);
211 vterr (
"vppcom_session_stream_connect()", rv);
215 vtinf (
"Test session %d (fd %d) connected.", i, ts->
fd);
229 uint32_t n_test_sessions;
230 uint32_t
flags, flen;
233 if (vcm->
proto == VPPCOM_PROTO_QUIC)
237 if (n_test_sessions < 1)
254 vterr (
"failed to alloc sessions", -errno);
258 for (i = 0; i < n_test_sessions; i++)
261 ts->
fd = vppcom_session_create (vcm->
proto, 0 );
264 vterr (
"vppcom_session_create()", ts->
fd);
272 vterr (
"vppcom_session_connect()", rv);
276 flen =
sizeof (
flags);
277 vppcom_session_attr (ts->
fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
278 vtinf (
"Test session %d (fd %d) connected.", i, ts->
fd);
283 vtinf (
"All test sessions (%d) connected!", n_test_sessions);
314 ts->
txbuf[j] = j & 0xff;
318 FD_SET (vppcom_session_index (ts->
fd), &wrk->
wr_fdset);
319 FD_SET (vppcom_session_index (ts->
fd), &wrk->
rd_fdset);
320 sidx = vppcom_session_index (ts->
fd);
343 if (vppcom_worker_register ())
345 vtwrn (
"failed to register worker");
353 vterr (
"vtc_connect_test_sessions ()", rv);
360 vtinf (
"Sending config to server on all sessions ...");
383 while (__sync_lock_test_and_set (&
stats_lock, 1))
397 snprintf (buf,
sizeof (buf),
"CLIENT (fd %d) RESULTS", ts->
fd);
425 vtinf (
"(fd %d): Sending exit cfg to server...", ts->
fd);
429 sizeof (ts->
cfg), &ts->
stats, verbose);
441 uint32_t n_active_sessions, n_bytes;
442 fd_set _wfdset, *wfdset = &_wfdset;
443 fd_set _rfdset, *rfdset = &_rfdset;
445 int i, rv, check_rx = 0;
450 vterr (
"vtc_worker_init()", rv);
454 vtinf (
"Starting test ...");
457 clock_gettime (CLOCK_REALTIME, &ctrl->
stats.
start);
461 while (n_active_sessions)
466 rv = vppcom_select (wrk->
max_fd_index, (
unsigned long *) rfdset,
467 (
unsigned long *) wfdset, NULL, 0);
470 vterr (
"vppcom_select()", rv);
483 if (FD_ISSET (vppcom_session_index (ts->
fd), rfdset)
490 if (FD_ISSET (vppcom_session_index (ts->
fd), wfdset)
495 n_bytes = strlen (ctrl->
txbuf) + 1;
500 vtwrn (
"vppcom_test_write (%d) failed -- aborting test",
508 clock_gettime (CLOCK_REALTIME, &ts->
stats.
stop);
542 vtinf (
" ctrl session info\n" 546 " rxbuf size: %u (0x%08x)\n" 548 " txbuf size: %u (0x%08x)\n" 550 ctrl->
fd, (uint32_t) ctrl->
fd,
556 snprintf (buf,
sizeof (buf),
"Echo");
558 snprintf (buf,
sizeof (buf),
"%s-directional Stream",
570 memset (&ctrl->
stats, 0, sizeof (ctrl->
stats));
592 uint32_t
i, n_conn, n_conn_per_wrk;
594 vtinf (
"%s-directional Stream Test Starting!",
601 vtwrn (
"test cfg sync failed -- aborting!");
605 memset (&ctrl->
stats, 0, sizeof (ctrl->
stats));
608 n_conn_per_wrk = n_conn / vcm->
n_workers;
629 vtinf (
"Sending config on ctrl session (fd %d) for stats...", ctrl->
fd);
632 vtwrn (
"test cfg sync failed -- aborting!");
641 vtwrn (
"post-test cfg sync failed!");
649 printf (
"CLIENT: Test configuration commands:" 651 "\t\t\tDisplay help." 653 "\t\t\tExit test client & server." 655 "\t\t\tShow the current test cfg." 657 "\t\t\tRun the Uni-directional test." 659 "\t\t\tRun the Bi-directional test." 661 "\t\t\tToggle verbose setting." 663 "<rxbuf size>\tRx buffer size (bytes)." 665 "<txbuf size>\tTx buffer size (bytes)." 667 "<# of writes>\tNumber of txbuf writes to server." "\n");
676 uint64_t txbuf_size = strtoull ((
const char *) p, NULL, 10);
687 vtwrn (
"Invalid txbuf size (%lu) < minimum buf size (%u)!",
697 uint32_t num_writes = strtoul ((
const char *) p, NULL, 10);
707 vtwrn (
"invalid num writes: %u", num_writes);
717 uint32_t num_test_sessions = strtoul ((
const char *) p, NULL, 10);
719 if ((num_test_sessions > 0) &&
727 vtwrn (
"invalid num test sessions: %u, (%d max)",
738 uint64_t rxbuf_size = strtoull ((
const char *) p, NULL, 10);
748 vtwrn (
"Invalid rxbuf size (%lu) < minimum buf size (%u)!",
820 "vcl_test_client [OPTIONS] <ipaddr> <port>\n" 822 " -h Print this message and exit.\n" 824 " -c Print test config before test.\n" 825 " -w <dir> Write test results to <dir>.\n" 826 " -X Exit after running test.\n" 827 " -p <proto> Use <proto> transport layer\n" 828 " -D Use UDP transport layer\n" 829 " -L Use TLS transport layer\n" 830 " -E Run Echo test.\n" 831 " -N <num-writes> Test Cfg: number of writes.\n" 832 " -R <rxbuf-size> Test Cfg: rx buffer size.\n" 833 " -T <txbuf-size> Test Cfg: tx buffer size.\n" 834 " -U Run Uni-directional test.\n" 835 " -B Run Bi-directional test.\n" 836 " -V Verbose mode.\n" 837 " -I <N> Use N sessions.\n" 838 " -s <N> Use N sessions.\n" 839 " -q <n> QUIC : use N Ssessions on top of n Qsessions\n");
850 while ((c = getopt (argc, argv,
"chnp:w:XE:I:N:R:T:UBV6DLs:q:")) != -1)
862 vtwrn (
"Invalid value for option -%c!", c);
868 vtwrn (
"Invalid number of sessions (%d) specified for option -%c!" 869 "\n Valid range is 1 - %d",
880 vtwrn (
"Invalid value for option -%c!", c);
886 vtwrn (
"Invalid number of Stream sessions (%d) per Qsession" 887 "for option -%c!\nValid range is 1 - %d",
895 if (sscanf (optarg,
"%d", &v) != 1)
897 vtwrn (
"Invalid value for option -%c!", c);
911 vtwrn (
"Option -%c value larger than txbuf size (%d)!",
923 vtwrn (
"Invalid value for option -%c!", c);
933 vtwrn (
"Invalid value for option -%c!", c);
940 (uint8_t **) & ctrl->
rxbuf,
945 vtwrn (
"rxbuf size (%lu) less than minumum (%u)",
956 vtwrn (
"Invalid value for option -%c!", c);
963 (uint8_t **) & ctrl->
txbuf,
970 vtwrn (
"txbuf size (%lu) less than minumum (%u)!",
993 if (vppcom_unformat_proto (&vcm->
proto, optarg))
994 vtwrn (
"Invalid vppcom protocol %s, defaulting to TCP", optarg);
998 vcm->
proto = VPPCOM_PROTO_UDP;
1002 vcm->
proto = VPPCOM_PROTO_TLS;
1016 vtwrn (
"Option -%c requires an argument.", optopt);
1020 if (isprint (optopt))
1021 vtwrn (
"Unknown option `-%c'.", optopt);
1023 vtwrn (
"Unknown option character `\\x%x'.", optopt);
1031 if (argc < (optind + 2))
1033 vtwrn (
"Insufficient number of arguments!");
1044 struct sockaddr_in6 *sddr6 = (
struct sockaddr_in6 *) &vcm->
server_addr;
1045 sddr6->sin6_family = AF_INET6;
1046 inet_pton (AF_INET6, argv[optind++], &(sddr6->sin6_addr));
1047 sddr6->sin6_port = htons (atoi (argv[optind]));
1055 struct sockaddr_in *saddr4 = (
struct sockaddr_in *) &vcm->
server_addr;
1056 saddr4->sin_family = AF_INET;
1057 inet_pton (AF_INET, argv[optind++], &(saddr4->sin_addr));
1058 saddr4->sin_port = htons (atoi (argv[optind]));
1069 printf (
"\nType some characters and hit <return>\n" 1074 if (strlen (ctrl->
txbuf) == 1)
1076 printf (
"\nNothing to send! Please try again...\n");
1096 vtinf (
"(fd %d): Sending exit cfg to server...", ctrl->
fd);
1100 sizeof (ctrl->
cfg), &ctrl->
stats, verbose);
1118 rv = vppcom_app_create (
"vcl_test_client");
1120 vtfail (
"vppcom_app_create()", rv);
1122 ctrl->
fd = vppcom_session_create (vcm->
proto, 0 );
1124 vtfail (
"vppcom_session_create()", ctrl->
fd);
1126 if (vcm->
proto == VPPCOM_PROTO_TLS || vcm->
proto == VPPCOM_PROTO_QUIC)
1128 vtinf (
"Adding tls certs ...");
1135 vtinf (
"Connecting to server...");
1136 if (vcm->
proto == VPPCOM_PROTO_QUIC)
1138 quic_session->
fd = vppcom_session_create (vcm->
proto,
1140 if (quic_session->
fd < 0)
1141 vtfail (
"vppcom_session_create()", quic_session->
fd);
1142 rv = vppcom_session_connect (quic_session->
fd, &vcm->
server_endpt);
1144 vtfail (
"vppcom_session_connect()", rv);
1145 vtinf (
"Connecting to stream...");
1146 rv = vppcom_session_stream_connect (ctrl->
fd, quic_session->
fd);
1151 vtfail (
"vppcom_session_connect()", rv);
1152 vtinf (
"Control session (fd %d) connected.", ctrl->
fd);
1156 vtfail (
"vtc_cfg_sync()", rv);
1159 memset (&ctrl->
stats, 0, sizeof (ctrl->
stats));
1221 vppcom_session_close (quic_session->
fd);
1222 vppcom_app_destroy ();
static void dump_help(void)
#define VCL_TEST_TOKEN_RXBUF_SIZE
uint32_t vcl_test_crt_rsa_len
int main(int argc, char **argv)
static vcl_test_t parse_input()
uint32_t num_test_qsessions
vcl_test_session_t ctrl_session
vcl_test_session_t quic_session
vcl_test_client_main_t vcl_client_main
uint32_t num_test_sessions
#define VCL_TEST_CFG_BUF_SIZE_MIN
#define VCL_TEST_DELAY_DISCONNECT
vcl_test_session_t * sessions
static void vtc_worker_sessions_exit(vcl_test_client_worker_t *wrk)
#define VCL_TEST_TOKEN_NUM_WRITES
#define VCL_TEST_TOKEN_SHOW_CFG
void print_usage_and_exit(void)
struct sockaddr_storage server_addr
volatile int active_workers
static int vtc_worker_test_setup(vcl_test_client_worker_t *wrk)
static void vtc_echo_client(vcl_test_client_main_t *vcm)
static void vcl_test_stats_dump(char *header, vcl_test_stats_t *stats, uint8_t show_rx, uint8_t show_tx, uint8_t verbose)
static void * vtc_worker_loop(void *arg)
vppcom_endpt_t server_endpt
static void vtc_stream_client(vcl_test_client_main_t *vcm)
vcl_test_client_worker_t * workers
static int vtc_cfg_sync(vcl_test_session_t *ts)
static void cfg_num_writes_set(void)
#define VCL_TEST_SEPARATOR_STRING
static void vcl_test_session_buf_alloc(vcl_test_session_t *socket)
static void vcl_test_cfg_dump(vcl_test_cfg_t *cfg, uint8_t is_client)
static void cfg_txbuf_size_set(void)
vcl_test_session_t * qsessions
#define VCL_TEST_CFG_CTRL_MAGIC
vcl_test_session_t * sessions
#define VCL_TEST_TOKEN_RUN_BI
static void vcl_test_cfg_init(vcl_test_cfg_t *cfg)
#define VCL_TEST_TOKEN_TXBUF_SIZE
#define VCL_TEST_TOKEN_VERBOSE
static void cfg_rxbuf_size_set(void)
#define vt_atomic_add(_ptr, _val)
static void vtc_print_stats(vcl_test_session_t *ctrl)
uint32_t num_test_sessions_perq
#define VCL_TEST_TOKEN_HELP
#define vtinf(_fmt, _args...)
static void vcl_test_buf_alloc(vcl_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf, uint32_t *bufsize)
static int vcl_test_read(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats)
static int vtc_quic_connect_test_sessions(vcl_test_client_worker_t *wrk)
static int vcl_test_write(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats, uint32_t verbose)
static void vtc_accumulate_stats(vcl_test_client_worker_t *wrk, vcl_test_session_t *ctrl)
uint32_t vcl_test_key_rsa_len
static int vtc_connect_test_sessions(vcl_test_client_worker_t *wrk)
#define VCL_TEST_TOKEN_RUN_UNI
static int vcl_comp_tspec(struct timespec *a, struct timespec *b)
static void vcl_test_stats_accumulate(vcl_test_stats_t *accum, vcl_test_stats_t *incr)
static void vtc_read_user_input(vcl_test_session_t *ctrl)
static int vtc_worker_init(vcl_test_client_worker_t *wrk)
static void cfg_verbose_toggle(void)
#define VCL_TEST_TOKEN_NUM_TEST_SESS
#define VCL_TEST_TOKEN_EXIT
static int vcl_test_cfg_verify(vcl_test_cfg_t *cfg, vcl_test_cfg_t *valid_cfg)
static void cfg_num_test_sessions_set(void)
static void vtc_ctrl_session_exit(void)
static void vtc_process_opts(vcl_test_client_main_t *vcm, int argc, char **argv)
#define VCL_TEST_CFG_MAX_TEST_SESS
#define vtwrn(_fmt, _args...)