drivers/net/netkit.c

Source file repositories/reference/linux-study-clean/drivers/net/netkit.c

File Facts

System
Linux kernel
Corpus path
drivers/net/netkit.c
Extension
.c
Size
33656 bytes
Lines
1309
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops netkit_netdev_ops = {
	.ndo_init		= netkit_init,
	.ndo_open		= netkit_open,
	.ndo_stop		= netkit_close,
	.ndo_start_xmit		= netkit_xmit,
	.ndo_set_rx_mode_async	= netkit_set_multicast,
	.ndo_set_rx_headroom	= netkit_set_headroom,
	.ndo_set_mac_address	= netkit_set_macaddr,
	.ndo_get_iflink		= netkit_get_iflink,
	.ndo_get_peer_dev	= netkit_peer_dev,
	.ndo_get_stats64	= netkit_get_stats,
	.ndo_uninit		= netkit_uninit,
	.ndo_bpf		= netkit_xsk,
	.ndo_xsk_wakeup		= netkit_xsk_wakeup,
	.ndo_features_check	= passthru_features_check,
};

static void netkit_get_drvinfo(struct net_device *dev,
			       struct ethtool_drvinfo *info)
{
	strscpy(info->driver, NETKIT_DRV_NAME, sizeof(info->driver));
}

static const struct ethtool_ops netkit_ethtool_ops = {
	.get_drvinfo		= netkit_get_drvinfo,
};

static int netkit_queue_create(struct net_device *dev,
			       struct netlink_ext_ack *extack)
{
	struct netkit *nk = netkit_priv(dev);
	u32 rxq_count_old, rxq_count_new;
	int err;

	rxq_count_old = dev->real_num_rx_queues;
	rxq_count_new = rxq_count_old + 1;

	/* In paired mode, only the non-primary (peer) device can
	 * create leased queues since the primary is the management
	 * side. In single device mode, leasing is always allowed.
	 */
	if (nk->pair == NETKIT_DEVICE_PAIR && nk->primary) {
		NL_SET_ERR_MSG(extack,
			       "netkit can only lease against the peer device");
		return -EOPNOTSUPP;
	}

	err = netif_set_real_num_rx_queues(dev, rxq_count_new);
	if (err) {
		if (rxq_count_new > dev->num_rx_queues)
			NL_SET_ERR_MSG(extack,
				       "netkit maximum queue limit reached");
		else
			NL_SET_ERR_MSG_FMT(extack,
					   "netkit cannot create more queues err=%d", err);
		return err;
	}

	return rxq_count_old;
}

static const struct netdev_queue_mgmt_ops netkit_queue_mgmt_ops = {
	.ndo_queue_create	= netkit_queue_create,
};

static struct net_device *netkit_alloc(struct nlattr *tb[],
				       const char *ifname,
				       unsigned char name_assign_type,
				       unsigned int num_tx_queues,
				       unsigned int num_rx_queues)
{
	const struct rtnl_link_ops *ops = &netkit_link_ops;
	struct net_device *dev;

	if (num_tx_queues > NETKIT_NUM_TX_QUEUES_MAX ||
	    num_rx_queues > NETKIT_NUM_RX_QUEUES_MAX)
		return ERR_PTR(-EOPNOTSUPP);

	dev = alloc_netdev_mqs(ops->priv_size, ifname,
			       name_assign_type, ops->setup,
			       num_tx_queues, num_rx_queues);
	if (dev) {
		dev->real_num_tx_queues = NETKIT_NUM_TX_QUEUES_REAL;
		dev->real_num_rx_queues = NETKIT_NUM_RX_QUEUES_REAL;
	}
	return dev;
}

static void netkit_queue_unlease(struct net_device *dev)
{

Annotation

Implementation Notes