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 <danieloak@gmail.com>
This commit is contained in:
Claude 2026-09-25 16:37:16 +00:00 • committed by Alan C. Assis
parent b7001f2d9f
commit 6e14c8cfe5
3 changed files with 117 additions and 0 deletions

View file

@ -43,6 +43,7 @@
#include <net/ethernet.h>
#include <netinet/in.h>
#include <nuttx/ethtool.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/vlan.h>
@ -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.
*/