aboutsummaryrefslogtreecommitdiffstats
path: root/sbin/ping
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2019-08-13 19:27:23 +0000
committerAlan Somers <asomers@FreeBSD.org>2019-08-13 19:27:23 +0000
commit1ad76f1b604723ea01ff0a96b3265615b30705a3 (patch)
treebf5cd5e00817d535b1224dc5dc6cbe72c03b9a6b /sbin/ping
parent42bf9655289d3fa0af5e82135bf9bb9c5056b6fd (diff)
downloadsrc-1ad76f1b604723ea01ff0a96b3265615b30705a3.tar.gz
src-1ad76f1b604723ea01ff0a96b3265615b30705a3.zip
ping: use the monotonic clock to measure durations
Submitted by: Ján Sučan <sucanjan@gmail.com> MFC after: 2 weeks Sponsored by: Google, inc. (Google Summer of Code 2019) Differential Revision: https://reviews.freebsd.org/D21245
Notes
Notes: svn path=/head/; revision=350998
Diffstat (limited to 'sbin/ping')
-rw-r--r--sbin/ping/ping.c91
1 files changed, 36 insertions, 55 deletions
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 762196062c29..e39b1520a017 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
+#include <time.h>
#include <unistd.h>
#define INADDR_LEN ((int)sizeof(in_addr_t))
@@ -119,7 +120,7 @@ __FBSDID("$FreeBSD$");
struct tv32 {
int32_t tv32_sec;
- int32_t tv32_usec;
+ int32_t tv32_nsec;
};
/* various options */
@@ -217,11 +218,10 @@ static char *pr_addr(struct in_addr);
static char *pr_ntime(n_time);
static void pr_icmph(struct icmp *);
static void pr_iph(struct ip *);
-static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *);
+static void pr_pack(char *, int, struct sockaddr_in *, struct timespec *);
static void pr_retip(struct ip *);
static void status(int);
static void stopit(int);
-static void tvsub(struct timeval *, const struct timeval *);
static void usage(void) __dead2;
int
@@ -229,7 +229,7 @@ main(int argc, char *const *argv)
{
struct sockaddr_in from, sock_in;
struct in_addr ifaddr;
- struct timeval last, intvl;
+ struct timespec last, intvl;
struct iovec iov;
struct ip *ip;
struct msghdr msg;
@@ -247,7 +247,7 @@ main(int argc, char *const *argv)
long ltmp;
int almost_done, ch, df, hold, i, icmp_len, mib[4], preload;
int ssend_errno, srecv_errno, tos, ttl;
- char ctrl[CMSG_SPACE(sizeof(struct timeval))];
+ char ctrl[CMSG_SPACE(sizeof(struct timespec))];
char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
#ifdef IP_OPTIONS
char rspace[MAX_IPOPTLEN]; /* record route space */
@@ -871,19 +871,19 @@ main(int argc, char *const *argv)
while (preload--) /* fire off them quickies */
pinger();
}
- (void)gettimeofday(&last, NULL);
+ (void)clock_gettime(CLOCK_MONOTONIC, &last);
if (options & F_FLOOD) {
intvl.tv_sec = 0;
- intvl.tv_usec = 10000;
+ intvl.tv_nsec = 10000000;
} else {
intvl.tv_sec = interval / 1000;
- intvl.tv_usec = interval % 1000 * 1000;
+ intvl.tv_nsec = interval % 1000 * 1000000;
}
almost_done = 0;
while (!finish_up) {
- struct timeval now, timeout;
+ struct timespec now, timeout;
fd_set rfds;
int cc, n;
@@ -892,24 +892,16 @@ main(int argc, char *const *argv)
errx(EX_OSERR, "descriptor too large");
FD_ZERO(&rfds);
FD_SET(srecv, &rfds);
- (void)gettimeofday(&now, NULL);
- timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
- timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
- while (timeout.tv_usec < 0) {
- timeout.tv_usec += 1000000;
- timeout.tv_sec--;
- }
- while (timeout.tv_usec >= 1000000) {
- timeout.tv_usec -= 1000000;
- timeout.tv_sec++;
- }
+ (void)clock_gettime(CLOCK_MONOTONIC, &now);
+ timespecadd(&last, &intvl, &timeout);
+ timespecsub(&timeout, &now, &timeout);
if (timeout.tv_sec < 0)
- timerclear(&timeout);
- n = select(srecv + 1, &rfds, NULL, NULL, &timeout);
+ timespecclear(&timeout);
+ n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL);
if (n < 0)
continue; /* Must be EINTR. */
if (n == 1) {
- struct timeval *tv = NULL;
+ struct timespec *tv = NULL;
#ifdef SO_TIMESTAMP
struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl;
@@ -932,7 +924,7 @@ main(int argc, char *const *argv)
}
#endif
if (tv == NULL) {
- (void)gettimeofday(&now, NULL);
+ (void)clock_gettime(CLOCK_MONOTONIC, &now);
tv = &now;
}
pr_pack((char *)packet, cc, &from, tv);
@@ -956,17 +948,17 @@ main(int argc, char *const *argv)
if (almost_done)
break;
almost_done = 1;
- intvl.tv_usec = 0;
+ intvl.tv_nsec = 0;
if (nreceived) {
intvl.tv_sec = 2 * tmax / 1000;
if (!intvl.tv_sec)
intvl.tv_sec = 1;
} else {
intvl.tv_sec = waittime / 1000;
- intvl.tv_usec = waittime % 1000 * 1000;
+ intvl.tv_nsec = waittime % 1000 * 1000000;
}
}
- (void)gettimeofday(&last, NULL);
+ (void)clock_gettime(CLOCK_MONOTONIC, &last);
if (ntransmitted - nreceived - 1 > nmissedmax) {
nmissedmax = ntransmitted - nreceived - 1;
if (options & F_MISSED)
@@ -1003,13 +995,13 @@ stopit(int sig __unused)
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
* and the sequence number is an ascending integer. The first TIMEVAL_LEN
- * bytes of the data portion are used to hold a UNIX "timeval" struct in
+ * bytes of the data portion are used to hold a UNIX "timespec" struct in
* host byte-order, to compute the round-trip time.
*/
static void
pinger(void)
{
- struct timeval now;
+ struct timespec now;
struct tv32 tv32;
struct ip *ip;
struct icmp *icp;
@@ -1027,13 +1019,18 @@ pinger(void)
CLR(ntransmitted % mx_dup_ck);
if ((options & F_TIME) || timing) {
- (void)gettimeofday(&now, NULL);
-
- tv32.tv32_sec = htonl(now.tv_sec);
- tv32.tv32_usec = htonl(now.tv_usec);
+ (void)clock_gettime(CLOCK_MONOTONIC, &now);
+ /*
+ * Truncate seconds down to 32 bits in order
+ * to fit the timestamp within 8 bytes of the
+ * packet. We're only concerned with
+ * durations, not absolute times.
+ */
+ tv32.tv32_sec = (uint32_t)htonl(now.tv_sec);
+ tv32.tv32_nsec = (uint32_t)htonl(now.tv_nsec);
if (options & F_TIME)
icp->icmp_otime = htonl((now.tv_sec % (24*60*60))
- * 1000 + now.tv_usec / 1000);
+ * 1000 + now.tv_nsec / 1000000);
if (timing)
bcopy((void *)&tv32,
(void *)&outpack[ICMP_MINLEN + phdr_len],
@@ -1079,7 +1076,7 @@ pinger(void)
* program to be run without having intermingled output (or statistics!).
*/
static void
-pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv)
+pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timespec *tv)
{
struct in_addr ina;
u_char *cp, *dp;
@@ -1112,7 +1109,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv)
++nreceived;
triptime = 0.0;
if (timing) {
- struct timeval tv1;
+ struct timespec tv1;
struct tv32 tv32;
#ifndef icmp_data
tp = &icp->icmp_ip;
@@ -1126,10 +1123,10 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv)
/* Copy to avoid alignment problems: */
memcpy(&tv32, tp, sizeof(tv32));
tv1.tv_sec = ntohl(tv32.tv32_sec);
- tv1.tv_usec = ntohl(tv32.tv32_usec);
- tvsub(tv, &tv1);
+ tv1.tv_nsec = ntohl(tv32.tv32_nsec);
+ timespecsub(tv, &tv1, tv);
triptime = ((double)tv->tv_sec) * 1000.0 +
- ((double)tv->tv_usec) / 1000.0;
+ ((double)tv->tv_nsec) / 1000000.0;
tsum += triptime;
tsumsq += triptime * triptime;
if (triptime < tmin)
@@ -1384,22 +1381,6 @@ in_cksum(u_short *addr, int len)
}
/*
- * tvsub --
- * Subtract 2 timeval structs: out = out - in. Out is assumed to
- * be >= in.
- */
-static void
-tvsub(struct timeval *out, const struct timeval *in)
-{
-
- if ((out->tv_usec -= in->tv_usec) < 0) {
- --out->tv_sec;
- out->tv_usec += 1000000;
- }
- out->tv_sec -= in->tv_sec;
-}
-
-/*
* status --
* Print out statistics when SIGINFO is received.
*/