mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 21:51:05 +00:00
net: socket infrastructure for SO_TIMESTAMPING
The overlap with the old SO_TIMESTAMP[NS] options is handled so that time stamping in software (net_enable_timestamp()) is enabled when SO_TIMESTAMP[NS] and/or SO_TIMESTAMPING_RX_SOFTWARE is set. It's disabled if all of these are off. Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ac45f602ee
commit
20d4947353
4 changed files with 185 additions and 41 deletions
82
net/socket.c
82
net/socket.c
|
@ -545,6 +545,18 @@ void sock_release(struct socket *sock)
|
|||
sock->file = NULL;
|
||||
}
|
||||
|
||||
int sock_tx_timestamp(struct msghdr *msg, struct sock *sk,
|
||||
union skb_shared_tx *shtx)
|
||||
{
|
||||
shtx->flags = 0;
|
||||
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
|
||||
shtx->hardware = 1;
|
||||
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
|
||||
shtx->software = 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(sock_tx_timestamp);
|
||||
|
||||
static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
struct msghdr *msg, size_t size)
|
||||
{
|
||||
|
@ -595,33 +607,65 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
return result;
|
||||
}
|
||||
|
||||
static int ktime2ts(ktime_t kt, struct timespec *ts)
|
||||
{
|
||||
if (kt.tv64) {
|
||||
*ts = ktime_to_timespec(kt);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
|
||||
*/
|
||||
void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
ktime_t kt = skb->tstamp;
|
||||
int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
|
||||
struct timespec ts[3];
|
||||
int empty = 1;
|
||||
struct skb_shared_hwtstamps *shhwtstamps =
|
||||
skb_hwtstamps(skb);
|
||||
|
||||
if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
||||
struct timeval tv;
|
||||
/* Race occurred between timestamp enabling and packet
|
||||
receiving. Fill in the current time for now. */
|
||||
if (kt.tv64 == 0)
|
||||
kt = ktime_get_real();
|
||||
skb->tstamp = kt;
|
||||
tv = ktime_to_timeval(kt);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
|
||||
} else {
|
||||
struct timespec ts;
|
||||
/* Race occurred between timestamp enabling and packet
|
||||
receiving. Fill in the current time for now. */
|
||||
if (kt.tv64 == 0)
|
||||
kt = ktime_get_real();
|
||||
skb->tstamp = kt;
|
||||
ts = ktime_to_timespec(kt);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
|
||||
/* Race occurred between timestamp enabling and packet
|
||||
receiving. Fill in the current time for now. */
|
||||
if (need_software_tstamp && skb->tstamp.tv64 == 0)
|
||||
__net_timestamp(skb);
|
||||
|
||||
if (need_software_tstamp) {
|
||||
if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
||||
struct timeval tv;
|
||||
skb_get_timestamp(skb, &tv);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
|
||||
sizeof(tv), &tv);
|
||||
} else {
|
||||
struct timespec ts;
|
||||
skb_get_timestampns(skb, &ts);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
|
||||
sizeof(ts), &ts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset(ts, 0, sizeof(ts));
|
||||
if (skb->tstamp.tv64 &&
|
||||
sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
|
||||
skb_get_timestampns(skb, ts + 0);
|
||||
empty = 0;
|
||||
}
|
||||
if (shhwtstamps) {
|
||||
if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
|
||||
ktime2ts(shhwtstamps->syststamp, ts + 1))
|
||||
empty = 0;
|
||||
if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
|
||||
ktime2ts(shhwtstamps->hwtstamp, ts + 2))
|
||||
empty = 0;
|
||||
}
|
||||
if (!empty)
|
||||
put_cmsg(msg, SOL_SOCKET,
|
||||
SCM_TIMESTAMPING, sizeof(ts), &ts);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue