1 From: Ron Rindjunsky <ron.rindjunsky@intel.com>
2 Date: Sat, 9 Aug 2008 03:02:19 +0300
3 Subject: [PATCH] mac80211: add direct probe before association
4 Patch-mainline: 2.6.28-rc1
7 This patch adds a direct probe request as first step in the association
8 flow if data we have is not up to date. Motivation of this step is to make
9 sure that the bss information we have is correct, since last scan could
10 have been done a while ago, and beacons do not fully answer this need as
11 there are potential differences between them and probe responses (e.g.
12 WMM parameter element)
14 Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
15 Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
16 Signed-off-by: John W. Linville <linville@tuxdriver.com>
18 Modified not to break kABI: auth_tries is overriden to also mean
19 direct_probe_tries, last_probe_resp is moved to the end of the
20 ieee80211_sta_bss structure.
22 Signed-off-by: Jiri Benc <jbenc@suse.cz>
25 net/mac80211/ieee80211_i.h | 10 +++++
26 net/mac80211/mlme.c | 79 ++++++++++++++++++++++++++++++++++++++-------
27 2 files changed, 77 insertions(+), 12 deletions(-)
29 --- linux-2.6.27.orig/net/mac80211/ieee80211_i.h
30 +++ linux-2.6.27/net/mac80211/ieee80211_i.h
31 @@ -117,6 +117,10 @@ struct ieee80211_sta_bss {
32 * otherwise, you probably don't want to use them. */
37 + unsigned long last_probe_resp;
41 static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
42 @@ -310,6 +314,9 @@ struct ieee80211_if_sta {
43 IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
44 IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
47 + , IEEE80211_DIRECT_PROBE
51 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
52 @@ -363,6 +370,7 @@ struct ieee80211_if_sta {
53 #define IEEE80211_STA_REQ_SCAN 0
54 #define IEEE80211_STA_REQ_AUTH 1
55 #define IEEE80211_STA_REQ_RUN 2
56 +#define IEEE80211_STA_REQ_DIRECT_PROBE 3
58 #define IEEE80211_AUTH_ALG_OPEN BIT(0)
59 #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
60 --- linux-2.6.27.orig/net/mac80211/mlme.c
61 +++ linux-2.6.27/net/mac80211/mlme.c
62 @@ -658,6 +658,36 @@ static void ieee80211_send_auth(struct n
63 ieee80211_sta_tx(dev, skb, encrypt);
66 +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
67 + struct ieee80211_if_sta *ifsta)
69 + DECLARE_MAC_BUF(mac);
71 + ifsta->auth_tries++; /* used as direct_probe_tries */
72 + if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
73 + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
74 + sdata->dev->name, print_mac(mac, ifsta->bssid));
75 + ifsta->state = IEEE80211_DISABLED;
79 + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n",
80 + sdata->dev->name, print_mac(mac, ifsta->bssid),
83 + ifsta->state = IEEE80211_DIRECT_PROBE;
85 + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request);
87 + /* Direct probe is sent to broadcast address as some APs
88 + * will not answer to direct packet in unassociated state.
90 + ieee80211_send_probe_req(sdata->dev, NULL,
91 + ifsta->ssid, ifsta->ssid_len);
93 + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
97 static void ieee80211_authenticate(struct net_device *dev,
98 struct ieee80211_if_sta *ifsta)
99 @@ -1958,7 +1988,7 @@ static void ieee80211_rx_mgmt_deauth(str
100 if (ifsta->state == IEEE80211_AUTHENTICATE ||
101 ifsta->state == IEEE80211_ASSOCIATE ||
102 ifsta->state == IEEE80211_ASSOCIATED) {
103 - ifsta->state = IEEE80211_AUTHENTICATE;
104 + ifsta->state = IEEE80211_DIRECT_PROBE;
105 mod_timer(&ifsta->timer, jiffies +
106 IEEE80211_RETRY_AUTH_INTERVAL);
108 @@ -2559,8 +2589,7 @@ static void ieee80211_rx_bss_info(struct
109 struct ieee80211_mgmt *mgmt,
111 struct ieee80211_rx_status *rx_status,
112 - struct ieee802_11_elems *elems,
114 + struct ieee802_11_elems *elems)
116 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
118 @@ -2569,6 +2598,7 @@ static void ieee80211_rx_bss_info(struct
119 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
120 u64 beacon_timestamp, rx_timestamp;
121 struct ieee80211_channel *channel;
122 + bool beacon = ieee80211_is_beacon(mgmt->frame_control);
123 DECLARE_MAC_BUF(mac);
124 DECLARE_MAC_BUF(mac2);
126 @@ -2728,15 +2758,14 @@ static void ieee80211_rx_bss_info(struct
127 bss->signal = rx_status->signal;
128 bss->noise = rx_status->noise;
129 bss->qual = rx_status->qual;
130 - if (!beacon && !bss->probe_resp)
131 - bss->probe_resp = true;
134 + bss->last_probe_resp = jiffies;
136 * In STA mode, the remaining parameters should not be overridden
137 * by beacons because they're not necessarily accurate there.
139 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
140 - bss->probe_resp && beacon) {
141 + bss->last_probe_resp && beacon) {
142 ieee80211_rx_bss_put(local, bss);
145 @@ -2891,6 +2920,8 @@ static void ieee80211_rx_mgmt_probe_resp
148 struct ieee802_11_elems elems;
149 + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
150 + struct ieee80211_if_sta *ifsta = &sdata->u.sta;
152 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
154 @@ -2899,7 +2930,17 @@ static void ieee80211_rx_mgmt_probe_resp
155 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
158 - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0);
159 + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
161 + /* direct probe may be part of the association flow */
162 + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
163 + &ifsta->request)) {
164 + printk(KERN_DEBUG "%s direct probe responded\n",
166 + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */
167 + ieee80211_authenticate(dev, ifsta);
173 @@ -2923,7 +2964,7 @@ static void ieee80211_rx_mgmt_beacon(str
175 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
177 - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1);
178 + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
180 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
181 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
182 @@ -3361,7 +3402,8 @@ void ieee80211_sta_work(struct work_stru
183 mesh_path_start_discovery(dev);
186 - if (ifsta->state != IEEE80211_AUTHENTICATE &&
187 + if (ifsta->state != IEEE80211_DIRECT_PROBE &&
188 + ifsta->state != IEEE80211_AUTHENTICATE &&
189 ifsta->state != IEEE80211_ASSOCIATE &&
190 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
191 if (ifsta->scan_ssid_len)
192 @@ -3381,6 +3423,10 @@ void ieee80211_sta_work(struct work_stru
193 switch (ifsta->state) {
194 case IEEE80211_DISABLED:
196 + case IEEE80211_DIRECT_PROBE:
197 + ieee80211_direct_probe(sdata, ifsta);
200 case IEEE80211_AUTHENTICATE:
201 ieee80211_authenticate(dev, ifsta);
203 @@ -3541,8 +3587,18 @@ static int ieee80211_sta_config_auth(str
205 ieee80211_sta_set_bssid(dev, selected->bssid);
206 ieee80211_sta_def_wmm_params(dev, selected, 0);
208 + /* Send out direct probe if no probe resp was received or
209 + * the one we have is outdated
211 + if (!selected->last_probe_resp ||
212 + time_after(jiffies, selected->last_probe_resp
213 + + IEEE80211_SCAN_RESULT_EXPIRE))
214 + ifsta->state = IEEE80211_DIRECT_PROBE;
216 + ifsta->state = IEEE80211_AUTHENTICATE;
218 ieee80211_rx_bss_put(local, selected);
219 - ifsta->state = IEEE80211_AUTHENTICATE;
220 ieee80211_sta_reset_auth(dev, ifsta);
223 @@ -3553,6 +3609,7 @@ static int ieee80211_sta_config_auth(str
224 ieee80211_sta_start_scan(dev, ifsta->ssid,
226 ifsta->state = IEEE80211_AUTHENTICATE;
227 + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */
228 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
230 ifsta->state = IEEE80211_DISABLED;