aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-09-02 21:03:00 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-02 21:03:00 -0400
commit2e59af3dcbdf11635c03f22bfc9706744465d589 (patch)
treec01e87c0ef6568bae987f4628a8656ba0d05aa23
parent5848cc096a23b80b3d15c27d72299f79caf7c517 (diff)
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>
-rw-r--r--include/net/rtnetlink.h3
-rw-r--r--net/8021q/vlan.c5
-rw-r--r--net/8021q/vlan_netlink.c20
-rw-r--r--net/core/rtnetlink.c10
4 files changed, 35 insertions, 3 deletions
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 3c1895e54b7f..b630196b5627 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -70,6 +70,9 @@ struct rtnl_link_ops {
70 size_t (*get_xstats_size)(const struct net_device *dev); 70 size_t (*get_xstats_size)(const struct net_device *dev);
71 int (*fill_xstats)(struct sk_buff *skb, 71 int (*fill_xstats)(struct sk_buff *skb,
72 const struct net_device *dev); 72 const struct net_device *dev);
73 int (*get_tx_queues)(struct net *net, struct nlattr *tb[],
74 unsigned int *tx_queues,
75 unsigned int *real_tx_queues);
73}; 76};
74 77
75extern int __rtnl_link_register(struct rtnl_link_ops *ops); 78extern int __rtnl_link_register(struct rtnl_link_ops *ops);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index e814794b0a1a..8836575f9d79 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -330,12 +330,13 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
330 snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); 330 snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
331 } 331 }
332 332
333 new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, 333 new_dev = alloc_netdev_mq(sizeof(struct vlan_dev_info), name,
334 vlan_setup); 334 vlan_setup, real_dev->num_tx_queues);
335 335
336 if (new_dev == NULL) 336 if (new_dev == NULL)
337 return -ENOBUFS; 337 return -ENOBUFS;
338 338
339 new_dev->real_num_tx_queues = real_dev->real_num_tx_queues;
339 dev_net_set(new_dev, net); 340 dev_net_set(new_dev, net);
340 /* need 4 bytes for extra VLAN header info, 341 /* need 4 bytes for extra VLAN header info,
341 * hope the underlying device can handle it. 342 * hope the underlying device can handle it.
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index e9c91dcecc9b..343146e1bceb 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -100,6 +100,25 @@ static int vlan_changelink(struct net_device *dev,
100 return 0; 100 return 0;
101} 101}
102 102
103static int vlan_get_tx_queues(struct net *net,
104 struct nlattr *tb[],
105 unsigned int *num_tx_queues,
106 unsigned int *real_num_tx_queues)
107{
108 struct net_device *real_dev;
109
110 if (!tb[IFLA_LINK])
111 return -EINVAL;
112
113 real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
114 if (!real_dev)
115 return -ENODEV;
116
117 *num_tx_queues = real_dev->num_tx_queues;
118 *real_num_tx_queues = real_dev->real_num_tx_queues;
119 return 0;
120}
121
103static int vlan_newlink(struct net_device *dev, 122static int vlan_newlink(struct net_device *dev,
104 struct nlattr *tb[], struct nlattr *data[]) 123 struct nlattr *tb[], struct nlattr *data[])
105{ 124{
@@ -216,6 +235,7 @@ struct rtnl_link_ops vlan_link_ops __read_mostly = {
216 .maxtype = IFLA_VLAN_MAX, 235 .maxtype = IFLA_VLAN_MAX,
217 .policy = vlan_policy, 236 .policy = vlan_policy,
218 .priv_size = sizeof(struct vlan_dev_info), 237 .priv_size = sizeof(struct vlan_dev_info),
238 .get_tx_queues = vlan_get_tx_queues,
219 .setup = vlan_setup, 239 .setup = vlan_setup,
220 .validate = vlan_validate, 240 .validate = vlan_validate,
221 .newlink = vlan_newlink, 241 .newlink = vlan_newlink,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b44775f9f2bf..bbcba2a41018 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -974,12 +974,20 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
974{ 974{
975 int err; 975 int err;
976 struct net_device *dev; 976 struct net_device *dev;
977 unsigned int num_queues = 1;
978 unsigned int real_num_queues = 1;
977 979
980 if (ops->get_tx_queues) {
981 err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues);
982 if (err)
983 goto err;
984 }
978 err = -ENOMEM; 985 err = -ENOMEM;
979 dev = alloc_netdev(ops->priv_size, ifname, ops->setup); 986 dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues);
980 if (!dev) 987 if (!dev)
981 goto err; 988 goto err;
982 989
990 dev->real_num_tx_queues = real_num_queues;
983 if (strchr(dev->name, '%')) { 991 if (strchr(dev->name, '%')) {
984 err = dev_alloc_name(dev, dev->name); 992 err = dev_alloc_name(dev, dev->name);
985 if (err < 0) 993 if (err < 0)