svn commit: r338617 - in stable/11: lib/libc/sys sys/compat/freebsd32 sys/kern sys/netinet sys/netinet6 sys/sys tools/regression/sockets/udp_pingpong tools/regression/sockets/unix_cmsg
Maxim Sobolev
sobomax at FreeBSD.org
Wed Sep 12 18:52:22 UTC 2018
Author: sobomax
Date: Wed Sep 12 18:52:18 2018
New Revision: 338617
URL: https://svnweb.freebsd.org/changeset/base/338617
Log:
MFC r312296 and r323254, which is new a socket option
SO_TS_CLOCK to pick from several different clock sources to
return timestamps when SO_TIMESTAMP is enabled and two
new nanosecond-precision timestamp types. This also fixes
recvmsg32() system call to properly down-convert layout of the
64-bit structures to match what 32-bit app(s) expect.
Bump __FreeBSD_version to indicate presence of a new
functionality.
Differential Revision: https://reviews.freebsd.org/D9171
Added:
stable/11/tools/regression/sockets/udp_pingpong/
- copied from r312296, head/tools/regression/sockets/udp_pingpong/
Modified:
stable/11/lib/libc/sys/getsockopt.2
stable/11/sys/compat/freebsd32/freebsd32.h
stable/11/sys/compat/freebsd32/freebsd32_misc.c
stable/11/sys/kern/uipc_socket.c
stable/11/sys/kern/uipc_usrreq.c
stable/11/sys/netinet/ip_input.c
stable/11/sys/netinet6/ip6_input.c
stable/11/sys/sys/param.h
stable/11/sys/sys/socket.h
stable/11/sys/sys/socketvar.h
stable/11/tools/regression/sockets/unix_cmsg/Makefile
stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/lib/libc/sys/getsockopt.2
==============================================================================
--- stable/11/lib/libc/sys/getsockopt.2 Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/lib/libc/sys/getsockopt.2 Wed Sep 12 18:52:18 2018 (r338617)
@@ -187,6 +187,7 @@ The following options are recognized in
.It Dv SO_LISTENQLEN Ta "get complete queue length of the socket (get only)"
.It Dv SO_LISTENINCQLEN Ta "get incomplete queue length of the socket (get only)"
.It Dv SO_USER_COOKIE Ta "set the 'so_user_cookie' value for the socket (uint32_t, set only)"
+.It Dv SO_TS_CLOCK Ta "set specific format of timestamp returned by SO_TIMESTAMP"
.El
.Pp
.Dv SO_DEBUG
@@ -435,7 +436,7 @@ for
.Dv SO_BINTIME .
The
.Vt cmsghdr
-fields have the following values for TIMESTAMP:
+fields have the following values for TIMESTAMP by default:
.Bd -literal
cmsg_len = CMSG_LEN(sizeof(struct timeval));
cmsg_level = SOL_SOCKET;
@@ -449,6 +450,24 @@ and for
cmsg_level = SOL_SOCKET;
cmsg_type = SCM_BINTIME;
.Ed
+.Pp
+Additional timestamp types are available by following
+.Dv SO_TIMESTAMP
+with
+.Dv SO_TS_CLOCK ,
+which requests specific timestamp format to be returned instead of
+.Dv SCM_TIMESTAMP when
+.Dv SO_TIMESTAMP is enabled.
+The following
+.Dv SO_TS_CLOCK
+values are recognized in
+.Fx :
+.Bl -column SO_TS_CLOCK -offset indent
+.It Dv SO_TS_REALTIME_MICRO Ta "realtime (SCM_TIMESTAMP, struct timeval), default"
+.It Dv SO_TS_BINTIME Ta "realtime (SCM_BINTIME, struct bintime)"
+.It Dv SO_TS_REALTIME Ta "realtime (SCM_REALTIME, struct timespec)"
+.It Dv SO_TS_MONOTONIC Ta "monotonic time (SCM_MONOTONIC, struct timespec)"
+.El
.Pp
.Dv SO_ACCEPTCONN ,
.Dv SO_TYPE ,
Modified: stable/11/sys/compat/freebsd32/freebsd32.h
==============================================================================
--- stable/11/sys/compat/freebsd32/freebsd32.h Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/compat/freebsd32/freebsd32.h Wed Sep 12 18:52:18 2018 (r338617)
@@ -78,6 +78,15 @@ struct itimerspec32 {
TS_CP((src), (dst), it_value); \
} while (0)
+struct bintime32 {
+ uint32_t sec;
+ uint32_t frac[2];
+};
+#define BT_CP(src, dst, fld) do { \
+ CP((src).fld, (dst).fld, sec); \
+ *(uint64_t *)&(dst).fld.frac[0] = (src).fld.frac; \
+} while (0)
+
struct rusage32 {
struct timeval32 ru_utime;
struct timeval32 ru_stime;
Modified: stable/11/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/11/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/compat/freebsd32/freebsd32_misc.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -117,6 +117,7 @@ FEATURE(compat_freebsd_32bit, "Compatible with 32-bit
CTASSERT(sizeof(struct timeval32) == 8);
CTASSERT(sizeof(struct timespec32) == 8);
CTASSERT(sizeof(struct itimerval32) == 16);
+CTASSERT(sizeof(struct bintime32) == 12);
#endif
CTASSERT(sizeof(struct statfs32) == 256);
#ifndef __mips__
@@ -904,12 +905,67 @@ freebsd32_copyoutmsghdr(struct msghdr *msg, struct msg
#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \
FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
+
+static size_t
+freebsd32_cmsg_convert(struct cmsghdr *cm, void *data, socklen_t datalen)
+{
+ size_t copylen;
+ union {
+ struct timespec32 ts;
+ struct timeval32 tv;
+ struct bintime32 bt;
+ } tmp32;
+
+ union {
+ struct timespec ts;
+ struct timeval tv;
+ struct bintime bt;
+ } *in;
+
+ in = data;
+ copylen = 0;
+ switch (cm->cmsg_level) {
+ case SOL_SOCKET:
+ switch (cm->cmsg_type) {
+ case SCM_TIMESTAMP:
+ TV_CP(*in, tmp32, tv);
+ copylen = sizeof(tmp32.tv);
+ break;
+
+ case SCM_BINTIME:
+ BT_CP(*in, tmp32, bt);
+ copylen = sizeof(tmp32.bt);
+ break;
+
+ case SCM_REALTIME:
+ case SCM_MONOTONIC:
+ TS_CP(*in, tmp32, ts);
+ copylen = sizeof(tmp32.ts);
+ break;
+
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (copylen == 0)
+ return (datalen);
+
+ KASSERT((datalen >= copylen), ("corrupted cmsghdr"));
+
+ bcopy(&tmp32, data, copylen);
+ return (copylen);
+}
+
static int
freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
{
struct cmsghdr *cm;
void *data;
- socklen_t clen, datalen;
+ socklen_t clen, datalen, datalen_out;
int error;
caddr_t ctlbuf;
int len, maxlen, copylen;
@@ -933,16 +989,16 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf
cm->cmsg_len > clen) {
error = EINVAL;
break;
- }
+ }
data = CMSG_DATA(cm);
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
+ datalen_out = freebsd32_cmsg_convert(cm, data, datalen);
/* Adjust message length */
cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
- datalen;
+ datalen_out;
-
/* Copy cmsghdr */
copylen = sizeof(struct cmsghdr);
if (len < copylen) {
@@ -950,7 +1006,7 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf
copylen = len;
}
- error = copyout(cm,ctlbuf,copylen);
+ error = copyout(cm, ctlbuf, copylen);
if (error)
goto exit;
@@ -961,13 +1017,13 @@ freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf
break;
/* Copy data */
- copylen = datalen;
+ copylen = datalen_out;
if (len < copylen) {
msg->msg_flags |= MSG_CTRUNC;
copylen = len;
}
- error = copyout(data,ctlbuf,copylen);
+ error = copyout(data, ctlbuf, copylen);
if (error)
goto exit;
Modified: stable/11/sys/kern/uipc_socket.c
==============================================================================
--- stable/11/sys/kern/uipc_socket.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/kern/uipc_socket.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -2696,6 +2696,18 @@ sosetopt(struct socket *so, struct sockopt *sopt)
#endif
break;
+ case SO_TS_CLOCK:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ goto bad;
+ if (optval < 0 || optval > SO_TS_CLOCK_MAX) {
+ error = EINVAL;
+ goto bad;
+ }
+ so->so_ts_clock = optval;
+ break;
+
default:
if (V_socket_hhh[HHOOK_SOCKET_OPT]->hhh_nhooks > 0)
error = hhook_run_socket(so, sopt,
@@ -2881,6 +2893,10 @@ integer:
case SO_LISTENINCQLEN:
optval = so->so_incqlen;
+ goto integer;
+
+ case SO_TS_CLOCK:
+ optval = so->so_ts_clock;
goto integer;
default:
Modified: stable/11/sys/kern/uipc_usrreq.c
==============================================================================
--- stable/11/sys/kern/uipc_usrreq.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/kern/uipc_usrreq.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -1908,6 +1908,7 @@ unp_internalize(struct mbuf **controlp, struct thread
struct filedescent *fde, **fdep, *fdev;
struct file *fp;
struct timeval *tv;
+ struct timespec *ts;
int i, *fdp;
void *data;
socklen_t clen = control->m_len, datalen;
@@ -2026,6 +2027,30 @@ unp_internalize(struct mbuf **controlp, struct thread
bt = (struct bintime *)
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
bintime(bt);
+ break;
+
+ case SCM_REALTIME:
+ *controlp = sbcreatecontrol(NULL, sizeof(*ts),
+ SCM_REALTIME, SOL_SOCKET);
+ if (*controlp == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ ts = (struct timespec *)
+ CMSG_DATA(mtod(*controlp, struct cmsghdr *));
+ nanotime(ts);
+ break;
+
+ case SCM_MONOTONIC:
+ *controlp = sbcreatecontrol(NULL, sizeof(*ts),
+ SCM_MONOTONIC, SOL_SOCKET);
+ if (*controlp == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ ts = (struct timespec *)
+ CMSG_DATA(mtod(*controlp, struct cmsghdr *));
+ nanouptime(ts);
break;
default:
Modified: stable/11/sys/netinet/ip_input.c
==============================================================================
--- stable/11/sys/netinet/ip_input.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/netinet/ip_input.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -1138,30 +1138,48 @@ ip_forward(struct mbuf *m, int srcrt)
icmp_error(mcopy, type, code, dest.s_addr, mtu);
}
+#define CHECK_SO_CT(sp, ct) \
+ (((sp->so_options & SO_TIMESTAMP) && (sp->so_ts_clock == ct)) ? 1 : 0)
+
void
ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
struct mbuf *m)
{
- if (inp->inp_socket->so_options & (SO_BINTIME | SO_TIMESTAMP)) {
+ if ((inp->inp_socket->so_options & SO_BINTIME) ||
+ CHECK_SO_CT(inp->inp_socket, SO_TS_BINTIME)) {
struct bintime bt;
bintime(&bt);
- if (inp->inp_socket->so_options & SO_BINTIME) {
- *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt),
- SCM_BINTIME, SOL_SOCKET);
- if (*mp)
- mp = &(*mp)->m_next;
- }
- if (inp->inp_socket->so_options & SO_TIMESTAMP) {
- struct timeval tv;
+ *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt),
+ SCM_BINTIME, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+ if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME_MICRO)) {
+ struct timeval tv;
- bintime2timeval(&bt, &tv);
- *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv),
- SCM_TIMESTAMP, SOL_SOCKET);
- if (*mp)
- mp = &(*mp)->m_next;
- }
+ microtime(&tv);
+ *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv),
+ SCM_TIMESTAMP, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME)) {
+ struct timespec ts;
+
+ nanotime(&ts);
+ *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts),
+ SCM_REALTIME, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_MONOTONIC)) {
+ struct timespec ts;
+
+ nanouptime(&ts);
+ *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts),
+ SCM_MONOTONIC, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
}
if (inp->inp_flags & INP_RECVDSTADDR) {
*mp = sbcreatecontrol((caddr_t)&ip->ip_dst,
Modified: stable/11/sys/netinet6/ip6_input.c
==============================================================================
--- stable/11/sys/netinet6/ip6_input.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/netinet6/ip6_input.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -1213,13 +1213,48 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m,
#ifdef SO_TIMESTAMP
if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
- struct timeval tv;
+ union {
+ struct timeval tv;
+ struct bintime bt;
+ struct timespec ts;
+ } t;
- microtime(&tv);
- *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
- SCM_TIMESTAMP, SOL_SOCKET);
- if (*mp)
- mp = &(*mp)->m_next;
+ switch (inp->inp_socket->so_ts_clock) {
+ case SO_TS_REALTIME_MICRO:
+ microtime(&t.tv);
+ *mp = sbcreatecontrol((caddr_t) &t.tv, sizeof(t.tv),
+ SCM_TIMESTAMP, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ break;
+
+ case SO_TS_BINTIME:
+ bintime(&t.bt);
+ *mp = sbcreatecontrol((caddr_t)&t.bt, sizeof(t.bt),
+ SCM_BINTIME, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ break;
+
+ case SO_TS_REALTIME:
+ nanotime(&t.ts);
+ *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts),
+ SCM_REALTIME, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ break;
+
+ case SO_TS_MONOTONIC:
+ nanouptime(&t.ts);
+ *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts),
+ SCM_MONOTONIC, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ break;
+
+ default:
+ panic("unknown (corrupted) so_ts_clock");
+ }
}
#endif
Modified: stable/11/sys/sys/param.h
==============================================================================
--- stable/11/sys/sys/param.h Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/sys/param.h Wed Sep 12 18:52:18 2018 (r338617)
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1102501 /* Master, propagated to newvers */
+#define __FreeBSD_version 1102502 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Modified: stable/11/sys/sys/socket.h
==============================================================================
--- stable/11/sys/sys/socket.h Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/sys/socket.h Wed Sep 12 18:52:18 2018 (r338617)
@@ -158,8 +158,18 @@ typedef __uintptr_t uintptr_t;
#define SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */
#define SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */
#define SO_PROTOTYPE SO_PROTOCOL /* alias for SO_PROTOCOL (SunOS name) */
+#define SO_TS_CLOCK 0x1017 /* clock type used for SO_TIMESTAMP */
#endif
+#if __BSD_VISIBLE
+#define SO_TS_REALTIME_MICRO 0 /* microsecond resolution, realtime */
+#define SO_TS_BINTIME 1 /* sub-nanosecond resolution, realtime */
+#define SO_TS_REALTIME 2 /* nanosecond resolution, realtime */
+#define SO_TS_MONOTONIC 3 /* nanosecond resolution, monotonic */
+#define SO_TS_DEFAULT SO_TS_REALTIME_MICRO
+#define SO_TS_CLOCK_MAX SO_TS_MONOTONIC
+#endif
+
/*
* Space reserved for new socket options added by third-party vendors.
* This range applies to all socket option levels. New socket options
@@ -534,6 +544,8 @@ struct sockcred {
#define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */
#define SCM_CREDS 0x03 /* process creds (struct cmsgcred) */
#define SCM_BINTIME 0x04 /* timestamp (struct bintime) */
+#define SCM_REALTIME 0x05 /* timestamp (struct timespec) */
+#define SCM_MONOTONIC 0x06 /* timestamp (struct timespec) */
#endif
#if __BSD_VISIBLE
Modified: stable/11/sys/sys/socketvar.h
==============================================================================
--- stable/11/sys/sys/socketvar.h Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/sys/sys/socketvar.h Wed Sep 12 18:52:18 2018 (r338617)
@@ -127,6 +127,8 @@ struct socket {
int so_fibnum; /* routing domain for this socket */
uint32_t so_user_cookie;
+ int so_ts_clock; /* type of the clock used for timestamps */
+
void *so_pspare[2]; /* packet pacing / general use */
int so_ispare[2]; /* packet pacing / general use */
};
Modified: stable/11/tools/regression/sockets/unix_cmsg/Makefile
==============================================================================
--- stable/11/tools/regression/sockets/unix_cmsg/Makefile Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/tools/regression/sockets/unix_cmsg/Makefile Wed Sep 12 18:52:18 2018 (r338617)
@@ -4,4 +4,29 @@ PROG= unix_cmsg
MAN=
WARNS?= 3
+REXP_bintime= 's|%%TTYPE%%|bintime|g ; s|%%DTYPE%%|bintime|g ; \
+ s|%%SCM_TTYPE%%|SCM_BINTIME|g ; \
+ s|%%MAJ_MEMB%%|sec|g ; s|%%MIN_MEMB%%|frac|g'
+REXP_timeval= 's|%%TTYPE%%|timeval|g ; s|%%DTYPE%%|timeval|g ; \
+ s|%%SCM_TTYPE%%|SCM_TIMESTAMP|g ; \
+ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_usec|g'
+REXP_timespec_real= 's|%%TTYPE%%|timespec_real|g ; s|%%DTYPE%%|timespec|g ; \
+ s|%%SCM_TTYPE%%|SCM_REALTIME|g ; \
+ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g'
+REXP_timespec_mono= 's|%%TTYPE%%|timespec_mono|g ; s|%%DTYPE%%|timespec|g ; \
+ s|%%SCM_TTYPE%%|SCM_MONOTONIC|g ; \
+ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g'
+
+.for ttype in bintime timeval timespec_real timespec_mono
+AUTOSRCS+= t_${ttype}.h t_${ttype}.c
+
+t_${ttype}.o: t_${ttype}.c t_${ttype}.h
+
+t_${ttype}.c: t_xxxtime.c.in
+ sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET}
+
+t_${ttype}.h: t_xxxtime.h.in
+ sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET}
+.endfor
+
.include <bsd.prog.mk>
Modified: stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c
==============================================================================
--- stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c Wed Sep 12 15:06:30 2018 (r338616)
+++ stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c Wed Sep 12 18:52:18 2018 (r338617)
@@ -52,6 +52,18 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
+#include "uc_common.h"
+#include "t_cmsgcred.h"
+#include "t_bintime.h"
+#include "t_generic.h"
+#include "t_peercred.h"
+#include "t_timeval.h"
+#include "t_sockcred.h"
+#include "t_cmsgcred_sockcred.h"
+#include "t_cmsg_len.h"
+#include "t_timespec_real.h"
+#include "t_timespec_mono.h"
+
/*
* There are tables with tests descriptions and pointers to test
* functions. Each t_*() function returns 0 if its test passed,
@@ -135,7 +147,19 @@ static const struct test_func test_stream_tbl[] = {
{
.func = t_peercred,
.desc = "Check LOCAL_PEERCRED socket option"
+ },
+#if defined(SCM_REALTIME)
+ {
+ .func = t_timespec_real,
+ .desc = "Sending, receiving realtime"
+ },
+#endif
+#if defined(SCM_MONOTONIC)
+ {
+ .func = t_timespec_mono,
+ .desc = "Sending, receiving monotonic time (uptime)"
}
+#endif
};
#define TEST_STREAM_TBL_SIZE \
@@ -170,6 +194,18 @@ static const struct test_func test_dgram_tbl[] = {
{
.func = t_cmsg_len,
.desc = "Check cmsghdr.cmsg_len"
+ },
+#endif
+#if defined(SCM_REALTIME)
+ {
+ .func = t_timespec_real,
+ .desc = "Sending, receiving realtime"
+ },
+#endif
+#if defined(SCM_MONOTONIC)
+ {
+ .func = t_timespec_mono,
+ .desc = "Sending, receiving monotonic time (uptime)"
}
#endif
};
More information about the svn-src-all
mailing list