From 6e14c8cfe59bdcfce88ca8e09f95e3bafe7bfec6 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 16:37:16 +0000 Subject: [PATCH] net/netdev: add NETDEV_TX_STAMP and handle SIOCETHTOOL ETHTOOL_GET_TS_INFO Add the NETDEV_TX_STAMP capability flag to d_features, next to the existing NETDEV_RX_STAMP, so a driver can declare that it delivers hardware TX timestamps. SIOCETHTOOL and ETHTOOL_GET_TS_INFO were already defined but not implemented. Add struct ethtool_ts_info, with the same layout as Linux, and handle SIOCETHTOOL in netdev_ioctl.c so that userspace (such as ptpd) can query the timestamping capabilities of an interface the same way linuxptp/ptp4l does on Linux: - ETHTOOL_GET_TS_INFO fills so_timestamping from d_features: RX_HARDWARE | RAW_HARDWARE with NETDEV_RX_STAMP, otherwise RX_SOFTWARE | SOFTWARE (the stack stamps received packets with CLOCK_REALTIME), and TX_HARDWARE | RAW_HARDWARE with NETDEV_TX_STAMP. phc_index is -1, tx_types and rx_filters are zero. - Any other ethtool command is passed to the driver's d_ioctl when CONFIG_NETDEV_IOCTL is enabled, otherwise -ENOTTY is returned. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Daniel P. Carvalho --- include/nuttx/ethtool.h | 31 ++++++++++++++ include/nuttx/net/netdev.h | 1 + net/netdev/netdev_ioctl.c | 85 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/include/nuttx/ethtool.h b/include/nuttx/ethtool.h index 26412a6a1f4..87cd3f0e1d5 100644 --- a/include/nuttx/ethtool.h +++ b/include/nuttx/ethtool.h @@ -23,6 +23,12 @@ #ifndef __INCLUDE_NUTTX_ETHTOOL_H #define __INCLUDE_NUTTX_ETHTOOL_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -221,4 +227,29 @@ struct ethtool_cmd uint32_t reserved[2]; }; +/* struct ethtool_ts_info - holds a device's timestamping and PHC + * association (ETHTOOL_GET_TS_INFO), same layout as Linux. + * @cmd: command number = %ETHTOOL_GET_TS_INFO + * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING + * flags (SOF_TIMESTAMPING_*) + * @phc_index: device index of the associated PHC, or -1 if there is none + * @tx_types: bit mask of the supported hwtstamp_tx_types values; zero, + * NuttX has no SIOCSHWTSTAMP to select them + * @tx_reserved: reserved for future use, zero + * @rx_filters: bit mask of the supported hwtstamp_rx_filters values; zero, + * NuttX has no SIOCSHWTSTAMP to select them + * @rx_reserved: reserved for future use, zero + */ + +struct ethtool_ts_info +{ + uint32_t cmd; + uint32_t so_timestamping; + int32_t phc_index; + uint32_t tx_types; + uint32_t tx_reserved[3]; + uint32_t rx_filters; + uint32_t rx_reserved[3]; +}; + #endif diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index c5395ba67cd..a5a78c078c7 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -85,6 +85,7 @@ #define NETDEV_TX_CSUM (1 << 1) /* Netdev support hardware tx checksum */ #define NETDEV_RX_CSUM (1 << 2) /* Netdev support hardware rx checksum */ #define NETDEV_RX_STAMP (1 << 3) /* Netdev support hardware timestamp */ +#define NETDEV_TX_STAMP (1 << 4) /* Netdev provides hardware TX timestamps */ /* Determine the largest possible address */ diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 4f6610f4396..1b846e30e61 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -767,6 +768,7 @@ static ssize_t net_ioctl_ifreq_arglen(uint8_t domain, int cmd) case SIOCGIFCOUNT: case SIOCSIFFLAGS: case SIOCGIFFLAGS: + case SIOCETHTOOL: case SIOCMIINOTIFY: case SIOCGMIIPHY: case SIOCGMIIREG: @@ -809,6 +811,85 @@ static ssize_t net_ioctl_ifreq_arglen(uint8_t domain, int cmd) return -ENOTTY; } +/**************************************************************************** + * Name: netdev_ethtool_ioctl + * + * Description: + * Handle the SIOCETHTOOL command. req->ifr_data points to an ethtool + * command structure whose first field is the ETHTOOL_* command. + * ETHTOOL_GET_TS_INFO is answered from the device features; any other + * command is passed to the driver. + * + * Input Parameters: + * dev The network device + * req The argument of the ioctl cmd + * + * Returned Value: + * >=0 on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +static int netdev_ethtool_ioctl(FAR struct net_driver_s *dev, + FAR struct ifreq *req) +{ + FAR uint32_t *ethcmd = req->ifr_data; + + if (ethcmd == NULL) + { + return -EINVAL; + } + + switch (*ethcmd) + { + case ETHTOOL_GET_TS_INFO: /* Get time stamping and PHC info */ + { + FAR struct ethtool_ts_info *info = req->ifr_data; + + memset(info, 0, sizeof(*info)); + info->cmd = ETHTOOL_GET_TS_INFO; + info->phc_index = -1; + +#ifdef CONFIG_NET_TIMESTAMP + /* Received packets carry the hardware timestamp when the driver + * provides one, and are stamped by the stack with CLOCK_REALTIME + * otherwise. + */ + + if ((dev->d_features & NETDEV_RX_STAMP) != 0) + { + info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + } + else + { + info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + } + + if ((dev->d_features & NETDEV_TX_STAMP) != 0) + { + info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + } +#endif + + return OK; + } + + default: +#ifdef CONFIG_NETDEV_IOCTL + if (dev->d_ioctl != NULL) + { + return dev->d_ioctl(dev, SIOCETHTOOL, + (unsigned long)(uintptr_t)req->ifr_data); + } +#endif + + return -ENOTTY; + } +} + /**************************************************************************** * Name: netdev_ifr_ioctl * @@ -1088,6 +1169,10 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, req->ifr_flags = dev->d_flags; break; + case SIOCETHTOOL: /* Ethtool interface */ + ret = netdev_ethtool_ioctl(dev, req); + break; + /* MAC address operations only make sense if Ethernet or 6LoWPAN are * supported. */