Skip to content

Commit

Permalink
vlan: multiqueue vlan device
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Sep 3, 2009
1 parent 5848cc0 commit 2e59af3
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions net/8021q/vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 20 additions & 0 deletions net/8021q/vlan_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[])
{
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 9 additions & 1 deletion net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 2e59af3

Please sign in to comment.