[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220105103326.3130875-1-mlichvar@redhat.com>
Date: Wed, 5 Jan 2022 11:33:26 +0100
From: Miroslav Lichvar <mlichvar@...hat.com>
To: netdev@...r.kernel.org
Cc: Miroslav Lichvar <mlichvar@...hat.com>,
Yangbo Lu <yangbo.lu@....com>,
Richard Cochran <richardcochran@...il.com>
Subject: [PATCH net-next] 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: d7c088265588 ("net: socket: support hardware timestamp conversion to PHC bound")
Signed-off-by: Miroslav Lichvar <mlichvar@...hat.com>
Cc: Yangbo Lu <yangbo.lu@....com>
Cc: Richard Cochran <richardcochran@...il.com>
---
drivers/ptp/ptp_vclock.c | 10 +++++-----
include/linux/ptp_clock_kernel.h | 12 +++++++-----
net/socket.c | 9 ++++++---
3 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c
index baee0379482b..ab1d233173e1 100644
--- a/drivers/ptp/ptp_vclock.c
+++ b/drivers/ptp/ptp_vclock.c
@@ -185,8 +185,8 @@ 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,
- int vclock_index)
+ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps,
+ int vclock_index)
{
char name[PTP_CLOCK_NAME_LEN] = "";
struct ptp_vclock *vclock;
@@ -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
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 2e5565067355..554454cb8693 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -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,
- int vclock_index);
+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,
- int vclock_index)
-{ }
+static inline ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps,
+ int vclock_index)
+{ return 0; }
#endif
diff --git a/net/socket.c b/net/socket.c
index 7f64a6eccf63..5053eb0100e4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -829,6 +829,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. */
@@ -877,10 +878,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) &&
--
2.33.1
Powered by blists - more mailing lists