ip: support for TX timestamps on UDP and RAW sockets
authorPatrick Ohly <patrick.ohly@intel.com>
Thu, 12 Feb 2009 05:03:39 +0000 (05:03 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Feb 2009 06:43:38 +0000 (22:43 -0800)
Instructions for time stamping outgoing packets are take from the
socket layer and later copied into the new skb.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/timestamping.txt
include/net/ip.h
net/can/raw.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv4/udp.c

index a681a65b5bc7c9fa9b3bb5700ad63c36a2e2d44b..0e58b4539176a7e04c78c15bdcfde7b14e3f7c64 100644 (file)
@@ -56,6 +56,8 @@ and including the link layer, the scm_timestamping control message and
 a sock_extended_err control message with ee_errno==ENOMSG and
 ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
 bounced packet is ready for reading as far as select() is concerned.
+If the outgoing packet has to be fragmented, then only the first
+fragment is time stamped and returned to the sending socket.
 
 All three values correspond to the same event in time, but were
 generated in different ways. Each of these values may be empty (= all
index 10868139e656464dea5076e8b5672a9536b0ea01..4ac7577f98d0ba37808d3d4c52db8e0fc6c79592 100644 (file)
@@ -55,6 +55,7 @@ struct ipcm_cookie
        __be32                  addr;
        int                     oif;
        struct ip_options       *opt;
+       union skb_shared_tx     shtx;
 };
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
index 0703cba4bf9f29bc269be1fd57a0215e4f37d420..6aa154e806ae722c53e71603c0b22865526452a0 100644 (file)
@@ -646,6 +646,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto put_dev;
 
        err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
+       if (err < 0)
+               goto free_skb;
+       err = sock_tx_timestamp(msg, sk, skb_tx(skb));
        if (err < 0)
                goto free_skb;
        skb->dev = dev;
index 705b33b184a33cb3181e698b191c08565229ed56..382800a62b31fd1a862d6e4d66dac2259cbc66c3 100644 (file)
@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        inet->tos = ip_hdr(skb)->tos;
        daddr = ipc.addr = rt->rt_src;
        ipc.opt = NULL;
+       ipc.shtx.flags = 0;
        if (icmp_param->replyopts.optlen) {
                ipc.opt = &icmp_param->replyopts;
                if (ipc.opt->srr)
@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        inet_sk(sk)->tos = tos;
        ipc.addr = iph->saddr;
        ipc.opt = &icmp_param.replyopts;
+       ipc.shtx.flags = 0;
 
        {
                struct flowi fl = {
index 8ebe86dd72af159e2250bc315251cf61561cc38a..3e7e910c7c0fd6f229a9ee67a10936f24db36a3f 100644 (file)
@@ -935,6 +935,10 @@ alloc_new_skb:
                                                           sk->sk_allocation);
                                if (unlikely(skb == NULL))
                                        err = -ENOBUFS;
+                               else
+                                       /* only the initial fragment is
+                                          time stamped */
+                                       ipc->shtx.flags = 0;
                        }
                        if (skb == NULL)
                                goto error;
@@ -945,6 +949,7 @@ alloc_new_skb:
                        skb->ip_summed = csummode;
                        skb->csum = 0;
                        skb_reserve(skb, hh_len);
+                       *skb_tx(skb) = ipc->shtx;
 
                        /*
                         *      Find where to start putting bytes.
@@ -1364,6 +1369,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 
        daddr = ipc.addr = rt->rt_src;
        ipc.opt = NULL;
+       ipc.shtx.flags = 0;
 
        if (replyopts.opt.optlen) {
                ipc.opt = &replyopts.opt;
index dff8bc4e0facd1cc804397bfc7e9c581962ae7c9..f774651f0a47fb6d9de74b49438d16b0915fa536 100644 (file)
@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        ipc.addr = inet->saddr;
        ipc.opt = NULL;
+       ipc.shtx.flags = 0;
        ipc.oif = sk->sk_bound_dev_if;
 
        if (msg->msg_controllen) {
index c47c989cb1fb162b9fb71f8f27a580f4ba8088d0..4bd178a111d567a81a1219fdcd28ce0e10712b14 100644 (file)
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                return -EOPNOTSUPP;
 
        ipc.opt = NULL;
+       ipc.shtx.flags = 0;
 
        if (up->pending) {
                /*
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        ipc.addr = inet->saddr;
 
        ipc.oif = sk->sk_bound_dev_if;
+       err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+       if (err)
+               return err;
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sock_net(sk), msg, &ipc);
                if (err)