net/devlink/port.c

Source file repositories/reference/linux-study-clean/net/devlink/port.c

File Facts

System
Linux kernel
Corpus path
net/devlink/port.c
Extension
.c
Size
46198 bytes
Lines
1608
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 = netdev->netdev_ops;

	/* If driver registers devlink port, it should set devlink port
	 * attributes accordingly so the compat functions are called
	 * and the original ops are not used.
	 */
	if (ops->ndo_get_phys_port_name) {
		/* Some drivers use the same set of ndos for netdevs
		 * that have devlink_port registered and also for
		 * those who don't. Make sure that ndo_get_phys_port_name
		 * returns -EOPNOTSUPP here in case it is defined.
		 * Warn if not.
		 */
		char name[IFNAMSIZ];
		int err;

		err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
		WARN_ON(err != -EOPNOTSUPP);
	}
	if (ops->ndo_get_port_parent_id) {
		/* Some drivers use the same set of ndos for netdevs
		 * that have devlink_port registered and also for
		 * those who don't. Make sure that ndo_get_port_parent_id
		 * returns -EOPNOTSUPP here in case it is defined.
		 * Warn if not.
		 */
		struct netdev_phys_item_id ppid;
		int err;

		err = ops->ndo_get_port_parent_id(netdev, &ppid);
		WARN_ON(err != -EOPNOTSUPP);
	}
}

static void __devlink_port_type_set(struct devlink_port *devlink_port,
				    enum devlink_port_type type,
				    void *type_dev)
{
	struct net_device *netdev = type_dev;

	ASSERT_DEVLINK_PORT_REGISTERED(devlink_port);

	if (type == DEVLINK_PORT_TYPE_NOTSET) {
		devlink_port_type_warn_schedule(devlink_port);
	} else {
		devlink_port_type_warn_cancel(devlink_port);
		if (type == DEVLINK_PORT_TYPE_ETH && netdev)
			devlink_port_type_netdev_checks(devlink_port, netdev);
	}

	spin_lock_bh(&devlink_port->type_lock);
	devlink_port->type = type;
	switch (type) {
	case DEVLINK_PORT_TYPE_ETH:
		devlink_port->type_eth.netdev = netdev;
		if (netdev) {
			ASSERT_RTNL();
			devlink_port->type_eth.ifindex = netdev->ifindex;
			BUILD_BUG_ON(sizeof(devlink_port->type_eth.ifname) !=
				     sizeof(netdev->name));
			strcpy(devlink_port->type_eth.ifname, netdev->name);
		}
		break;
	case DEVLINK_PORT_TYPE_IB:
		devlink_port->type_ib.ibdev = type_dev;
		break;
	default:
		break;
	}
	spin_unlock_bh(&devlink_port->type_lock);
	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
}

/**
 *	devlink_port_type_eth_set - Set port type to Ethernet
 *
 *	@devlink_port: devlink port
 *
 *	If driver is calling this, most likely it is doing something wrong.
 */
void devlink_port_type_eth_set(struct devlink_port *devlink_port)
{
	devl_warn(devlink_port->devlink,
		  "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
		  devlink_port->index);
	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL);
}
EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);

/**

Annotation

Implementation Notes