summaryrefslogtreecommitdiff
path: root/src/tools/oping/oping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/oping/oping.c')
-rw-r--r--src/tools/oping/oping.c179
1 files changed, 135 insertions, 44 deletions
diff --git a/src/tools/oping/oping.c b/src/tools/oping/oping.c
index 3c1d4fe9..ed3529e5 100644
--- a/src/tools/oping/oping.c
+++ b/src/tools/oping/oping.c
@@ -1,10 +1,10 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2018
+ * Ouroboros - Copyright (C) 2016 - 2024
*
* Ouroboros ping application
*
- * Dimitri Staessens <dimitri.staessens@ugent.be>
- * Sander Vrijders <sander.vrijders@ugent.be>
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,9 +42,11 @@
#include <ouroboros/dev.h>
#include <ouroboros/fccntl.h>
#include <ouroboros/fqueue.h>
+#include <ouroboros/qos.h>
#include "time_utils.h"
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
@@ -58,22 +60,43 @@
#include <errno.h>
#include <float.h>
-#define OPING_BUF_SIZE 1500
-
-#define ECHO_REQUEST 0
-#define ECHO_REPLY 1
-
+#define OPING_BUF_SIZE 1500
+#define ECHO_REQUEST 0
+#define ECHO_REPLY 1
#define OPING_MAX_FLOWS 256
-struct c {
- char * s_apn;
- int interval;
- uint32_t count;
- int size;
+#define USAGE_STRING \
+"Usage: oping [OPTION]...\n" \
+"\n" \
+"Checks liveness between a client and a server\n" \
+"and reports the Round Trip Time (RTT)\n" \
+"\n" \
+" -l, --listen Run in server mode\n" \
+"\n" \
+" -c, --count Number of packets\n" \
+" -d, --duration Duration of the test (default 1s)\n" \
+" -i, --interval Interval (default 1000ms)\n" \
+" -n, --server-name Name of the oping server\n" \
+" -q, --qos QoS (raw, raw_crypt, best, video, voice, data)\n" \
+" -s, --size Payload size (B, default 64)\n" \
+" -Q, --quiet Only print final statistics\n" \
+" -D, --timeofday Print time of day before each line\n" \
+"\n" \
+" --help Display this help text and exit\n" \
+
+struct {
+ char * s_apn;
+ int interval;
+ uint32_t count;
+ int size;
+ bool timestamp;
+ qosspec_t qs;
/* stats */
uint32_t sent;
uint32_t rcvd;
+ size_t ooo;
+ bool quiet;
double rtt_min;
double rtt_max;
@@ -84,12 +107,14 @@ struct c {
pthread_t writer_pt;
} client;
-struct s {
+struct {
struct timespec times[OPING_MAX_FLOWS];
fset_t * flows;
fqueue_t * fq;
pthread_mutex_t lock;
+ bool quiet;
+
pthread_t cleaner_pt;
pthread_t accept_pt;
pthread_t server_pt;
@@ -108,67 +133,130 @@ struct oping_msg {
static void usage(void)
{
- printf("Usage: oping [OPTION]...\n"
- "Checks liveness between a client and a server\n"
- "and reports the Round Trip Time (RTT)\n\n"
- " -l, --listen Run in server mode\n"
- "\n"
- " -c, --count Number of packets (default 1000)\n"
- " -i, --interval Interval (ms, default 1000)\n"
- " -n, --server-apn Name of the oping server\n"
- " -s, --size Payload size (B, default 64)\n"
- " --help Display this help text and exit\n");
+ printf(USAGE_STRING);
+}
+
+/* Times are in ms. */
+static int time_mul(const char * rem)
+{
+ if (strcmp(rem, "ms") == 0 || strcmp(rem, "") == 0)
+ return 1;
+ else if(strcmp(rem, "s") == 0)
+ return 1000;
+ else if (strcmp(rem, "m") == 0)
+ return 60 * 1000;
+ else if (strcmp(rem, "h") == 0)
+ return 60 * 60 * 1000;
+ else if (strcmp(rem, "d") == 0)
+ return 60 * 60 * 24 * 1000;
+
+ printf("Unknown time unit: %s.\n", rem);
+
+ exit(EXIT_FAILURE);
}
-int main(int argc, char ** argv)
+int main(int argc,
+ char ** argv)
{
- int ret = -1;
- char * rem = NULL;
- bool serv = false;
+ int ret = -1;
+ char * rem = NULL;
+ bool serv = false;
+ long duration = 0;
+ char * qos = NULL;
argc--;
argv++;
- client.s_apn = NULL;
- client.interval = 1000;
- client.size = 64;
- client.count = 1000;
+ client.s_apn = NULL;
+ client.interval = 1000;
+ client.size = 64;
+ client.count = INT_MAX;
+ client.timestamp = false;
+ client.qs = qos_raw;
+ client.quiet = false;
+ server.quiet = false;
while (argc > 0) {
- if (strcmp(*argv, "-i") == 0 ||
- strcmp(*argv, "--interval") == 0) {
+ if ((strcmp(*argv, "-i") == 0 ||
+ strcmp(*argv, "--interval") == 0) &&
+ argc > 1) {
client.interval = strtol(*(++argv), &rem, 10);
+ client.interval *= time_mul(rem);
--argc;
- } else if (strcmp(*argv, "-n") == 0 ||
- strcmp(*argv, "--server_apn") == 0) {
+ } else if ((strcmp(*argv, "-n") == 0 ||
+ strcmp(*argv, "--server-name") == 0) &&
+ argc > 1) {
client.s_apn = *(++argv);
--argc;
- } else if (strcmp(*argv, "-c") == 0 ||
- strcmp(*argv, "--count") == 0) {
+ } else if ((strcmp(*argv, "-c") == 0 ||
+ strcmp(*argv, "--count") == 0) &&
+ argc > 1) {
client.count = strtol(*(++argv), &rem, 10);
--argc;
- } else if (strcmp(*argv, "-s") == 0 ||
- strcmp(*argv, "--size") == 0) {
+ } else if ((strcmp(*argv, "-d") == 0 ||
+ strcmp(*argv, "--duration") == 0) &&
+ argc > 1) {
+ duration = strtol(*(++argv), &rem, 10);
+ duration *= time_mul(rem);
+ --argc;
+ } else if ((strcmp(*argv, "-s") == 0 ||
+ strcmp(*argv, "--size") == 0) &&
+ argc > 1) {
client.size = strtol(*(++argv), &rem, 10);
--argc;
+ } else if ((strcmp(*argv, "-q") == 0 ||
+ strcmp(*argv, "--qos") == 0) &&
+ argc > 1) {
+ qos = *(++argv);
+ --argc;
} else if (strcmp(*argv, "-l") == 0 ||
strcmp(*argv, "--listen") == 0) {
serv = true;
+ } else if (strcmp(*argv, "-D") == 0 ||
+ strcmp(*argv, "--timeofday") == 0) {
+ client.timestamp = true;
+ } else if (strcmp(*argv, "-Q") == 0 ||
+ strcmp(*argv, "--quiet") == 0) {
+ client.quiet = true;
+ server.quiet = true;
} else {
- usage();
- exit(EXIT_SUCCESS);
+ goto fail;
}
argc--;
argv++;
}
+ if (duration > 0) {
+ if (client.interval == 0)
+ client.count = duration * 10;
+ else
+ client.count = duration / client.interval;
+ }
+
+ if (qos != NULL) {
+ if (strcmp(qos, "best") == 0)
+ client.qs = qos_best_effort;
+ else if (strcmp(qos, "raw") == 0)
+ client.qs = qos_raw;
+ else if (strcmp(qos, "video") == 0)
+ client.qs = qos_video;
+ else if (strcmp(qos, "voice") == 0)
+ client.qs = qos_voice;
+ else if (strcmp(qos, "data") == 0)
+ client.qs = qos_data;
+ else if (strcmp(qos, "raw_crypt") == 0)
+ client.qs = qos_raw_crypt;
+ else
+ printf("Unknown QoS cube, defaulting to raw.\n");
+ }
+
if (serv) {
ret = server_main();
} else {
if (client.s_apn == NULL) {
printf("No server specified.\n");
usage();
- exit(EXIT_SUCCESS);
+ exit(EXIT_FAILURE);
}
if (client.interval > 10000) {
printf("Ping interval truncated to 10s.\n");
@@ -179,7 +267,6 @@ int main(int argc, char ** argv)
OPING_BUF_SIZE);
client.size = OPING_BUF_SIZE;
}
-
if (client.size < 64) {
printf("Packet size set to 64 bytes.\n");
client.size = 64;
@@ -192,4 +279,8 @@ int main(int argc, char ** argv)
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
+
+ fail:
+ usage();
+ exit(EXIT_FAILURE);
}