forked from mirrors/linux
		
	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: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5848cc096a
								
							
						
					
					
						commit
						2e59af3dcb
					
				
					 4 changed files with 35 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue