ntp: Calculate transmit time from receive time and monotonic delta
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 25 Sep 2012 10:28:02 +0000 (13:28 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 1 Oct 2012 10:19:17 +0000 (13:19 +0300)
Calculate transmit time used in NTP as the reception time minus
the delta of the monotonic receive and transmit times. When
calculated this way, it does not matter if the time happens to
be set to something else between the sending and receiving of the
NTP packet.

On sending the added monotonic time and the previous transmit time
are saved at the same point in time. On reception the monotonic time
is evaluated after the packet has been received by ConnMan. This is
in contrast to the actual reception wall clock time which is added
by the kernel. The difference between the reception times on a normal
system is about 100µs, which is neglible.

src/ntp.c

index 2ef0cf2..b588c99 100644 (file)
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -110,7 +110,7 @@ struct ntp_msg {
 #define NTP_PRECISION_NS   -29
 
 static guint channel_watch = 0;
-static struct timeval transmit_timeval;
+static struct timespec mtx_time;
 static int transmit_fd = 0;
 
 static char *timeserver = NULL;
@@ -146,6 +146,7 @@ static void send_packet(int fd, const char *server)
 {
        struct ntp_msg msg;
        struct sockaddr_in addr;
+       struct timeval transmit_timeval;
        ssize_t len;
 
        /*
@@ -166,6 +167,7 @@ static void send_packet(int fd, const char *server)
        addr.sin_addr.s_addr = inet_addr(server);
 
        gettimeofday(&transmit_timeval, NULL);
+       clock_gettime(CLOCK_MONOTONIC, &mtx_time);
 
        msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
        msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
@@ -214,10 +216,11 @@ static void reset_timeout(void)
        retries = 0;
 }
 
-static void decode_msg(void *base, size_t len, struct timeval *tv)
+static void decode_msg(void *base, size_t len, struct timeval *tv,
+               struct timespec *mrx_time)
 {
        struct ntp_msg *msg = base;
-       double org, rec, xmt, dst;
+       double m_delta, org, rec, xmt, dst;
        double delay, offset;
        static guint transmit_delay;
 
@@ -260,8 +263,10 @@ static void decode_msg(void *base, size_t len, struct timeval *tv)
                return;
        }
 
-       org = transmit_timeval.tv_sec +
-                       (1.0e-6 * transmit_timeval.tv_usec) + OFFSET_1900_1970;
+       m_delta = mrx_time->tv_sec - mtx_time.tv_sec +
+               1.0e-9 * (mrx_time->tv_nsec - mtx_time.tv_nsec);
+
+       org = tv->tv_sec + (1.0e-6 * tv->tv_usec) - m_delta + OFFSET_1900_1970;
        rec = ntohl(msg->rectime.seconds) +
                        ((double) ntohl(msg->rectime.fraction) / UINT_MAX);
        xmt = ntohl(msg->xmttime.seconds) +
@@ -334,6 +339,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
        struct iovec iov;
        struct cmsghdr *cmsg;
        struct timeval *tv;
+       struct timespec mrx_time;
        char aux[128];
        ssize_t len;
        int fd;
@@ -360,6 +366,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
                return TRUE;
 
        tv = NULL;
+       clock_gettime(CLOCK_MONOTONIC, &mrx_time);
 
        for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
                if (cmsg->cmsg_level != SOL_SOCKET)
@@ -372,7 +379,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition,
                }
        }
 
-       decode_msg(iov.iov_base, iov.iov_len, tv);
+       decode_msg(iov.iov_base, iov.iov_len, tv, &mrx_time);
 
        return TRUE;
 }