summaryrefslogtreecommitdiffstats
path: root/net/ipv4/raw.c
diff options
context:
space:
mode:
authorSoheil Hassas Yeganeh <soheil@google.com>2016-04-02 23:08:12 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-04 15:50:30 -0400
commitc14ac9451c34832554db33386a4393be8bba3a7b (patch)
tree99f4d7c46d01732fcbfdf8de89e1d9846d56c3b3 /net/ipv4/raw.c
parentad1e46a837163a3e7160a1250825bcfafd2e714b (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.c11
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
340static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, 340static 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;