diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 4deec1b3b76e..0e533ca7e9d6 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -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) { diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 167193a3758c..eea5e14eeed4 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1221,43 +1221,97 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, 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 diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 33678c5d7690..95fddcb2d25c 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -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