aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorBruno Randolf <bruno@thinktube.com>2008-02-17 21:21:36 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:37:12 -0500
commit9d9bf77d16ba527f6f63846ca18cf20ae6e8d697 (patch)
treea8ae534cb92ef2368fee0b5fb4d092530a8017ee /net
parenta607268a0d5532d6ae3777ddd0339ff7d8b037a0 (diff)
mac80211: enable IBSS merging
enable IBSS cell merging. if an IBSS beacon with the same channel, same ESSID and a TSF higher than the local TSF (mactime) is received, we have to join its BSSID. while this might not be immediately apparent from reading the 802.11 standard it is compliant and necessary to make IBSS mode functional in many cases. most drivers have a similar behaviour. * move the relevant code section (previously only containing debug code) down to the end of the function, so we can reuse the bss structure. * we have to compare the mactime (TSF at the time of packet receive) rather than the current TSF. since mactime is defined as the time the first data symbol arrived we add the time until byte 24 where the timestamp resides, since this is how the beacon timestamp is defined. as some some drivers are not able to give a reliable mactime we fall back to use the current TSF, which will be enough to catch most (but not all) cases where an IBSS merge is necessary. * in IBSS mode we want to allow beacons to override probe response info so we can correctly do merges. * we don't only configure beacons based on scan results, so change that message. * to enable this we have to let all beacons thru in IBSS mode, even if they have a different BSSID. Signed-off-by: Bruno Randolf <bruno@thinktube.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_sta.c90
-rw-r--r--net/mac80211/rx.c5
2 files changed, 65 insertions, 30 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index a84ead49b1e..6e5b57dccc5 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 472b19fc914..279ee493520 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;