diff options
author | Soheil Hassas Yeganeh <soheil@google.com> | 2016-04-02 23:08:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-04 15:50:30 -0400 |
commit | c14ac9451c34832554db33386a4393be8bba3a7b (patch) | |
tree | 99f4d7c46d01732fcbfdf8de89e1d9846d56c3b3 /net/ipv4/raw.c | |
parent | ad1e46a837163a3e7160a1250825bcfafd2e714b (diff) |
sock: enable timestamping using control messages
Currently, SOL_TIMESTAMPING can only be enabled using setsockopt.
This is very costly when users want to sample writes to gather
tx timestamps.
Add support for enabling SO_TIMESTAMPING via control messages by
using tsflags added in `struct sockcm_cookie` (added in the previous
patches in this series) to set the tx_flags of the last skb created in
a sendmsg. With this patch, the timestamp recording bits in tx_flags
of the skbuff is overridden if SO_TIMESTAMPING is passed in a cmsg.
Please note that this is only effective for overriding the recording
timestamps flags. Users should enable timestamp reporting (e.g.,
SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID) using
socket options and then should ask for SOF_TIMESTAMPING_TX_*
using control messages per sendmsg to sample timestamps for each
write.
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r-- | net/ipv4/raw.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 088ce665fc7b..438f50c1a676 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -339,8 +339,8 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb) | |||
339 | 339 | ||
340 | static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, | 340 | static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, |
341 | struct msghdr *msg, size_t length, | 341 | struct msghdr *msg, size_t length, |
342 | struct rtable **rtp, | 342 | struct rtable **rtp, unsigned int flags, |
343 | unsigned int flags) | 343 | const struct sockcm_cookie *sockc) |
344 | { | 344 | { |
345 | struct inet_sock *inet = inet_sk(sk); | 345 | struct inet_sock *inet = inet_sk(sk); |
346 | struct net *net = sock_net(sk); | 346 | struct net *net = sock_net(sk); |
@@ -379,7 +379,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, | |||
379 | 379 | ||
380 | skb->ip_summed = CHECKSUM_NONE; | 380 | skb->ip_summed = CHECKSUM_NONE; |
381 | 381 | ||
382 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); | 382 | sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags); |
383 | 383 | ||
384 | skb->transport_header = skb->network_header; | 384 | skb->transport_header = skb->network_header; |
385 | err = -EFAULT; | 385 | err = -EFAULT; |
@@ -540,6 +540,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) | |||
540 | daddr = inet->inet_daddr; | 540 | daddr = inet->inet_daddr; |
541 | } | 541 | } |
542 | 542 | ||
543 | ipc.sockc.tsflags = sk->sk_tsflags; | ||
543 | ipc.addr = inet->inet_saddr; | 544 | ipc.addr = inet->inet_saddr; |
544 | ipc.opt = NULL; | 545 | ipc.opt = NULL; |
545 | ipc.tx_flags = 0; | 546 | ipc.tx_flags = 0; |
@@ -638,10 +639,10 @@ back_from_confirm: | |||
638 | 639 | ||
639 | if (inet->hdrincl) | 640 | if (inet->hdrincl) |
640 | err = raw_send_hdrinc(sk, &fl4, msg, len, | 641 | err = raw_send_hdrinc(sk, &fl4, msg, len, |
641 | &rt, msg->msg_flags); | 642 | &rt, msg->msg_flags, &ipc.sockc); |
642 | 643 | ||
643 | else { | 644 | else { |
644 | sock_tx_timestamp(sk, &ipc.tx_flags); | 645 | sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags); |
645 | 646 | ||
646 | if (!ipc.addr) | 647 | if (!ipc.addr) |
647 | ipc.addr = fl4.daddr; | 648 | ipc.addr = fl4.daddr; |