public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] Implement PTP support in netdevsim
@ 2026-02-19 14:05 Maciek Machnikowski
  2026-02-19 14:05 ` [PATCH net-next 1/2] ptp: Expose ptp_clock_info to external drivers Maciek Machnikowski
  2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
  0 siblings, 2 replies; 8+ messages in thread
From: Maciek Machnikowski @ 2026-02-19 14:05 UTC (permalink / raw)
  To: kuba; +Cc: maciek, richardcochran, netdev, milena.olech

This patchset adds support to the PTP HW timestamping emulation in the
netdevsim. It uses existing binding between netdevsim and ptp_mock
driver to generate transmit and receive timestamps.


Maciek Machnikowski (2):
  ptp: Expose ptp_clock_info to external drivers
  netdevsim: Implement basic ptp support

 drivers/net/netdevsim/ethtool.c   | 12 +++++
 drivers/net/netdevsim/netdev.c    | 90 +++++++++++++++++++++++++++++++
 drivers/net/netdevsim/netdevsim.h |  1 +
 drivers/ptp/ptp_mock.c            |  6 +++
 include/linux/ptp_mock.h          |  5 ++
 5 files changed, 114 insertions(+)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH net-next 1/2] ptp: Expose ptp_clock_info to external drivers
  2026-02-19 14:05 [PATCH net-next 0/2] Implement PTP support in netdevsim Maciek Machnikowski
@ 2026-02-19 14:05 ` Maciek Machnikowski
  2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
  1 sibling, 0 replies; 8+ messages in thread
From: Maciek Machnikowski @ 2026-02-19 14:05 UTC (permalink / raw)
  To: kuba; +Cc: maciek, richardcochran, netdev, milena.olech

Allow exposing the ptp_clock_info of the ptp_mock to the external drivers.
This is a prerequisite for implementing ptp support on netdevsim mock.

Co-developed-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Maciek Machnikowski <maciek@machnikowski.net>
---
 drivers/ptp/ptp_mock.c   | 6 ++++++
 include/linux/ptp_mock.h | 5 +++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/ptp/ptp_mock.c b/drivers/ptp/ptp_mock.c
index bbd14ce24..0d0936298 100644
--- a/drivers/ptp/ptp_mock.c
+++ b/drivers/ptp/ptp_mock.c
@@ -171,5 +171,11 @@ void mock_phc_destroy(struct mock_phc *phc)
 }
 EXPORT_SYMBOL_GPL(mock_phc_destroy);
 
+struct ptp_clock_info *mock_phc_get_ptp_info(struct mock_phc *phc)
+{
+	return &phc->info;
+}
+EXPORT_SYMBOL_GPL(mock_phc_get_ptp_info);
+
 MODULE_DESCRIPTION("Mock-up PTP Hardware Clock driver");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/ptp_mock.h b/include/linux/ptp_mock.h
index 72eb40103..e33188dec 100644
--- a/include/linux/ptp_mock.h
+++ b/include/linux/ptp_mock.h
@@ -16,6 +16,7 @@ struct mock_phc;
 struct mock_phc *mock_phc_create(struct device *dev);
 void mock_phc_destroy(struct mock_phc *phc);
 int mock_phc_index(struct mock_phc *phc);
+struct ptp_clock_info *mock_phc_get_ptp_info(struct mock_phc *phc);
 
 #else
 
@@ -33,6 +34,10 @@ static inline int mock_phc_index(struct mock_phc *phc)
 	return -1;
 }
 
+static inline struct ptp_clock_info *mock_phc_get_ptp_info(struct mock_phc *phc)
+{
+	return NULL;
+}
 #endif
 
 #endif /* _PTP_MOCK_H_ */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-19 14:05 [PATCH net-next 0/2] Implement PTP support in netdevsim Maciek Machnikowski
  2026-02-19 14:05 ` [PATCH net-next 1/2] ptp: Expose ptp_clock_info to external drivers Maciek Machnikowski
@ 2026-02-19 14:05 ` Maciek Machnikowski
  2026-02-19 16:16   ` Andrew Lunn
                     ` (2 more replies)
  1 sibling, 3 replies; 8+ messages in thread
From: Maciek Machnikowski @ 2026-02-19 14:05 UTC (permalink / raw)
  To: kuba; +Cc: maciek, richardcochran, netdev, milena.olech

Add support for virtual timestamping inside the netdevsim driver.
The implementation uses two attached ptp_mock clocks, reads the timestamps
of the ones attached either to the netdevsim or its peer and returns
timestamps using standard timestamps APIs.

This implementation enables running ptp4l on netdevsim adapters.

Co-developed-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Maciek Machnikowski <maciek@machnikowski.net>
---
 drivers/net/netdevsim/ethtool.c   | 12 +++++
 drivers/net/netdevsim/netdev.c    | 90 +++++++++++++++++++++++++++++++
 drivers/net/netdevsim/netdevsim.h |  1 +
 3 files changed, 103 insertions(+)

diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 36a201533..367c7ca8b 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -201,6 +201,18 @@ static int nsim_get_ts_info(struct net_device *dev,
 	struct netdevsim *ns = netdev_priv(dev);
 
 	info->phc_index = mock_phc_index(ns->phc);
+	if (info->phc_index < 0)
+		return 0;
+
+	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+				SOF_TIMESTAMPING_RX_SOFTWARE |
+				SOF_TIMESTAMPING_SOFTWARE |
+				SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
 
 	return 0;
 }
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 6285fbefe..b1161c1ca 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -30,6 +30,8 @@
 #include <net/rtnetlink.h>
 #include <net/udp_tunnel.h>
 #include <net/busy_poll.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/timecounter.h>
 
 #include "netdevsim.h"
 
@@ -119,12 +121,17 @@ static int nsim_forward_skb(struct net_device *tx_dev,
 
 static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct skb_shared_hwtstamps shhwtstamps = {};
 	struct netdevsim *ns = netdev_priv(dev);
+	struct ptp_clock_info *ptp_info;
+	struct timespec64 tx_ts, rx_ts;
+	struct sk_buff *skb_orig = skb;
 	struct skb_ext *psp_ext = NULL;
 	struct net_device *peer_dev;
 	unsigned int len = skb->len;
 	struct netdevsim *peer_ns;
 	struct netdev_config *cfg;
+	bool gen_tx_tstamp = false;
 	struct nsim_rq *rq;
 	int rxq;
 	int dr;
@@ -161,6 +168,27 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		skb_linearize(skb);
 
 	skb_tx_timestamp(skb);
+	gen_tx_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
+	if (gen_tx_tstamp) {
+		ptp_info = mock_phc_get_ptp_info(ns->phc);
+
+		/* Create a copy of tx skb to keep the tx reference */
+		skb_orig = skb;
+		skb = skb_copy(skb_orig, GFP_ATOMIC);
+		skb_shinfo(skb_orig)->tx_flags |= SKBTX_IN_PROGRESS;
+
+		/* Timestamp as late as possible */
+		if (ptp_info)
+			ptp_info->gettime64(ptp_info, &tx_ts);
+	}
+
+	/* Generate Rx tstamp based on the peer clock */
+	ptp_info = mock_phc_get_ptp_info(peer_ns->phc);
+	if (ptp_info) {
+		ptp_info->gettime64(ptp_info, &rx_ts);
+		skb_hwtstamps(skb)->hwtstamp = timespec64_to_ktime(rx_ts);
+	}
+
 	if (unlikely(nsim_forward_skb(dev, peer_dev,
 				      skb, rq, psp_ext) == NET_RX_DROP))
 		goto out_drop_cnt;
@@ -168,6 +196,13 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (!hrtimer_active(&rq->napi_timer))
 		hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL);
 
+	/* only timestamp the outbound packet if user requested it */
+	if (gen_tx_tstamp) {
+		shhwtstamps.hwtstamp = timespec64_to_ktime(tx_ts);
+		skb_tstamp_tx(skb_orig, &shhwtstamps);
+		dev_kfree_skb_any(skb_orig);
+	}
+
 	rcu_read_unlock();
 	dev_dstats_tx_add(dev, len);
 	return NETDEV_TX_OK;
@@ -182,6 +217,59 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static int nsim_set_ts_config(struct net_device *netdev,
+			      struct kernel_hwtstamp_config *config,
+			      struct netlink_ext_ack *extack)
+{
+	struct netdevsim *ns = netdev_priv(netdev);
+
+	if (!ns->phc)
+		return -EOPNOTSUPP;
+
+	switch (config->tx_type) {
+	case HWTSTAMP_TX_OFF:
+		ns->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+		break;
+	case HWTSTAMP_TX_ON:
+		ns->tstamp_config.tx_type = HWTSTAMP_TX_ON;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config->rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_NTP_ALL:
+	case HWTSTAMP_FILTER_ALL:
+		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static int nsim_get_ts_config(struct net_device *netdev,
+			      struct kernel_hwtstamp_config *config)
+{
+	struct netdevsim *ns = netdev_priv(netdev);
+
+	*config = ns->tstamp_config;
+	return 0;
+}
+
 static void nsim_set_rx_mode(struct net_device *dev)
 {
 }
@@ -660,6 +748,8 @@ static const struct net_device_ops nsim_netdev_ops = {
 	.ndo_open		= nsim_open,
 	.ndo_stop		= nsim_stop,
 	.net_shaper_ops		= &nsim_shaper_ops,
+	.ndo_hwtstamp_get	= nsim_get_ts_config,
+	.ndo_hwtstamp_set	= nsim_set_ts_config,
 };
 
 static const struct net_device_ops nsim_vf_netdev_ops = {
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index f767fc8a7..6d3e8700c 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -103,6 +103,7 @@ struct netdevsim {
 	struct net_device *netdev;
 	struct nsim_dev *nsim_dev;
 	struct nsim_dev_port *nsim_dev_port;
+	struct kernel_hwtstamp_config tstamp_config;
 	struct mock_phc *phc;
 	struct nsim_rq **rq;
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
@ 2026-02-19 16:16   ` Andrew Lunn
  2026-02-19 20:42   ` Jakub Kicinski
  2026-02-20 20:08   ` Willem de Bruijn
  2 siblings, 0 replies; 8+ messages in thread
From: Andrew Lunn @ 2026-02-19 16:16 UTC (permalink / raw)
  To: Maciek Machnikowski; +Cc: kuba, richardcochran, netdev, milena.olech

On Thu, Feb 19, 2026 at 03:05:30PM +0100, Maciek Machnikowski wrote:
> Add support for virtual timestamping inside the netdevsim driver.
> The implementation uses two attached ptp_mock clocks, reads the timestamps
> of the ones attached either to the netdevsim or its peer and returns
> timestamps using standard timestamps APIs.
> 
> This implementation enables running ptp4l on netdevsim adapters.

https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html

  1.8.3. netdevsim

  netdevsim is a test driver which can be used to exercise driver
  configuration APIs without requiring capable hardware. Mock-ups and
  tests based on netdevsim are strongly encouraged when adding new
  APIs, but netdevsim in itself is not considered a use case/user. You
  must also implement the new APIs in a real driver.

  We give no guarantees that netdevsim won’t change in the future in a
  way which would break what would normally be considered uAPI.

  netdevsim is reserved for use by upstream tests only, so any new
  netdevsim features must be accompanied by selftests under
  tools/testing/selftests/.

Please add to the commit message which of the existing tests in
tools/testing/selftests/ can be used with this new feature. Or include
a new test if needed. net/forwarding/tsn_lib.sh has some helpers which
might be interesting, to start and stop ptp4l. Add a test which shows
ptp4l runs and returns sensible values?

	Andrew

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
  2026-02-19 16:16   ` Andrew Lunn
@ 2026-02-19 20:42   ` Jakub Kicinski
  2026-02-20 21:07     ` Maciek Machnikowski
  2026-02-20 20:08   ` Willem de Bruijn
  2 siblings, 1 reply; 8+ messages in thread
From: Jakub Kicinski @ 2026-02-19 20:42 UTC (permalink / raw)
  To: Maciek Machnikowski; +Cc: richardcochran, netdev, milena.olech, Vadim Fedorenko

On Thu, 19 Feb 2026 15:05:30 +0100 Maciek Machnikowski wrote:
> +	gen_tx_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
> +	if (gen_tx_tstamp) {
> +		ptp_info = mock_phc_get_ptp_info(ns->phc);
> +
> +		/* Create a copy of tx skb to keep the tx reference */
> +		skb_orig = skb;
> +		skb = skb_copy(skb_orig, GFP_ATOMIC);
> +		skb_shinfo(skb_orig)->tx_flags |= SKBTX_IN_PROGRESS;
> +
> +		/* Timestamp as late as possible */
> +		if (ptp_info)
> +			ptp_info->gettime64(ptp_info, &tx_ts);
> +	}

Like Andrew said we need a test in tree. But Vadim has been promising me
a timestamping test for a while, so adding him here. You can probably
work together (unless you already have such a test).

When you respin - note that mock_phc takes a spin lock without _bh
around its internals. It needs to be changed to _bh() if we call
it form the xmit path.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
  2026-02-19 16:16   ` Andrew Lunn
  2026-02-19 20:42   ` Jakub Kicinski
@ 2026-02-20 20:08   ` Willem de Bruijn
  2026-02-20 21:06     ` Maciek Machnikowski
  2 siblings, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2026-02-20 20:08 UTC (permalink / raw)
  To: Maciek Machnikowski, kuba; +Cc: maciek, richardcochran, netdev, milena.olech

Maciek Machnikowski wrote:
> Add support for virtual timestamping inside the netdevsim driver.
> The implementation uses two attached ptp_mock clocks, reads the timestamps
> of the ones attached either to the netdevsim or its peer and returns
> timestamps using standard timestamps APIs.
> 
> This implementation enables running ptp4l on netdevsim adapters.
> 
> Co-developed-by: Milena Olech <milena.olech@intel.com>
> Signed-off-by: Milena Olech <milena.olech@intel.com>
> Signed-off-by: Maciek Machnikowski <maciek@machnikowski.net>
> ---
>  drivers/net/netdevsim/ethtool.c   | 12 +++++
>  drivers/net/netdevsim/netdev.c    | 90 +++++++++++++++++++++++++++++++
>  drivers/net/netdevsim/netdevsim.h |  1 +
>  3 files changed, 103 insertions(+)
> 
> diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
> index 36a201533..367c7ca8b 100644
> --- a/drivers/net/netdevsim/ethtool.c
> +++ b/drivers/net/netdevsim/ethtool.c
> @@ -201,6 +201,18 @@ static int nsim_get_ts_info(struct net_device *dev,
>  	struct netdevsim *ns = netdev_priv(dev);
>  
>  	info->phc_index = mock_phc_index(ns->phc);
> +	if (info->phc_index < 0)
> +		return 0;
> +
> +	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
> +				SOF_TIMESTAMPING_RX_SOFTWARE |
> +				SOF_TIMESTAMPING_SOFTWARE |
> +				SOF_TIMESTAMPING_TX_HARDWARE |
> +				SOF_TIMESTAMPING_RX_HARDWARE |
> +				SOF_TIMESTAMPING_RAW_HARDWARE;

preferred model is to populate the device independent defaults with
ethtool_op_get_ts_info, then extend where relevant. See for instance
gve_get_ts_info.
> +
> +	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
> +	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
>  
>  	return 0;
>  }
> diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
> index 6285fbefe..b1161c1ca 100644
> --- a/drivers/net/netdevsim/netdev.c
> +++ b/drivers/net/netdevsim/netdev.c
> @@ -30,6 +30,8 @@
>  #include <net/rtnetlink.h>
>  #include <net/udp_tunnel.h>
>  #include <net/busy_poll.h>
> +#include <linux/ptp_clock_kernel.h>
> +#include <linux/timecounter.h>
>  
>  #include "netdevsim.h"
>  
> @@ -119,12 +121,17 @@ static int nsim_forward_skb(struct net_device *tx_dev,
>  
>  static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  {
> +	struct skb_shared_hwtstamps shhwtstamps = {};
>  	struct netdevsim *ns = netdev_priv(dev);
> +	struct ptp_clock_info *ptp_info;
> +	struct timespec64 tx_ts, rx_ts;
> +	struct sk_buff *skb_orig = skb;
>  	struct skb_ext *psp_ext = NULL;
>  	struct net_device *peer_dev;
>  	unsigned int len = skb->len;
>  	struct netdevsim *peer_ns;
>  	struct netdev_config *cfg;
> +	bool gen_tx_tstamp = false;
>  	struct nsim_rq *rq;
>  	int rxq;
>  	int dr;
> @@ -161,6 +168,27 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  		skb_linearize(skb);
>  
>  	skb_tx_timestamp(skb);
> +	gen_tx_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
> +	if (gen_tx_tstamp) {
> +		ptp_info = mock_phc_get_ptp_info(ns->phc);
> +
> +		/* Create a copy of tx skb to keep the tx reference */
> +		skb_orig = skb;
> +		skb = skb_copy(skb_orig, GFP_ATOMIC);

This should not be needed

skb_tstamp_tx itself will cal skg_clone or alloc_skb for the
notification skb.

Just queue the tx timestamp before nsim_forward_skb?

> +		skb_shinfo(skb_orig)->tx_flags |= SKBTX_IN_PROGRESS;
> +
> +		/* Timestamp as late as possible */
> +		if (ptp_info)
> +			ptp_info->gettime64(ptp_info, &tx_ts);
> +	}
> +
> +	/* Generate Rx tstamp based on the peer clock */
> +	ptp_info = mock_phc_get_ptp_info(peer_ns->phc);
> +	if (ptp_info) {
> +		ptp_info->gettime64(ptp_info, &rx_ts);
> +		skb_hwtstamps(skb)->hwtstamp = timespec64_to_ktime(rx_ts);
> +	}
> +
>  	if (unlikely(nsim_forward_skb(dev, peer_dev,
>  				      skb, rq, psp_ext) == NET_RX_DROP))
>  		goto out_drop_cnt;
> @@ -168,6 +196,13 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  	if (!hrtimer_active(&rq->napi_timer))
>  		hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL);
>  
> +	/* only timestamp the outbound packet if user requested it */
> +	if (gen_tx_tstamp) {
> +		shhwtstamps.hwtstamp = timespec64_to_ktime(tx_ts);
> +		skb_tstamp_tx(skb_orig, &shhwtstamps);
> +		dev_kfree_skb_any(skb_orig);
> +	}
> +
>  	rcu_read_unlock();
>  	dev_dstats_tx_add(dev, len);
>  	return NETDEV_TX_OK;
> @@ -182,6 +217,59 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  	return NETDEV_TX_OK;
>  }
>  
> +static int nsim_set_ts_config(struct net_device *netdev,
> +			      struct kernel_hwtstamp_config *config,
> +			      struct netlink_ext_ack *extack)
> +{
> +	struct netdevsim *ns = netdev_priv(netdev);
> +
> +	if (!ns->phc)
> +		return -EOPNOTSUPP;
> +
> +	switch (config->tx_type) {
> +	case HWTSTAMP_TX_OFF:
> +		ns->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
> +		break;
> +	case HWTSTAMP_TX_ON:
> +		ns->tstamp_config.tx_type = HWTSTAMP_TX_ON;
> +		break;
> +	default:
> +		return -ERANGE;
> +	}
> +
> +	switch (config->rx_filter) {
> +	case HWTSTAMP_FILTER_NONE:
> +		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
> +		break;
> +	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
> +	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
> +	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
> +	case HWTSTAMP_FILTER_PTP_V2_EVENT:
> +	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
> +	case HWTSTAMP_FILTER_PTP_V2_SYNC:
> +	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
> +	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
> +	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
> +	case HWTSTAMP_FILTER_NTP_ALL:
> +	case HWTSTAMP_FILTER_ALL:
> +		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
> +		break;
> +	default:
> +		return -ERANGE;
> +	}
> +
> +	return 0;
> +}
> +
> +static int nsim_get_ts_config(struct net_device *netdev,
> +			      struct kernel_hwtstamp_config *config)
> +{
> +	struct netdevsim *ns = netdev_priv(netdev);
> +
> +	*config = ns->tstamp_config;
> +	return 0;
> +}
> +
>  static void nsim_set_rx_mode(struct net_device *dev)
>  {
>  }
> @@ -660,6 +748,8 @@ static const struct net_device_ops nsim_netdev_ops = {
>  	.ndo_open		= nsim_open,
>  	.ndo_stop		= nsim_stop,
>  	.net_shaper_ops		= &nsim_shaper_ops,
> +	.ndo_hwtstamp_get	= nsim_get_ts_config,
> +	.ndo_hwtstamp_set	= nsim_set_ts_config,
>  };
>  
>  static const struct net_device_ops nsim_vf_netdev_ops = {
> diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
> index f767fc8a7..6d3e8700c 100644
> --- a/drivers/net/netdevsim/netdevsim.h
> +++ b/drivers/net/netdevsim/netdevsim.h
> @@ -103,6 +103,7 @@ struct netdevsim {
>  	struct net_device *netdev;
>  	struct nsim_dev *nsim_dev;
>  	struct nsim_dev_port *nsim_dev_port;
> +	struct kernel_hwtstamp_config tstamp_config;
>  	struct mock_phc *phc;
>  	struct nsim_rq **rq;
>  
> -- 
> 2.53.0
> 



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-20 20:08   ` Willem de Bruijn
@ 2026-02-20 21:06     ` Maciek Machnikowski
  0 siblings, 0 replies; 8+ messages in thread
From: Maciek Machnikowski @ 2026-02-20 21:06 UTC (permalink / raw)
  To: Willem de Bruijn, kuba; +Cc: richardcochran, netdev, milena.olech



On 20/02/2026 21:08, Willem de Bruijn wrote:
> Maciek Machnikowski wrote:
>> Add support for virtual timestamping inside the netdevsim driver.
>> The implementation uses two attached ptp_mock clocks, reads the timestamps
>> of the ones attached either to the netdevsim or its peer and returns
>> timestamps using standard timestamps APIs.
>>
>> This implementation enables running ptp4l on netdevsim adapters.
>>
>> Co-developed-by: Milena Olech <milena.olech@intel.com>
>> Signed-off-by: Milena Olech <milena.olech@intel.com>
>> Signed-off-by: Maciek Machnikowski <maciek@machnikowski.net>
>> ---
>>  drivers/net/netdevsim/ethtool.c   | 12 +++++
>>  drivers/net/netdevsim/netdev.c    | 90 +++++++++++++++++++++++++++++++
>>  drivers/net/netdevsim/netdevsim.h |  1 +
>>  3 files changed, 103 insertions(+)
>>
>> diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
>> index 36a201533..367c7ca8b 100644
>> --- a/drivers/net/netdevsim/ethtool.c
>> +++ b/drivers/net/netdevsim/ethtool.c
>> @@ -201,6 +201,18 @@ static int nsim_get_ts_info(struct net_device *dev,
>>  	struct netdevsim *ns = netdev_priv(dev);
>>  
>>  	info->phc_index = mock_phc_index(ns->phc);
>> +	if (info->phc_index < 0)
>> +		return 0;
>> +
>> +	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
>> +				SOF_TIMESTAMPING_RX_SOFTWARE |
>> +				SOF_TIMESTAMPING_SOFTWARE |
>> +				SOF_TIMESTAMPING_TX_HARDWARE |
>> +				SOF_TIMESTAMPING_RX_HARDWARE |
>> +				SOF_TIMESTAMPING_RAW_HARDWARE;
> 
> preferred model is to populate the device independent defaults with
> ethtool_op_get_ts_info, then extend where relevant. See for instance
> gve_get_ts_info.

Thanks for pointing that one out - will refactor to use the new way.

>> +
>> +	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
>> +	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
>>  
>>  	return 0;
>>  }
>> diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
>> index 6285fbefe..b1161c1ca 100644
>> --- a/drivers/net/netdevsim/netdev.c
>> +++ b/drivers/net/netdevsim/netdev.c
>> @@ -30,6 +30,8 @@
>>  #include <net/rtnetlink.h>
>>  #include <net/udp_tunnel.h>
>>  #include <net/busy_poll.h>
>> +#include <linux/ptp_clock_kernel.h>
>> +#include <linux/timecounter.h>
>>  
>>  #include "netdevsim.h"
>>  
>> @@ -119,12 +121,17 @@ static int nsim_forward_skb(struct net_device *tx_dev,
>>  
>>  static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>>  {
>> +	struct skb_shared_hwtstamps shhwtstamps = {};
>>  	struct netdevsim *ns = netdev_priv(dev);
>> +	struct ptp_clock_info *ptp_info;
>> +	struct timespec64 tx_ts, rx_ts;
>> +	struct sk_buff *skb_orig = skb;
>>  	struct skb_ext *psp_ext = NULL;
>>  	struct net_device *peer_dev;
>>  	unsigned int len = skb->len;
>>  	struct netdevsim *peer_ns;
>>  	struct netdev_config *cfg;
>> +	bool gen_tx_tstamp = false;
>>  	struct nsim_rq *rq;
>>  	int rxq;
>>  	int dr;
>> @@ -161,6 +168,27 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>>  		skb_linearize(skb);
>>  
>>  	skb_tx_timestamp(skb);
>> +	gen_tx_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
>> +	if (gen_tx_tstamp) {
>> +		ptp_info = mock_phc_get_ptp_info(ns->phc);
>> +
>> +		/* Create a copy of tx skb to keep the tx reference */
>> +		skb_orig = skb;
>> +		skb = skb_copy(skb_orig, GFP_ATOMIC);
> 
> This should not be needed
> 
> skb_tstamp_tx itself will cal skg_clone or alloc_skb for the
> notification skb.
> 
> Just queue the tx timestamp before nsim_forward_skb?

This is specific to netdevsim and need to be that way - the original skb
gets forwarded to the peer device in the nsim_forward_sk. If I queue the
tx timestamp before forwarding - the same skb would be freed when the
timestamp is delivered.

> 
>> +		skb_shinfo(skb_orig)->tx_flags |= SKBTX_IN_PROGRESS;
>> +
>> +		/* Timestamp as late as possible */
>> +		if (ptp_info)
>> +			ptp_info->gettime64(ptp_info, &tx_ts);
>> +	}
>> +
>> +	/* Generate Rx tstamp based on the peer clock */
>> +	ptp_info = mock_phc_get_ptp_info(peer_ns->phc);
>> +	if (ptp_info) {
>> +		ptp_info->gettime64(ptp_info, &rx_ts);
>> +		skb_hwtstamps(skb)->hwtstamp = timespec64_to_ktime(rx_ts);
>> +	}
>> +
>>  	if (unlikely(nsim_forward_skb(dev, peer_dev,
>>  				      skb, rq, psp_ext) == NET_RX_DROP))
>>  		goto out_drop_cnt;
>> @@ -168,6 +196,13 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>>  	if (!hrtimer_active(&rq->napi_timer))
>>  		hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL);
>>  
>> +	/* only timestamp the outbound packet if user requested it */
>> +	if (gen_tx_tstamp) {
>> +		shhwtstamps.hwtstamp = timespec64_to_ktime(tx_ts);
>> +		skb_tstamp_tx(skb_orig, &shhwtstamps);
>> +		dev_kfree_skb_any(skb_orig);
>> +	}
>> +
>>  	rcu_read_unlock();
>>  	dev_dstats_tx_add(dev, len);
>>  	return NETDEV_TX_OK;
>> @@ -182,6 +217,59 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
>>  	return NETDEV_TX_OK;
>>  }
>>  
>> +static int nsim_set_ts_config(struct net_device *netdev,
>> +			      struct kernel_hwtstamp_config *config,
>> +			      struct netlink_ext_ack *extack)
>> +{
>> +	struct netdevsim *ns = netdev_priv(netdev);
>> +
>> +	if (!ns->phc)
>> +		return -EOPNOTSUPP;
>> +
>> +	switch (config->tx_type) {
>> +	case HWTSTAMP_TX_OFF:
>> +		ns->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
>> +		break;
>> +	case HWTSTAMP_TX_ON:
>> +		ns->tstamp_config.tx_type = HWTSTAMP_TX_ON;
>> +		break;
>> +	default:
>> +		return -ERANGE;
>> +	}
>> +
>> +	switch (config->rx_filter) {
>> +	case HWTSTAMP_FILTER_NONE:
>> +		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
>> +		break;
>> +	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
>> +	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
>> +	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
>> +	case HWTSTAMP_FILTER_PTP_V2_EVENT:
>> +	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
>> +	case HWTSTAMP_FILTER_PTP_V2_SYNC:
>> +	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
>> +	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
>> +	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
>> +	case HWTSTAMP_FILTER_NTP_ALL:
>> +	case HWTSTAMP_FILTER_ALL:
>> +		ns->tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
>> +		break;
>> +	default:
>> +		return -ERANGE;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int nsim_get_ts_config(struct net_device *netdev,
>> +			      struct kernel_hwtstamp_config *config)
>> +{
>> +	struct netdevsim *ns = netdev_priv(netdev);
>> +
>> +	*config = ns->tstamp_config;
>> +	return 0;
>> +}
>> +
>>  static void nsim_set_rx_mode(struct net_device *dev)
>>  {
>>  }
>> @@ -660,6 +748,8 @@ static const struct net_device_ops nsim_netdev_ops = {
>>  	.ndo_open		= nsim_open,
>>  	.ndo_stop		= nsim_stop,
>>  	.net_shaper_ops		= &nsim_shaper_ops,
>> +	.ndo_hwtstamp_get	= nsim_get_ts_config,
>> +	.ndo_hwtstamp_set	= nsim_set_ts_config,
>>  };
>>  
>>  static const struct net_device_ops nsim_vf_netdev_ops = {
>> diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
>> index f767fc8a7..6d3e8700c 100644
>> --- a/drivers/net/netdevsim/netdevsim.h
>> +++ b/drivers/net/netdevsim/netdevsim.h
>> @@ -103,6 +103,7 @@ struct netdevsim {
>>  	struct net_device *netdev;
>>  	struct nsim_dev *nsim_dev;
>>  	struct nsim_dev_port *nsim_dev_port;
>> +	struct kernel_hwtstamp_config tstamp_config;
>>  	struct mock_phc *phc;
>>  	struct nsim_rq **rq;
>>  
>> -- 
>> 2.53.0
>>
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net-next 2/2] netdevsim: Implement basic ptp support
  2026-02-19 20:42   ` Jakub Kicinski
@ 2026-02-20 21:07     ` Maciek Machnikowski
  0 siblings, 0 replies; 8+ messages in thread
From: Maciek Machnikowski @ 2026-02-20 21:07 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: richardcochran, netdev, milena.olech, Vadim Fedorenko



On 19/02/2026 21:42, Jakub Kicinski wrote:
> On Thu, 19 Feb 2026 15:05:30 +0100 Maciek Machnikowski wrote:
>> +	gen_tx_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
>> +	if (gen_tx_tstamp) {
>> +		ptp_info = mock_phc_get_ptp_info(ns->phc);
>> +
>> +		/* Create a copy of tx skb to keep the tx reference */
>> +		skb_orig = skb;
>> +		skb = skb_copy(skb_orig, GFP_ATOMIC);
>> +		skb_shinfo(skb_orig)->tx_flags |= SKBTX_IN_PROGRESS;
>> +
>> +		/* Timestamp as late as possible */
>> +		if (ptp_info)
>> +			ptp_info->gettime64(ptp_info, &tx_ts);
>> +	}
> 
> Like Andrew said we need a test in tree. But Vadim has been promising me
> a timestamping test for a while, so adding him here. You can probably
> work together (unless you already have such a test).
> 
> When you respin - note that mock_phc takes a spin lock without _bh
> around its internals. It needs to be changed to _bh() if we call
> it form the xmit path.
> 

Sure! Will resubmit with a basic ptp functional test and work on
extending it with Vadim.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-02-20 21:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-19 14:05 [PATCH net-next 0/2] Implement PTP support in netdevsim Maciek Machnikowski
2026-02-19 14:05 ` [PATCH net-next 1/2] ptp: Expose ptp_clock_info to external drivers Maciek Machnikowski
2026-02-19 14:05 ` [PATCH net-next 2/2] netdevsim: Implement basic ptp support Maciek Machnikowski
2026-02-19 16:16   ` Andrew Lunn
2026-02-19 20:42   ` Jakub Kicinski
2026-02-20 21:07     ` Maciek Machnikowski
2026-02-20 20:08   ` Willem de Bruijn
2026-02-20 21:06     ` Maciek Machnikowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox