aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c143
1 files changed, 112 insertions, 31 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a3a9421555af..794807914940 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -28,13 +28,19 @@
28#include "rate.h" 28#include "rate.h"
29#include "led.h" 29#include "led.h"
30 30
31#define IEEE80211_MAX_NULLFUNC_TRIES 2
31#define IEEE80211_MAX_PROBE_TRIES 5 32#define IEEE80211_MAX_PROBE_TRIES 5
32 33
33/* 34/*
34 * beacon loss detection timeout 35 * Beacon loss timeout is calculated as N frames times the
35 * XXX: should depend on beacon interval 36 * advertised beacon interval. This may need to be somewhat
37 * higher than what hardware might detect to account for
38 * delays in the host processing frames. But since we also
39 * probe on beacon miss before declaring the connection lost
40 * default to what we want.
36 */ 41 */
37#define IEEE80211_BEACON_LOSS_TIME (2 * HZ) 42#define IEEE80211_BEACON_LOSS_COUNT 7
43
38/* 44/*
39 * Time the connection can be idle before we probe 45 * Time the connection can be idle before we probe
40 * it to see if we can still talk to the AP. 46 * it to see if we can still talk to the AP.
@@ -121,7 +127,7 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
121 return; 127 return;
122 128
123 mod_timer(&sdata->u.mgd.bcn_mon_timer, 129 mod_timer(&sdata->u.mgd.bcn_mon_timer,
124 round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); 130 round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
125} 131}
126 132
127void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) 133void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
@@ -871,6 +877,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
871 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 877 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
872 cbss->capability, bss->has_erp_value, bss->erp_value); 878 cbss->capability, bss->has_erp_value, bss->erp_value);
873 879
880 sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
881 IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int));
882
874 sdata->u.mgd.associated = cbss; 883 sdata->u.mgd.associated = cbss;
875 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); 884 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
876 885
@@ -1026,6 +1035,51 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1026 ieee80211_sta_reset_conn_monitor(sdata); 1035 ieee80211_sta_reset_conn_monitor(sdata);
1027} 1036}
1028 1037
1038static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
1039{
1040 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1041
1042 if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
1043 IEEE80211_STA_CONNECTION_POLL)))
1044 return;
1045
1046 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1047 IEEE80211_STA_BEACON_POLL);
1048 mutex_lock(&sdata->local->iflist_mtx);
1049 ieee80211_recalc_ps(sdata->local, -1);
1050 mutex_unlock(&sdata->local->iflist_mtx);
1051
1052 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1053 return;
1054
1055 /*
1056 * We've received a probe response, but are not sure whether
1057 * we have or will be receiving any beacons or data, so let's
1058 * schedule the timers again, just in case.
1059 */
1060 ieee80211_sta_reset_beacon_monitor(sdata);
1061
1062 mod_timer(&ifmgd->conn_mon_timer,
1063 round_jiffies_up(jiffies +
1064 IEEE80211_CONNECTION_IDLE_TIME));
1065}
1066
1067void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1068 struct ieee80211_hdr *hdr)
1069{
1070 if (!ieee80211_is_data(hdr->frame_control) &&
1071 !ieee80211_is_nullfunc(hdr->frame_control))
1072 return;
1073
1074 ieee80211_sta_reset_conn_monitor(sdata);
1075
1076 if (ieee80211_is_nullfunc(hdr->frame_control) &&
1077 sdata->u.mgd.probe_send_count > 0) {
1078 sdata->u.mgd.probe_send_count = 0;
1079 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
1080 }
1081}
1082
1029static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) 1083static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1030{ 1084{
1031 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1085 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1041,8 +1095,19 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1041 if (ifmgd->probe_send_count >= unicast_limit) 1095 if (ifmgd->probe_send_count >= unicast_limit)
1042 dst = NULL; 1096 dst = NULL;
1043 1097
1044 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1098 /*
1045 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); 1099 * When the hardware reports an accurate Tx ACK status, it's
1100 * better to send a nullfunc frame instead of a probe request,
1101 * as it will kick us off the AP quickly if we aren't associated
1102 * anymore. The timeout will be reset if the frame is ACKed by
1103 * the AP.
1104 */
1105 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
1106 ieee80211_send_nullfunc(sdata->local, sdata, 0);
1107 else {
1108 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1109 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
1110 }
1046 1111
1047 ifmgd->probe_send_count++; 1112 ifmgd->probe_send_count++;
1048 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; 1113 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
@@ -1108,6 +1173,30 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
1108 mutex_unlock(&ifmgd->mtx); 1173 mutex_unlock(&ifmgd->mtx);
1109} 1174}
1110 1175
1176struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1177 struct ieee80211_vif *vif)
1178{
1179 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1180 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1181 struct sk_buff *skb;
1182 const u8 *ssid;
1183
1184 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
1185 return NULL;
1186
1187 ASSERT_MGD_MTX(ifmgd);
1188
1189 if (!ifmgd->associated)
1190 return NULL;
1191
1192 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1193 skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
1194 ssid + 2, ssid[1], NULL, 0);
1195
1196 return skb;
1197}
1198EXPORT_SYMBOL(ieee80211_ap_probereq_get);
1199
1111static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) 1200static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1112{ 1201{
1113 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1202 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1485,29 +1574,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1485 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); 1574 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false);
1486 1575
1487 if (ifmgd->associated && 1576 if (ifmgd->associated &&
1488 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && 1577 memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0)
1489 ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1578 ieee80211_reset_ap_probe(sdata);
1490 IEEE80211_STA_CONNECTION_POLL)) {
1491 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
1492 IEEE80211_STA_BEACON_POLL);
1493 mutex_lock(&sdata->local->iflist_mtx);
1494 ieee80211_recalc_ps(sdata->local, -1);
1495 mutex_unlock(&sdata->local->iflist_mtx);
1496
1497 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1498 return;
1499
1500 /*
1501 * We've received a probe response, but are not sure whether
1502 * we have or will be receiving any beacons or data, so let's
1503 * schedule the timers again, just in case.
1504 */
1505 ieee80211_sta_reset_beacon_monitor(sdata);
1506
1507 mod_timer(&ifmgd->conn_mon_timer,
1508 round_jiffies_up(jiffies +
1509 IEEE80211_CONNECTION_IDLE_TIME));
1510 }
1511} 1579}
1512 1580
1513/* 1581/*
@@ -1857,12 +1925,23 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1857 IEEE80211_STA_CONNECTION_POLL) && 1925 IEEE80211_STA_CONNECTION_POLL) &&
1858 ifmgd->associated) { 1926 ifmgd->associated) {
1859 u8 bssid[ETH_ALEN]; 1927 u8 bssid[ETH_ALEN];
1928 int max_tries;
1860 1929
1861 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); 1930 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
1862 if (time_is_after_jiffies(ifmgd->probe_timeout)) 1931
1932 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
1933 max_tries = IEEE80211_MAX_NULLFUNC_TRIES;
1934 else
1935 max_tries = IEEE80211_MAX_PROBE_TRIES;
1936
1937 /* ACK received for nullfunc probing frame */
1938 if (!ifmgd->probe_send_count)
1939 ieee80211_reset_ap_probe(sdata);
1940
1941 else if (time_is_after_jiffies(ifmgd->probe_timeout))
1863 run_again(ifmgd, ifmgd->probe_timeout); 1942 run_again(ifmgd, ifmgd->probe_timeout);
1864 1943
1865 else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { 1944 else if (ifmgd->probe_send_count < max_tries) {
1866#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1945#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1867 wiphy_debug(local->hw.wiphy, 1946 wiphy_debug(local->hw.wiphy,
1868 "%s: No probe response from AP %pM" 1947 "%s: No probe response from AP %pM"
@@ -1988,6 +2067,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
1988 add_timer(&ifmgd->timer); 2067 add_timer(&ifmgd->timer);
1989 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) 2068 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
1990 add_timer(&ifmgd->chswitch_timer); 2069 add_timer(&ifmgd->chswitch_timer);
2070 ieee80211_sta_reset_beacon_monitor(sdata);
2071 ieee80211_restart_sta_timer(sdata);
1991} 2072}
1992#endif 2073#endif
1993 2074