Commit 007747a9 authored by Miroslav Lichvar's avatar Miroslav Lichvar Committed by David S. Miller
Browse files

net: fix SOF_TIMESTAMPING_BIND_PHC to work with multiple sockets



When multiple sockets using the SOF_TIMESTAMPING_BIND_PHC flag received
a packet with a hardware timestamp (e.g. multiple PTP instances in
different PTP domains using the UDPv4/v6 multicast or L2 transport),
the timestamps received on some sockets were corrupted due to repeated
conversion of the same timestamp (by the same or different vclocks).

Fix ptp_convert_timestamp() to not modify the shared skb timestamp
and return the converted timestamp as a ktime_t instead. If the
conversion fails, return 0 to not confuse the application with
timestamps corresponding to an unexpected PHC.

Fixes: d7c08826 ("net: socket: support hardware timestamp conversion to PHC bound")
Signed-off-by: default avatarMiroslav Lichvar <mlichvar@redhat.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1b26d364
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ int ptp_get_vclocks_index(int pclock_index, int **vclock_index)
}
EXPORT_SYMBOL(ptp_get_vclocks_index);

void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps,
ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps,
			      int vclock_index)
{
	char name[PTP_CLOCK_NAME_LEN] = "";
@@ -198,12 +198,12 @@ void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps,
	snprintf(name, PTP_CLOCK_NAME_LEN, "ptp%d", vclock_index);
	dev = class_find_device_by_name(ptp_class, name);
	if (!dev)
		return;
		return 0;

	ptp = dev_get_drvdata(dev);
	if (!ptp->is_virtual_clock) {
		put_device(dev);
		return;
		return 0;
	}

	vclock = info_to_vclock(ptp->info);
@@ -215,7 +215,7 @@ void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps,
	spin_unlock_irqrestore(&vclock->lock, flags);

	put_device(dev);
	hwtstamps->hwtstamp = ns_to_ktime(ns);
	return ns_to_ktime(ns);
}
EXPORT_SYMBOL(ptp_convert_timestamp);
#endif
+7 −5
Original line number Diff line number Diff line
@@ -351,15 +351,17 @@ int ptp_get_vclocks_index(int pclock_index, int **vclock_index);
 *
 * @hwtstamps:    skb_shared_hwtstamps structure pointer
 * @vclock_index: phc index of ptp vclock.
 *
 * Returns converted timestamp, or 0 on error.
 */
void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps,
ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps,
			      int vclock_index);
#else
static inline int ptp_get_vclocks_index(int pclock_index, int **vclock_index)
{ return 0; }
static inline void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps,
static inline ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps,
					    int vclock_index)
{ }
{ return 0; }

#endif

+6 −3
Original line number Diff line number Diff line
@@ -830,6 +830,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
	int empty = 1, false_tstamp = 0;
	struct skb_shared_hwtstamps *shhwtstamps =
		skb_hwtstamps(skb);
	ktime_t hwtstamp;

	/* Race occurred between timestamp enabling and packet
	   receiving.  Fill in the current time for now. */
@@ -878,10 +879,12 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
	    (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
	    !skb_is_swtx_tstamp(skb, false_tstamp)) {
		if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)
			ptp_convert_timestamp(shhwtstamps, sk->sk_bind_phc);
			hwtstamp = ptp_convert_timestamp(shhwtstamps,
							 sk->sk_bind_phc);
		else
			hwtstamp = shhwtstamps->hwtstamp;

		if (ktime_to_timespec64_cond(shhwtstamps->hwtstamp,
					     tss.ts + 2)) {
		if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
			empty = 0;

			if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&