]> git.ozlabs.org Git - ppp.git/commitdiff
pppd: linux: use monotonic time if possible
authorVladislav Grishenko <themiron@mail.ru>
Wed, 15 Aug 2018 17:03:45 +0000 (22:03 +0500)
committerVladislav Grishenko <themiron@mail.ru>
Fri, 22 May 2020 07:53:20 +0000 (12:53 +0500)
gettimeofday() suffers from time jumps due ntp or any manual change,
so duration measurements and scheduling can not be accurate.
let's use monotonic time source instead, if available.

it's known glibc (< 2.3.4) & old uclibc don't provide CLOCK_MONOTONIC
denine, but kernel may have it supported. so, use clock_gettime()
with fallback to gettimeofday() if first call has failed.

several gettimeofday()/time() calls still have to be preserved for
debug, pseudoterminal timestamping and string formatting. all the
rest calls are replaced to new get_time() call.

solaris kept with gettimeofday() as before, corresponding get_time()
system implementation can be updated/added in any future.

Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
pppd/Makefile.linux
pppd/main.c
pppd/plugins/radius/buildreq.c
pppd/plugins/rp-pppoe/discovery.c
pppd/pppd.h
pppd/sys-linux.c
pppd/sys-solaris.c
pppd/tty.c

index 8d5ce99d92202c4326730393c0d9e56d327fbefe..2a05bc42492b4b2973653b05cc2007e9eb963238 100644 (file)
@@ -33,7 +33,7 @@ endif
 # CC = gcc
 #
 COPTS = -O2 -pipe -Wall -g
-LIBS =
+LIBS = -lrt
 
 # Uncomment the next line to include support for Microsoft's
 # MS-CHAP authentication protocol.  Also, edit plugins/radius/Makefile.linux.
index e09b6ffcce32bd06389d91da6276f24c1e009007..dccd78b28d07aacdf45a1da146ecbf439f99bf9e 100644 (file)
@@ -522,7 +522,7 @@ main(argc, argv)
            info("Starting link");
        }
 
-       gettimeofday(&start_time, NULL);
+       get_time(&start_time);
        script_unsetenv("CONNECT_TIME");
        script_unsetenv("BYTES_SENT");
        script_unsetenv("BYTES_RCVD");
@@ -1216,7 +1216,7 @@ reset_link_stats(u)
 {
     if (!get_ppp_stats(u, &old_link_stats))
        return;
-    gettimeofday(&start_time, NULL);
+    get_time(&start_time);
 }
 
 /*
@@ -1230,7 +1230,7 @@ update_link_stats(u)
     char numbuf[32];
 
     if (!get_ppp_stats(u, &link_stats)
-       || gettimeofday(&now, NULL) < 0)
+       || get_time(&now) < 0)
        return;
     link_connect_time = now.tv_sec - start_time.tv_sec;
     link_stats_valid = 1;
@@ -1277,7 +1277,7 @@ timeout(func, arg, secs, usecs)
        fatal("Out of memory in timeout()!");
     newp->c_arg = arg;
     newp->c_func = func;
-    gettimeofday(&timenow, NULL);
+    get_time(&timenow);
     newp->c_time.tv_sec = timenow.tv_sec + secs;
     newp->c_time.tv_usec = timenow.tv_usec + usecs;
     if (newp->c_time.tv_usec >= 1000000) {
@@ -1331,7 +1331,7 @@ calltimeout()
     while (callout != NULL) {
        p = callout;
 
-       if (gettimeofday(&timenow, NULL) < 0)
+       if (get_time(&timenow) < 0)
            fatal("Failed to get time of day: %m");
        if (!(p->c_time.tv_sec < timenow.tv_sec
              || (p->c_time.tv_sec == timenow.tv_sec
@@ -1356,7 +1356,7 @@ timeleft(tvp)
     if (callout == NULL)
        return NULL;
 
-    gettimeofday(&timenow, NULL);
+    get_time(&timenow);
     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
     if (tvp->tv_usec < 0) {
index 955b05234b8e408513a3d04eb4d04a28da900475..3edd5ea92e1c0e0a864975670f5fa57b8aa87aa0 100644 (file)
@@ -293,7 +293,7 @@ int rc_acct_using_server(SERVER *acctserver,
        SEND_DATA       data;
        VALUE_PAIR      *adt_vp;
        int             result;
-       time_t          start_time, dtime;
+       struct timeval  start_time, dtime;
        char            msg[4096];
        int             i;
        int             timeout = rc_conf_int("radius_timeout");
@@ -320,11 +320,11 @@ int rc_acct_using_server(SERVER *acctserver,
         * Fill in Acct-Delay-Time
         */
 
-       dtime = 0;
-       if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
+       dtime.tv_sec = 0;
+       if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime.tv_sec, 0, VENDOR_NONE)) == NULL)
                return (ERROR_RC);
 
-       start_time = time(NULL);
+       get_time(&start_time);
        result = ERROR_RC;
        for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
                ; i++)
@@ -336,8 +336,9 @@ int rc_acct_using_server(SERVER *acctserver,
                rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
                            acctserver->port[i], timeout, retries);
 
-               dtime = time(NULL) - start_time;
-               rc_avpair_assign(adt_vp, &dtime, 0);
+               get_time(&dtime);
+               dtime.tv_sec -= start_time.tv_sec;
+               rc_avpair_assign(adt_vp, &dtime.tv_sec, 0);
 
                result = rc_send_server (&data, msg, NULL);
        }
index 2aebcd1c13ac1205511e32bade4d9d22442668b7..a4e4cec93ce1c21ebd8841813b6ee33cdc67d13f 100644 (file)
@@ -45,8 +45,8 @@ static int time_left(struct timeval *diff, struct timeval *exp)
 {
     struct timeval now;
 
-    if (gettimeofday(&now, NULL) < 0) {
-       error("gettimeofday: %m");
+    if (get_time(&now) < 0) {
+       error("get_time: %m");
        return 0;
     }
 
@@ -353,8 +353,8 @@ waitForPADO(PPPoEConnection *conn, int timeout)
     conn->seenMaxPayload = 0;
     conn->error = 0;
 
-    if (gettimeofday(&expire_at, NULL) < 0) {
-       error("gettimeofday (waitForPADO): %m");
+    if (get_time(&expire_at) < 0) {
+       error("get_time (waitForPADO): %m");
        return;
     }
     expire_at.tv_sec += timeout;
@@ -533,8 +533,8 @@ waitForPADS(PPPoEConnection *conn, int timeout)
     PPPoEPacket packet;
     int len;
 
-    if (gettimeofday(&expire_at, NULL) < 0) {
-       error("gettimeofday (waitForPADS): %m");
+    if (get_time(&expire_at) < 0) {
+       error("get_time (waitForPADS): %m");
        return;
     }
     expire_at.tv_sec += timeout;
index 6e3743fd9c97de74caf9638e717aa60525bebabb..9214aaeb6ff1c778032c922af3cc62bc6de10b5b 100644 (file)
@@ -705,6 +705,8 @@ int  cipxfaddr __P((int));
 #endif
 int  get_if_hwaddr __P((u_char *addr, char *name));
 char *get_first_ethernet __P((void));
+int get_time __P((struct timeval *));
+                               /* Get current time, monotonic if possible. */
 
 /* Procedures exported from options.c */
 int setipaddr __P((char *, char **, int)); /* Set local/remote ip addresses */
index 761aafc88f92530b27264d4bfa87215b66ff194c..b3959915938c19b758c38b0d267e0d2a95abce6a 100644 (file)
@@ -2966,3 +2966,38 @@ ether_to_eui64(eui64_t *p_eui64)
     return 1;
 }
 #endif
+
+/********************************************************************
+ *
+ * get_time - Get current time, monotonic if possible.
+ */
+int
+get_time(struct timeval *tv)
+{
+/* Old glibc (< 2.3.4) does define CLOCK_MONOTONIC, but kernel may have it.
+ * Runtime checking makes it safe. */
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC 1
+#endif
+    static int monotonic = -1;
+    struct timespec ts;
+    int ret;
+
+    if (monotonic) {
+       ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+       if (ret == 0) {
+           monotonic = 1;
+           if (tv) {
+               tv->tv_sec = ts.tv_sec;
+               tv->tv_usec = ts.tv_nsec / 1000;
+           }
+           return ret;
+       } else if (monotonic > 0)
+           return ret;
+
+       monotonic = 0;
+       warn("Couldn't use monotonic clock source: %m");
+    }
+
+    return gettimeofday(tv, NULL);
+}
index 93d90332e0d4f2116b17800970e082cf193640dd..83b1815080cd60be33e0e02aa283ed6bbb73b4be 100644 (file)
 #include <sys/dlpi.h>
 #include <sys/stat.h>
 #include <sys/mkdev.h>
+#include <sys/time.h>
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <net/route.h>
@@ -2783,3 +2784,13 @@ get_pty(master_fdp, slave_fdp, slave_name, uid)
 
     return 1;
 }
+
+/********************************************************************
+ *
+ * get_time - Get current time, monotonic if possible.
+ */
+int
+get_time(struct timeval *tv)
+{
+    return gettimeofday(tv, NULL);
+}
index c9a0b33715bc829a7dae446f5f5e1b29d1d78e26..485a44d8102cf665b878c384279896217789eb5f 100644 (file)
@@ -1072,7 +1072,7 @@ charshunt(ifd, ofd, record_file)
     pty_readable = stdin_readable = 1;
 
     ilevel = olevel = 0;
-    gettimeofday(&levelt, NULL);
+    get_time(&levelt);
     if (max_data_rate) {
        max_level = max_data_rate / 10;
        if (max_level < 100)
@@ -1121,7 +1121,7 @@ charshunt(ifd, ofd, record_file)
            int nbt;
            struct timeval now;
 
-           gettimeofday(&now, NULL);
+           get_time(&now);
            dt = (now.tv_sec - levelt.tv_sec
                  + (now.tv_usec - levelt.tv_usec) / 1e6);
            nbt = (int)(dt * max_data_rate);