Simon Wunderlich wrote:
> we have found a regression in the IBSS creation/joining part of mac80211
> which
> is appearently connected to the TSF-syncing patches introduced last year[1].
> It prevents beaconing of an adhoc member after rejoining a cell when this
> cell
> is currently empty. The problem is present in at least 3.10 and 3.13.
>
> To reproduce, use two adhoc peers and let them join/leave in the following
> order:
>
> station 1: join
> station 2: join
> station 2: leave
> station 1: leave
> station 1: join
>
> now we would expect that station 1 sends beacons, but it doesn't. After
> inspecting the code, station 1 actually selected the "old" ibss network and
> waits for a beacon to sync the tsf which is never received, as all members
> already left the network. An easy workaround is to set the IBSS creator
> always
> to true.
The race condition is that station-1 (the creator) removes station-2 only
after a while, based on the expiration/inactive timer.
The small window that IEEE80211_IBSS_MERGE_INTERVAL introduces when
ieee80211_ibss_disconnect() is called causes the race, since we assume that
station-2 is still active and do not remove the BSS from cfg80211.
I am not sure why we have to keep the BSS around when we are leaving the
network.
Is this patch the right approach ?
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 771080e..e1688cd 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -688,17 +688,18 @@ static int ieee80211_sta_active_ibss(struct
ieee80211_sub_if_data *sdata)
return active;
}
-static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata,
bool leave)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct cfg80211_bss *cbss;
struct beacon_data *presp;
struct sta_info *sta;
- int active_ibss;
+ int active_ibss = 0;
u16 capability;
- active_ibss = ieee80211_sta_active_ibss(sdata);
+ if (!leave)
+ active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
capability = WLAN_CAPABILITY_IBSS;
@@ -765,7 +766,7 @@ static void ieee80211_csa_connection_drop_work(struct
work_struct *work)
sdata_lock(sdata);
- ieee80211_ibss_disconnect(sdata);
+ ieee80211_ibss_disconnect(sdata, false);
synchronize_rcu();
skb_queue_purge(&sdata->skb_queue);
@@ -1721,7 +1722,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data
*sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- ieee80211_ibss_disconnect(sdata);
+ ieee80211_ibss_disconnect(sdata, true);
ifibss->ssid_len = 0;
memset(ifibss->bssid, 0, ETH_ALEN);
Sujith
_______________________________________________
ath9k-devel mailing list
[email protected]
https://lists.ath9k.org/mailman/listinfo/ath9k-devel