net: TX timestamps for IPv6 UDP packets
authorAnders Berggren <anders@halon.se>
Mon, 28 Feb 2011 20:32:11 +0000 (12:32 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Feb 2011 20:32:11 +0000 (12:32 -0800)
Enabling TX timestamps (SO_TIMESTAMPING) for IPv6 UDP packets, in
the same fashion as for IPv4. Necessary in order for NICs such as
Intel 82580 to timestamp IPv6 packets.

Signed-off-by: Anders Berggren <anders@halon.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/ip6_output.c

index 25a2647f99426251c1fd1c67d69a63ce4ffc8542..065b3f7614fb694c75a361ec0e2ad5c125163083 100644 (file)
@@ -1118,6 +1118,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        int err;
        int offset = 0;
        int csummode = CHECKSUM_NONE;
+       __u8 tx_flags = 0;
 
        if (flags&MSG_PROBE)
                return 0;
@@ -1202,6 +1203,13 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                }
        }
 
+       /* For UDP, check if TX timestamp is enabled */
+       if (sk->sk_type == SOCK_DGRAM) {
+               err = sock_tx_timestamp(sk, &tx_flags);
+               if (err)
+                       goto error;
+       }
+
        /*
         * Let's try using as much space as possible.
         * Use MTU if total length of the message fits into the MTU.
@@ -1306,6 +1314,12 @@ alloc_new_skb:
                                                           sk->sk_allocation);
                                if (unlikely(skb == NULL))
                                        err = -ENOBUFS;
+                               else {
+                                       /* Only the initial fragment
+                                        * is time stamped.
+                                        */
+                                       tx_flags = 0;
+                               }
                        }
                        if (skb == NULL)
                                goto error;
@@ -1317,6 +1331,9 @@ alloc_new_skb:
                        /* reserve for fragmentation */
                        skb_reserve(skb, hh_len+sizeof(struct frag_hdr));
 
+                       if (sk->sk_type == SOCK_DGRAM)
+                               skb_shinfo(skb)->tx_flags = tx_flags;
+
                        /*
                         *      Find where to start putting bytes
                         */