]> git.karo-electronics.de Git - linux-beck.git/commitdiff
vlan: multiqueue vlan device
authorEric Dumazet <eric.dumazet@gmail.com>
Thu, 3 Sep 2009 01:03:00 +0000 (18:03 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 Sep 2009 01:03:00 +0000 (18:03 -0700)
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>
include/net/rtnetlink.h
net/8021q/vlan.c
net/8021q/vlan_netlink.c
net/core/rtnetlink.c

index 3c1895e54b7f91a672cd43c61262b6485184ea52..b630196b562779abaa785cb47e5df2e0ae8b0483 100644 (file)
@@ -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);
index e814794b0a1ac33c84aaf54699d0dc4a28539e77..8836575f9d79dcd9b28c1cfa7d01d034dde9f0c5 100644 (file)
@@ -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.
index e9c91dcecc9bc8552cb71e63637aa0565df53a2c..343146e1bceb0998e1b2a0804b5a798944669ea5 100644 (file)
@@ -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,
index b44775f9f2bfa8b807ebf38e1b314aba7c6d2956..bbcba2a41018b7c2d8768449199a034585c935c9 100644 (file)
@@ -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)