diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2009-02-12 00:03:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 01:43:38 -0500 |
commit | 51f31cabe3ce5345b51e4a4f82138b38c4d5dc91 (patch) | |
tree | f59504adbbe37e6e28ac78e6a49f045508daa78e | |
parent | 20d4947353be60e909e6b1a79d241457edd6833f (diff) |
ip: support for TX timestamps on UDP and RAW sockets
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>
-rw-r--r-- | Documentation/networking/timestamping.txt | 2 | ||||
-rw-r--r-- | include/net/ip.h | 1 | ||||
-rw-r--r-- | net/can/raw.c | 3 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 6 | ||||
-rw-r--r-- | net/ipv4/raw.c | 1 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 |
7 files changed, 19 insertions, 0 deletions
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index a681a65b5bc7..0e58b4539176 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt | |||
@@ -56,6 +56,8 @@ and including the link layer, the scm_timestamping control message and | |||
56 | a sock_extended_err control message with ee_errno==ENOMSG and | 56 | a sock_extended_err control message with ee_errno==ENOMSG and |
57 | ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending | 57 | ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending |
58 | bounced packet is ready for reading as far as select() is concerned. | 58 | bounced packet is ready for reading as far as select() is concerned. |
59 | If the outgoing packet has to be fragmented, then only the first | ||
60 | fragment is time stamped and returned to the sending socket. | ||
59 | 61 | ||
60 | All three values correspond to the same event in time, but were | 62 | All three values correspond to the same event in time, but were |
61 | generated in different ways. Each of these values may be empty (= all | 63 | generated in different ways. Each of these values may be empty (= all |
diff --git a/include/net/ip.h b/include/net/ip.h index 10868139e656..4ac7577f98d0 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -55,6 +55,7 @@ struct ipcm_cookie | |||
55 | __be32 addr; | 55 | __be32 addr; |
56 | int oif; | 56 | int oif; |
57 | struct ip_options *opt; | 57 | struct ip_options *opt; |
58 | union skb_shared_tx shtx; | ||
58 | }; | 59 | }; |
59 | 60 | ||
60 | #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) | 61 | #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) |
diff --git a/net/can/raw.c b/net/can/raw.c index 0703cba4bf9f..6aa154e806ae 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -648,6 +648,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
648 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 648 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
649 | if (err < 0) | 649 | if (err < 0) |
650 | goto free_skb; | 650 | goto free_skb; |
651 | err = sock_tx_timestamp(msg, sk, skb_tx(skb)); | ||
652 | if (err < 0) | ||
653 | goto free_skb; | ||
651 | skb->dev = dev; | 654 | skb->dev = dev; |
652 | skb->sk = sk; | 655 | skb->sk = sk; |
653 | 656 | ||
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 705b33b184a3..382800a62b31 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -375,6 +375,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
375 | inet->tos = ip_hdr(skb)->tos; | 375 | inet->tos = ip_hdr(skb)->tos; |
376 | daddr = ipc.addr = rt->rt_src; | 376 | daddr = ipc.addr = rt->rt_src; |
377 | ipc.opt = NULL; | 377 | ipc.opt = NULL; |
378 | ipc.shtx.flags = 0; | ||
378 | if (icmp_param->replyopts.optlen) { | 379 | if (icmp_param->replyopts.optlen) { |
379 | ipc.opt = &icmp_param->replyopts; | 380 | ipc.opt = &icmp_param->replyopts; |
380 | if (ipc.opt->srr) | 381 | if (ipc.opt->srr) |
@@ -532,6 +533,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
532 | inet_sk(sk)->tos = tos; | 533 | inet_sk(sk)->tos = tos; |
533 | ipc.addr = iph->saddr; | 534 | ipc.addr = iph->saddr; |
534 | ipc.opt = &icmp_param.replyopts; | 535 | ipc.opt = &icmp_param.replyopts; |
536 | ipc.shtx.flags = 0; | ||
535 | 537 | ||
536 | { | 538 | { |
537 | struct flowi fl = { | 539 | struct flowi fl = { |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8ebe86dd72af..3e7e910c7c0f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -935,6 +935,10 @@ alloc_new_skb: | |||
935 | sk->sk_allocation); | 935 | sk->sk_allocation); |
936 | if (unlikely(skb == NULL)) | 936 | if (unlikely(skb == NULL)) |
937 | err = -ENOBUFS; | 937 | err = -ENOBUFS; |
938 | else | ||
939 | /* only the initial fragment is | ||
940 | time stamped */ | ||
941 | ipc->shtx.flags = 0; | ||
938 | } | 942 | } |
939 | if (skb == NULL) | 943 | if (skb == NULL) |
940 | goto error; | 944 | goto error; |
@@ -945,6 +949,7 @@ alloc_new_skb: | |||
945 | skb->ip_summed = csummode; | 949 | skb->ip_summed = csummode; |
946 | skb->csum = 0; | 950 | skb->csum = 0; |
947 | skb_reserve(skb, hh_len); | 951 | skb_reserve(skb, hh_len); |
952 | *skb_tx(skb) = ipc->shtx; | ||
948 | 953 | ||
949 | /* | 954 | /* |
950 | * Find where to start putting bytes. | 955 | * 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 | |||
1364 | 1369 | ||
1365 | daddr = ipc.addr = rt->rt_src; | 1370 | daddr = ipc.addr = rt->rt_src; |
1366 | ipc.opt = NULL; | 1371 | ipc.opt = NULL; |
1372 | ipc.shtx.flags = 0; | ||
1367 | 1373 | ||
1368 | if (replyopts.opt.optlen) { | 1374 | if (replyopts.opt.optlen) { |
1369 | ipc.opt = &replyopts.opt; | 1375 | ipc.opt = &replyopts.opt; |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index dff8bc4e0fac..f774651f0a47 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -493,6 +493,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
493 | 493 | ||
494 | ipc.addr = inet->saddr; | 494 | ipc.addr = inet->saddr; |
495 | ipc.opt = NULL; | 495 | ipc.opt = NULL; |
496 | ipc.shtx.flags = 0; | ||
496 | ipc.oif = sk->sk_bound_dev_if; | 497 | ipc.oif = sk->sk_bound_dev_if; |
497 | 498 | ||
498 | if (msg->msg_controllen) { | 499 | if (msg->msg_controllen) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c47c989cb1fb..4bd178a111d5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
596 | return -EOPNOTSUPP; | 596 | return -EOPNOTSUPP; |
597 | 597 | ||
598 | ipc.opt = NULL; | 598 | ipc.opt = NULL; |
599 | ipc.shtx.flags = 0; | ||
599 | 600 | ||
600 | if (up->pending) { | 601 | if (up->pending) { |
601 | /* | 602 | /* |
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
643 | ipc.addr = inet->saddr; | 644 | ipc.addr = inet->saddr; |
644 | 645 | ||
645 | ipc.oif = sk->sk_bound_dev_if; | 646 | ipc.oif = sk->sk_bound_dev_if; |
647 | err = sock_tx_timestamp(msg, sk, &ipc.shtx); | ||
648 | if (err) | ||
649 | return err; | ||
646 | if (msg->msg_controllen) { | 650 | if (msg->msg_controllen) { |
647 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | 651 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); |
648 | if (err) | 652 | if (err) |