diff options
author | Willem de Bruijn <willemb@google.com> | 2014-08-04 22:11:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-05 19:35:53 -0400 |
commit | f24b9be5957b38bb420b838115040dc2031b7d0c (patch) | |
tree | 9fdb50bbe86f08ff9c012137fa854d45e156b8f9 /net/socket.c | |
parent | a2b81b35f9e5ade210e4df2001f7a30ac390114d (diff) |
net-timestamp: extend SCM_TIMESTAMPING ancillary data struct
Applications that request kernel tx timestamps with SO_TIMESTAMPING
read timestamps as recvmsg() ancillary data. The response is defined
implicitly as timespec[3].
1) define struct scm_timestamping explicitly and
2) add support for new tstamp types. On tx, scm_timestamping always
accompanies a sock_extended_err. Define previously unused field
ee_info to signal the type of ts[0]. Introduce SCM_TSTAMP_SND to
define the existing behavior.
The reception path is not modified. On rx, no struct similar to
sock_extended_err is passed along with SCM_TIMESTAMPING.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/socket.c b/net/socket.c index d8222c025061..dc0cc5d95ee5 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -106,6 +106,7 @@ | |||
106 | #include <linux/sockios.h> | 106 | #include <linux/sockios.h> |
107 | #include <linux/atalk.h> | 107 | #include <linux/atalk.h> |
108 | #include <net/busy_poll.h> | 108 | #include <net/busy_poll.h> |
109 | #include <linux/errqueue.h> | ||
109 | 110 | ||
110 | #ifdef CONFIG_NET_RX_BUSY_POLL | 111 | #ifdef CONFIG_NET_RX_BUSY_POLL |
111 | unsigned int sysctl_net_busy_read __read_mostly; | 112 | unsigned int sysctl_net_busy_read __read_mostly; |
@@ -697,7 +698,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
697 | struct sk_buff *skb) | 698 | struct sk_buff *skb) |
698 | { | 699 | { |
699 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); | 700 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
700 | struct timespec ts[3]; | 701 | struct scm_timestamping tss; |
701 | int empty = 1; | 702 | int empty = 1; |
702 | struct skb_shared_hwtstamps *shhwtstamps = | 703 | struct skb_shared_hwtstamps *shhwtstamps = |
703 | skb_hwtstamps(skb); | 704 | skb_hwtstamps(skb); |
@@ -714,24 +715,25 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
714 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, | 715 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
715 | sizeof(tv), &tv); | 716 | sizeof(tv), &tv); |
716 | } else { | 717 | } else { |
717 | skb_get_timestampns(skb, &ts[0]); | 718 | struct timespec ts; |
719 | skb_get_timestampns(skb, &ts); | ||
718 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | 720 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, |
719 | sizeof(ts[0]), &ts[0]); | 721 | sizeof(ts), &ts); |
720 | } | 722 | } |
721 | } | 723 | } |
722 | 724 | ||
723 | 725 | memset(&tss, 0, sizeof(tss)); | |
724 | memset(ts, 0, sizeof(ts)); | 726 | if ((sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) || |
725 | if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) && | 727 | skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) && |
726 | ktime_to_timespec_cond(skb->tstamp, ts + 0)) | 728 | ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) |
727 | empty = 0; | 729 | empty = 0; |
728 | if (shhwtstamps && | 730 | if (shhwtstamps && |
729 | sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && | 731 | sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && |
730 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2)) | 732 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) |
731 | empty = 0; | 733 | empty = 0; |
732 | if (!empty) | 734 | if (!empty) |
733 | put_cmsg(msg, SOL_SOCKET, | 735 | put_cmsg(msg, SOL_SOCKET, |
734 | SCM_TIMESTAMPING, sizeof(ts), &ts); | 736 | SCM_TIMESTAMPING, sizeof(tss), &tss); |
735 | } | 737 | } |
736 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 738 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
737 | 739 | ||