aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h3
-rw-r--r--net/mac80211/ieee80211_sta.c90
-rw-r--r--net/mac80211/rx.c5
3 files changed, 67 insertions, 31 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1a1d0d8203aa..784ab769b00b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -276,7 +276,8 @@ struct ieee80211_tx_control {
276 * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on 276 * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
277 * the frame. 277 * the frame.
278 * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) 278 * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field)
279 * is valid. 279 * is valid. This is useful in monitor mode and necessary for beacon frames
280 * to enable IBSS merging.
280 */ 281 */
281enum mac80211_rx_flags { 282enum mac80211_rx_flags {
282 RX_FLAG_MMIC_ERROR = 1<<0, 283 RX_FLAG_MMIC_ERROR = 1<<0,
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index a84ead49b1e6..6e5b57dccc50 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2199,7 +2199,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2199 struct ieee80211_sta_bss *bss; 2199 struct ieee80211_sta_bss *bss;
2200 struct sta_info *sta; 2200 struct sta_info *sta;
2201 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2201 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2202 u64 timestamp; 2202 u64 beacon_timestamp, rx_timestamp;
2203 DECLARE_MAC_BUF(mac); 2203 DECLARE_MAC_BUF(mac);
2204 DECLARE_MAC_BUF(mac2); 2204 DECLARE_MAC_BUF(mac2);
2205 2205
@@ -2216,31 +2216,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2216 if (baselen > len) 2216 if (baselen > len)
2217 return; 2217 return;
2218 2218
2219 timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); 2219 beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
2220
2221 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
2222 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
2223#ifdef CONFIG_MAC80211_IBSS_DEBUG
2224 static unsigned long last_tsf_debug = 0;
2225 u64 tsf;
2226 if (local->ops->get_tsf)
2227 tsf = local->ops->get_tsf(local_to_hw(local));
2228 else
2229 tsf = -1LLU;
2230 if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
2231 printk(KERN_DEBUG "RX beacon SA=%s BSSID="
2232 "%s TSF=0x%llx BCN=0x%llx diff=%lld "
2233 "@%lu\n",
2234 print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),
2235 (unsigned long long)tsf,
2236 (unsigned long long)timestamp,
2237 (unsigned long long)(tsf - timestamp),
2238 jiffies);
2239 last_tsf_debug = jiffies;
2240 }
2241#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2242 }
2243
2244 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); 2220 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
2245 2221
2246 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && 2222 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
@@ -2326,8 +2302,10 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2326 2302
2327 bss->band = rx_status->band; 2303 bss->band = rx_status->band;
2328 2304
2329 if (bss->probe_resp && beacon) { 2305 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2330 /* Do not allow beacon to override data from Probe Response. */ 2306 bss->probe_resp && beacon) {
2307 /* STA mode:
2308 * Do not allow beacon to override data from Probe Response. */
2331 ieee80211_rx_bss_put(dev, bss); 2309 ieee80211_rx_bss_put(dev, bss);
2332 return; 2310 return;
2333 } 2311 }
@@ -2424,13 +2402,67 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2424 bss->ht_ie_len = 0; 2402 bss->ht_ie_len = 0;
2425 } 2403 }
2426 2404
2427 bss->timestamp = timestamp; 2405 bss->timestamp = beacon_timestamp;
2428 bss->last_update = jiffies; 2406 bss->last_update = jiffies;
2429 bss->rssi = rx_status->ssi; 2407 bss->rssi = rx_status->ssi;
2430 bss->signal = rx_status->signal; 2408 bss->signal = rx_status->signal;
2431 bss->noise = rx_status->noise; 2409 bss->noise = rx_status->noise;
2432 if (!beacon) 2410 if (!beacon)
2433 bss->probe_resp++; 2411 bss->probe_resp++;
2412
2413 /* check if we need to merge IBSS */
2414 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
2415 !local->sta_sw_scanning && !local->sta_hw_scanning &&
2416 mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
2417 bss->freq == local->oper_channel->center_freq &&
2418 elems.ssid_len == sdata->u.sta.ssid_len &&
2419 memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) == 0) {
2420 if (rx_status->flag & RX_FLAG_TSFT) {
2421 /* in order for correct IBSS merging we need mactime
2422 *
2423 * since mactime is defined as the time the first data
2424 * symbol of the frame hits the PHY, and the timestamp
2425 * of the beacon is defined as "the time that the data
2426 * symbol containing the first bit of the timestamp is
2427 * transmitted to the PHY plus the transmitting STA’s
2428 * delays through its local PHY from the MAC-PHY
2429 * interface to its interface with the WM"
2430 * (802.11 11.1.2) - equals the time this bit arrives at
2431 * the receiver - we have to take into account the
2432 * offset between the two.
2433 * e.g: at 1 MBit that means mactime is 192 usec earlier
2434 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
2435 */
2436 int rate = local->hw.wiphy->bands[rx_status->band]->
2437 bitrates[rx_status->rate_idx].bitrate;
2438 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
2439 } else if (local && local->ops && local->ops->get_tsf)
2440 /* second best option: get current TSF */
2441 rx_timestamp = local->ops->get_tsf(local_to_hw(local));
2442 else
2443 /* can't merge without knowing the TSF */
2444 rx_timestamp = -1LLU;
2445#ifdef CONFIG_MAC80211_IBSS_DEBUG
2446 printk(KERN_DEBUG "RX beacon SA=%s BSSID="
2447 "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
2448 print_mac(mac, mgmt->sa),
2449 print_mac(mac2, mgmt->bssid),
2450 (unsigned long long)rx_timestamp,
2451 (unsigned long long)beacon_timestamp,
2452 (unsigned long long)(rx_timestamp - beacon_timestamp),
2453 jiffies);
2454#endif /* CONFIG_MAC80211_IBSS_DEBUG */
2455 if (beacon_timestamp > rx_timestamp) {
2456 if (CONFIG_MAC80211_IBSS_DEBUG || net_ratelimit())
2457 printk(KERN_DEBUG "%s: beacon TSF higher than "
2458 "local TSF - IBSS merge with BSSID %s\n",
2459 dev->name, print_mac(mac, mgmt->bssid));
2460 ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
2461 ieee80211_ibss_add_sta(dev, NULL,
2462 mgmt->bssid, mgmt->sa);
2463 }
2464 }
2465
2434 ieee80211_rx_bss_put(dev, bss); 2466 ieee80211_rx_bss_put(dev, bss);
2435} 2467}
2436 2468
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 472b19fc9143..279ee493520d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1695,7 +1695,10 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
1695 case IEEE80211_IF_TYPE_IBSS: 1695 case IEEE80211_IF_TYPE_IBSS:
1696 if (!bssid) 1696 if (!bssid)
1697 return 0; 1697 return 0;
1698 if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { 1698 if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
1699 (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
1700 return 1;
1701 else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
1699 if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) 1702 if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
1700 return 0; 1703 return 0;
1701 rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; 1704 rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;