From 65ac6a5fa658b90f1be700c55e7cd72e4611015d Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 20 Oct 2010 13:56:05 +0000 Subject: 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 Signed-off-by: David S. Miller --- net/8021q/vlan.c | 64 +++++++++----------------------------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) (limited to 'net/8021q/vlan.c') diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 54f22d820ef..f862dccf6bb 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -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 "; @@ -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 */ -- cgit v1.2.3