Commit 2410251c authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jakub Kicinski
Browse files

net: timestamp: add helper returning skb's tx tstamp



Add a helper function skb_get_tx_timestamp() that returns a tx timestamp
associated with an error queue skb.

Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
Acked-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/702357dd8936ef4c0d3864441e853bfe3224a677.1750065793.git.asml.silence@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 19272b37
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2677,6 +2677,10 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
			     struct sk_buff *skb);

bool skb_has_tx_timestamp(struct sk_buff *skb, const struct sock *sk);
int skb_get_tx_timestamp(struct sk_buff *skb, struct sock *sk,
			 struct timespec64 *ts);

static inline void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
{
+46 −0
Original line number Diff line number Diff line
@@ -843,6 +843,52 @@ static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
		 sizeof(ts_pktinfo), &ts_pktinfo);
}

bool skb_has_tx_timestamp(struct sk_buff *skb, const struct sock *sk)
{
	const struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
	u32 tsflags = READ_ONCE(sk->sk_tsflags);

	if (serr->ee.ee_errno != ENOMSG ||
	   serr->ee.ee_origin != SO_EE_ORIGIN_TIMESTAMPING)
		return false;

	/* software time stamp available and wanted */
	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && skb->tstamp)
		return true;
	/* hardware time stamps available and wanted */
	return (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
		skb_hwtstamps(skb)->hwtstamp;
}

int skb_get_tx_timestamp(struct sk_buff *skb, struct sock *sk,
			  struct timespec64 *ts)
{
	u32 tsflags = READ_ONCE(sk->sk_tsflags);
	ktime_t hwtstamp;
	int if_index = 0;

	if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
	    ktime_to_timespec64_cond(skb->tstamp, ts))
		return SOF_TIMESTAMPING_TX_SOFTWARE;

	if (!(tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) ||
	    skb_is_swtx_tstamp(skb, false))
		return -ENOENT;

	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
		hwtstamp = get_timestamp(sk, skb, &if_index);
	else
		hwtstamp = skb_hwtstamps(skb)->hwtstamp;

	if (tsflags & SOF_TIMESTAMPING_BIND_PHC)
		hwtstamp = ptp_convert_timestamp(&hwtstamp,
						READ_ONCE(sk->sk_bind_phc));
	if (!ktime_to_timespec64_cond(hwtstamp, ts))
		return -ENOENT;

	return SOF_TIMESTAMPING_TX_HARDWARE;
}

/*
 * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
 */