|
@@ -44,9 +44,6 @@
|
|
|
|
|
|
int vlan_net_id __read_mostly;
|
|
|
|
|
|
-/* Our listing of VLAN group(s) */
|
|
|
-static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
|
|
|
-
|
|
|
const char vlan_fullname[] = "802.1Q VLAN Support";
|
|
|
const char vlan_version[] = DRV_VERSION;
|
|
|
static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
|
|
@@ -59,40 +56,6 @@ static struct packet_type vlan_packet_type __read_mostly = {
|
|
|
|
|
|
/* End of global variables definitions. */
|
|
|
|
|
|
-static inline unsigned int vlan_grp_hashfn(unsigned int idx)
|
|
|
-{
|
|
|
- return ((idx >> VLAN_GRP_HASH_SHIFT) ^ idx) & VLAN_GRP_HASH_MASK;
|
|
|
-}
|
|
|
-
|
|
|
-/* Must be invoked with RCU read lock (no preempt) */
|
|
|
-static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
|
|
|
-{
|
|
|
- struct vlan_group *grp;
|
|
|
- struct hlist_node *n;
|
|
|
- int hash = vlan_grp_hashfn(real_dev->ifindex);
|
|
|
-
|
|
|
- hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
|
|
|
- if (grp->real_dev == real_dev)
|
|
|
- return grp;
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/* Find the protocol handler. Assumes VID < VLAN_VID_MASK.
|
|
|
- *
|
|
|
- * Must be invoked with RCU read lock (no preempt)
|
|
|
- */
|
|
|
-struct net_device *__find_vlan_dev(struct net_device *real_dev, u16 vlan_id)
|
|
|
-{
|
|
|
- struct vlan_group *grp = __vlan_find_group(real_dev);
|
|
|
-
|
|
|
- if (grp)
|
|
|
- return vlan_group_get_device(grp, vlan_id);
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
static void vlan_group_free(struct vlan_group *grp)
|
|
|
{
|
|
|
int i;
|
|
@@ -111,8 +74,6 @@ static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
|
|
|
return NULL;
|
|
|
|
|
|
grp->real_dev = real_dev;
|
|
|
- hlist_add_head_rcu(&grp->hlist,
|
|
|
- &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
|
|
|
return grp;
|
|
|
}
|
|
|
|
|
@@ -151,7 +112,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
|
|
|
- grp = __vlan_find_group(real_dev);
|
|
|
+ grp = real_dev->vlgrp;
|
|
|
BUG_ON(!grp);
|
|
|
|
|
|
/* 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)
|
|
|
if (grp->nr_vlans == 0) {
|
|
|
vlan_gvrp_uninit_applicant(real_dev);
|
|
|
|
|
|
+ rcu_assign_pointer(real_dev->vlgrp, NULL);
|
|
|
if (real_dev->features & NETIF_F_HW_VLAN_RX)
|
|
|
ops->ndo_vlan_rx_register(real_dev, NULL);
|
|
|
|
|
|
- hlist_del_rcu(&grp->hlist);
|
|
|
-
|
|
|
/* Free the group, after all cpu's are done. */
|
|
|
call_rcu(&grp->rcu, vlan_rcu_free);
|
|
|
}
|
|
@@ -207,7 +167,7 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
- if (__find_vlan_dev(real_dev, vlan_id) != NULL)
|
|
|
+ if (vlan_find_dev(real_dev, vlan_id) != NULL)
|
|
|
return -EEXIST;
|
|
|
|
|
|
return 0;
|
|
@@ -222,7 +182,7 @@ int register_vlan_dev(struct net_device *dev)
|
|
|
struct vlan_group *grp, *ngrp = NULL;
|
|
|
int err;
|
|
|
|
|
|
- grp = __vlan_find_group(real_dev);
|
|
|
+ grp = real_dev->vlgrp;
|
|
|
if (!grp) {
|
|
|
ngrp = grp = vlan_group_alloc(real_dev);
|
|
|
if (!grp)
|
|
@@ -252,8 +212,11 @@ int register_vlan_dev(struct net_device *dev)
|
|
|
vlan_group_set_device(grp, vlan_id, dev);
|
|
|
grp->nr_vlans++;
|
|
|
|
|
|
- if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
|
|
|
- ops->ndo_vlan_rx_register(real_dev, ngrp);
|
|
|
+ if (ngrp) {
|
|
|
+ if (real_dev->features & NETIF_F_HW_VLAN_RX)
|
|
|
+ ops->ndo_vlan_rx_register(real_dev, ngrp);
|
|
|
+ rcu_assign_pointer(real_dev->vlgrp, ngrp);
|
|
|
+ }
|
|
|
if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
|
|
|
ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
|
|
|
|
|
@@ -264,7 +227,6 @@ out_uninit_applicant:
|
|
|
vlan_gvrp_uninit_applicant(real_dev);
|
|
|
out_free_group:
|
|
|
if (ngrp) {
|
|
|
- hlist_del_rcu(&ngrp->hlist);
|
|
|
/* Free the group, after all cpu's are done. */
|
|
|
call_rcu(&ngrp->rcu, vlan_rcu_free);
|
|
|
}
|
|
@@ -428,7 +390,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
|
|
|
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
|
|
|
}
|
|
|
|
|
|
- grp = __vlan_find_group(dev);
|
|
|
+ grp = dev->vlgrp;
|
|
|
if (!grp)
|
|
|
goto out;
|
|
|
|
|
@@ -746,8 +708,6 @@ err0:
|
|
|
|
|
|
static void __exit vlan_cleanup_module(void)
|
|
|
{
|
|
|
- unsigned int i;
|
|
|
-
|
|
|
vlan_ioctl_set(NULL);
|
|
|
vlan_netlink_fini();
|
|
|
|
|
@@ -755,10 +715,6 @@ static void __exit vlan_cleanup_module(void)
|
|
|
|
|
|
dev_remove_pack(&vlan_packet_type);
|
|
|
|
|
|
- /* This table must be empty if there are no module references left. */
|
|
|
- for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
|
|
|
- BUG_ON(!hlist_empty(&vlan_group_hash[i]));
|
|
|
-
|
|
|
unregister_pernet_subsys(&vlan_net_ops);
|
|
|
rcu_barrier(); /* Wait for completion of call_rcu()'s */
|
|
|
|