diff options
author | Johannes Berg <johannes.berg@intel.com> | 2015-02-13 21:55:15 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-04-01 10:06:26 +0200 |
commit | 7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35 (patch) | |
tree | f156540ff672dec031e81a64fc60796dd34ea867 /net/mac80211/status.c | |
parent | 9911674fcf1f239ff3c87e56177c4826e33dfd95 (diff) | |
download | linux-stable-7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35.tar.gz linux-stable-7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35.tar.bz2 linux-stable-7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35.zip |
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.c | 8 |
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) struct ieee80211_supported_band *sband; struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; - struct sta_info *sta, *tmp; + struct sta_info *sta; + struct rhash_head *tmp; int retry_count; int rates_idx; bool send_to_cooked; @@ -663,6 +664,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) int rtap_len; int shift = 0; int tid = IEEE80211_NUM_TIDS; + const struct bucket_table *tbl; rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); @@ -671,7 +673,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) sband = local->hw.wiphy->bands[info->band]; fc = hdr->frame_control; - for_each_sta_info(local, hdr->addr1, sta, tmp) { + tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash); + + for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) { /* skip wrong virtual interface */ if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) continue; |