aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan.c')
-rw-r--r--net/8021q/vlan.c147
1 files changed, 104 insertions, 43 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index b33410abfd6b..2a739adaa92b 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -32,6 +32,7 @@
32#include <linux/rtnetlink.h> 32#include <linux/rtnetlink.h>
33#include <linux/notifier.h> 33#include <linux/notifier.h>
34#include <net/net_namespace.h> 34#include <net/net_namespace.h>
35#include <net/netns/generic.h>
35 36
36#include <linux/if_vlan.h> 37#include <linux/if_vlan.h>
37#include "vlan.h" 38#include "vlan.h"
@@ -41,6 +42,8 @@
41 42
42/* Global VLAN variables */ 43/* Global VLAN variables */
43 44
45int vlan_net_id;
46
44/* Our listing of VLAN group(s) */ 47/* Our listing of VLAN group(s) */
45static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE]; 48static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
46 49
@@ -49,9 +52,6 @@ static char vlan_version[] = DRV_VERSION;
49static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; 52static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
50static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; 53static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
51 54
52/* Determines interface naming scheme. */
53unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
54
55static struct packet_type vlan_packet_type = { 55static struct packet_type vlan_packet_type = {
56 .type = __constant_htons(ETH_P_8021Q), 56 .type = __constant_htons(ETH_P_8021Q),
57 .func = vlan_skb_recv, /* VLAN receive method */ 57 .func = vlan_skb_recv, /* VLAN receive method */
@@ -65,14 +65,14 @@ static inline unsigned int vlan_grp_hashfn(unsigned int idx)
65} 65}
66 66
67/* Must be invoked with RCU read lock (no preempt) */ 67/* Must be invoked with RCU read lock (no preempt) */
68static struct vlan_group *__vlan_find_group(int real_dev_ifindex) 68static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
69{ 69{
70 struct vlan_group *grp; 70 struct vlan_group *grp;
71 struct hlist_node *n; 71 struct hlist_node *n;
72 int hash = vlan_grp_hashfn(real_dev_ifindex); 72 int hash = vlan_grp_hashfn(real_dev->ifindex);
73 73
74 hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) { 74 hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
75 if (grp->real_dev_ifindex == real_dev_ifindex) 75 if (grp->real_dev == real_dev)
76 return grp; 76 return grp;
77 } 77 }
78 78
@@ -86,7 +86,7 @@ static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
86struct net_device *__find_vlan_dev(struct net_device *real_dev, 86struct net_device *__find_vlan_dev(struct net_device *real_dev,
87 unsigned short VID) 87 unsigned short VID)
88{ 88{
89 struct vlan_group *grp = __vlan_find_group(real_dev->ifindex); 89 struct vlan_group *grp = __vlan_find_group(real_dev);
90 90
91 if (grp) 91 if (grp)
92 return vlan_group_get_device(grp, VID); 92 return vlan_group_get_device(grp, VID);
@@ -103,32 +103,38 @@ static void vlan_group_free(struct vlan_group *grp)
103 kfree(grp); 103 kfree(grp);
104} 104}
105 105
106static struct vlan_group *vlan_group_alloc(int ifindex) 106static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
107{ 107{
108 struct vlan_group *grp; 108 struct vlan_group *grp;
109 unsigned int size;
110 unsigned int i;
111 109
112 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); 110 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
113 if (!grp) 111 if (!grp)
114 return NULL; 112 return NULL;
115 113
116 size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN; 114 grp->real_dev = real_dev;
117
118 for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
119 grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
120 if (!grp->vlan_devices_arrays[i])
121 goto err;
122 }
123
124 grp->real_dev_ifindex = ifindex;
125 hlist_add_head_rcu(&grp->hlist, 115 hlist_add_head_rcu(&grp->hlist,
126 &vlan_group_hash[vlan_grp_hashfn(ifindex)]); 116 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
127 return grp; 117 return grp;
118}
128 119
129err: 120static int vlan_group_prealloc_vid(struct vlan_group *vg, int vid)
130 vlan_group_free(grp); 121{
131 return NULL; 122 struct net_device **array;
123 unsigned int size;
124
125 ASSERT_RTNL();
126
127 array = vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN];
128 if (array != NULL)
129 return 0;
130
131 size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
132 array = kzalloc(size, GFP_KERNEL);
133 if (array == NULL)
134 return -ENOBUFS;
135
136 vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN] = array;
137 return 0;
132} 138}
133 139
134static void vlan_rcu_free(struct rcu_head *rcu) 140static void vlan_rcu_free(struct rcu_head *rcu)
@@ -145,11 +151,9 @@ void unregister_vlan_dev(struct net_device *dev)
145 151
146 ASSERT_RTNL(); 152 ASSERT_RTNL();
147 153
148 grp = __vlan_find_group(real_dev->ifindex); 154 grp = __vlan_find_group(real_dev);
149 BUG_ON(!grp); 155 BUG_ON(!grp);
150 156
151 vlan_proc_rem_dev(dev);
152
153 /* Take it out of our own structures, but be sure to interlock with 157 /* Take it out of our own structures, but be sure to interlock with
154 * HW accelerating devices or SW vlan input packet processing. 158 * HW accelerating devices or SW vlan input packet processing.
155 */ 159 */
@@ -240,13 +244,17 @@ int register_vlan_dev(struct net_device *dev)
240 struct vlan_group *grp, *ngrp = NULL; 244 struct vlan_group *grp, *ngrp = NULL;
241 int err; 245 int err;
242 246
243 grp = __vlan_find_group(real_dev->ifindex); 247 grp = __vlan_find_group(real_dev);
244 if (!grp) { 248 if (!grp) {
245 ngrp = grp = vlan_group_alloc(real_dev->ifindex); 249 ngrp = grp = vlan_group_alloc(real_dev);
246 if (!grp) 250 if (!grp)
247 return -ENOBUFS; 251 return -ENOBUFS;
248 } 252 }
249 253
254 err = vlan_group_prealloc_vid(grp, vlan_id);
255 if (err < 0)
256 goto out_free_group;
257
250 err = register_netdevice(dev); 258 err = register_netdevice(dev);
251 if (err < 0) 259 if (err < 0)
252 goto out_free_group; 260 goto out_free_group;
@@ -268,9 +276,6 @@ int register_vlan_dev(struct net_device *dev)
268 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 276 if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
269 real_dev->vlan_rx_add_vid(real_dev, vlan_id); 277 real_dev->vlan_rx_add_vid(real_dev, vlan_id);
270 278
271 if (vlan_proc_add_dev(dev) < 0)
272 pr_warning("8021q: failed to add proc entry for %s\n",
273 dev->name);
274 return 0; 279 return 0;
275 280
276out_free_group: 281out_free_group:
@@ -286,6 +291,8 @@ static int register_vlan_device(struct net_device *real_dev,
286 unsigned short VLAN_ID) 291 unsigned short VLAN_ID)
287{ 292{
288 struct net_device *new_dev; 293 struct net_device *new_dev;
294 struct net *net = dev_net(real_dev);
295 struct vlan_net *vn = net_generic(net, vlan_net_id);
289 char name[IFNAMSIZ]; 296 char name[IFNAMSIZ];
290 int err; 297 int err;
291 298
@@ -297,7 +304,7 @@ static int register_vlan_device(struct net_device *real_dev,
297 return err; 304 return err;
298 305
299 /* Gotta set up the fields for the device. */ 306 /* Gotta set up the fields for the device. */
300 switch (vlan_name_type) { 307 switch (vn->name_type) {
301 case VLAN_NAME_TYPE_RAW_PLUS_VID: 308 case VLAN_NAME_TYPE_RAW_PLUS_VID:
302 /* name will look like: eth1.0005 */ 309 /* name will look like: eth1.0005 */
303 snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID); 310 snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
@@ -328,6 +335,7 @@ static int register_vlan_device(struct net_device *real_dev,
328 if (new_dev == NULL) 335 if (new_dev == NULL)
329 return -ENOBUFS; 336 return -ENOBUFS;
330 337
338 dev_net_set(new_dev, net);
331 /* need 4 bytes for extra VLAN header info, 339 /* need 4 bytes for extra VLAN header info,
332 * hope the underlying device can handle it. 340 * hope the underlying device can handle it.
333 */ 341 */
@@ -383,6 +391,14 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
383 pr_warning("8021q: failed to change proc name for %s\n", 391 pr_warning("8021q: failed to change proc name for %s\n",
384 dev->name); 392 dev->name);
385 break; 393 break;
394 case NETDEV_REGISTER:
395 if (vlan_proc_add_dev(dev) < 0)
396 pr_warning("8021q: failed to add proc entry for %s\n",
397 dev->name);
398 break;
399 case NETDEV_UNREGISTER:
400 vlan_proc_rem_dev(dev);
401 break;
386 } 402 }
387} 403}
388 404
@@ -394,15 +410,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
394 int i, flgs; 410 int i, flgs;
395 struct net_device *vlandev; 411 struct net_device *vlandev;
396 412
397 if (dev->nd_net != &init_net)
398 return NOTIFY_DONE;
399
400 if (is_vlan_dev(dev)) { 413 if (is_vlan_dev(dev)) {
401 __vlan_device_event(dev, event); 414 __vlan_device_event(dev, event);
402 goto out; 415 goto out;
403 } 416 }
404 417
405 grp = __vlan_find_group(dev->ifindex); 418 grp = __vlan_find_group(dev);
406 if (!grp) 419 if (!grp)
407 goto out; 420 goto out;
408 421
@@ -522,7 +535,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
522 case GET_VLAN_REALDEV_NAME_CMD: 535 case GET_VLAN_REALDEV_NAME_CMD:
523 case GET_VLAN_VID_CMD: 536 case GET_VLAN_VID_CMD:
524 err = -ENODEV; 537 err = -ENODEV;
525 dev = __dev_get_by_name(&init_net, args.device1); 538 dev = __dev_get_by_name(net, args.device1);
526 if (!dev) 539 if (!dev)
527 goto out; 540 goto out;
528 541
@@ -567,7 +580,10 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
567 break; 580 break;
568 if ((args.u.name_type >= 0) && 581 if ((args.u.name_type >= 0) &&
569 (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { 582 (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
570 vlan_name_type = args.u.name_type; 583 struct vlan_net *vn;
584
585 vn = net_generic(net, vlan_net_id);
586 vn->name_type = args.u.name_type;
571 err = 0; 587 err = 0;
572 } else { 588 } else {
573 err = -EINVAL; 589 err = -EINVAL;
@@ -615,6 +631,51 @@ out:
615 return err; 631 return err;
616} 632}
617 633
634static int vlan_init_net(struct net *net)
635{
636 int err;
637 struct vlan_net *vn;
638
639 err = -ENOMEM;
640 vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
641 if (vn == NULL)
642 goto err_alloc;
643
644 err = net_assign_generic(net, vlan_net_id, vn);
645 if (err < 0)
646 goto err_assign;
647
648 vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
649
650 err = vlan_proc_init(net);
651 if (err < 0)
652 goto err_proc;
653
654 return 0;
655
656err_proc:
657 /* nothing */
658err_assign:
659 kfree(vn);
660err_alloc:
661 return err;
662}
663
664static void vlan_exit_net(struct net *net)
665{
666 struct vlan_net *vn;
667
668 vn = net_generic(net, vlan_net_id);
669 rtnl_kill_links(net, &vlan_link_ops);
670 vlan_proc_cleanup(net);
671 kfree(vn);
672}
673
674static struct pernet_operations vlan_net_ops = {
675 .init = vlan_init_net,
676 .exit = vlan_exit_net,
677};
678
618static int __init vlan_proto_init(void) 679static int __init vlan_proto_init(void)
619{ 680{
620 int err; 681 int err;
@@ -622,9 +683,9 @@ static int __init vlan_proto_init(void)
622 pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright); 683 pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
623 pr_info("All bugs added by %s\n", vlan_buggyright); 684 pr_info("All bugs added by %s\n", vlan_buggyright);
624 685
625 err = vlan_proc_init(); 686 err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
626 if (err < 0) 687 if (err < 0)
627 goto err1; 688 goto err0;
628 689
629 err = register_netdevice_notifier(&vlan_notifier_block); 690 err = register_netdevice_notifier(&vlan_notifier_block);
630 if (err < 0) 691 if (err < 0)
@@ -641,8 +702,8 @@ static int __init vlan_proto_init(void)
641err3: 702err3:
642 unregister_netdevice_notifier(&vlan_notifier_block); 703 unregister_netdevice_notifier(&vlan_notifier_block);
643err2: 704err2:
644 vlan_proc_cleanup(); 705 unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
645err1: 706err0:
646 return err; 707 return err;
647} 708}
648 709
@@ -661,7 +722,7 @@ static void __exit vlan_cleanup_module(void)
661 for (i = 0; i < VLAN_GRP_HASH_SIZE; i++) 722 for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
662 BUG_ON(!hlist_empty(&vlan_group_hash[i])); 723 BUG_ON(!hlist_empty(&vlan_group_hash[i]));
663 724
664 vlan_proc_cleanup(); 725 unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
665 726
666 synchronize_net(); 727 synchronize_net();
667} 728}