forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
vlan: Avoid hash table lookup to find group.
A struct net_device always maps to zero or one vlan groups and we always know the device when we are looking up a group. We currently do a hash table lookup on the device to find the group but it is much simpler to just store a pointer. Signed-off-by: Jesse Gross <[email protected]> Signed-off-by: David S. Miller <[email protected]>
- Loading branch information
1 parent
7b9c609
commit 65ac6a5
Showing
5 changed files
with
34 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 <[email protected]>"; | ||
|
@@ -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 @@ int register_vlan_dev(struct net_device *dev) | |
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,19 +708,13 @@ static int __init vlan_proto_init(void) | |
|
||
static void __exit vlan_cleanup_module(void) | ||
{ | ||
unsigned int i; | ||
|
||
vlan_ioctl_set(NULL); | ||
vlan_netlink_fini(); | ||
|
||
unregister_netdevice_notifier(&vlan_notifier_block); | ||
|
||
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 */ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters