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
ath9k-devel@lists.ath9k.org
https://lists.ath9k.org/mailman/listinfo/ath9k-devel

Reply via email to