net: fix SOF_TIMESTAMPING_BIND_PHC to work with multiple sockets
[ Upstream commit 007747a984ea5e895b7d8b056b24ebf431e1e71d ]
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: d7c0882655 ("net: socket: support hardware timestamp conversion to PHC bound")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Cc: Yangbo Lu <yangbo.lu@nxp.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
29a0827b74
commit
ff53c861e9
@@ -185,8 +185,8 @@ out:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ptp_get_vclocks_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)
|
int vclock_index)
|
||||||
{
|
{
|
||||||
char name[PTP_CLOCK_NAME_LEN] = "";
|
char name[PTP_CLOCK_NAME_LEN] = "";
|
||||||
struct ptp_vclock *vclock;
|
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);
|
snprintf(name, PTP_CLOCK_NAME_LEN, "ptp%d", vclock_index);
|
||||||
dev = class_find_device_by_name(ptp_class, name);
|
dev = class_find_device_by_name(ptp_class, name);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
ptp = dev_get_drvdata(dev);
|
ptp = dev_get_drvdata(dev);
|
||||||
if (!ptp->is_virtual_clock) {
|
if (!ptp->is_virtual_clock) {
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vclock = info_to_vclock(ptp->info);
|
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);
|
spin_unlock_irqrestore(&vclock->lock, flags);
|
||||||
|
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
hwtstamps->hwtstamp = ns_to_ktime(ns);
|
return ns_to_ktime(ns);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ptp_convert_timestamp);
|
EXPORT_SYMBOL(ptp_convert_timestamp);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -351,15 +351,17 @@ int ptp_get_vclocks_index(int pclock_index, int **vclock_index);
|
|||||||
*
|
*
|
||||||
* @hwtstamps: skb_shared_hwtstamps structure pointer
|
* @hwtstamps: skb_shared_hwtstamps structure pointer
|
||||||
* @vclock_index: phc index of ptp vclock.
|
* @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);
|
int vclock_index);
|
||||||
#else
|
#else
|
||||||
static inline int ptp_get_vclocks_index(int pclock_index, int **vclock_index)
|
static inline int ptp_get_vclocks_index(int pclock_index, int **vclock_index)
|
||||||
{ return 0; }
|
{ 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)
|
int vclock_index)
|
||||||
{ }
|
{ return 0; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -829,6 +829,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
|||||||
int empty = 1, false_tstamp = 0;
|
int empty = 1, false_tstamp = 0;
|
||||||
struct skb_shared_hwtstamps *shhwtstamps =
|
struct skb_shared_hwtstamps *shhwtstamps =
|
||||||
skb_hwtstamps(skb);
|
skb_hwtstamps(skb);
|
||||||
|
ktime_t hwtstamp;
|
||||||
|
|
||||||
/* Race occurred between timestamp enabling and packet
|
/* Race occurred between timestamp enabling and packet
|
||||||
receiving. Fill in the current time for now. */
|
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) &&
|
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
|
||||||
!skb_is_swtx_tstamp(skb, false_tstamp)) {
|
!skb_is_swtx_tstamp(skb, false_tstamp)) {
|
||||||
if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)
|
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,
|
if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
|
||||||
tss.ts + 2)) {
|
|
||||||
empty = 0;
|
empty = 0;
|
||||||
|
|
||||||
if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
|
if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
|
||||||
|
|||||||
Reference in New Issue
Block a user