From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Subject: [PATCH 8/8] mac80211: remove dummy STA support
Date: Thu, 05 Jan 2012 16:30:51 +0100 [thread overview]
Message-ID: <20120105153229.292037462@sipsolutions.net> (raw)
In-Reply-To: 20120105153043.568616380@sipsolutions.net
From: Johannes Berg <johannes.berg@intel.com>
The dummy STA support was added because I didn't
want to change the driver API at the time. Now
that we have state transitions triggering station
add/remove in the driver, we only call add once a
station reaches ASSOCIATED, so we can remove the
dummy station stuff again.
While at it, tighten the RX check and accept only
port control (EAP) frames from the AP station if
it's not associated yet -- in other cases there's
no race.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 15 +----
net/mac80211/rx.c | 13 +++-
net/mac80211/sta_info.c | 135 ++++++++----------------------------------------
net/mac80211/sta_info.h | 30 ----------
4 files changed, 38 insertions(+), 155 deletions(-)
--- a/net/mac80211/sta_info.h 2012-01-05 16:29:49.000000000 +0100
+++ b/net/mac80211/sta_info.h 2012-01-05 16:29:50.000000000 +0100
@@ -267,8 +267,6 @@ struct sta_ampdu_mlme {
* @dead: set to true when sta is unlinked
* @uploaded: set to true when sta is uploaded to the driver
* @lost_packets: number of consecutive lost packets
- * @dummy: indicate a dummy station created for receiving
- * EAP frames before association
* @sta: station information we share with the driver
* @sta_state: duplicates information about station state (for debug)
* @beacon_loss_count: number of times beacon loss has triggered
@@ -366,9 +364,6 @@ struct sta_info {
unsigned int lost_packets;
unsigned int beacon_loss_count;
- /* should be right in front of sta to be in the same cache line */
- bool dummy;
-
/* keep last! */
struct ieee80211_sta sta;
};
@@ -470,15 +465,9 @@ rcu_dereference_protected_tid_tx(struct
struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
-struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
-struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
static inline
void for_each_sta_info_type_check(struct ieee80211_local *local,
const u8 *addr,
@@ -487,23 +476,7 @@ void for_each_sta_info_type_check(struct
{
}
-#define for_each_sta_info(local, _addr, _sta, nxt) \
- for ( /* initialise loop */ \
- _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
- nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
- /* typecheck */ \
- for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
- /* continue condition */ \
- _sta; \
- /* advance loop */ \
- _sta = nxt, \
- nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
- ) \
- /* run code only if address matches and it's not a dummy sta */ \
- if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \
- !_sta->dummy)
-
-#define for_each_sta_info_rx(local, _addr, _sta, nxt) \
+#define for_each_sta_info(local, _addr, _sta, nxt) \
for ( /* initialise loop */ \
_sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
@@ -542,7 +515,6 @@ void sta_info_free(struct ieee80211_loca
*/
int sta_info_insert(struct sta_info *sta);
int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
-int sta_info_reinsert(struct sta_info *sta);
int __must_check __sta_info_destroy(struct sta_info *sta);
int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/sta_info.c 2012-01-05 16:29:46.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-05 16:29:50.000000000 +0100
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct iee
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
lockdep_is_held(&local->sta_mtx));
while (sta) {
- if (sta->sdata == sdata && !sta->dummy &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
- break;
- sta = rcu_dereference_check(sta->hnext,
- lockdep_is_held(&local->sta_mtx));
- }
- return sta;
-}
-
-/* get a station info entry even if it is a dummy station*/
-struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
- lockdep_is_held(&local->sta_mtx));
- while (sta) {
if (sta->sdata == sdata &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct
while (sta) {
if ((sta->sdata == sdata ||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
- !sta->dummy &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
- break;
- sta = rcu_dereference_check(sta->hnext,
- lockdep_is_held(&local->sta_mtx));
- }
- return sta;
-}
-
-/*
- * Get sta info either from the specified interface
- * or from one of its vlans (including dummy stations)
- */
-struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
- lockdep_is_held(&local->sta_mtx));
- while (sta) {
- if ((sta->sdata == sdata ||
- (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference_check(sta->hnext,
@@ -399,66 +356,43 @@ static int sta_info_insert_finish(struct
{
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct sta_info *exist_sta;
- bool dummy_reinsert = false;
+ struct station_info sinfo;
int err = 0;
lockdep_assert_held(&local->sta_mtx);
- /*
- * check if STA exists already.
- * only accept a scenario of a second call to sta_info_insert_finish
- * with a dummy station entry that was inserted earlier
- * in that case - assume that the dummy station flag should
- * be removed.
- */
- exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);
- if (exist_sta) {
- if (exist_sta == sta && sta->dummy) {
- dummy_reinsert = true;
- } else {
- err = -EEXIST;
- goto out_err;
- }
+ /* check if STA exists already */
+ if (sta_info_get_bss(sdata, sta->sta.addr)) {
+ err = -EEXIST;
+ goto out_err;
}
- if (!sta->dummy || dummy_reinsert) {
- /* notify driver */
- err = sta_info_insert_drv_state(local, sdata, sta);
- if (err)
- goto out_err;
- }
-
- if (!dummy_reinsert) {
- local->num_sta++;
- local->sta_generation++;
- smp_mb();
+ /* notify driver */
+ err = sta_info_insert_drv_state(local, sdata, sta);
+ if (err)
+ goto out_err;
- /* make the station visible */
- sta_info_hash_add(local, sta);
+ local->num_sta++;
+ local->sta_generation++;
+ smp_mb();
- list_add(&sta->list, &local->sta_list);
+ /* make the station visible */
+ sta_info_hash_add(local, sta);
- set_sta_flag(sta, WLAN_STA_INSERTED);
- } else {
- sta->dummy = false;
- }
+ list_add(&sta->list, &local->sta_list);
- if (!sta->dummy) {
- struct station_info sinfo;
+ set_sta_flag(sta, WLAN_STA_INSERTED);
- ieee80211_sta_debugfs_add(sta);
- rate_control_add_sta_debugfs(sta);
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
- memset(&sinfo, 0, sizeof(sinfo));
- sinfo.filled = 0;
- sinfo.generation = local->sta_generation;
- cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
- }
+ memset(&sinfo, 0, sizeof(sinfo));
+ sinfo.filled = 0;
+ sinfo.generation = local->sta_generation;
+ cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n",
- sta->dummy ? "dummy " : "", sta->sta.addr);
+ wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
/* move reference to rcu-protected */
@@ -510,25 +444,6 @@ int sta_info_insert(struct sta_info *sta
return err;
}
-/* Caller must hold sta->local->sta_mtx */
-int sta_info_reinsert(struct sta_info *sta)
-{
- struct ieee80211_local *local = sta->local;
- int err = 0;
-
- err = sta_info_insert_check(sta);
- if (err) {
- mutex_unlock(&local->sta_mtx);
- return err;
- }
-
- might_sleep();
-
- err = sta_info_insert_finish(sta);
- rcu_read_unlock();
- return err;
-}
-
static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
{
/*
@@ -889,7 +804,7 @@ int sta_info_destroy_addr(struct ieee802
int ret;
mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get_rx(sdata, addr);
+ sta = sta_info_get(sdata, addr);
ret = __sta_info_destroy(sta);
mutex_unlock(&sdata->local->sta_mtx);
@@ -903,7 +818,7 @@ int sta_info_destroy_addr_bss(struct iee
int ret;
mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get_bss_rx(sdata, addr);
+ sta = sta_info_get_bss(sdata, addr);
ret = __sta_info_destroy(sta);
mutex_unlock(&sdata->local->sta_mtx);
--- a/net/mac80211/mlme.c 2012-01-05 16:04:34.000000000 +0100
+++ b/net/mac80211/mlme.c 2012-01-05 16:29:50.000000000 +0100
@@ -1579,7 +1579,7 @@ static bool ieee80211_assoc_success(stru
* station info was already allocated and inserted before
* the association and should be available to us
*/
- sta = sta_info_get_rx(sdata, cbss->bssid);
+ sta = sta_info_get(sdata, cbss->bssid);
if (WARN_ON(!sta)) {
mutex_unlock(&sdata->local->sta_mtx);
return false;
@@ -1646,14 +1646,7 @@ static bool ieee80211_assoc_success(stru
return false;
}
- /* sta_info_reinsert will also unlock the mutex lock */
- err = sta_info_reinsert(sta);
- sta = NULL;
- if (err) {
- printk(KERN_DEBUG "%s: failed to insert STA entry for"
- " the AP (error %d)\n", sdata->name, err);
- return false;
- }
+ mutex_unlock(&sdata->local->sta_mtx);
/*
* Always handle WMM once after association regardless
@@ -2534,12 +2527,10 @@ static int ieee80211_pre_assoc(struct ie
if (!sta)
return -ENOMEM;
- sta->dummy = true;
-
err = sta_info_insert(sta);
sta = NULL;
if (err) {
- printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for"
+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
" the AP (error %d)\n", sdata->name, err);
return err;
}
--- a/net/mac80211/rx.c 2012-01-05 16:04:34.000000000 +0100
+++ b/net/mac80211/rx.c 2012-01-05 16:29:50.000000000 +0100
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
- if (rx->sta && rx->sta->dummy &&
+ /*
+ * accept port control frames from the AP even when it's not
+ * yet marked ASSOC to prevent a race where we don't set the
+ * assoc bit quickly enough before it sends the first frame
+ */
+ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
ieee80211_is_data_present(hdr->frame_control)) {
u16 ethertype;
u8 *payload;
@@ -2975,7 +2980,7 @@ static void __ieee80211_rx_handle_packet
if (ieee80211_is_data(fc)) {
prev_sta = NULL;
- for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {
+ for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
@@ -3019,7 +3024,7 @@ static void __ieee80211_rx_handle_packet
continue;
}
- rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
ieee80211_prepare_and_rx_handle(&rx, skb, false);
@@ -3027,7 +3032,7 @@ static void __ieee80211_rx_handle_packet
}
if (prev) {
- rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
next prev parent reply other threads:[~2012-01-05 15:33 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
2012-01-05 15:30 ` [PATCH 1/8] mac80211: move managed mode station state modification Johannes Berg
2012-01-05 15:30 ` [PATCH 2/8] mac80211: simplify AP_VLAN handling Johannes Berg
2012-01-05 15:30 ` [PATCH 3/8] mac80211: dont program keys for stations not uploaded Johannes Berg
2012-01-05 15:30 ` [PATCH 4/8] mac80211: add NOTEXIST station state Johannes Berg
2012-01-05 15:30 ` [PATCH 5/8] mac80211: add sta_state callback Johannes Berg
2012-01-05 15:30 ` [PATCH 6/8] mac80211: implement sta_add/sta_remove in sta_state Johannes Berg
2012-01-05 15:30 ` [PATCH 7/8] mac80211: call rate control only after init Johannes Berg
2012-01-05 15:30 ` Johannes Berg [this message]
2012-01-12 8:25 ` [PATCH 0/8] more station handling refactoring Johannes Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120105153229.292037462@sipsolutions.net \
--to=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).