Re: [Patch net-next v2 07/13] net: dsa: microchip: ptp: add packet reception timestamping

From: Vladimir Oltean
Date: Tue Dec 06 2022 - 07:54:18 EST


On Tue, Dec 06, 2022 at 02:44:22PM +0530, Arun Ramadoss wrote:
> +static void ksz_rcv_timestamp(struct sk_buff *skb, u8 *tag,
> + struct net_device *dev, unsigned int port)
> +{
> + struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
> + struct dsa_switch *ds = dev->dsa_ptr->ds;
> + u8 *tstamp_raw = tag - KSZ_PTP_TAG_LEN;
> + struct ksz_tagger_data *tagger_data;
> + struct ptp_header *ptp_hdr;
> + unsigned int ptp_type;
> + u8 ptp_msg_type;
> + ktime_t tstamp;
> + s64 correction;
> +
> + tagger_data = ksz_tagger_data(ds);
> + if (!tagger_data->meta_tstamp_handler)
> + return;

The meta_tstamp_handler doesn't seem to be needed.

Just save the partial timestamp in KSZ_SKB_CB(), and reconstruct that
timestamp with the full PTP time in the ds->ops->port_rxtstamp() method.

Biggest advantage is that ptp_classify_raw() won't be called twice in
the RX path for the same packet, as will currently happen with your code.

> +
> + /* convert time stamp and write to skb */
> + tstamp = ksz_decode_tstamp(get_unaligned_be32(tstamp_raw));
> + memset(hwtstamps, 0, sizeof(*hwtstamps));
> + hwtstamps->hwtstamp = tagger_data->meta_tstamp_handler(ds, tstamp);
> +
> + if (skb_headroom(skb) < ETH_HLEN)
> + return;
> +
> + __skb_push(skb, ETH_HLEN);
> + ptp_type = ptp_classify_raw(skb);
> + __skb_pull(skb, ETH_HLEN);
> +
> + if (ptp_type == PTP_CLASS_NONE)
> + return;
> +
> + ptp_hdr = ptp_parse_header(skb, ptp_type);
> + if (!ptp_hdr)
> + return;
> +
> + ptp_msg_type = ptp_get_msgtype(ptp_hdr, ptp_type);
> + if (ptp_msg_type != PTP_MSGTYPE_PDELAY_REQ)
> + return;
> +
> + /* Only subtract the partial time stamp from the correction field. When
> + * the hardware adds the egress time stamp to the correction field of
> + * the PDelay_Resp message on tx, also only the partial time stamp will
> + * be added.
> + */
> + correction = (s64)get_unaligned_be64(&ptp_hdr->correction);
> + correction -= ktime_to_ns(tstamp) << 16;
> +
> + ptp_header_update_correction(skb, ptp_type, ptp_hdr, correction);
> +}
> +
> /* Time stamp tag *needs* to be inserted if PTP is enabled in hardware.
> * Regardless of Whether it is a PTP frame or not.
> */
> @@ -215,8 +268,10 @@ static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
> unsigned int len = KSZ_EGRESS_TAG_LEN;
>
> /* Extra 4-bytes PTP timestamp */
> - if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
> - len += KSZ9477_PTP_TAG_LEN;
> + if (tag[0] & KSZ9477_PTP_TAG_INDICATION) {
> + ksz_rcv_timestamp(skb, tag, dev, port);
> + len += KSZ_PTP_TAG_LEN;
> + }
>
> return ksz_common_rcv(skb, dev, port, len);
> }