From bedee0b0aac97fb195288ec81837e192cbb7b27c Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 20 Jun 2018 18:15:43 +0200 Subject: tools: Add unidirectional test to operf This adds a unidirectional test to operf, which is handy for testing unidirectional streams. Signed-off-by: Sander Vrijders Signed-off-by: Dimitri Staessens --- src/tools/operf/operf_client.c | 119 ++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 48 deletions(-) (limited to 'src/tools/operf/operf_client.c') diff --git a/src/tools/operf/operf_client.c b/src/tools/operf/operf_client.c index d299e239..c8873c54 100644 --- a/src/tools/operf/operf_client.c +++ b/src/tools/operf/operf_client.c @@ -36,6 +36,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +bool stop; + static void busy_wait_until(const struct timespec * deadline) { struct timespec now; @@ -45,7 +47,6 @@ static void busy_wait_until(const struct timespec * deadline) while (now.tv_sec == deadline->tv_sec && now.tv_nsec < deadline->tv_nsec) clock_gettime(CLOCK_REALTIME, &now); - pthread_testcancel(); } void shutdown_client(int signo, siginfo_t * info, void * c) @@ -57,8 +58,7 @@ void shutdown_client(int signo, siginfo_t * info, void * c) case SIGINT: case SIGTERM: case SIGHUP: - pthread_cancel(client.reader_pt); - pthread_cancel(client.writer_pt); + stop = true; default: return; } @@ -74,7 +74,14 @@ void * reader(void * o) fccntl(fd, FLOWSRCVTIMEO, &timeout); - while ((msg_len = flow_read(fd, buf, OPERF_BUF_SIZE)) != -ETIMEDOUT) { + while (!stop) { + msg_len = flow_read(fd, buf, OPERF_BUF_SIZE); + if (msg_len == -ETIMEDOUT) { + printf("Server timed out.\n"); + stop = true; + break; + } + if (msg_len != client.size) { printf("Invalid message on fd %d.\n", fd); continue; @@ -96,7 +103,10 @@ void * writer(void * o) struct timespec intv = {(gap / BILLION), gap % BILLION}; struct timespec end = {0, 0}; - char * buf = malloc(client.size); + char * buf; + struct msg * msg; + + buf = malloc(client.size); if (buf == NULL) return (void *) -ENOMEM; @@ -107,53 +117,49 @@ void * writer(void * o) memset(buf, 0, client.size); + msg = (struct msg *) buf; + if (client.flood) printf("Flooding %s with %d byte SDUs for %d seconds.\n\n", - client.s_apn, client.size, client.duration / 1000); + client.server_name, client.size, + client.duration / 1000); else printf("Sending %d byte SDUs for %d s to %s at %.3lf Mb/s.\n\n", - client.size, client.duration / 1000, client.s_apn, + client.size, client.duration / 1000, + client.server_name, client.rate / (double) MILLION); clock_gettime(CLOCK_REALTIME, &start); clock_gettime(CLOCK_REALTIME, &now); - pthread_cleanup_push((void (*) (void *)) free, buf); - - if (client.flood) { - while (ts_diff_ms(&start, &now) < client.duration) { - if (flow_write(*fdp, buf, client.size) == -1) { - printf("Failed to send SDU.\n"); - flow_dealloc(*fdp); - free(buf); - return (void *) -1; - } + while (!stop && ts_diff_ms(&start, &now) < client.duration) { + if (!client.flood) { + clock_gettime(CLOCK_REALTIME, &now); + ts_add(&now, &intv, &end); + } - ++client.sent; + msg->id = client.sent; - clock_gettime(CLOCK_REALTIME, &now); + if (flow_write(*fdp, buf, client.size) == -1) { + printf("Failed to send SDU.\n"); + flow_dealloc(*fdp); + free(buf); + return (void *) -1; } - } else { - while (ts_diff_ms(&start, &now) < client.duration) { - clock_gettime(CLOCK_REALTIME, &now); - ts_add(&now, &intv, &end); - if (flow_write(*fdp, buf, client.size) == -1) { - printf("Failed to send SDU.\n"); - flow_dealloc(*fdp); - free(buf); - return (void *) -1; - } + ++client.sent; - ++client.sent; + if (!client.flood) { if (client.sleep) nanosleep(&intv, NULL); else busy_wait_until(&end); + } else { + clock_gettime(CLOCK_REALTIME, &now); } } - pthread_cleanup_pop(true); + free(buf); printf("Test finished.\n"); @@ -183,34 +189,51 @@ int client_main(void) client.sent = 0; client.rcvd = 0; + stop = false; - fd = flow_alloc(client.s_apn, NULL, NULL); + /* FIXME: Allow selecting QoS. */ + fd = flow_alloc(client.server_name, NULL, NULL); if (fd < 0) { printf("Failed to allocate flow.\n"); return -1; } - clock_gettime(CLOCK_REALTIME, &tic); + if (client.conf.test_type == TEST_TYPE_BI) + printf("Doing a bidirectional test.\n"); + else + printf("Doing a unidirectional test.\n"); - pthread_create(&client.reader_pt, NULL, reader, &fd); - pthread_create(&client.writer_pt, NULL, writer, &fd); + if (flow_write(fd, &client.conf, sizeof(client.conf))) { + printf("Failed to send configuration.\n"); + flow_dealloc(fd); + return -1; + } - pthread_join(client.writer_pt, NULL); + sleep(1); + + clock_gettime(CLOCK_REALTIME, &tic); - clock_gettime(CLOCK_REALTIME, &toc); + if (client.conf.test_type == TEST_TYPE_BI) + pthread_create(&client.reader_pt, NULL, reader, &fd); - pthread_join(client.reader_pt, NULL); + pthread_create(&client.writer_pt, NULL, writer, &fd); + pthread_join(client.writer_pt, NULL); - printf("\n"); - printf("--- %s perf statistics ---\n", client.s_apn); - printf("%ld SDUs transmitted, ", client.sent); - printf("%ld received, ", client.rcvd); - printf("%ld%% packet loss, ", client.sent == 0 ? 0 : - 100 - ((100 * client.rcvd) / client.sent)); - printf("time: %.3f ms, ", ts_diff_us(&tic, &toc) / 1000.0); - printf("bandwidth: %.3lf Mb/s.\n", - (client.rcvd * client.size * 8) - / (double) ts_diff_us(&tic, &toc)); + if (client.conf.test_type == TEST_TYPE_BI){ + clock_gettime(CLOCK_REALTIME, &toc); + pthread_join(client.reader_pt, NULL); + + printf("\n"); + printf("--- %s perf statistics ---\n", client.server_name); + printf("%ld SDUs transmitted, ", client.sent); + printf("%ld received, ", client.rcvd); + printf("%ld%% packet loss, ", client.sent == 0 ? 0 : + 100 - ((100 * client.rcvd) / client.sent)); + printf("time: %.3f ms, ", ts_diff_us(&tic, &toc) / 1000.0); + printf("bandwidth: %.3lf Mb/s.\n", + (client.rcvd * client.size * 8) + / (double) ts_diff_us(&tic, &toc)); + } flow_dealloc(fd); -- cgit v1.2.3