Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e59af3d authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

vlan: multiqueue vlan device



vlan devices are currently not multi-queue capable.

We can do that with a new rtnl_link_ops method,
get_tx_queues(), called from rtnl_create_link()

This new method gets num_tx_queues/real_num_tx_queues
from real device.

register_vlan_device() is also handled.

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5848cc09
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ struct rtnl_link_ops {
	size_t			(*get_xstats_size)(const struct net_device *dev);
	int			(*fill_xstats)(struct sk_buff *skb,
					       const struct net_device *dev);
	int			(*get_tx_queues)(struct net *net, struct nlattr *tb[],
						 unsigned int *tx_queues,
						 unsigned int *real_tx_queues);
};

extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
+3 −2
Original line number Diff line number Diff line
@@ -330,12 +330,13 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
	}

	new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
			       vlan_setup);
	new_dev = alloc_netdev_mq(sizeof(struct vlan_dev_info), name,
				  vlan_setup, real_dev->num_tx_queues);

	if (new_dev == NULL)
		return -ENOBUFS;

	new_dev->real_num_tx_queues = real_dev->real_num_tx_queues;
	dev_net_set(new_dev, net);
	/* need 4 bytes for extra VLAN header info,
	 * hope the underlying device can handle it.
+20 −0
Original line number Diff line number Diff line
@@ -100,6 +100,25 @@ static int vlan_changelink(struct net_device *dev,
	return 0;
}

static int vlan_get_tx_queues(struct net *net,
			      struct nlattr *tb[],
			      unsigned int *num_tx_queues,
			      unsigned int *real_num_tx_queues)
{
	struct net_device *real_dev;

	if (!tb[IFLA_LINK])
		return -EINVAL;

	real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
	if (!real_dev)
		return -ENODEV;

	*num_tx_queues      = real_dev->num_tx_queues;
	*real_num_tx_queues = real_dev->real_num_tx_queues;
	return 0;
}

static int vlan_newlink(struct net_device *dev,
			struct nlattr *tb[], struct nlattr *data[])
{
@@ -216,6 +235,7 @@ struct rtnl_link_ops vlan_link_ops __read_mostly = {
	.maxtype	= IFLA_VLAN_MAX,
	.policy		= vlan_policy,
	.priv_size	= sizeof(struct vlan_dev_info),
	.get_tx_queues  = vlan_get_tx_queues,
	.setup		= vlan_setup,
	.validate	= vlan_validate,
	.newlink	= vlan_newlink,
+9 −1
Original line number Diff line number Diff line
@@ -974,12 +974,20 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
{
	int err;
	struct net_device *dev;
	unsigned int num_queues = 1;
	unsigned int real_num_queues = 1;

	if (ops->get_tx_queues) {
		err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues);
		if (err)
			goto err;
	}
	err = -ENOMEM;
	dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
	dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues);
	if (!dev)
		goto err;

	dev->real_num_tx_queues = real_num_queues;
	if (strchr(dev->name, '%')) {
		err = dev_alloc_name(dev, dev->name);
		if (err < 0)