From owner-svn-src-head@freebsd.org Tue Nov 7 09:46:28 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2FB4DE53EDC; Tue, 7 Nov 2017 09:46:28 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0C7F274AC7; Tue, 7 Nov 2017 09:46:27 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vA79kRth003940; Tue, 7 Nov 2017 09:46:27 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vA79kRs0003937; Tue, 7 Nov 2017 09:46:27 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201711070946.vA79kRs0003937@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Tue, 7 Nov 2017 09:46:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r325507 - in head/sys: netinet netinet6 sys X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: in head/sys: netinet netinet6 sys X-SVN-Commit-Revision: 325507 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Nov 2017 09:46:28 -0000 Author: kib Date: Tue Nov 7 09:46:26 2017 New Revision: 325507 URL: https://svnweb.freebsd.org/changeset/base/325507 Log: Use hardware timestamps to report packet timestamps for SO_TIMESTAMP and other similar socket options. Provide new control message SCM_TIME_INFO to supply information about timestamp. Currently it indicates that the timestamp was hardware-assisted and high-precision, for software timestamps the message is not returned. Reserved fields are added to ABI to report additional info about it, it is expected that raw hardware clock value might be useful for some applications. Reviewed by: gallatin (previous version), hselasky Sponsored by: Mellanox Technologies MFC after: 2 weeks X-Differential revision: https://reviews.freebsd.org/D12638 Modified: head/sys/netinet/ip_input.c head/sys/netinet6/ip6_input.c head/sys/sys/socket.h Modified: head/sys/netinet/ip_input.c ============================================================================== --- head/sys/netinet/ip_input.c Tue Nov 7 09:29:14 2017 (r325506) +++ head/sys/netinet/ip_input.c Tue Nov 7 09:46:26 2017 (r325507) @@ -1143,40 +1143,96 @@ void ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, struct mbuf *m) { + bool stamped; + stamped = false; if ((inp->inp_socket->so_options & SO_BINTIME) || CHECK_SO_CT(inp->inp_socket, SO_TS_BINTIME)) { - struct bintime bt; + struct bintime boottimebin, bt; + struct timespec ts1; - bintime(&bt); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &ts1); + timespec2bintime(&ts1, &bt); + getboottimebin(&boottimebin); + bintime_add(&bt, &boottimebin); + } else { + bintime(&bt); + } *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt), SCM_BINTIME, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } } if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME_MICRO)) { + struct bintime boottimebin, bt1; + struct timespec ts1;; struct timeval tv; - microtime(&tv); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &ts1); + timespec2bintime(&ts1, &bt1); + getboottimebin(&boottimebin); + bintime_add(&bt1, &boottimebin); + bintime2timeval(&bt1, &tv); + } else { + microtime(&tv); + } *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_REALTIME)) { - struct timespec ts; + struct bintime boottimebin; + struct timespec ts, ts1; - nanotime(&ts); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &ts); + getboottimebin(&boottimebin); + bintime2timespec(&boottimebin, &ts1); + timespecadd(&ts, &ts1); + } else { + nanotime(&ts); + } *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts), SCM_REALTIME, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } } else if (CHECK_SO_CT(inp->inp_socket, SO_TS_MONOTONIC)) { struct timespec ts; - nanouptime(&ts); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) + mbuf_tstmp2timespec(m, &ts); + else + nanouptime(&ts); *mp = sbcreatecontrol((caddr_t)&ts, sizeof(ts), SCM_MONOTONIC, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { + mp = &(*mp)->m_next; + stamped = true; + } + } + if (stamped && (m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + struct sock_timestamp_info sti; + + bzero(&sti, sizeof(sti)); + sti.st_info_flags = ST_INFO_HW; + if ((m->m_flags & M_TSTMP_HPREC) != 0) + sti.st_info_flags |= ST_INFO_HW_HPREC; + *mp = sbcreatecontrol((caddr_t)&sti, sizeof(sti), SCM_TIME_INFO, + SOL_SOCKET); + if (*mp != NULL) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVDSTADDR) { Modified: head/sys/netinet6/ip6_input.c ============================================================================== --- head/sys/netinet6/ip6_input.c Tue Nov 7 09:29:14 2017 (r325506) +++ head/sys/netinet6/ip6_input.c Tue Nov 7 09:46:26 2017 (r325507) @@ -1221,42 +1221,96 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct bintime bt; struct timespec ts; } t; + struct bintime boottimebin, bt1; + struct timespec ts1; + bool stamped; + stamped = false; switch (inp->inp_socket->so_ts_clock) { case SO_TS_REALTIME_MICRO: - microtime(&t.tv); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &ts1); + timespec2bintime(&ts1, &bt1); + getboottimebin(&boottimebin); + bintime_add(&bt1, &boottimebin); + bintime2timeval(&bt1, &t.tv); + } else { + microtime(&t.tv); + } *mp = sbcreatecontrol((caddr_t) &t.tv, sizeof(t.tv), SCM_TIMESTAMP, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } break; case SO_TS_BINTIME: - bintime(&t.bt); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &ts1); + timespec2bintime(&ts1, &t.bt); + getboottimebin(&boottimebin); + bintime_add(&t.bt, &boottimebin); + } else { + bintime(&t.bt); + } *mp = sbcreatecontrol((caddr_t)&t.bt, sizeof(t.bt), SCM_BINTIME, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } break; case SO_TS_REALTIME: - nanotime(&t.ts); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) { + mbuf_tstmp2timespec(m, &t.ts); + getboottimebin(&boottimebin); + bintime2timespec(&boottimebin, &ts1); + timespecadd(&t.ts, &ts1); + } else { + nanotime(&t.ts); + } *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts), SCM_REALTIME, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } break; case SO_TS_MONOTONIC: - nanouptime(&t.ts); + if ((m->m_flags & (M_PKTHDR | M_TSTMP)) == (M_PKTHDR | + M_TSTMP)) + mbuf_tstmp2timespec(m, &t.ts); + else + nanouptime(&t.ts); *mp = sbcreatecontrol((caddr_t)&t.ts, sizeof(t.ts), SCM_MONOTONIC, SOL_SOCKET); - if (*mp) + if (*mp != NULL) { mp = &(*mp)->m_next; + stamped = true; + } break; default: panic("unknown (corrupted) so_ts_clock"); + } + if (stamped && (m->m_flags & (M_PKTHDR | M_TSTMP)) == + (M_PKTHDR | M_TSTMP)) { + struct sock_timestamp_info sti; + + bzero(&sti, sizeof(sti)); + sti.st_info_flags = ST_INFO_HW; + if ((m->m_flags & M_TSTMP_HPREC) != 0) + sti.st_info_flags |= ST_INFO_HW_HPREC; + *mp = sbcreatecontrol((caddr_t)&sti, sizeof(sti), + SCM_TIME_INFO, SOL_SOCKET); + if (*mp != NULL) + mp = &(*mp)->m_next; } } #endif Modified: head/sys/sys/socket.h ============================================================================== --- head/sys/sys/socket.h Tue Nov 7 09:29:14 2017 (r325506) +++ head/sys/sys/socket.h Tue Nov 7 09:46:26 2017 (r325507) @@ -563,6 +563,17 @@ struct sockcred { #define SCM_BINTIME 0x04 /* timestamp (struct bintime) */ #define SCM_REALTIME 0x05 /* timestamp (struct timespec) */ #define SCM_MONOTONIC 0x06 /* timestamp (struct timespec) */ +#define SCM_TIME_INFO 0x07 /* timestamp info */ + +struct sock_timestamp_info { + __uint32_t st_info_flags; + __uint32_t st_info_pad0; + __uint64_t st_info_rsv[7]; +}; + +#define ST_INFO_HW 0x0001 /* SCM_TIMESTAMP was hw */ +#define ST_INFO_HW_HPREC 0x0002 /* SCM_TIMESTAMP was hw-assisted + on entrance */ #endif #if __BSD_VISIBLE