Modify the batctl ping utility to accept both integer and floating-point
values for the interval between sending pings. This enhancement allows
specifying intervals with subsecond precision.
For example:
`sudo batctl ping aa:bb:cc:dd:ee:ff -i 0.5`
Signed-off-by: Noah Peterson <noahbpeterson1997(a)gmail.com>
---
v3: Rebasing on latest commit, reformatting code based on comments by Sven
<sven(a)narfation.org>
v2: Fixing use-after-free, adding a missing header file, noted by Sven
<sven(a)narfation.org>
---
ping.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/ping.c b/ping.c
index 52bce4d..9142a5a 100644
--- a/ping.c
+++ b/ping.c
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <sys/select.h>
#include <sys/time.h>
+#include <time.h>
#include <netinet/if_ether.h>
#include "batadv_packet_compat.h"
@@ -65,14 +66,19 @@ static int ping(struct state *state, int argc, char **argv)
struct bat_host *bat_host, *rr_host;
ssize_t read_len;
int ret = EXIT_FAILURE, res, optchar, found_args = 1;
- int loop_count = -1, loop_interval = 0, timeout = 1, rr = 0, i;
+ int loop_count = -1, timeout = 1, rr = 0, i;
unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, packets_loss;
char *dst_string, *mac_string, *rr_string;
+ char *end = NULL;
double time_delta;
+ double ping_interval = 0.0;
+ double integral_part = 0.0;
+ double fractional_part = 0.0;
float min = 0.0, max = 0.0, avg = 0.0, mdev = 0.0;
uint8_t last_rr_cur = 0, last_rr[BATADV_RR_LEN][ETH_ALEN];
size_t packet_len;
int disable_translate_mac = 0;
+ struct timespec loop_interval = {0, 0};
while ((optchar = getopt(argc, argv, "hc:i:t:RT")) != -1) {
switch (optchar) {
@@ -86,9 +92,17 @@ static int ping(struct state *state, int argc, char **argv)
ping_usage();
return EXIT_SUCCESS;
case 'i':
- loop_interval = strtol(optarg, NULL , 10);
- if (loop_interval < 1)
- loop_interval = 1;
+ errno = 0;
+ ping_interval = strtod(optarg, &end);
+ if (errno) {
+ fprintf(stderr, "Error - invalid ping interval '%s'\n", optarg);
+ goto out;
+ } else {
+ ping_interval = fmax(ping_interval, 0.001);
+ }
+ fractional_part = modf(ping_interval, &integral_part);
+ loop_interval.tv_sec = (time_t)integral_part;
+ loop_interval.tv_nsec = (long)(fractional_part * 1000000000l);
found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
break;
case 't':
@@ -285,9 +299,8 @@ static int ping(struct state *state, int argc, char **argv)
/* skip last sleep in case no more packets will be sent out */
if (loop_count == 0)
continue;
-
- if (loop_interval > 0)
- sleep(loop_interval);
+ if (loop_interval.tv_sec > 0 || loop_interval.tv_nsec > 0)
+ nanosleep(&loop_interval, NULL);
else if ((tv.tv_sec != 0) || (tv.tv_usec != 0))
select(0, NULL, NULL, NULL, &tv);
}
--
2.39.5 (Apple Git-154)