Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c14ac945 authored by Soheil Hassas Yeganeh's avatar Soheil Hassas Yeganeh Committed by David S. Miller
Browse files

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: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Acked-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ad1e46a8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -861,7 +861,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
		goto drop;

	if (skb->sk && sk_fullsock(skb->sk)) {
		sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags);
		sock_tx_timestamp(skb->sk, skb->sk->sk_tsflags,
				  &skb_shinfo(skb)->tx_flags);
		sw_tx_timestamp(skb);
	}

+4 −2
Original line number Diff line number Diff line
@@ -867,7 +867,8 @@ int ip6_append_data(struct sock *sk,
				int odd, struct sk_buff *skb),
		    void *from, int length, int transhdrlen, int hlimit,
		    int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
		    struct rt6_info *rt, unsigned int flags, int dontfrag);
		    struct rt6_info *rt, unsigned int flags, int dontfrag,
		    const struct sockcm_cookie *sockc);

int ip6_push_pending_frames(struct sock *sk);

@@ -884,7 +885,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
			     void *from, int length, int transhdrlen,
			     int hlimit, int tclass, struct ipv6_txoptions *opt,
			     struct flowi6 *fl6, struct rt6_info *rt,
			     unsigned int flags, int dontfrag);
			     unsigned int flags, int dontfrag,
			     const struct sockcm_cookie *sockc);

static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
{
+6 −4
Original line number Diff line number Diff line
@@ -2057,19 +2057,21 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
		sk->sk_stamp = skb->tstamp;
}

void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags);
void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags);

/**
 * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
 * @sk:		socket sending this packet
 * @tsflags:	timestamping flags to use
 * @tx_flags:	completed with instructions for time stamping
 *
 * Note : callers should take care of initial *tx_flags value (usually 0)
 */
static inline void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags)
static inline void sock_tx_timestamp(const struct sock *sk, __u16 tsflags,
				     __u8 *tx_flags)
{
	if (unlikely(sk->sk_tsflags))
		__sock_tx_timestamp(sk, tx_flags);
	if (unlikely(tsflags))
		__sock_tx_timestamp(tsflags, tx_flags);
	if (unlikely(sock_flag(sk, SOCK_WIFI_STATUS)))
		*tx_flags |= SKBTX_WIFI_STATUS;
}
+1 −1
Original line number Diff line number Diff line
@@ -755,7 +755,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
	if (err < 0)
		goto free_skb;

	sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
	sock_tx_timestamp(sk, sk->sk_tsflags, &skb_shinfo(skb)->tx_flags);

	skb->dev = dev;
	skb->sk  = sk;
+3 −2
Original line number Diff line number Diff line
@@ -737,6 +737,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
		/* no remote port */
	}

	ipc.sockc.tsflags = sk->sk_tsflags;
	ipc.addr = inet->inet_saddr;
	ipc.opt = NULL;
	ipc.oif = sk->sk_bound_dev_if;
@@ -744,8 +745,6 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
	ipc.ttl = 0;
	ipc.tos = -1;

	sock_tx_timestamp(sk, &ipc.tx_flags);

	if (msg->msg_controllen) {
		err = ip_cmsg_send(sk, msg, &ipc, false);
		if (unlikely(err)) {
@@ -768,6 +767,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
		rcu_read_unlock();
	}

	sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags);

	saddr = ipc.addr;
	ipc.addr = faddr = daddr;

Loading