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.c93
1 files changed, 24 insertions, 69 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a2ad15250575..05b867e43757 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -44,9 +44,6 @@
44 44
45int vlan_net_id __read_mostly; 45int vlan_net_id __read_mostly;
46 46
47/* Our listing of VLAN group(s) */
48static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
49
50const char vlan_fullname[] = "802.1Q VLAN Support"; 47const char vlan_fullname[] = "802.1Q VLAN Support";
51const char vlan_version[] = DRV_VERSION; 48const char vlan_version[] = DRV_VERSION;
52static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; 49static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
@@ -59,40 +56,6 @@ static struct packet_type vlan_packet_type __read_mostly = {
59 56
60/* End of global variables definitions. */ 57/* End of global variables definitions. */
61 58
62static inline unsigned int vlan_grp_hashfn(unsigned int idx)
63{
64 return ((idx >> VLAN_GRP_HASH_SHIFT) ^ idx) & VLAN_GRP_HASH_MASK;
65}
66
67/* Must be invoked with RCU read lock (no preempt) */
68static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
69{
70 struct vlan_group *grp;
71 struct hlist_node *n;
72 int hash = vlan_grp_hashfn(real_dev->ifindex);
73
74 hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
75 if (grp->real_dev == real_dev)
76 return grp;
77 }
78
79 return NULL;
80}
81
82/* Find the protocol handler. Assumes VID < VLAN_VID_MASK.
83 *
84 * Must be invoked with RCU read lock (no preempt)
85 */
86struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
87{
88 struct vlan_group *grp = __vlan_find_group(real_dev);
89
90 if (grp)
91 return vlan_group_get_device(grp, vlan_id);
92
93 return NULL;
94}
95
96static void vlan_group_free(struct vlan_group *grp) 59static void vlan_group_free(struct vlan_group *grp)
97{ 60{
98 int i; 61 int i;
@@ -111,8 +74,6 @@ static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
111 return NULL; 74 return NULL;
112 75
113 grp->real_dev = real_dev; 76 grp->real_dev = real_dev;
114 hlist_add_head_rcu(&grp->hlist,
115 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
116 return grp; 77 return grp;
117} 78}
118 79
@@ -151,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
151 112
152 ASSERT_RTNL(); 113 ASSERT_RTNL();
153 114
154 grp = __vlan_find_group(real_dev); 115 grp = real_dev->vlgrp;
155 BUG_ON(!grp); 116 BUG_ON(!grp);
156 117
157 /* Take it out of our own structures, but be sure to interlock with 118 /* Take it out of our own structures, but be sure to interlock with
@@ -173,11 +134,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
173 if (grp->nr_vlans == 0) { 134 if (grp->nr_vlans == 0) {
174 vlan_gvrp_uninit_applicant(real_dev); 135 vlan_gvrp_uninit_applicant(real_dev);
175 136
176 if (real_dev->features & NETIF_F_HW_VLAN_RX) 137 rcu_assign_pointer(real_dev->vlgrp, NULL);
138 if (ops->ndo_vlan_rx_register)
177 ops->ndo_vlan_rx_register(real_dev, NULL); 139 ops->ndo_vlan_rx_register(real_dev, NULL);
178 140
179 hlist_del_rcu(&grp->hlist);
180
181 /* Free the group, after all cpu's are done. */ 141 /* Free the group, after all cpu's are done. */
182 call_rcu(&grp->rcu, vlan_rcu_free); 142 call_rcu(&grp->rcu, vlan_rcu_free);
183 } 143 }
@@ -196,18 +156,13 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
196 return -EOPNOTSUPP; 156 return -EOPNOTSUPP;
197 } 157 }
198 158
199 if ((real_dev->features & NETIF_F_HW_VLAN_RX) && !ops->ndo_vlan_rx_register) {
200 pr_info("8021q: device %s has buggy VLAN hw accel\n", name);
201 return -EOPNOTSUPP;
202 }
203
204 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && 159 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
205 (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) { 160 (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
206 pr_info("8021q: Device %s has buggy VLAN hw accel\n", name); 161 pr_info("8021q: Device %s has buggy VLAN hw accel\n", name);
207 return -EOPNOTSUPP; 162 return -EOPNOTSUPP;
208 } 163 }
209 164
210 if (__find_vlan_dev(real_dev, vlan_id) != NULL) 165 if (vlan_find_dev(real_dev, vlan_id) != NULL)
211 return -EEXIST; 166 return -EEXIST;
212 167
213 return 0; 168 return 0;
@@ -222,7 +177,7 @@ int register_vlan_dev(struct net_device *dev)
222 struct vlan_group *grp, *ngrp = NULL; 177 struct vlan_group *grp, *ngrp = NULL;
223 int err; 178 int err;
224 179
225 grp = __vlan_find_group(real_dev); 180 grp = real_dev->vlgrp;
226 if (!grp) { 181 if (!grp) {
227 ngrp = grp = vlan_group_alloc(real_dev); 182 ngrp = grp = vlan_group_alloc(real_dev);
228 if (!grp) 183 if (!grp)
@@ -252,8 +207,11 @@ int register_vlan_dev(struct net_device *dev)
252 vlan_group_set_device(grp, vlan_id, dev); 207 vlan_group_set_device(grp, vlan_id, dev);
253 grp->nr_vlans++; 208 grp->nr_vlans++;
254 209
255 if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) 210 if (ngrp) {
256 ops->ndo_vlan_rx_register(real_dev, ngrp); 211 if (ops->ndo_vlan_rx_register)
212 ops->ndo_vlan_rx_register(real_dev, ngrp);
213 rcu_assign_pointer(real_dev->vlgrp, ngrp);
214 }
257 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 215 if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
258 ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); 216 ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
259 217
@@ -264,7 +222,6 @@ out_uninit_applicant:
264 vlan_gvrp_uninit_applicant(real_dev); 222 vlan_gvrp_uninit_applicant(real_dev);
265out_free_group: 223out_free_group:
266 if (ngrp) { 224 if (ngrp) {
267 hlist_del_rcu(&ngrp->hlist);
268 /* Free the group, after all cpu's are done. */ 225 /* Free the group, after all cpu's are done. */
269 call_rcu(&ngrp->rcu, vlan_rcu_free); 226 call_rcu(&ngrp->rcu, vlan_rcu_free);
270 } 227 }
@@ -321,7 +278,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
321 if (new_dev == NULL) 278 if (new_dev == NULL)
322 return -ENOBUFS; 279 return -ENOBUFS;
323 280
324 new_dev->real_num_tx_queues = real_dev->real_num_tx_queues; 281 netif_copy_real_num_queues(new_dev, real_dev);
325 dev_net_set(new_dev, net); 282 dev_net_set(new_dev, net);
326 /* need 4 bytes for extra VLAN header info, 283 /* need 4 bytes for extra VLAN header info,
327 * hope the underlying device can handle it. 284 * hope the underlying device can handle it.
@@ -428,7 +385,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
428 dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); 385 dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
429 } 386 }
430 387
431 grp = __vlan_find_group(dev); 388 grp = dev->vlgrp;
432 if (!grp) 389 if (!grp)
433 goto out; 390 goto out;
434 391
@@ -439,7 +396,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
439 switch (event) { 396 switch (event) {
440 case NETDEV_CHANGE: 397 case NETDEV_CHANGE:
441 /* Propagate real device state to vlan devices */ 398 /* Propagate real device state to vlan devices */
442 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 399 for (i = 0; i < VLAN_N_VID; i++) {
443 vlandev = vlan_group_get_device(grp, i); 400 vlandev = vlan_group_get_device(grp, i);
444 if (!vlandev) 401 if (!vlandev)
445 continue; 402 continue;
@@ -450,7 +407,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
450 407
451 case NETDEV_CHANGEADDR: 408 case NETDEV_CHANGEADDR:
452 /* Adjust unicast filters on underlying device */ 409 /* Adjust unicast filters on underlying device */
453 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 410 for (i = 0; i < VLAN_N_VID; i++) {
454 vlandev = vlan_group_get_device(grp, i); 411 vlandev = vlan_group_get_device(grp, i);
455 if (!vlandev) 412 if (!vlandev)
456 continue; 413 continue;
@@ -464,7 +421,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
464 break; 421 break;
465 422
466 case NETDEV_CHANGEMTU: 423 case NETDEV_CHANGEMTU:
467 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 424 for (i = 0; i < VLAN_N_VID; i++) {
468 vlandev = vlan_group_get_device(grp, i); 425 vlandev = vlan_group_get_device(grp, i);
469 if (!vlandev) 426 if (!vlandev)
470 continue; 427 continue;
@@ -478,7 +435,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
478 435
479 case NETDEV_FEAT_CHANGE: 436 case NETDEV_FEAT_CHANGE:
480 /* Propagate device features to underlying device */ 437 /* Propagate device features to underlying device */
481 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 438 for (i = 0; i < VLAN_N_VID; i++) {
482 vlandev = vlan_group_get_device(grp, i); 439 vlandev = vlan_group_get_device(grp, i);
483 if (!vlandev) 440 if (!vlandev)
484 continue; 441 continue;
@@ -490,7 +447,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
490 447
491 case NETDEV_DOWN: 448 case NETDEV_DOWN:
492 /* Put all VLANs for this dev in the down state too. */ 449 /* Put all VLANs for this dev in the down state too. */
493 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 450 for (i = 0; i < VLAN_N_VID; i++) {
494 vlandev = vlan_group_get_device(grp, i); 451 vlandev = vlan_group_get_device(grp, i);
495 if (!vlandev) 452 if (!vlandev)
496 continue; 453 continue;
@@ -508,7 +465,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
508 465
509 case NETDEV_UP: 466 case NETDEV_UP:
510 /* Put all VLANs for this dev in the up state too. */ 467 /* Put all VLANs for this dev in the up state too. */
511 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 468 for (i = 0; i < VLAN_N_VID; i++) {
512 vlandev = vlan_group_get_device(grp, i); 469 vlandev = vlan_group_get_device(grp, i);
513 if (!vlandev) 470 if (!vlandev)
514 continue; 471 continue;
@@ -525,10 +482,14 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
525 break; 482 break;
526 483
527 case NETDEV_UNREGISTER: 484 case NETDEV_UNREGISTER:
485 /* twiddle thumbs on netns device moves */
486 if (dev->reg_state != NETREG_UNREGISTERING)
487 break;
488
528 /* Delete all VLANs for this dev. */ 489 /* Delete all VLANs for this dev. */
529 grp->killall = 1; 490 grp->killall = 1;
530 491
531 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 492 for (i = 0; i < VLAN_N_VID; i++) {
532 vlandev = vlan_group_get_device(grp, i); 493 vlandev = vlan_group_get_device(grp, i);
533 if (!vlandev) 494 if (!vlandev)
534 continue; 495 continue;
@@ -536,7 +497,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
536 /* unregistration of last vlan destroys group, abort 497 /* unregistration of last vlan destroys group, abort
537 * afterwards */ 498 * afterwards */
538 if (grp->nr_vlans == 1) 499 if (grp->nr_vlans == 1)
539 i = VLAN_GROUP_ARRAY_LEN; 500 i = VLAN_N_VID;
540 501
541 unregister_vlan_dev(vlandev, &list); 502 unregister_vlan_dev(vlandev, &list);
542 } 503 }
@@ -742,8 +703,6 @@ err0:
742 703
743static void __exit vlan_cleanup_module(void) 704static void __exit vlan_cleanup_module(void)
744{ 705{
745 unsigned int i;
746
747 vlan_ioctl_set(NULL); 706 vlan_ioctl_set(NULL);
748 vlan_netlink_fini(); 707 vlan_netlink_fini();
749 708
@@ -751,10 +710,6 @@ static void __exit vlan_cleanup_module(void)
751 710
752 dev_remove_pack(&vlan_packet_type); 711 dev_remove_pack(&vlan_packet_type);
753 712
754 /* This table must be empty if there are no module references left. */
755 for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
756 BUG_ON(!hlist_empty(&vlan_group_hash[i]));
757
758 unregister_pernet_subsys(&vlan_net_ops); 713 unregister_pernet_subsys(&vlan_net_ops);
759 rcu_barrier(); /* Wait for completion of call_rcu()'s */ 714 rcu_barrier(); /* Wait for completion of call_rcu()'s */
760 715