diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-09-02 21:03:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-02 21:03:00 -0400 |
commit | 2e59af3dcbdf11635c03f22bfc9706744465d589 (patch) | |
tree | c01e87c0ef6568bae987f4628a8656ba0d05aa23 | |
parent | 5848cc096a23b80b3d15c27d72299f79caf7c517 (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.h | 3 | ||||
-rw-r--r-- | net/8021q/vlan.c | 5 | ||||
-rw-r--r-- | net/8021q/vlan_netlink.c | 20 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 10 |
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 | ||
75 | extern int __rtnl_link_register(struct rtnl_link_ops *ops); | 78 | extern 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 | ||
103 | static 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 | |||
103 | static int vlan_newlink(struct net_device *dev, | 122 | static 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) |