* [PATCH v3] mac80211: Optimize sta lookup for many VIFs
@ 2013-03-26 0:57 greearb
2013-03-26 19:42 ` Johannes Berg
0 siblings, 1 reply; 4+ messages in thread
From: greearb @ 2013-03-26 0:57 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
The sta_info hash is designed to deal with an AP
with lots of stations associated, or a station interface
connected to a single AP.
However, when you have lots of station VIFs connected
to the same AP, the sta_info hash becomes worthless
as there is a single hash bucket that contains all the
entries in a linked list.
So, have the sdata object cache one of its station
interfaces. If we are a station VIF with a single
sta_info, then this means we can ignore the sta_info
hash entirely.
On a test case with 128 stations and 50 TCP streams,
tx performance went from around 80Mbps to 124Mbps.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v3: Use rcu_dereference_protected as suggested.
:100644 100644 a618bda... 9b10bbf... M net/mac80211/cfg.c
:100644 100644 493e2e8... c6386c7... M net/mac80211/ieee80211_i.h
:100644 100644 415f9c6... a958ebc... M net/mac80211/sta_info.c
net/mac80211/cfg.c | 5 +++++
net/mac80211/ieee80211_i.h | 6 ++++++
net/mac80211/sta_info.c | 22 +++++++++++++++++++++-
3 files changed, 32 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a618bda..9b10bbf 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1287,6 +1287,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
if (params->vlan && params->vlan != sta->sdata->dev) {
bool prev_4addr = false;
bool new_4addr = false;
+ struct sta_info *some_sta;
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
@@ -1312,7 +1313,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
prev_4addr = true;
}
+ some_sta = rcu_dereference_protected(sta->sdata->some_sta, 1);
+ if (some_sta == sta)
+ rcu_assign_pointer(sta->sdata->some_sta, NULL);
sta->sdata = vlansdata;
+ rcu_assign_pointer(sta->sdata->some_sta, sta);
if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
prev_4addr != new_4addr) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 493e2e8..c6386c7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -669,6 +669,12 @@ struct ieee80211_sub_if_data {
/* count for keys needing tailroom space allocation */
int crypto_tx_tailroom_needed_cnt;
+ /* A pointer to some station associated with this interface, or
+ * NULL. This allows opportunistic lookup for sta_info objects when
+ * sdata is a station with a single sta_info.
+ */
+ struct sta_info __rcu *some_sta;
+
struct net_device *dev;
struct ieee80211_local *local;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 415f9c6..a958ebc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -67,7 +67,11 @@
static int sta_info_hash_del(struct ieee80211_local *local,
struct sta_info *sta)
{
- struct sta_info *s;
+ struct sta_info *s, *some_sta;
+
+ some_sta = rcu_dereference_protected(sta->sdata->some_sta, 1);
+ if (some_sta == sta)
+ rcu_assign_pointer(sta->sdata->some_sta, NULL);
s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)],
lockdep_is_held(&local->sta_mtx));
@@ -195,6 +199,20 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ struct sta_info *some_sta;
+
+ /* Shortcut for finding station entries for STATION VIFs */
+ some_sta = rcu_dereference(sdata->some_sta);
+ if (some_sta) {
+ if (WARN_ON(some_sta->sdata != sdata))
+ rcu_assign_pointer(sdata->some_sta, NULL);
+ else
+ if (ether_addr_equal(some_sta->sta.addr, addr))
+ return some_sta;
+ }
+ }
+
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
lockdep_is_held(&local->sta_mtx));
while (sta) {
@@ -278,6 +296,8 @@ static void sta_info_hash_add(struct ieee80211_local *local,
lockdep_assert_held(&local->sta_mtx);
sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
+
+ rcu_assign_pointer(sta->sdata->some_sta, sta);
}
static void sta_unblock(struct work_struct *wk)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3] mac80211: Optimize sta lookup for many VIFs
2013-03-26 0:57 [PATCH v3] mac80211: Optimize sta lookup for many VIFs greearb
@ 2013-03-26 19:42 ` Johannes Berg
2013-03-27 18:35 ` Ben Greear
0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2013-03-26 19:42 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless
On Mon, 2013-03-25 at 17:57 -0700, greearb@candelatech.com wrote:
> v3: Use rcu_dereference_protected as suggested.
Heh.
> + some_sta = rcu_dereference_protected(sta->sdata->some_sta, 1);
No no no, you're supposed to give it a proper argument like
"lockdep_is_held(&local->sta_mtx)"
johannes
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] mac80211: Optimize sta lookup for many VIFs
2013-03-26 19:42 ` Johannes Berg
@ 2013-03-27 18:35 ` Ben Greear
2013-03-27 19:48 ` Johannes Berg
0 siblings, 1 reply; 4+ messages in thread
From: Ben Greear @ 2013-03-27 18:35 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 03/26/2013 12:42 PM, Johannes Berg wrote:
> On Mon, 2013-03-25 at 17:57 -0700, greearb@candelatech.com wrote:
>
>> v3: Use rcu_dereference_protected as suggested.
>
> Heh.
>
>> + some_sta = rcu_dereference_protected(sta->sdata->some_sta, 1);
>
> No no no, you're supposed to give it a proper argument like
> "lockdep_is_held(&local->sta_mtx)"
Before I screw this up again..do you prefer that I line up
method arguments and go over 80 character line length, or
force the argument leftward to meet the 80 char limit?
I see no good way to make it fit in 80 chars and also
line up properly.
Thanks,
Ben
>
> johannes
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] mac80211: Optimize sta lookup for many VIFs
2013-03-27 18:35 ` Ben Greear
@ 2013-03-27 19:48 ` Johannes Berg
0 siblings, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2013-03-27 19:48 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Wed, 2013-03-27 at 11:35 -0700, Ben Greear wrote:
> On 03/26/2013 12:42 PM, Johannes Berg wrote:
> > On Mon, 2013-03-25 at 17:57 -0700, greearb@candelatech.com wrote:
> >
> >> v3: Use rcu_dereference_protected as suggested.
> >
> > Heh.
> >
> >> + some_sta = rcu_dereference_protected(sta->sdata->some_sta, 1);
> >
> > No no no, you're supposed to give it a proper argument like
> > "lockdep_is_held(&local->sta_mtx)"
>
> Before I screw this up again..do you prefer that I line up
> method arguments and go over 80 character line length, or
> force the argument leftward to meet the 80 char limit?
>
> I see no good way to make it fit in 80 chars and also
> line up properly.
Huh, no idea. I guess I'd rather have it less than 80 cols.
johannes
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-03-27 19:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-26 0:57 [PATCH v3] mac80211: Optimize sta lookup for many VIFs greearb
2013-03-26 19:42 ` Johannes Berg
2013-03-27 18:35 ` Ben Greear
2013-03-27 19:48 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).