aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-02-13 15:55:15 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-04-01 04:06:26 -0400
commit7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35 (patch)
treef156540ff672dec031e81a64fc60796dd34ea867 /net/mac80211/status.c
parent9911674fcf1f239ff3c87e56177c4826e33dfd95 (diff)
mac80211: use rhashtable for station table
We currently have a hand-rolled table with 256 entries and are using the last byte of the MAC address as the hash. This hash is obviously very fast, but collisions are easily created and we waste a lot of space in the common case of just connecting as a client to an AP where we just have a single station. The other common case of an AP is also suboptimal due to the size of the hash table and the ease of causing collisions. Convert all of this to use rhashtable with jhash, which gives us the advantage of a far better hash function (with random perturbation to avoid hash collision attacks) and of course that the hash table grows and shrinks dynamically with chain length, improving both cases above. Use a specialised hash function (using jhash, but with fixed length) to achieve better compiler optimisation as suggested by Sergey Ryazanov. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 2c51742428d5..005fdbe39a8b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -654,7 +654,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
654 struct ieee80211_supported_band *sband; 654 struct ieee80211_supported_band *sband;
655 struct ieee80211_sub_if_data *sdata; 655 struct ieee80211_sub_if_data *sdata;
656 struct net_device *prev_dev = NULL; 656 struct net_device *prev_dev = NULL;
657 struct sta_info *sta, *tmp; 657 struct sta_info *sta;
658 struct rhash_head *tmp;
658 int retry_count; 659 int retry_count;
659 int rates_idx; 660 int rates_idx;
660 bool send_to_cooked; 661 bool send_to_cooked;
@@ -663,6 +664,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
663 int rtap_len; 664 int rtap_len;
664 int shift = 0; 665 int shift = 0;
665 int tid = IEEE80211_NUM_TIDS; 666 int tid = IEEE80211_NUM_TIDS;
667 const struct bucket_table *tbl;
666 668
667 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); 669 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
668 670
@@ -671,7 +673,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
671 sband = local->hw.wiphy->bands[info->band]; 673 sband = local->hw.wiphy->bands[info->band];
672 fc = hdr->frame_control; 674 fc = hdr->frame_control;
673 675
674 for_each_sta_info(local, hdr->addr1, sta, tmp) { 676 tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
677
678 for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) {
675 /* skip wrong virtual interface */ 679 /* skip wrong virtual interface */
676 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) 680 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
677 continue; 681 continue;