[RFC,net-next,v2,1/8] net: ptp: add helper for one-step P2P clocks

Message ID 20221121154150.9573-2-arun.ramadoss@microchip.com
State New
Headers
Series net: dsa: microchip: add PTP support for KSZ9x and LAN937x |

Commit Message

Arun Ramadoss Nov. 21, 2022, 3:41 p.m. UTC
  From: Christian Eggers <ceggers@arri.de>

For P2P delay measurement, the ingress time stamp of the PDelay_Req is
required for the correction field of the PDelay_Resp. The application
echoes back the correction field of the PDelay_Req when sending the
PDelay_Resp.

Some hardware (like the ZHAW InES PTP time stamping IP core) subtracts
the ingress timestamp autonomously from the correction field, so that
the hardware only needs to add the egress timestamp on tx. Other
hardware (like the Microchip KSZ9563) reports the ingress time stamp via
an interrupt and requires that the software provides this time stamp via
tail-tag on tx.

In order to avoid introducing a further application interface for this,
the driver can simply emulate the behavior of the InES device and
subtract the ingress time stamp in software from the correction field.

On egress, the correction field can either be kept as it is (and the
time stamp field in the tail-tag is set to zero) or move the value from
the correction field back to the tail-tag.

Changing the correction field requires updating the UDP checksum (if UDP
is used as transport).

Signed-off-by: Christian Eggers <ceggers@arri.de>
---
 include/linux/ptp_classify.h | 73 ++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
  

Comments

Richard Cochran Nov. 22, 2022, 2:34 p.m. UTC | #1
On Mon, Nov 21, 2022 at 09:11:43PM +0530, Arun Ramadoss wrote:
> +/**
> + * ptp_header_update_correction - Update PTP header's correction field
> + * @skb: packet buffer
> + * @type: type of the packet (see ptp_classify_raw())
> + * @hdr: ptp header
> + * @correction: new correction value
> + *
> + * This updates the correction field of a PTP header and updates the UDP
> + * checksum (if UDP is used as transport). It is needed for hardware capable of
> + * one-step P2P that does not already modify the correction field of Pdelay_Req
> + * event messages on ingress.
> + */

Does this really belong in the common PTP header?

Seems more like a driver/hardware specific workaround to me.

Thanks,
Richard
  
Arun Ramadoss Nov. 23, 2022, 7:10 a.m. UTC | #2
Hi Richard,
Thanks for the comment.

On Tue, 2022-11-22 at 06:34 -0800, Richard Cochran wrote:
> [Some people who received this message don't often get email from
> richardcochran@gmail.com. Learn why this is important at 
> https://aka.ms/LearnAboutSenderIdentification ]
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
> 
> On Mon, Nov 21, 2022 at 09:11:43PM +0530, Arun Ramadoss wrote:
> > +/**
> > + * ptp_header_update_correction - Update PTP header's correction
> > field
> > + * @skb: packet buffer
> > + * @type: type of the packet (see ptp_classify_raw())
> > + * @hdr: ptp header
> > + * @correction: new correction value
> > + *
> > + * This updates the correction field of a PTP header and updates
> > the UDP
> > + * checksum (if UDP is used as transport). It is needed for
> > hardware capable of
> > + * one-step P2P that does not already modify the correction field
> > of Pdelay_Req
> > + * event messages on ingress.
> > + */
> 
> Does this really belong in the common PTP header?
> 
> Seems more like a driver/hardware specific workaround to me.

This patch series is extension of PTP support for KSZ9563 patch series
submitted two years back which is not mainlined.
In that patch review feedback, it was suggested to make this function
generic and so it was moved from ksz_common.h to ptp_classify.h

Link: 
https://lore.kernel.org/netdev/20201022113243.4shddtywgvpcqq6c@skbuf/


https://lore.kernel.org/netdev/20201022143429.GA9743@hoboy.vegasvil.org/

> 
> Thanks,
> Richard
  
Richard Cochran Nov. 24, 2022, 2:52 p.m. UTC | #3
On Wed, Nov 23, 2022 at 07:10:58AM +0000, Arun.Ramadoss@microchip.com wrote:
> This patch series is extension of PTP support for KSZ9563 patch series
> submitted two years back which is not mainlined.
> In that patch review feedback, it was suggested to make this function
> generic and so it was moved from ksz_common.h to ptp_classify.h
> 
> Link: 
> https://lore.kernel.org/netdev/20201022113243.4shddtywgvpcqq6c@skbuf/
> 
> 
> https://lore.kernel.org/netdev/20201022143429.GA9743@hoboy.vegasvil.org/

okay

Thanks,
Richard
  

Patch

diff --git a/include/linux/ptp_classify.h b/include/linux/ptp_classify.h
index 2b6ea36ad162..e32efe3c4d66 100644
--- a/include/linux/ptp_classify.h
+++ b/include/linux/ptp_classify.h
@@ -10,8 +10,12 @@ 
 #ifndef _PTP_CLASSIFY_H_
 #define _PTP_CLASSIFY_H_
 
+#include <asm/unaligned.h>
 #include <linux/ip.h>
+#include <linux/ktime.h>
 #include <linux/skbuff.h>
+#include <linux/udp.h>
+#include <net/checksum.h>
 
 #define PTP_CLASS_NONE  0x00 /* not a PTP event message */
 #define PTP_CLASS_V1    0x01 /* protocol version 1 */
@@ -129,6 +133,67 @@  static inline u8 ptp_get_msgtype(const struct ptp_header *hdr,
 	return msgtype;
 }
 
+/**
+ * ptp_check_diff8 - Computes new checksum (when altering a 64-bit field)
+ * @old: old field value
+ * @new: new field value
+ * @oldsum: previous checksum
+ *
+ * This function can be used to calculate a new checksum when only a single
+ * field is changed. Similar as ip_vs_check_diff*() in ip_vs.h.
+ *
+ * Return: Updated checksum
+ */
+static inline __wsum ptp_check_diff8(__be64 old, __be64 new, __wsum oldsum)
+{
+	__be64 diff[2] = { ~old, new };
+
+	return csum_partial(diff, sizeof(diff), oldsum);
+}
+
+/**
+ * ptp_header_update_correction - Update PTP header's correction field
+ * @skb: packet buffer
+ * @type: type of the packet (see ptp_classify_raw())
+ * @hdr: ptp header
+ * @correction: new correction value
+ *
+ * This updates the correction field of a PTP header and updates the UDP
+ * checksum (if UDP is used as transport). It is needed for hardware capable of
+ * one-step P2P that does not already modify the correction field of Pdelay_Req
+ * event messages on ingress.
+ */
+static inline
+void ptp_header_update_correction(struct sk_buff *skb, unsigned int type,
+				  struct ptp_header *hdr, s64 correction)
+{
+	__be64 correction_old;
+	struct udphdr *uhdr;
+
+	/* previous correction value is required for checksum update. */
+	memcpy(&correction_old,  &hdr->correction, sizeof(correction_old));
+
+	/* write new correction value */
+	put_unaligned_be64((u64)correction, &hdr->correction);
+
+	switch (type & PTP_CLASS_PMASK) {
+	case PTP_CLASS_IPV4:
+	case PTP_CLASS_IPV6:
+		/* locate udp header */
+		uhdr = (struct udphdr *)((char *)hdr - sizeof(struct udphdr));
+		break;
+	default:
+		return;
+	}
+
+	/* update checksum */
+	uhdr->check = csum_fold(ptp_check_diff8(correction_old,
+						hdr->correction,
+						~csum_unfold(uhdr->check)));
+	if (!uhdr->check)
+		uhdr->check = CSUM_MANGLED_0;
+}
+
 /**
  * ptp_msg_is_sync - Evaluates whether the given skb is a PTP Sync message
  * @skb: packet buffer
@@ -166,5 +231,13 @@  static inline bool ptp_msg_is_sync(struct sk_buff *skb, unsigned int type)
 {
 	return false;
 }
+
+static inline
+void ptp_onestep_p2p_move_t2_to_correction(struct sk_buff *skb,
+					   unsigned int type,
+					   struct ptp_header *hdr,
+					   ktime_t t2)
+{
+}
 #endif
 #endif /* _PTP_CLASSIFY_H_ */