Skip to content

Commit

Permalink
net: Expose available time stamping layers to user space.
Browse files Browse the repository at this point in the history
Time stamping on network packets may happen either in the MAC or in
the PHY, but not both.  In preparation for making the choice
selectable, expose both the current and available layers via sysfs.

In accordance with the kernel implementation as it stands, the current
layer will always read as "phy" when a PHY time stamping device is
present.  Future patches will allow changing the current layer
administratively.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
  • Loading branch information
richardcochran authored and intel-lab-lkp committed Jan 3, 2022
1 parent 9beda15 commit c7ffd87
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Documentation/ABI/testing/sysfs-class-net-timestamping
@@ -0,0 +1,17 @@
What: /sys/class/net/<iface>/available_timestamping_providers
Date: January 2022
Contact: Richard Cochran <richardcochran@gmail.com>
Description:
Enumerates the available providers for SO_TIMESTAMPING.
The possible values are:
- "mac" The MAC provides time stamping.
- "phy" The PHY or MII device provides time stamping.

What: /sys/class/net/<iface>/current_timestamping_provider
Date: January 2022
Contact: Richard Cochran <richardcochran@gmail.com>
Description:
Show the current SO_TIMESTAMPING provider.
The possible values are:
- "mac" The MAC provides time stamping.
- "phy" The PHY or MII device provides time stamping.
2 changes: 2 additions & 0 deletions drivers/net/phy/phy_device.c
Expand Up @@ -1415,6 +1415,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,

phydev->phy_link_change = phy_link_change;
if (dev) {
dev->selected_timestamping_layer = PHY_TIMESTAMPING;
phydev->attached_dev = dev;
dev->phydev = phydev;

Expand Down Expand Up @@ -1727,6 +1728,7 @@ void phy_detach(struct phy_device *phydev)

phy_suspend(phydev);
if (dev) {
dev->selected_timestamping_layer = MAC_TIMESTAMPING;
phydev->attached_dev->phydev = NULL;
phydev->attached_dev = NULL;
}
Expand Down
10 changes: 10 additions & 0 deletions include/linux/netdevice.h
Expand Up @@ -1687,6 +1687,11 @@ enum netdev_ml_priv_type {
ML_PRIV_CAN,
};

enum timestamping_layer {
MAC_TIMESTAMPING,
PHY_TIMESTAMPING,
};

/**
* struct net_device - The DEVICE structure.
*
Expand Down Expand Up @@ -1927,6 +1932,9 @@ enum netdev_ml_priv_type {
*
* @threaded: napi threaded mode is enabled
*
* @selected_timestamping_layer: Tracks whether the MAC or the PHY
* performs packet time stamping.
*
* @net_notifier_list: List of per-net netdev notifier block
* that follow this device when it is moved
* to another network namespace.
Expand Down Expand Up @@ -2263,6 +2271,8 @@ struct net_device {
unsigned wol_enabled:1;
unsigned threaded:1;

enum timestamping_layer selected_timestamping_layer;

struct list_head net_notifier_list;

#if IS_ENABLED(CONFIG_MACSEC)
Expand Down
60 changes: 60 additions & 0 deletions net/core/net-sysfs.c
Expand Up @@ -618,6 +618,64 @@ static ssize_t threaded_store(struct device *dev,
}
static DEVICE_ATTR_RW(threaded);

static ssize_t available_timestamping_providers_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
const struct ethtool_ops *ops;
struct net_device *netdev;
struct phy_device *phydev;
int ret = 0;

netdev = to_net_dev(dev);
phydev = netdev->phydev;
ops = netdev->ethtool_ops;

if (!rtnl_trylock())
return restart_syscall();

ret += sprintf(buf, "%s\n", "mac");
buf += 4;

if (phy_has_tsinfo(phydev)) {
ret += sprintf(buf, "%s\n", "phy");
buf += 4;
}

rtnl_unlock();

return ret;
}
static DEVICE_ATTR_RO(available_timestamping_providers);

static ssize_t current_timestamping_provider_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
const struct ethtool_ops *ops;
struct net_device *netdev;
struct phy_device *phydev;
int ret;

netdev = to_net_dev(dev);
phydev = netdev->phydev;
ops = netdev->ethtool_ops;

if (!rtnl_trylock())
return restart_syscall();

if (phy_has_tsinfo(phydev)) {
ret = sprintf(buf, "%s\n", "phy");
} else {
ret = sprintf(buf, "%s\n", "mac");
}

rtnl_unlock();

return ret;
}
static DEVICE_ATTR_RO(current_timestamping_provider);

static struct attribute *net_class_attrs[] __ro_after_init = {
&dev_attr_netdev_group.attr,
&dev_attr_type.attr,
Expand Down Expand Up @@ -651,6 +709,8 @@ static struct attribute *net_class_attrs[] __ro_after_init = {
&dev_attr_carrier_up_count.attr,
&dev_attr_carrier_down_count.attr,
&dev_attr_threaded.attr,
&dev_attr_available_timestamping_providers.attr,
&dev_attr_current_timestamping_provider.attr,
NULL,
};
ATTRIBUTE_GROUPS(net_class);
Expand Down

0 comments on commit c7ffd87

Please sign in to comment.