aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2008-02-23 09:17:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:41 -0500
commitf709fc696d72d31273a77b82aa32cb6d19857011 (patch)
treef10a435b01cd3edf0f350c66de750984370872c4 /net/mac80211/ieee80211_sta.c
parentee3858551ae6d044578f598f8001db5f1a9fd52e (diff)
mac80211: mesh changes to the MLME
This includes support for mesh network scanning. The ugly code in ieee80211_sta_scan_result() is my approach to work around wext. This has been tested with wireless tools version 29 and works as expected (the new interface mode is just not shown). Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r--net/mac80211/ieee80211_sta.c322
1 files changed, 263 insertions, 59 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index b4b498ae60f2..d2dedcb5a954 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -31,12 +31,16 @@
31#include "ieee80211_i.h" 31#include "ieee80211_i.h"
32#include "ieee80211_rate.h" 32#include "ieee80211_rate.h"
33#include "ieee80211_led.h" 33#include "ieee80211_led.h"
34#ifdef CONFIG_MAC80211_MESH
35#include "mesh.h"
36#endif
34 37
35#define IEEE80211_AUTH_TIMEOUT (HZ / 5) 38#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
36#define IEEE80211_AUTH_MAX_TRIES 3 39#define IEEE80211_AUTH_MAX_TRIES 3
37#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 40#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
38#define IEEE80211_ASSOC_MAX_TRIES 3 41#define IEEE80211_ASSOC_MAX_TRIES 3
39#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 42#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
43#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
40#define IEEE80211_PROBE_INTERVAL (60 * HZ) 44#define IEEE80211_PROBE_INTERVAL (60 * HZ)
41#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) 45#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
42#define IEEE80211_SCAN_INTERVAL (2 * HZ) 46#define IEEE80211_SCAN_INTERVAL (2 * HZ)
@@ -49,6 +53,7 @@
49#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) 53#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
50#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) 54#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
51#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) 55#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
56#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
52 57
53#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 58#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
54 59
@@ -1891,8 +1896,15 @@ static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
1891 struct ieee80211_sta_bss *bss) 1896 struct ieee80211_sta_bss *bss)
1892{ 1897{
1893 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1898 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1894 bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)]; 1899 u8 hash_idx;
1895 local->sta_bss_hash[STA_HASH(bss->bssid)] = bss; 1900#ifdef CONFIG_MAC80211_MESH
1901 if (bss->mesh_cfg)
1902 hash_idx = mesh_id_hash(bss->mesh_id, bss->mesh_id_len);
1903 else
1904#endif
1905 hash_idx = STA_HASH(bss->bssid);
1906 bss->hnext = local->sta_bss_hash[hash_idx];
1907 local->sta_bss_hash[hash_idx] = bss;
1896} 1908}
1897 1909
1898 1910
@@ -1945,7 +1957,6 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq,
1945 return bss; 1957 return bss;
1946} 1958}
1947 1959
1948
1949static struct ieee80211_sta_bss * 1960static struct ieee80211_sta_bss *
1950ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, 1961ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
1951 u8 *ssid, u8 ssid_len) 1962 u8 *ssid, u8 ssid_len)
@@ -1956,7 +1967,7 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
1956 spin_lock_bh(&local->sta_bss_lock); 1967 spin_lock_bh(&local->sta_bss_lock);
1957 bss = local->sta_bss_hash[STA_HASH(bssid)]; 1968 bss = local->sta_bss_hash[STA_HASH(bssid)];
1958 while (bss) { 1969 while (bss) {
1959 if (!memcmp(bss->bssid, bssid, ETH_ALEN) && 1970 if (!bss->mesh_cfg && !memcmp(bss->bssid, bssid, ETH_ALEN) &&
1960 bss->freq == freq && 1971 bss->freq == freq &&
1961 bss->ssid_len == ssid_len && 1972 bss->ssid_len == ssid_len &&
1962 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { 1973 (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
@@ -1969,6 +1980,72 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
1969 return bss; 1980 return bss;
1970} 1981}
1971 1982
1983#ifdef CONFIG_MAC80211_MESH
1984static struct ieee80211_sta_bss *
1985ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
1986 u8 *mesh_cfg, int freq)
1987{
1988 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1989 struct ieee80211_sta_bss *bss;
1990
1991 spin_lock_bh(&local->sta_bss_lock);
1992 bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
1993 while (bss) {
1994 if (bss->mesh_cfg &&
1995 !memcmp(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN) &&
1996 bss->freq == freq &&
1997 mesh_id_len == bss->mesh_id_len &&
1998 (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
1999 mesh_id_len))) {
2000 atomic_inc(&bss->users);
2001 break;
2002 }
2003 bss = bss->hnext;
2004 }
2005 spin_unlock_bh(&local->sta_bss_lock);
2006 return bss;
2007}
2008
2009static struct ieee80211_sta_bss *
2010ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
2011 u8 *mesh_cfg, int freq)
2012{
2013 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2014 struct ieee80211_sta_bss *bss;
2015
2016 bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
2017 if (!bss)
2018 return NULL;
2019
2020 bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
2021 if (!bss->mesh_cfg) {
2022 kfree(bss);
2023 return NULL;
2024 }
2025
2026 if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
2027 bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
2028 if (!bss->mesh_id) {
2029 kfree(bss->mesh_cfg);
2030 kfree(bss);
2031 return NULL;
2032 }
2033 memcpy(bss->mesh_id, mesh_id, mesh_id_len);
2034 }
2035
2036 atomic_inc(&bss->users);
2037 atomic_inc(&bss->users);
2038 memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
2039 bss->mesh_id_len = mesh_id_len;
2040 bss->freq = freq;
2041 spin_lock_bh(&local->sta_bss_lock);
2042 /* TODO: order by RSSI? */
2043 list_add_tail(&bss->list, &local->sta_bss_list);
2044 __ieee80211_rx_bss_hash_add(dev, bss);
2045 spin_unlock_bh(&local->sta_bss_lock);
2046 return bss;
2047}
2048#endif
1972 2049
1973static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) 2050static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
1974{ 2051{
@@ -1976,6 +2053,10 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
1976 kfree(bss->rsn_ie); 2053 kfree(bss->rsn_ie);
1977 kfree(bss->wmm_ie); 2054 kfree(bss->wmm_ie);
1978 kfree(bss->ht_ie); 2055 kfree(bss->ht_ie);
2056#ifdef CONFIG_MAC80211_MESH
2057 kfree(bss->mesh_id);
2058 kfree(bss->mesh_cfg);
2059#endif
1979 kfree(bss); 2060 kfree(bss);
1980} 2061}
1981 2062
@@ -2171,6 +2252,42 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
2171 return res; 2252 return res;
2172} 2253}
2173 2254
2255u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
2256 struct ieee802_11_elems *elems,
2257 enum ieee80211_band band)
2258{
2259 struct ieee80211_supported_band *sband;
2260 struct ieee80211_rate *bitrates;
2261 size_t num_rates;
2262 u64 supp_rates;
2263 int i, j;
2264 sband = local->hw.wiphy->bands[band];
2265
2266 if (!sband) {
2267 WARN_ON(1);
2268 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
2269 }
2270
2271 bitrates = sband->bitrates;
2272 num_rates = sband->n_bitrates;
2273 supp_rates = 0;
2274 for (i = 0; i < elems->supp_rates_len +
2275 elems->ext_supp_rates_len; i++) {
2276 u8 rate = 0;
2277 int own_rate;
2278 if (i < elems->supp_rates_len)
2279 rate = elems->supp_rates[i];
2280 else if (elems->ext_supp_rates)
2281 rate = elems->ext_supp_rates
2282 [i - elems->supp_rates_len];
2283 own_rate = 5 * (rate & 0x7f);
2284 for (j = 0; j < num_rates; j++)
2285 if (bitrates[j].bitrate == own_rate)
2286 supp_rates |= BIT(j);
2287 }
2288 return supp_rates;
2289}
2290
2174 2291
2175static void ieee80211_rx_bss_info(struct net_device *dev, 2292static void ieee80211_rx_bss_info(struct net_device *dev,
2176 struct ieee80211_mgmt *mgmt, 2293 struct ieee80211_mgmt *mgmt,
@@ -2205,41 +2322,23 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2205 beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); 2322 beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
2206 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); 2323 ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
2207 2324
2325#ifdef CONFIG_MAC80211_MESH
2326 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && elems.mesh_id
2327 && elems.mesh_config)
2328 if (mesh_matches_local(&elems, dev)) {
2329 u64 rates = ieee80211_sta_get_rates(local, &elems,
2330 rx_status->band);
2331 mesh_neighbour_update(mgmt->sa, rates, dev,
2332 mesh_peer_accepts_plinks(&elems, dev));
2333 }
2334#endif
2335
2208 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && 2336 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
2209 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && 2337 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
2210 (sta = sta_info_get(local, mgmt->sa))) { 2338 (sta = sta_info_get(local, mgmt->sa))) {
2211 struct ieee80211_supported_band *sband; 2339 u64 prev_rates;
2212 struct ieee80211_rate *bitrates; 2340 u64 supp_rates = ieee80211_sta_get_rates(local, &elems,
2213 size_t num_rates; 2341 rx_status->band);
2214 u64 supp_rates, prev_rates;
2215 int i, j;
2216
2217 sband = local->hw.wiphy->bands[rx_status->band];
2218
2219 if (!sband) {
2220 WARN_ON(1);
2221 sband = local->hw.wiphy->bands[
2222 local->hw.conf.channel->band];
2223 }
2224
2225 bitrates = sband->bitrates;
2226 num_rates = sband->n_bitrates;
2227
2228 supp_rates = 0;
2229 for (i = 0; i < elems.supp_rates_len +
2230 elems.ext_supp_rates_len; i++) {
2231 u8 rate = 0;
2232 int own_rate;
2233 if (i < elems.supp_rates_len)
2234 rate = elems.supp_rates[i];
2235 else if (elems.ext_supp_rates)
2236 rate = elems.ext_supp_rates
2237 [i - elems.supp_rates_len];
2238 own_rate = 5 * (rate & 0x7f);
2239 for (j = 0; j < num_rates; j++)
2240 if (bitrates[j].bitrate == own_rate)
2241 supp_rates |= BIT(j);
2242 }
2243 2342
2244 prev_rates = sta->supp_rates[rx_status->band]; 2343 prev_rates = sta->supp_rates[rx_status->band];
2245 sta->supp_rates[rx_status->band] &= supp_rates; 2344 sta->supp_rates[rx_status->band] &= supp_rates;
@@ -2262,19 +2361,28 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2262 sta_info_put(sta); 2361 sta_info_put(sta);
2263 } 2362 }
2264 2363
2265 if (!elems.ssid)
2266 return;
2267
2268 if (elems.ds_params && elems.ds_params_len == 1) 2364 if (elems.ds_params && elems.ds_params_len == 1)
2269 freq = ieee80211_channel_to_frequency(elems.ds_params[0]); 2365 freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
2270 else 2366 else
2271 freq = rx_status->freq; 2367 freq = rx_status->freq;
2272 2368
2273 bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, 2369#ifdef CONFIG_MAC80211_MESH
2274 elems.ssid, elems.ssid_len); 2370 if (elems.mesh_config)
2275 if (!bss) { 2371 bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id,
2276 bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, 2372 elems.mesh_id_len, elems.mesh_config, freq);
2373 else
2374#endif
2375 bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq,
2277 elems.ssid, elems.ssid_len); 2376 elems.ssid, elems.ssid_len);
2377 if (!bss) {
2378#ifdef CONFIG_MAC80211_MESH
2379 if (elems.mesh_config)
2380 bss = ieee80211_rx_mesh_bss_add(dev, elems.mesh_id,
2381 elems.mesh_id_len, elems.mesh_config, freq);
2382 else
2383#endif
2384 bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq,
2385 elems.ssid, elems.ssid_len);
2278 if (!bss) 2386 if (!bss)
2279 return; 2387 return;
2280 } else { 2388 } else {
@@ -2601,8 +2709,13 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
2601static void ieee80211_rx_mgmt_action(struct net_device *dev, 2709static void ieee80211_rx_mgmt_action(struct net_device *dev,
2602 struct ieee80211_if_sta *ifsta, 2710 struct ieee80211_if_sta *ifsta,
2603 struct ieee80211_mgmt *mgmt, 2711 struct ieee80211_mgmt *mgmt,
2604 size_t len) 2712 size_t len,
2713 struct ieee80211_rx_status *rx_status)
2605{ 2714{
2715#ifdef CONFIG_MAC80211_MESH
2716 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2717#endif
2718
2606 if (len < IEEE80211_MIN_ACTION_SIZE) 2719 if (len < IEEE80211_MIN_ACTION_SIZE)
2607 return; 2720 return;
2608 2721
@@ -2634,7 +2747,21 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev,
2634 break; 2747 break;
2635 } 2748 }
2636 break; 2749 break;
2750#ifdef CONFIG_MAC80211_MESH
2751 case PLINK_CATEGORY:
2752 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
2753 mesh_rx_plink_frame(dev, mgmt, len, rx_status);
2754 break;
2755
2756 case MESH_PATH_SEL_CATEGORY:
2757 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
2758 mesh_rx_path_sel_frame(dev, mgmt, len);
2759 break;
2760#endif
2637 default: 2761 default:
2762 if (net_ratelimit())
2763 printk(KERN_DEBUG "%s: Rx unknown action frame - "
2764 "category=%d\n", dev->name, mgmt->u.action.category);
2638 break; 2765 break;
2639 } 2766 }
2640} 2767}
@@ -2661,13 +2788,13 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
2661 case IEEE80211_STYPE_PROBE_REQ: 2788 case IEEE80211_STYPE_PROBE_REQ:
2662 case IEEE80211_STYPE_PROBE_RESP: 2789 case IEEE80211_STYPE_PROBE_RESP:
2663 case IEEE80211_STYPE_BEACON: 2790 case IEEE80211_STYPE_BEACON:
2791 case IEEE80211_STYPE_ACTION:
2664 memcpy(skb->cb, rx_status, sizeof(*rx_status)); 2792 memcpy(skb->cb, rx_status, sizeof(*rx_status));
2665 case IEEE80211_STYPE_AUTH: 2793 case IEEE80211_STYPE_AUTH:
2666 case IEEE80211_STYPE_ASSOC_RESP: 2794 case IEEE80211_STYPE_ASSOC_RESP:
2667 case IEEE80211_STYPE_REASSOC_RESP: 2795 case IEEE80211_STYPE_REASSOC_RESP:
2668 case IEEE80211_STYPE_DEAUTH: 2796 case IEEE80211_STYPE_DEAUTH:
2669 case IEEE80211_STYPE_DISASSOC: 2797 case IEEE80211_STYPE_DISASSOC:
2670 case IEEE80211_STYPE_ACTION:
2671 skb_queue_tail(&ifsta->skb_queue, skb); 2798 skb_queue_tail(&ifsta->skb_queue, skb);
2672 queue_work(local->hw.workqueue, &ifsta->work); 2799 queue_work(local->hw.workqueue, &ifsta->work);
2673 return; 2800 return;
@@ -2726,7 +2853,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
2726 ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); 2853 ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
2727 break; 2854 break;
2728 case IEEE80211_STYPE_ACTION: 2855 case IEEE80211_STYPE_ACTION:
2729 ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len); 2856 ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status);
2730 break; 2857 break;
2731 } 2858 }
2732 2859
@@ -2791,7 +2918,7 @@ static int ieee80211_sta_active_ibss(struct net_device *dev)
2791} 2918}
2792 2919
2793 2920
2794static void ieee80211_sta_expire(struct net_device *dev) 2921static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
2795{ 2922{
2796 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 2923 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
2797 struct sta_info *sta, *tmp; 2924 struct sta_info *sta, *tmp;
@@ -2800,8 +2927,7 @@ static void ieee80211_sta_expire(struct net_device *dev)
2800 2927
2801 write_lock_bh(&local->sta_lock); 2928 write_lock_bh(&local->sta_lock);
2802 list_for_each_entry_safe(sta, tmp, &local->sta_list, list) 2929 list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
2803 if (time_after(jiffies, sta->last_rx + 2930 if (time_after(jiffies, sta->last_rx + exp_time)) {
2804 IEEE80211_IBSS_INACTIVITY_LIMIT)) {
2805 printk(KERN_DEBUG "%s: expiring inactive STA %s\n", 2931 printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
2806 dev->name, print_mac(mac, sta->addr)); 2932 dev->name, print_mac(mac, sta->addr));
2807 __sta_info_get(sta); 2933 __sta_info_get(sta);
@@ -2822,7 +2948,7 @@ static void ieee80211_sta_merge_ibss(struct net_device *dev,
2822{ 2948{
2823 mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); 2949 mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
2824 2950
2825 ieee80211_sta_expire(dev); 2951 ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT);
2826 if (ieee80211_sta_active_ibss(dev)) 2952 if (ieee80211_sta_active_ibss(dev))
2827 return; 2953 return;
2828 2954
@@ -2832,6 +2958,36 @@ static void ieee80211_sta_merge_ibss(struct net_device *dev,
2832} 2958}
2833 2959
2834 2960
2961#ifdef CONFIG_MAC80211_MESH
2962static void ieee80211_mesh_housekeeping(struct net_device *dev,
2963 struct ieee80211_if_sta *ifsta)
2964{
2965 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2966 bool free_plinks;
2967
2968 ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
2969 mesh_path_expire(dev);
2970
2971 free_plinks = mesh_plink_availables(sdata);
2972 if (free_plinks != sdata->u.sta.accepting_plinks)
2973 ieee80211_if_config_beacon(dev);
2974
2975 mod_timer(&ifsta->timer, jiffies +
2976 IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
2977}
2978
2979
2980void ieee80211_start_mesh(struct net_device *dev)
2981{
2982 struct ieee80211_if_sta *ifsta;
2983 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2984 ifsta = &sdata->u.sta;
2985 ifsta->state = IEEE80211_MESH_UP;
2986 ieee80211_sta_timer((unsigned long)sdata);
2987}
2988#endif
2989
2990
2835void ieee80211_sta_timer(unsigned long data) 2991void ieee80211_sta_timer(unsigned long data)
2836{ 2992{
2837 struct ieee80211_sub_if_data *sdata = 2993 struct ieee80211_sub_if_data *sdata =
@@ -2843,7 +2999,6 @@ void ieee80211_sta_timer(unsigned long data)
2843 queue_work(local->hw.workqueue, &ifsta->work); 2999 queue_work(local->hw.workqueue, &ifsta->work);
2844} 3000}
2845 3001
2846
2847void ieee80211_sta_work(struct work_struct *work) 3002void ieee80211_sta_work(struct work_struct *work)
2848{ 3003{
2849 struct ieee80211_sub_if_data *sdata = 3004 struct ieee80211_sub_if_data *sdata =
@@ -2860,7 +3015,8 @@ void ieee80211_sta_work(struct work_struct *work)
2860 return; 3015 return;
2861 3016
2862 if (sdata->vif.type != IEEE80211_IF_TYPE_STA && 3017 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2863 sdata->vif.type != IEEE80211_IF_TYPE_IBSS) { 3018 sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
3019 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) {
2864 printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface " 3020 printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
2865 "(type=%d)\n", dev->name, sdata->vif.type); 3021 "(type=%d)\n", dev->name, sdata->vif.type);
2866 return; 3022 return;
@@ -2870,6 +3026,12 @@ void ieee80211_sta_work(struct work_struct *work)
2870 while ((skb = skb_dequeue(&ifsta->skb_queue))) 3026 while ((skb = skb_dequeue(&ifsta->skb_queue)))
2871 ieee80211_sta_rx_queued_mgmt(dev, skb); 3027 ieee80211_sta_rx_queued_mgmt(dev, skb);
2872 3028
3029#ifdef CONFIG_MAC80211_MESH
3030 if (ifsta->preq_queue_len && time_after(jiffies, ifsta->last_preq +
3031 msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
3032 mesh_path_start_discovery(dev);
3033#endif
3034
2873 if (ifsta->state != IEEE80211_AUTHENTICATE && 3035 if (ifsta->state != IEEE80211_AUTHENTICATE &&
2874 ifsta->state != IEEE80211_ASSOCIATE && 3036 ifsta->state != IEEE80211_ASSOCIATE &&
2875 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { 3037 test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
@@ -2905,6 +3067,11 @@ void ieee80211_sta_work(struct work_struct *work)
2905 case IEEE80211_IBSS_JOINED: 3067 case IEEE80211_IBSS_JOINED:
2906 ieee80211_sta_merge_ibss(dev, ifsta); 3068 ieee80211_sta_merge_ibss(dev, ifsta);
2907 break; 3069 break;
3070#ifdef CONFIG_MAC80211_MESH
3071 case IEEE80211_MESH_UP:
3072 ieee80211_mesh_housekeeping(dev, ifsta);
3073 break;
3074#endif
2908 default: 3075 default:
2909 printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n", 3076 printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
2910 ifsta->state); 3077 ifsta->state);
@@ -3109,7 +3276,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
3109 sband = local->hw.wiphy->bands[bss->band]; 3276 sband = local->hw.wiphy->bands[bss->band];
3110 3277
3111 if (local->hw.conf.beacon_int == 0) 3278 if (local->hw.conf.beacon_int == 0)
3112 local->hw.conf.beacon_int = 100; 3279 local->hw.conf.beacon_int = 10000;
3113 bss->beacon_int = local->hw.conf.beacon_int; 3280 bss->beacon_int = local->hw.conf.beacon_int;
3114 bss->last_update = jiffies; 3281 bss->last_update = jiffies;
3115 bss->capability = WLAN_CAPABILITY_IBSS; 3282 bss->capability = WLAN_CAPABILITY_IBSS;
@@ -3398,6 +3565,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
3398 ieee80211_sta_timer((unsigned long)sdata); 3565 ieee80211_sta_timer((unsigned long)sdata);
3399 } 3566 }
3400 3567
3568 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
3569 ieee80211_sta_timer((unsigned long)sdata);
3570
3401 netif_wake_queue(sdata->dev); 3571 netif_wake_queue(sdata->dev);
3402 } 3572 }
3403 rcu_read_unlock(); 3573 rcu_read_unlock();
@@ -3640,15 +3810,27 @@ ieee80211_sta_scan_result(struct net_device *dev,
3640 3810
3641 memset(&iwe, 0, sizeof(iwe)); 3811 memset(&iwe, 0, sizeof(iwe));
3642 iwe.cmd = SIOCGIWESSID; 3812 iwe.cmd = SIOCGIWESSID;
3643 iwe.u.data.length = bss->ssid_len; 3813 if (bss->mesh_cfg) {
3644 iwe.u.data.flags = 1; 3814#ifdef CONFIG_MAC80211_MESH
3645 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, 3815 iwe.u.data.length = bss->mesh_id_len;
3646 bss->ssid); 3816 iwe.u.data.flags = 1;
3817 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
3818 bss->mesh_id);
3819#endif
3820 } else {
3821 iwe.u.data.length = bss->ssid_len;
3822 iwe.u.data.flags = 1;
3823 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
3824 bss->ssid);
3825 }
3647 3826
3648 if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { 3827 if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS
3828 || bss->mesh_cfg)) {
3649 memset(&iwe, 0, sizeof(iwe)); 3829 memset(&iwe, 0, sizeof(iwe));
3650 iwe.cmd = SIOCGIWMODE; 3830 iwe.cmd = SIOCGIWMODE;
3651 if (bss->capability & WLAN_CAPABILITY_ESS) 3831 if (bss->mesh_cfg)
3832 iwe.u.mode = IW_MODE_MESH;
3833 else if (bss->capability & WLAN_CAPABILITY_ESS)
3652 iwe.u.mode = IW_MODE_MASTER; 3834 iwe.u.mode = IW_MODE_MASTER;
3653 else 3835 else
3654 iwe.u.mode = IW_MODE_ADHOC; 3836 iwe.u.mode = IW_MODE_ADHOC;
@@ -3737,6 +3919,28 @@ ieee80211_sta_scan_result(struct net_device *dev,
3737 } 3919 }
3738 } 3920 }
3739 3921
3922 if (bss->mesh_cfg) {
3923 char *buf;
3924 u8 *cfg = bss->mesh_cfg;
3925 buf = kmalloc(200, GFP_ATOMIC);
3926 if (buf) {
3927 memset(&iwe, 0, sizeof(iwe));
3928 iwe.cmd = IWEVCUSTOM;
3929 sprintf(buf, "Mesh network (version %d)\n"
3930 "\t\t\tPath Selection Protocol ID: 0x%02X%02X%02X%02X\n"
3931 "\t\t\tPath Selection Metric ID: 0x%02X%02X%02X%02X\n"
3932 "\t\t\tCongestion Control Mode ID: 0x%02X%02X%02X%02X\n"
3933 "\t\t\tChannel Precedence: 0x%02X%02X%02X%02X",
3934 cfg[0], cfg[1], cfg[2], cfg[3], cfg[4], cfg[5], cfg[6],
3935 cfg[7], cfg[8], cfg[9], cfg[10], cfg[11], cfg[12],
3936 cfg[13], cfg[14], cfg[15], cfg[16]);
3937 iwe.u.data.length = strlen(buf);
3938 current_ev = iwe_stream_add_point(current_ev, end_buf,
3939 &iwe, buf);
3940 kfree(buf);
3941 }
3942 }
3943
3740 return current_ev; 3944 return current_ev;
3741} 3945}
3742 3946