net-timestamp: ACK timestamp for bytestreams
[cascardo/linux.git] / net / socket.c
index abf56b2..ae89569 100644 (file)
 #include <linux/sockios.h>
 #include <linux/atalk.h>
 #include <net/busy_poll.h>
+#include <linux/errqueue.h>
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
 unsigned int sysctl_net_busy_read __read_mostly;
@@ -612,10 +613,15 @@ EXPORT_SYMBOL(sock_release);
 void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 {
        *tx_flags = 0;
-       if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
+       if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
                *tx_flags |= SKBTX_HW_TSTAMP;
-       if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
+       if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
                *tx_flags |= SKBTX_SW_TSTAMP;
+       if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)
+               *tx_flags |= SKBTX_SCHED_TSTAMP;
+       if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)
+               *tx_flags |= SKBTX_ACK_TSTAMP;
+
        if (sock_flag(sk, SOCK_WIFI_STATUS))
                *tx_flags |= SKBTX_WIFI_STATUS;
 }
@@ -697,7 +703,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
        struct sk_buff *skb)
 {
        int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
-       struct timespec ts[3];
+       struct scm_timestamping tss;
        int empty = 1;
        struct skb_shared_hwtstamps *shhwtstamps =
                skb_hwtstamps(skb);
@@ -714,28 +720,25 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
                        put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP,
                                 sizeof(tv), &tv);
                } else {
-                       skb_get_timestampns(skb, &ts[0]);
+                       struct timespec ts;
+                       skb_get_timestampns(skb, &ts);
                        put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS,
-                                sizeof(ts[0]), &ts[0]);
+                                sizeof(ts), &ts);
                }
        }
 
-
-       memset(ts, 0, sizeof(ts));
-       if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
-           ktime_to_timespec_cond(skb->tstamp, ts + 0))
+       memset(&tss, 0, sizeof(tss));
+       if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
+            skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) &&
+           ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
+               empty = 0;
+       if (shhwtstamps &&
+           (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
+           ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
                empty = 0;
-       if (shhwtstamps) {
-               if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
-                   ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
-                       empty = 0;
-               if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
-                   ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
-                       empty = 0;
-       }
        if (!empty)
                put_cmsg(msg, SOL_SOCKET,
-                        SCM_TIMESTAMPING, sizeof(ts), &ts);
+                        SCM_TIMESTAMPING, sizeof(tss), &tss);
 }
 EXPORT_SYMBOL_GPL(__sock_recv_timestamp);