diff options
-rw-r--r-- | include/net/mac80211.h | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 90 | ||||
-rw-r--r-- | net/mac80211/rx.c | 5 |
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 | */ |
281 | enum mac80211_rx_flags { | 282 | enum 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; |