aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-12-02 15:01:08 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-06 15:58:44 -0500
commit04ac3c0ee2c773c321ec472d892635a20556f34d (patch)
treee9a3bf81d8feec787fa5b4c5c156652de5313c83 /net
parent75706d0e9d19601534446982b70102bb9327169b (diff)
mac80211: speed up AP probing using nullfunc frames
If the nullfunc frame used to probe the AP was not acked, there is no point in waiting for the probe timeout, so advance to the next try (or disconnect) immediately. If we do reach the probe timeout without having received a tx status, the connection is probably really bad and worth disconnecting. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mlme.c93
-rw-r--r--net/mac80211/status.c18
3 files changed, 79 insertions, 35 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 66b0b52b828d..e7c880725639 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -357,6 +357,7 @@ struct ieee80211_if_managed {
357 unsigned long beacon_timeout; 357 unsigned long beacon_timeout;
358 unsigned long probe_timeout; 358 unsigned long probe_timeout;
359 int probe_send_count; 359 int probe_send_count;
360 bool nullfunc_failed;
360 361
361 struct mutex mtx; 362 struct mutex mtx;
362 struct cfg80211_bss *associated; 363 struct cfg80211_bss *associated;
@@ -1271,7 +1272,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
1271void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1272void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1272 struct ieee80211_hdr *hdr); 1273 struct ieee80211_hdr *hdr);
1273void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, 1274void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1274 struct ieee80211_hdr *hdr); 1275 struct ieee80211_hdr *hdr, bool ack);
1275void ieee80211_beacon_connection_loss_work(struct work_struct *work); 1276void ieee80211_beacon_connection_loss_work(struct work_struct *work);
1276 1277
1277void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1278void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f570801514f1..3a1dde3c7956 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1065,16 +1065,20 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
1065} 1065}
1066 1066
1067void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, 1067void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1068 struct ieee80211_hdr *hdr) 1068 struct ieee80211_hdr *hdr, bool ack)
1069{ 1069{
1070 if (!ieee80211_is_data(hdr->frame_control)) 1070 if (!ieee80211_is_data(hdr->frame_control))
1071 return; 1071 return;
1072 1072
1073 ieee80211_sta_reset_conn_monitor(sdata); 1073 if (ack)
1074 ieee80211_sta_reset_conn_monitor(sdata);
1074 1075
1075 if (ieee80211_is_nullfunc(hdr->frame_control) && 1076 if (ieee80211_is_nullfunc(hdr->frame_control) &&
1076 sdata->u.mgd.probe_send_count > 0) { 1077 sdata->u.mgd.probe_send_count > 0) {
1077 sdata->u.mgd.probe_send_count = 0; 1078 if (ack)
1079 sdata->u.mgd.probe_send_count = 0;
1080 else
1081 sdata->u.mgd.nullfunc_failed = true;
1078 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 1082 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
1079 } 1083 }
1080} 1084}
@@ -1101,9 +1105,10 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1101 * anymore. The timeout will be reset if the frame is ACKed by 1105 * anymore. The timeout will be reset if the frame is ACKed by
1102 * the AP. 1106 * the AP.
1103 */ 1107 */
1104 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 1108 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
1109 ifmgd->nullfunc_failed = false;
1105 ieee80211_send_nullfunc(sdata->local, sdata, 0); 1110 ieee80211_send_nullfunc(sdata->local, sdata, 0);
1106 else { 1111 } else {
1107 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1112 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1108 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); 1113 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
1109 } 1114 }
@@ -1912,6 +1917,31 @@ static void ieee80211_sta_timer(unsigned long data)
1912 ieee80211_queue_work(&local->hw, &sdata->work); 1917 ieee80211_queue_work(&local->hw, &sdata->work);
1913} 1918}
1914 1919
1920static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
1921 u8 *bssid)
1922{
1923 struct ieee80211_local *local = sdata->local;
1924 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1925
1926 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1927 IEEE80211_STA_BEACON_POLL);
1928
1929 ieee80211_set_disassoc(sdata, true, true);
1930 mutex_unlock(&ifmgd->mtx);
1931 mutex_lock(&local->mtx);
1932 ieee80211_recalc_idle(local);
1933 mutex_unlock(&local->mtx);
1934 /*
1935 * must be outside lock due to cfg80211,
1936 * but that's not a problem.
1937 */
1938 ieee80211_send_deauth_disassoc(sdata, bssid,
1939 IEEE80211_STYPE_DEAUTH,
1940 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1941 NULL, true);
1942 mutex_lock(&ifmgd->mtx);
1943}
1944
1915void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) 1945void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1916{ 1946{
1917 struct ieee80211_local *local = sdata->local; 1947 struct ieee80211_local *local = sdata->local;
@@ -1936,11 +1966,38 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1936 /* ACK received for nullfunc probing frame */ 1966 /* ACK received for nullfunc probing frame */
1937 if (!ifmgd->probe_send_count) 1967 if (!ifmgd->probe_send_count)
1938 ieee80211_reset_ap_probe(sdata); 1968 ieee80211_reset_ap_probe(sdata);
1939 1969 else if (ifmgd->nullfunc_failed) {
1940 else if (time_is_after_jiffies(ifmgd->probe_timeout)) 1970 if (ifmgd->probe_send_count < max_tries) {
1971#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1972 wiphy_debug(local->hw.wiphy,
1973 "%s: No ack for nullfunc frame to"
1974 " AP %pM, try %d\n",
1975 sdata->name, bssid,
1976 ifmgd->probe_send_count);
1977#endif
1978 ieee80211_mgd_probe_ap_send(sdata);
1979 } else {
1980#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1981 wiphy_debug(local->hw.wiphy,
1982 "%s: No ack for nullfunc frame to"
1983 " AP %pM, disconnecting.\n",
1984 sdata->name, bssid,
1985 ifmgd->probe_send_count);
1986#endif
1987 ieee80211_sta_connection_lost(sdata, bssid);
1988 }
1989 } else if (time_is_after_jiffies(ifmgd->probe_timeout))
1941 run_again(ifmgd, ifmgd->probe_timeout); 1990 run_again(ifmgd, ifmgd->probe_timeout);
1942 1991 else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
1943 else if (ifmgd->probe_send_count < max_tries) { 1992#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1993 wiphy_debug(local->hw.wiphy,
1994 "%s: Failed to send nullfunc to AP %pM"
1995 " after %dms, disconnecting.\n",
1996 sdata->name,
1997 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1998#endif
1999 ieee80211_sta_connection_lost(sdata, bssid);
2000 } else if (ifmgd->probe_send_count < max_tries) {
1944#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 2001#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1945 wiphy_debug(local->hw.wiphy, 2002 wiphy_debug(local->hw.wiphy,
1946 "%s: No probe response from AP %pM" 2003 "%s: No probe response from AP %pM"
@@ -1955,27 +2012,13 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1955 * We actually lost the connection ... or did we? 2012 * We actually lost the connection ... or did we?
1956 * Let's make sure! 2013 * Let's make sure!
1957 */ 2014 */
1958 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1959 IEEE80211_STA_BEACON_POLL);
1960 wiphy_debug(local->hw.wiphy, 2015 wiphy_debug(local->hw.wiphy,
1961 "%s: No probe response from AP %pM" 2016 "%s: No probe response from AP %pM"
1962 " after %dms, disconnecting.\n", 2017 " after %dms, disconnecting.\n",
1963 sdata->name, 2018 sdata->name,
1964 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 2019 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1965 ieee80211_set_disassoc(sdata, true, true); 2020
1966 mutex_unlock(&ifmgd->mtx); 2021 ieee80211_sta_connection_lost(sdata, bssid);
1967 mutex_lock(&local->mtx);
1968 ieee80211_recalc_idle(local);
1969 mutex_unlock(&local->mtx);
1970 /*
1971 * must be outside lock due to cfg80211,
1972 * but that's not a problem.
1973 */
1974 ieee80211_send_deauth_disassoc(sdata, bssid,
1975 IEEE80211_STYPE_DEAUTH,
1976 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1977 NULL, true);
1978 mutex_lock(&ifmgd->mtx);
1979 } 2022 }
1980 } 2023 }
1981 2024
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 4958710a7d92..38a797217a91 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -155,10 +155,6 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
155 155
156 ieee80211_queue_work(&local->hw, &local->recalc_smps); 156 ieee80211_queue_work(&local->hw, &local->recalc_smps);
157 } 157 }
158
159 if ((sdata->vif.type == NL80211_IFTYPE_STATION) &&
160 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
161 ieee80211_sta_tx_notify(sdata, (void *) skb->data);
162} 158}
163 159
164/* 160/*
@@ -186,6 +182,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
186 int retry_count = -1, i; 182 int retry_count = -1, i;
187 int rates_idx = -1; 183 int rates_idx = -1;
188 bool send_to_cooked; 184 bool send_to_cooked;
185 bool acked;
189 186
190 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 187 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
191 /* the HW cannot have attempted that rate */ 188 /* the HW cannot have attempted that rate */
@@ -211,8 +208,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
211 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) 208 if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
212 continue; 209 continue;
213 210
214 if (!(info->flags & IEEE80211_TX_STAT_ACK) && 211 acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
215 test_sta_flags(sta, WLAN_STA_PS_STA)) { 212 if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
216 /* 213 /*
217 * The STA is in power save mode, so assume 214 * The STA is in power save mode, so assume
218 * that this TX packet failed because of that. 215 * that this TX packet failed because of that.
@@ -244,7 +241,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
244 rcu_read_unlock(); 241 rcu_read_unlock();
245 return; 242 return;
246 } else { 243 } else {
247 if (!(info->flags & IEEE80211_TX_STAT_ACK)) 244 if (!acked)
248 sta->tx_retry_failed++; 245 sta->tx_retry_failed++;
249 sta->tx_retry_count += retry_count; 246 sta->tx_retry_count += retry_count;
250 } 247 }
@@ -253,10 +250,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
253 if (ieee80211_vif_is_mesh(&sta->sdata->vif)) 250 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
254 ieee80211s_update_metric(local, sta, skb); 251 ieee80211s_update_metric(local, sta, skb);
255 252
256 if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && 253 if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
257 (info->flags & IEEE80211_TX_STAT_ACK))
258 ieee80211_frame_acked(sta, skb); 254 ieee80211_frame_acked(sta, skb);
259 255
256 if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
257 (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
258 ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked);
259
260 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { 260 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
261 if (info->flags & IEEE80211_TX_STAT_ACK) { 261 if (info->flags & IEEE80211_TX_STAT_ACK) {
262 if (sta->lost_packets) 262 if (sta->lost_packets)