net/core/dev_ioctl.c

Source file repositories/reference/linux-study-clean/net/core/dev_ioctl.c

File Facts

System
Linux kernel
Corpus path
net/core/dev_ioctl.c
Extension
.c
Size
20206 bytes
Lines
850
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

const struct net_device_ops *ops = dev->netdev_ops;
	struct kernel_hwtstamp_config kernel_cfg = {};
	struct hwtstamp_config cfg;
	int err;

	if (!ops->ndo_hwtstamp_get)
		return -EOPNOTSUPP;

	if (!netif_device_present(dev))
		return -ENODEV;

	kernel_cfg.ifr = ifr;
	netdev_lock_ops(dev);
	err = dev_get_hwtstamp_phylib(dev, &kernel_cfg);
	netdev_unlock_ops(dev);
	if (err)
		return err;

	/* If the request was resolved through an unconverted driver, omit
	 * the copy_to_user(), since the implementation has already done that
	 */
	if (!kernel_cfg.copied_to_user) {
		hwtstamp_config_from_kernel(&cfg, &kernel_cfg);

		if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)))
			return -EFAULT;
	}

	return 0;
}

/**
 * dev_set_hwtstamp_phylib() - Change hardware timestamping of NIC
 *	or of attached phylib PHY
 * @dev: Network device
 * @cfg: Timestamping configuration structure
 * @extack: Netlink extended ack message structure, for error reporting
 *
 * Helper for enforcing a common policy that phylib timestamping, if available,
 * should take precedence in front of hardware timestamping provided by the
 * netdev. If the netdev driver needs to perform specific actions even for PHY
 * timestamping to work properly (a switch port must trap the timestamped
 * frames and not forward them), it must set dev->see_all_hwtstamp_requests.
 */
int dev_set_hwtstamp_phylib(struct net_device *dev,
			    struct kernel_hwtstamp_config *cfg,
			    struct netlink_ext_ack *extack)
{
	const struct net_device_ops *ops = dev->netdev_ops;
	struct kernel_hwtstamp_config old_cfg = {};
	struct hwtstamp_provider *hwprov;
	struct phy_device *phydev;
	bool changed = false;
	bool phy_ts;
	int err;

	hwprov = netdev_ops_lock_dereference(dev->hwprov, dev);
	if (hwprov) {
		if (hwprov->source == HWTSTAMP_SOURCE_PHYLIB &&
		    hwprov->phydev) {
			phy_ts = true;
			phydev = hwprov->phydev;
		} else if (hwprov->source == HWTSTAMP_SOURCE_NETDEV) {
			phy_ts = false;
		} else {
			return -EOPNOTSUPP;
		}

		cfg->qualifier = hwprov->desc.qualifier;
	} else {
		phy_ts = phy_is_default_hwtstamp(dev->phydev);
		if (phy_ts)
			phydev = dev->phydev;
	}

	cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV;

	if (phy_ts && dev->see_all_hwtstamp_requests) {
		err = ops->ndo_hwtstamp_get(dev, &old_cfg);
		if (err)
			return err;
	}

	if (!phy_ts || dev->see_all_hwtstamp_requests) {
		err = ops->ndo_hwtstamp_set(dev, cfg, extack);
		if (err) {
			if (extack->_msg)
				netdev_err(dev, "%s\n", extack->_msg);
			return err;
		}

Annotation

Implementation Notes