aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-18 13:55:32 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-18 13:55:32 -0500
commitdfef948ed2ba69cf041840b5e860d6b4e16fa0b1 (patch)
treeeab385cabe589346bcf19385c997ab8dabaef7bd /net
parentea31ba359c55e0734ff895692185d4c50cf0c537 (diff)
parentc85e9d7739fc8d879c4293ea020760926d6f87cd (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Kconfig13
-rw-r--r--net/mac80211/cfg.c47
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ieee80211_i.h27
-rw-r--r--net/mac80211/iface.c4
-rw-r--r--net/mac80211/mesh.c143
-rw-r--r--net/mac80211/mesh.h28
-rw-r--r--net/mac80211/mesh_hwmp.c388
-rw-r--r--net/mac80211/mesh_pathtbl.c18
-rw-r--r--net/mac80211/mesh_plink.c56
-rw-r--r--net/mac80211/mlme.c1
-rw-r--r--net/mac80211/rx.c40
-rw-r--r--net/mac80211/sta_info.c3
-rw-r--r--net/mac80211/tx.c47
-rw-r--r--net/mac80211/util.c4
-rw-r--r--net/wireless/nl80211.c208
-rw-r--r--net/wireless/util.c4
17 files changed, 742 insertions, 291 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 4d5543af3123..a10d508b07e1 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -194,6 +194,19 @@ config MAC80211_VERBOSE_MPL_DEBUG
194 194
195 Do not select this option. 195 Do not select this option.
196 196
197config MAC80211_VERBOSE_MHWMP_DEBUG
198 bool "Verbose mesh HWMP routing debugging"
199 depends on MAC80211_DEBUG_MENU
200 depends on MAC80211_MESH
201 ---help---
202 Selecting this option causes mac80211 to print out very
203 verbose mesh routing (HWMP) debugging messages (when mac80211
204 is taking part in a mesh network).
205 It should not be selected on production systems as those
206 messages are remotely triggerable.
207
208 Do not select this option.
209
197config MAC80211_DEBUG_COUNTERS 210config MAC80211_DEBUG_COUNTERS
198 bool "Extra statistics for TX/RX debugging" 211 bool "Extra statistics for TX/RX debugging"
199 depends on MAC80211_DEBUG_MENU 212 depends on MAC80211_DEBUG_MENU
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 56319b51d170..7f18c8fa1880 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -36,6 +36,24 @@ static bool nl80211_type_check(enum nl80211_iftype type)
36 } 36 }
37} 37}
38 38
39static bool nl80211_params_check(enum nl80211_iftype type,
40 struct vif_params *params)
41{
42 if (!nl80211_type_check(type))
43 return false;
44
45 if (params->use_4addr > 0) {
46 switch(type) {
47 case NL80211_IFTYPE_AP_VLAN:
48 case NL80211_IFTYPE_STATION:
49 break;
50 default:
51 return false;
52 }
53 }
54 return true;
55}
56
39static int ieee80211_add_iface(struct wiphy *wiphy, char *name, 57static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
40 enum nl80211_iftype type, u32 *flags, 58 enum nl80211_iftype type, u32 *flags,
41 struct vif_params *params) 59 struct vif_params *params)
@@ -45,7 +63,7 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
45 struct ieee80211_sub_if_data *sdata; 63 struct ieee80211_sub_if_data *sdata;
46 int err; 64 int err;
47 65
48 if (!nl80211_type_check(type)) 66 if (!nl80211_params_check(type, params))
49 return -EINVAL; 67 return -EINVAL;
50 68
51 err = ieee80211_if_add(local, name, &dev, type, params); 69 err = ieee80211_if_add(local, name, &dev, type, params);
@@ -75,7 +93,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
75 if (netif_running(dev)) 93 if (netif_running(dev))
76 return -EBUSY; 94 return -EBUSY;
77 95
78 if (!nl80211_type_check(type)) 96 if (!nl80211_params_check(type, params))
79 return -EINVAL; 97 return -EINVAL;
80 98
81 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 99 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -89,6 +107,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
89 params->mesh_id_len, 107 params->mesh_id_len,
90 params->mesh_id); 108 params->mesh_id);
91 109
110 if (params->use_4addr >= 0)
111 sdata->use_4addr = !!params->use_4addr;
112
92 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) 113 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
93 return 0; 114 return 0;
94 115
@@ -806,6 +827,13 @@ static int ieee80211_change_station(struct wiphy *wiphy,
806 return -EINVAL; 827 return -EINVAL;
807 } 828 }
808 829
830 if (vlansdata->use_4addr) {
831 if (vlansdata->u.vlan.sta)
832 return -EBUSY;
833
834 rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
835 }
836
809 sta->sdata = vlansdata; 837 sta->sdata = vlansdata;
810 ieee80211_send_layer2_update(sta); 838 ieee80211_send_layer2_update(sta);
811 } 839 }
@@ -907,7 +935,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
907 pinfo->generation = mesh_paths_generation; 935 pinfo->generation = mesh_paths_generation;
908 936
909 pinfo->filled = MPATH_INFO_FRAME_QLEN | 937 pinfo->filled = MPATH_INFO_FRAME_QLEN |
910 MPATH_INFO_DSN | 938 MPATH_INFO_SN |
911 MPATH_INFO_METRIC | 939 MPATH_INFO_METRIC |
912 MPATH_INFO_EXPTIME | 940 MPATH_INFO_EXPTIME |
913 MPATH_INFO_DISCOVERY_TIMEOUT | 941 MPATH_INFO_DISCOVERY_TIMEOUT |
@@ -915,7 +943,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
915 MPATH_INFO_FLAGS; 943 MPATH_INFO_FLAGS;
916 944
917 pinfo->frame_qlen = mpath->frame_queue.qlen; 945 pinfo->frame_qlen = mpath->frame_queue.qlen;
918 pinfo->dsn = mpath->dsn; 946 pinfo->sn = mpath->sn;
919 pinfo->metric = mpath->metric; 947 pinfo->metric = mpath->metric;
920 if (time_before(jiffies, mpath->exp_time)) 948 if (time_before(jiffies, mpath->exp_time))
921 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies); 949 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
@@ -927,8 +955,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
927 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; 955 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
928 if (mpath->flags & MESH_PATH_RESOLVING) 956 if (mpath->flags & MESH_PATH_RESOLVING)
929 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; 957 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
930 if (mpath->flags & MESH_PATH_DSN_VALID) 958 if (mpath->flags & MESH_PATH_SN_VALID)
931 pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID; 959 pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
932 if (mpath->flags & MESH_PATH_FIXED) 960 if (mpath->flags & MESH_PATH_FIXED)
933 pinfo->flags |= NL80211_MPATH_FLAG_FIXED; 961 pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
934 if (mpath->flags & MESH_PATH_RESOLVING) 962 if (mpath->flags & MESH_PATH_RESOLVING)
@@ -1001,7 +1029,10 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1001{ 1029{
1002 struct mesh_config *conf; 1030 struct mesh_config *conf;
1003 struct ieee80211_sub_if_data *sdata; 1031 struct ieee80211_sub_if_data *sdata;
1032 struct ieee80211_if_mesh *ifmsh;
1033
1004 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1034 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1035 ifmsh = &sdata->u.mesh;
1005 1036
1006 /* Set the config options which we are interested in setting */ 1037 /* Set the config options which we are interested in setting */
1007 conf = &(sdata->u.mesh.mshcfg); 1038 conf = &(sdata->u.mesh.mshcfg);
@@ -1036,6 +1067,10 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1036 mask)) 1067 mask))
1037 conf->dot11MeshHWMPnetDiameterTraversalTime = 1068 conf->dot11MeshHWMPnetDiameterTraversalTime =
1038 nconf->dot11MeshHWMPnetDiameterTraversalTime; 1069 nconf->dot11MeshHWMPnetDiameterTraversalTime;
1070 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask)) {
1071 conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
1072 ieee80211_mesh_root_setup(ifmsh);
1073 }
1039 return 0; 1074 return 0;
1040} 1075}
1041 1076
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 8782264f49e7..472b2039906c 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -149,6 +149,8 @@ IEEE80211_IF_FILE(path_refresh_time,
149 u.mesh.mshcfg.path_refresh_time, DEC); 149 u.mesh.mshcfg.path_refresh_time, DEC);
150IEEE80211_IF_FILE(min_discovery_timeout, 150IEEE80211_IF_FILE(min_discovery_timeout,
151 u.mesh.mshcfg.min_discovery_timeout, DEC); 151 u.mesh.mshcfg.min_discovery_timeout, DEC);
152IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
153 u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
152#endif 154#endif
153 155
154 156
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1ef767366b77..b63b99fb2fd3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -208,6 +208,9 @@ struct ieee80211_if_wds {
208 208
209struct ieee80211_if_vlan { 209struct ieee80211_if_vlan {
210 struct list_head list; 210 struct list_head list;
211
212 /* used for all tx if the VLAN is configured to 4-addr mode */
213 struct sta_info *sta;
211}; 214};
212 215
213struct mesh_stats { 216struct mesh_stats {
@@ -352,6 +355,7 @@ struct ieee80211_if_mesh {
352 struct work_struct work; 355 struct work_struct work;
353 struct timer_list housekeeping_timer; 356 struct timer_list housekeeping_timer;
354 struct timer_list mesh_path_timer; 357 struct timer_list mesh_path_timer;
358 struct timer_list mesh_path_root_timer;
355 struct sk_buff_head skb_queue; 359 struct sk_buff_head skb_queue;
356 360
357 unsigned long timers_running; 361 unsigned long timers_running;
@@ -361,23 +365,23 @@ struct ieee80211_if_mesh {
361 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; 365 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
362 size_t mesh_id_len; 366 size_t mesh_id_len;
363 /* Active Path Selection Protocol Identifier */ 367 /* Active Path Selection Protocol Identifier */
364 u8 mesh_pp_id[4]; 368 u8 mesh_pp_id;
365 /* Active Path Selection Metric Identifier */ 369 /* Active Path Selection Metric Identifier */
366 u8 mesh_pm_id[4]; 370 u8 mesh_pm_id;
367 /* Congestion Control Mode Identifier */ 371 /* Congestion Control Mode Identifier */
368 u8 mesh_cc_id[4]; 372 u8 mesh_cc_id;
369 /* Synchronization Protocol Identifier */ 373 /* Synchronization Protocol Identifier */
370 u8 mesh_sp_id[4]; 374 u8 mesh_sp_id;
371 /* Authentication Protocol Identifier */ 375 /* Authentication Protocol Identifier */
372 u8 mesh_auth_id[4]; 376 u8 mesh_auth_id;
373 /* Local mesh Destination Sequence Number */ 377 /* Local mesh Sequence Number */
374 u32 dsn; 378 u32 sn;
375 /* Last used PREQ ID */ 379 /* Last used PREQ ID */
376 u32 preq_id; 380 u32 preq_id;
377 atomic_t mpaths; 381 atomic_t mpaths;
378 /* Timestamp of last DSN update */ 382 /* Timestamp of last SN update */
379 unsigned long last_dsn_update; 383 unsigned long last_sn_update;
380 /* Timestamp of last DSN sent */ 384 /* Timestamp of last SN sent */
381 unsigned long last_preq; 385 unsigned long last_preq;
382 struct mesh_rmc *rmc; 386 struct mesh_rmc *rmc;
383 spinlock_t mesh_preq_queue_lock; 387 spinlock_t mesh_preq_queue_lock;
@@ -457,6 +461,8 @@ struct ieee80211_sub_if_data {
457 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ 461 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
458 int max_ratectrl_rateidx; /* max TX rateidx for rate control */ 462 int max_ratectrl_rateidx; /* max TX rateidx for rate control */
459 463
464 bool use_4addr; /* use 4-address frames */
465
460 union { 466 union {
461 struct ieee80211_if_ap ap; 467 struct ieee80211_if_ap ap;
462 struct ieee80211_if_wds wds; 468 struct ieee80211_if_wds wds;
@@ -799,6 +805,7 @@ struct ieee802_11_elems {
799 u8 *preq; 805 u8 *preq;
800 u8 *prep; 806 u8 *prep;
801 u8 *perr; 807 u8 *perr;
808 struct ieee80211_rann_ie *rann;
802 u8 *ch_switch_elem; 809 u8 *ch_switch_elem;
803 u8 *country_elem; 810 u8 *country_elem;
804 u8 *pwr_constr_elem; 811 u8 *pwr_constr_elem;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8495161b99b8..1f02b0610e82 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -752,6 +752,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
752 ieee80211_mandatory_rates(sdata->local, 752 ieee80211_mandatory_rates(sdata->local,
753 sdata->local->hw.conf.channel->band); 753 sdata->local->hw.conf.channel->band);
754 sdata->drop_unencrypted = 0; 754 sdata->drop_unencrypted = 0;
755 sdata->use_4addr = 0;
755 756
756 return 0; 757 return 0;
757} 758}
@@ -819,6 +820,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
819 params->mesh_id_len, 820 params->mesh_id_len,
820 params->mesh_id); 821 params->mesh_id);
821 822
823 if (params && params->use_4addr >= 0)
824 sdata->use_4addr = !!params->use_4addr;
825
822 mutex_lock(&local->iflist_mtx); 826 mutex_lock(&local->iflist_mtx);
823 list_add_tail_rcu(&sdata->list, &local->interfaces); 827 list_add_tail_rcu(&sdata->list, &local->interfaces);
824 mutex_unlock(&local->iflist_mtx); 828 mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9a733890eb47..bbd56b087899 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 open80211s Ltd. 2 * Copyright (c) 2008, 2009 open80211s Ltd.
3 * Authors: Luis Carlos Cobo <luisca@cozybit.com> 3 * Authors: Luis Carlos Cobo <luisca@cozybit.com>
4 * Javier Cardona <javier@cozybit.com> 4 * Javier Cardona <javier@cozybit.com>
5 * 5 *
@@ -14,18 +14,20 @@
14 14
15#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) 15#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
16#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) 16#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
17#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)
17 18
18#define PP_OFFSET 1 /* Path Selection Protocol */ 19#define MESHCONF_PP_OFFSET 0 /* Path Selection Protocol */
19#define PM_OFFSET 5 /* Path Selection Metric */ 20#define MESHCONF_PM_OFFSET 1 /* Path Selection Metric */
20#define CC_OFFSET 9 /* Congestion Control Mode */ 21#define MESHCONF_CC_OFFSET 2 /* Congestion Control Mode */
21#define SP_OFFSET 13 /* Synchronization Protocol */ 22#define MESHCONF_SP_OFFSET 3 /* Synchronization Protocol */
22#define AUTH_OFFSET 17 /* Authentication Protocol */ 23#define MESHCONF_AUTH_OFFSET 4 /* Authentication Protocol */
23#define CAPAB_OFFSET 22 24#define MESHCONF_CAPAB_OFFSET 6
24#define CAPAB_ACCEPT_PLINKS 0x80 25#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01
25#define CAPAB_FORWARDING 0x10 26#define MESHCONF_CAPAB_FORWARDING 0x08
26 27
27#define TMR_RUNNING_HK 0 28#define TMR_RUNNING_HK 0
28#define TMR_RUNNING_MP 1 29#define TMR_RUNNING_MP 1
30#define TMR_RUNNING_MPR 2
29 31
30int mesh_allocated; 32int mesh_allocated;
31static struct kmem_cache *rm_cache; 33static struct kmem_cache *rm_cache;
@@ -85,11 +87,12 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
85 */ 87 */
86 if (ifmsh->mesh_id_len == ie->mesh_id_len && 88 if (ifmsh->mesh_id_len == ie->mesh_id_len &&
87 memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && 89 memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
88 memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && 90 (ifmsh->mesh_pp_id == *(ie->mesh_config + MESHCONF_PP_OFFSET))&&
89 memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && 91 (ifmsh->mesh_pm_id == *(ie->mesh_config + MESHCONF_PM_OFFSET))&&
90 memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0 && 92 (ifmsh->mesh_cc_id == *(ie->mesh_config + MESHCONF_CC_OFFSET))&&
91 memcmp(ifmsh->mesh_sp_id, ie->mesh_config + SP_OFFSET, 4) == 0 && 93 (ifmsh->mesh_sp_id == *(ie->mesh_config + MESHCONF_SP_OFFSET))&&
92 memcmp(ifmsh->mesh_auth_id, ie->mesh_config + AUTH_OFFSET, 4) == 0) 94 (ifmsh->mesh_auth_id == *(ie->mesh_config +
95 MESHCONF_AUTH_OFFSET)))
93 return true; 96 return true;
94 97
95 return false; 98 return false;
@@ -102,7 +105,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
102 */ 105 */
103bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) 106bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie)
104{ 107{
105 return (*(ie->mesh_config + CAPAB_OFFSET) & CAPAB_ACCEPT_PLINKS) != 0; 108 return (*(ie->mesh_config + MESHCONF_CAPAB_OFFSET) &
109 MESHCONF_CAPAB_ACCEPT_PLINKS) != 0;
106} 110}
107 111
108/** 112/**
@@ -128,18 +132,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
128 132
129void mesh_ids_set_default(struct ieee80211_if_mesh *sta) 133void mesh_ids_set_default(struct ieee80211_if_mesh *sta)
130{ 134{
131 u8 oui[3] = {0x00, 0x0F, 0xAC}; 135 sta->mesh_pp_id = 0; /* HWMP */
132 136 sta->mesh_pm_id = 0; /* Airtime */
133 memcpy(sta->mesh_pp_id, oui, sizeof(oui)); 137 sta->mesh_cc_id = 0; /* Disabled */
134 memcpy(sta->mesh_pm_id, oui, sizeof(oui)); 138 sta->mesh_sp_id = 0; /* Neighbor Offset */
135 memcpy(sta->mesh_cc_id, oui, sizeof(oui)); 139 sta->mesh_auth_id = 0; /* Disabled */
136 memcpy(sta->mesh_sp_id, oui, sizeof(oui));
137 memcpy(sta->mesh_auth_id, oui, sizeof(oui));
138 sta->mesh_pp_id[sizeof(oui)] = 0;
139 sta->mesh_pm_id[sizeof(oui)] = 0;
140 sta->mesh_cc_id[sizeof(oui)] = 0xff;
141 sta->mesh_sp_id[sizeof(oui)] = 0xff;
142 sta->mesh_auth_id[sizeof(oui)] = 0x0;
143} 140}
144 141
145int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) 142int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
@@ -228,6 +225,7 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
228 struct ieee80211_supported_band *sband; 225 struct ieee80211_supported_band *sband;
229 u8 *pos; 226 u8 *pos;
230 int len, i, rate; 227 int len, i, rate;
228 u8 neighbors;
231 229
232 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 230 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
233 len = sband->n_bitrates; 231 len = sband->n_bitrates;
@@ -251,6 +249,13 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
251 } 249 }
252 } 250 }
253 251
252 if (sband->band == IEEE80211_BAND_2GHZ) {
253 pos = skb_put(skb, 2 + 1);
254 *pos++ = WLAN_EID_DS_PARAMS;
255 *pos++ = 1;
256 *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq);
257 }
258
254 pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); 259 pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len);
255 *pos++ = WLAN_EID_MESH_ID; 260 *pos++ = WLAN_EID_MESH_ID;
256 *pos++ = sdata->u.mesh.mesh_id_len; 261 *pos++ = sdata->u.mesh.mesh_id_len;
@@ -260,37 +265,33 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
260 pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN); 265 pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN);
261 *pos++ = WLAN_EID_MESH_CONFIG; 266 *pos++ = WLAN_EID_MESH_CONFIG;
262 *pos++ = IEEE80211_MESH_CONFIG_LEN; 267 *pos++ = IEEE80211_MESH_CONFIG_LEN;
263 /* Version */
264 *pos++ = 1;
265 268
266 /* Active path selection protocol ID */ 269 /* Active path selection protocol ID */
267 memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); 270 *pos++ = sdata->u.mesh.mesh_pp_id;
268 pos += 4;
269 271
270 /* Active path selection metric ID */ 272 /* Active path selection metric ID */
271 memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); 273 *pos++ = sdata->u.mesh.mesh_pm_id;
272 pos += 4;
273 274
274 /* Congestion control mode identifier */ 275 /* Congestion control mode identifier */
275 memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); 276 *pos++ = sdata->u.mesh.mesh_cc_id;
276 pos += 4;
277 277
278 /* Synchronization protocol identifier */ 278 /* Synchronization protocol identifier */
279 memcpy(pos, sdata->u.mesh.mesh_sp_id, 4); 279 *pos++ = sdata->u.mesh.mesh_sp_id;
280 pos += 4;
281 280
282 /* Authentication Protocol identifier */ 281 /* Authentication Protocol identifier */
283 memcpy(pos, sdata->u.mesh.mesh_auth_id, 4); 282 *pos++ = sdata->u.mesh.mesh_auth_id;
284 pos += 4;
285 283
286 /* Mesh Formation Info */ 284 /* Mesh Formation Info - number of neighbors */
287 memset(pos, 0x00, 1); 285 neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
288 pos += 1; 286 /* Number of neighbor mesh STAs or 15 whichever is smaller */
287 neighbors = (neighbors > 15) ? 15 : neighbors;
288 *pos++ = neighbors << 1;
289 289
290 /* Mesh capability */ 290 /* Mesh capability */
291 sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); 291 sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata);
292 *pos = CAPAB_FORWARDING; 292 *pos = MESHCONF_CAPAB_FORWARDING;
293 *pos++ |= sdata->u.mesh.accepting_plinks ? CAPAB_ACCEPT_PLINKS : 0x00; 293 *pos++ |= sdata->u.mesh.accepting_plinks ?
294 MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
294 *pos++ = 0x00; 295 *pos++ = 0x00;
295 296
296 return; 297 return;
@@ -355,6 +356,34 @@ static void ieee80211_mesh_path_timer(unsigned long data)
355 ieee80211_queue_work(&local->hw, &ifmsh->work); 356 ieee80211_queue_work(&local->hw, &ifmsh->work);
356} 357}
357 358
359static void ieee80211_mesh_path_root_timer(unsigned long data)
360{
361 struct ieee80211_sub_if_data *sdata =
362 (struct ieee80211_sub_if_data *) data;
363 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
364 struct ieee80211_local *local = sdata->local;
365
366 set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
367
368 if (local->quiescing) {
369 set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
370 return;
371 }
372
373 ieee80211_queue_work(&local->hw, &ifmsh->work);
374}
375
376void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
377{
378 if (ifmsh->mshcfg.dot11MeshHWMPRootMode)
379 set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
380 else {
381 clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
382 /* stop running timer */
383 del_timer_sync(&ifmsh->mesh_path_root_timer);
384 }
385}
386
358/** 387/**
359 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame 388 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
360 * @hdr: 802.11 frame header 389 * @hdr: 802.11 frame header
@@ -448,6 +477,15 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
448 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); 477 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
449} 478}
450 479
480static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
481{
482 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
483
484 mesh_path_tx_root_frame(sdata);
485 mod_timer(&ifmsh->mesh_path_root_timer,
486 round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL));
487}
488
451#ifdef CONFIG_PM 489#ifdef CONFIG_PM
452void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) 490void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
453{ 491{
@@ -462,6 +500,8 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
462 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); 500 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
463 if (del_timer_sync(&ifmsh->mesh_path_timer)) 501 if (del_timer_sync(&ifmsh->mesh_path_timer))
464 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); 502 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
503 if (del_timer_sync(&ifmsh->mesh_path_root_timer))
504 set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
465} 505}
466 506
467void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) 507void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
@@ -472,6 +512,9 @@ void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
472 add_timer(&ifmsh->housekeeping_timer); 512 add_timer(&ifmsh->housekeeping_timer);
473 if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) 513 if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
474 add_timer(&ifmsh->mesh_path_timer); 514 add_timer(&ifmsh->mesh_path_timer);
515 if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running))
516 add_timer(&ifmsh->mesh_path_root_timer);
517 ieee80211_mesh_root_setup(ifmsh);
475} 518}
476#endif 519#endif
477 520
@@ -481,6 +524,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
481 struct ieee80211_local *local = sdata->local; 524 struct ieee80211_local *local = sdata->local;
482 525
483 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); 526 set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
527 ieee80211_mesh_root_setup(ifmsh);
484 ieee80211_queue_work(&local->hw, &ifmsh->work); 528 ieee80211_queue_work(&local->hw, &ifmsh->work);
485 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; 529 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
486 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 530 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
@@ -491,6 +535,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
491void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 535void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
492{ 536{
493 del_timer_sync(&sdata->u.mesh.housekeeping_timer); 537 del_timer_sync(&sdata->u.mesh.housekeeping_timer);
538 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
494 /* 539 /*
495 * If the timer fired while we waited for it, it will have 540 * If the timer fired while we waited for it, it will have
496 * requeued the work. Now the work will be running again 541 * requeued the work. Now the work will be running again
@@ -561,7 +606,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
561 struct ieee80211_rx_status *rx_status) 606 struct ieee80211_rx_status *rx_status)
562{ 607{
563 switch (mgmt->u.action.category) { 608 switch (mgmt->u.action.category) {
564 case PLINK_CATEGORY: 609 case MESH_PLINK_CATEGORY:
565 mesh_rx_plink_frame(sdata, mgmt, len, rx_status); 610 mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
566 break; 611 break;
567 case MESH_PATH_SEL_CATEGORY: 612 case MESH_PATH_SEL_CATEGORY:
@@ -628,6 +673,9 @@ static void ieee80211_mesh_work(struct work_struct *work)
628 673
629 if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) 674 if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
630 ieee80211_mesh_housekeeping(sdata, ifmsh); 675 ieee80211_mesh_housekeeping(sdata, ifmsh);
676
677 if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
678 ieee80211_mesh_rootpath(sdata);
631} 679}
632 680
633void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) 681void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
@@ -673,7 +721,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
673 MESH_MIN_DISCOVERY_TIMEOUT; 721 MESH_MIN_DISCOVERY_TIMEOUT;
674 ifmsh->accepting_plinks = true; 722 ifmsh->accepting_plinks = true;
675 ifmsh->preq_id = 0; 723 ifmsh->preq_id = 0;
676 ifmsh->dsn = 0; 724 ifmsh->sn = 0;
677 atomic_set(&ifmsh->mpaths, 0); 725 atomic_set(&ifmsh->mpaths, 0);
678 mesh_rmc_init(sdata); 726 mesh_rmc_init(sdata);
679 ifmsh->last_preq = jiffies; 727 ifmsh->last_preq = jiffies;
@@ -684,6 +732,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
684 setup_timer(&ifmsh->mesh_path_timer, 732 setup_timer(&ifmsh->mesh_path_timer,
685 ieee80211_mesh_path_timer, 733 ieee80211_mesh_path_timer,
686 (unsigned long) sdata); 734 (unsigned long) sdata);
735 setup_timer(&ifmsh->mesh_path_root_timer,
736 ieee80211_mesh_path_root_timer,
737 (unsigned long) sdata);
687 INIT_LIST_HEAD(&ifmsh->preq_queue.list); 738 INIT_LIST_HEAD(&ifmsh->preq_queue.list);
688 spin_lock_init(&ifmsh->mesh_preq_queue_lock); 739 spin_lock_init(&ifmsh->mesh_preq_queue_lock);
689} 740}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index dd1c19319f0a..bd0e1cbb9a1e 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 open80211s Ltd. 2 * Copyright (c) 2008, 2009 open80211s Ltd.
3 * Authors: Luis Carlos Cobo <luisca@cozybit.com> 3 * Authors: Luis Carlos Cobo <luisca@cozybit.com>
4 * Javier Cardona <javier@cozybit.com> 4 * Javier Cardona <javier@cozybit.com>
5 * 5 *
@@ -26,7 +26,7 @@
26 * 26 *
27 * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding 27 * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding
28 * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path 28 * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path
29 * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence 29 * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence
30 * number 30 * number
31 * @MESH_PATH_FIXED: the mesh path has been manually set and should not be 31 * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
32 * modified 32 * modified
@@ -38,7 +38,7 @@
38enum mesh_path_flags { 38enum mesh_path_flags {
39 MESH_PATH_ACTIVE = BIT(0), 39 MESH_PATH_ACTIVE = BIT(0),
40 MESH_PATH_RESOLVING = BIT(1), 40 MESH_PATH_RESOLVING = BIT(1),
41 MESH_PATH_DSN_VALID = BIT(2), 41 MESH_PATH_SN_VALID = BIT(2),
42 MESH_PATH_FIXED = BIT(3), 42 MESH_PATH_FIXED = BIT(3),
43 MESH_PATH_RESOLVED = BIT(4), 43 MESH_PATH_RESOLVED = BIT(4),
44}; 44};
@@ -53,11 +53,13 @@ enum mesh_path_flags {
53 * to grow. 53 * to grow.
54 * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to 54 * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
55 * grow 55 * grow
56 * @MESH_WORK_ROOT: the mesh root station needs to send a frame
56 */ 57 */
57enum mesh_deferred_task_flags { 58enum mesh_deferred_task_flags {
58 MESH_WORK_HOUSEKEEPING, 59 MESH_WORK_HOUSEKEEPING,
59 MESH_WORK_GROW_MPATH_TABLE, 60 MESH_WORK_GROW_MPATH_TABLE,
60 MESH_WORK_GROW_MPP_TABLE, 61 MESH_WORK_GROW_MPP_TABLE,
62 MESH_WORK_ROOT,
61}; 63};
62 64
63/** 65/**
@@ -70,7 +72,7 @@ enum mesh_deferred_task_flags {
70 * @timer: mesh path discovery timer 72 * @timer: mesh path discovery timer
71 * @frame_queue: pending queue for frames sent to this destination while the 73 * @frame_queue: pending queue for frames sent to this destination while the
72 * path is unresolved 74 * path is unresolved
73 * @dsn: destination sequence number of the destination 75 * @sn: target sequence number
74 * @metric: current metric to this destination 76 * @metric: current metric to this destination
75 * @hop_count: hops to destination 77 * @hop_count: hops to destination
76 * @exp_time: in jiffies, when the path will expire or when it expired 78 * @exp_time: in jiffies, when the path will expire or when it expired
@@ -94,7 +96,7 @@ struct mesh_path {
94 struct timer_list timer; 96 struct timer_list timer;
95 struct sk_buff_head frame_queue; 97 struct sk_buff_head frame_queue;
96 struct rcu_head rcu; 98 struct rcu_head rcu;
97 u32 dsn; 99 u32 sn;
98 u32 metric; 100 u32 metric;
99 u8 hop_count; 101 u8 hop_count;
100 unsigned long exp_time; 102 unsigned long exp_time;
@@ -174,7 +176,7 @@ struct mesh_rmc {
174#define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) 176#define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2)
175 177
176/* Default values, timeouts in ms */ 178/* Default values, timeouts in ms */
177#define MESH_TTL 5 179#define MESH_TTL 31
178#define MESH_MAX_RETR 3 180#define MESH_MAX_RETR 3
179#define MESH_RET_T 100 181#define MESH_RET_T 100
180#define MESH_CONF_T 100 182#define MESH_CONF_T 100
@@ -206,8 +208,14 @@ struct mesh_rmc {
206#define MESH_MAX_MPATHS 1024 208#define MESH_MAX_MPATHS 1024
207 209
208/* Pending ANA approval */ 210/* Pending ANA approval */
209#define PLINK_CATEGORY 30 211#define MESH_PLINK_CATEGORY 30
210#define MESH_PATH_SEL_CATEGORY 32 212#define MESH_PATH_SEL_CATEGORY 32
213#define MESH_PATH_SEL_ACTION 0
214
215/* PERR reason codes */
216#define PEER_RCODE_UNSPECIFIED 11
217#define PERR_RCODE_NO_ROUTE 12
218#define PERR_RCODE_DEST_UNREACH 13
211 219
212/* Public interfaces */ 220/* Public interfaces */
213/* Various */ 221/* Various */
@@ -234,6 +242,7 @@ ieee80211_rx_result
234ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); 242ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
235void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); 243void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
236void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); 244void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
245void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
237 246
238/* Mesh paths */ 247/* Mesh paths */
239int mesh_nexthop_lookup(struct sk_buff *skb, 248int mesh_nexthop_lookup(struct sk_buff *skb,
@@ -274,8 +283,8 @@ void mesh_mpp_table_grow(void);
274u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, 283u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
275 struct mesh_table *tbl); 284 struct mesh_table *tbl);
276/* Mesh paths */ 285/* Mesh paths */
277int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, 286int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode,
278 struct ieee80211_sub_if_data *sdata); 287 u8 *ra, struct ieee80211_sub_if_data *sdata);
279void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); 288void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
280void mesh_path_flush_pending(struct mesh_path *mpath); 289void mesh_path_flush_pending(struct mesh_path *mpath);
281void mesh_path_tx_pending(struct mesh_path *mpath); 290void mesh_path_tx_pending(struct mesh_path *mpath);
@@ -288,6 +297,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
288 struct ieee80211_sub_if_data *sdata); 297 struct ieee80211_sub_if_data *sdata);
289void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); 298void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
290void mesh_path_restart(struct ieee80211_sub_if_data *sdata); 299void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
300void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
291 301
292extern int mesh_paths_generation; 302extern int mesh_paths_generation;
293 303
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 29b82e98effa..5c67e7b8790f 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 open80211s Ltd. 2 * Copyright (c) 2008, 2009 open80211s Ltd.
3 * Author: Luis Carlos Cobo <luisca@cozybit.com> 3 * Author: Luis Carlos Cobo <luisca@cozybit.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -9,6 +9,12 @@
9 9
10#include "mesh.h" 10#include "mesh.h"
11 11
12#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
13#define mhwmp_dbg(fmt, args...) printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args)
14#else
15#define mhwmp_dbg(fmt, args...) do { (void)(0); } while (0)
16#endif
17
12#define TEST_FRAME_LEN 8192 18#define TEST_FRAME_LEN 8192
13#define MAX_METRIC 0xffffffff 19#define MAX_METRIC 0xffffffff
14#define ARITH_SHIFT 8 20#define ARITH_SHIFT 8
@@ -21,6 +27,12 @@
21#define MP_F_DO 0x1 27#define MP_F_DO 0x1
22/* Reply and forward */ 28/* Reply and forward */
23#define MP_F_RF 0x2 29#define MP_F_RF 0x2
30/* Unknown Sequence Number */
31#define MP_F_USN 0x01
32/* Reason code Present */
33#define MP_F_RCODE 0x02
34
35static void mesh_queue_preq(struct mesh_path *, u8);
24 36
25static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) 37static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
26{ 38{
@@ -29,6 +41,13 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
29 return get_unaligned_le32(preq_elem + offset); 41 return get_unaligned_le32(preq_elem + offset);
30} 42}
31 43
44static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
45{
46 if (ae)
47 offset += 6;
48 return get_unaligned_le16(preq_elem + offset);
49}
50
32/* HWMP IE processing macros */ 51/* HWMP IE processing macros */
33#define AE_F (1<<6) 52#define AE_F (1<<6)
34#define AE_F_SET(x) (*x & AE_F) 53#define AE_F_SET(x) (*x & AE_F)
@@ -37,30 +56,33 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
37#define PREQ_IE_TTL(x) (*(x + 2)) 56#define PREQ_IE_TTL(x) (*(x + 2))
38#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0) 57#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0)
39#define PREQ_IE_ORIG_ADDR(x) (x + 7) 58#define PREQ_IE_ORIG_ADDR(x) (x + 7)
40#define PREQ_IE_ORIG_DSN(x) u32_field_get(x, 13, 0); 59#define PREQ_IE_ORIG_SN(x) u32_field_get(x, 13, 0);
41#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x)); 60#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x));
42#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x)); 61#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x));
43#define PREQ_IE_DST_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26)) 62#define PREQ_IE_TARGET_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26))
44#define PREQ_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27) 63#define PREQ_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27)
45#define PREQ_IE_DST_DSN(x) u32_field_get(x, 33, AE_F_SET(x)); 64#define PREQ_IE_TARGET_SN(x) u32_field_get(x, 33, AE_F_SET(x));
46 65
47 66
48#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) 67#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
49#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) 68#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
50#define PREP_IE_TTL(x) PREQ_IE_TTL(x) 69#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
51#define PREP_IE_ORIG_ADDR(x) (x + 3) 70#define PREP_IE_ORIG_ADDR(x) (x + 3)
52#define PREP_IE_ORIG_DSN(x) u32_field_get(x, 9, 0); 71#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0);
53#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)); 72#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x));
54#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)); 73#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x));
55#define PREP_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) 74#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
56#define PREP_IE_DST_DSN(x) u32_field_get(x, 27, AE_F_SET(x)); 75#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x));
57 76
58#define PERR_IE_DST_ADDR(x) (x + 2) 77#define PERR_IE_TTL(x) (*(x))
59#define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0); 78#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
79#define PERR_IE_TARGET_ADDR(x) (x + 3)
80#define PERR_IE_TARGET_SN(x) u32_field_get(x, 9, 0);
81#define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0);
60 82
61#define MSEC_TO_TU(x) (x*1000/1024) 83#define MSEC_TO_TU(x) (x*1000/1024)
62#define DSN_GT(x, y) ((long) (y) - (long) (x) < 0) 84#define SN_GT(x, y) ((long) (y) - (long) (x) < 0)
63#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) 85#define SN_LT(x, y) ((long) (x) - (long) (y) < 0)
64 86
65#define net_traversal_jiffies(s) \ 87#define net_traversal_jiffies(s) \
66 msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) 88 msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
@@ -75,13 +97,15 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
75enum mpath_frame_type { 97enum mpath_frame_type {
76 MPATH_PREQ = 0, 98 MPATH_PREQ = 0,
77 MPATH_PREP, 99 MPATH_PREP,
78 MPATH_PERR 100 MPATH_PERR,
101 MPATH_RANN
79}; 102};
80 103
81static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, 104static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
82 u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, 105 u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target,
83 __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, 106 __le32 target_sn, u8 *da, u8 hop_count, u8 ttl,__le32 lifetime,
84 __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) 107 __le32 metric, __le32 preq_id,
108 struct ieee80211_sub_if_data *sdata)
85{ 109{
86 struct ieee80211_local *local = sdata->local; 110 struct ieee80211_local *local = sdata->local;
87 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); 111 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
@@ -103,21 +127,30 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
103 127
104 memcpy(mgmt->da, da, ETH_ALEN); 128 memcpy(mgmt->da, da, ETH_ALEN);
105 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 129 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
106 /* BSSID is left zeroed, wildcard value */ 130 /* BSSID == SA */
131 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
107 mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; 132 mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
108 mgmt->u.action.u.mesh_action.action_code = action; 133 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
109 134
110 switch (action) { 135 switch (action) {
111 case MPATH_PREQ: 136 case MPATH_PREQ:
137 mhwmp_dbg("sending PREQ to %pM\n", target);
112 ie_len = 37; 138 ie_len = 37;
113 pos = skb_put(skb, 2 + ie_len); 139 pos = skb_put(skb, 2 + ie_len);
114 *pos++ = WLAN_EID_PREQ; 140 *pos++ = WLAN_EID_PREQ;
115 break; 141 break;
116 case MPATH_PREP: 142 case MPATH_PREP:
143 mhwmp_dbg("sending PREP to %pM\n", target);
117 ie_len = 31; 144 ie_len = 31;
118 pos = skb_put(skb, 2 + ie_len); 145 pos = skb_put(skb, 2 + ie_len);
119 *pos++ = WLAN_EID_PREP; 146 *pos++ = WLAN_EID_PREP;
120 break; 147 break;
148 case MPATH_RANN:
149 mhwmp_dbg("sending RANN from %pM\n", orig_addr);
150 ie_len = sizeof(struct ieee80211_rann_ie);
151 pos = skb_put(skb, 2 + ie_len);
152 *pos++ = WLAN_EID_RANN;
153 break;
121 default: 154 default:
122 kfree_skb(skb); 155 kfree_skb(skb);
123 return -ENOTSUPP; 156 return -ENOTSUPP;
@@ -133,20 +166,24 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
133 } 166 }
134 memcpy(pos, orig_addr, ETH_ALEN); 167 memcpy(pos, orig_addr, ETH_ALEN);
135 pos += ETH_ALEN; 168 pos += ETH_ALEN;
136 memcpy(pos, &orig_dsn, 4); 169 memcpy(pos, &orig_sn, 4);
137 pos += 4;
138 memcpy(pos, &lifetime, 4);
139 pos += 4; 170 pos += 4;
171 if (action != MPATH_RANN) {
172 memcpy(pos, &lifetime, 4);
173 pos += 4;
174 }
140 memcpy(pos, &metric, 4); 175 memcpy(pos, &metric, 4);
141 pos += 4; 176 pos += 4;
142 if (action == MPATH_PREQ) { 177 if (action == MPATH_PREQ) {
143 /* destination count */ 178 /* destination count */
144 *pos++ = 1; 179 *pos++ = 1;
145 *pos++ = dst_flags; 180 *pos++ = target_flags;
181 }
182 if (action != MPATH_RANN) {
183 memcpy(pos, target, ETH_ALEN);
184 pos += ETH_ALEN;
185 memcpy(pos, &target_sn, 4);
146 } 186 }
147 memcpy(pos, dst, ETH_ALEN);
148 pos += ETH_ALEN;
149 memcpy(pos, &dst_dsn, 4);
150 187
151 ieee80211_tx_skb(sdata, skb, 1); 188 ieee80211_tx_skb(sdata, skb, 1);
152 return 0; 189 return 0;
@@ -155,11 +192,13 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
155/** 192/**
156 * mesh_send_path error - Sends a PERR mesh management frame 193 * mesh_send_path error - Sends a PERR mesh management frame
157 * 194 *
158 * @dst: broken destination 195 * @target: broken destination
159 * @dst_dsn: dsn of the broken destination 196 * @target_sn: SN of the broken destination
197 * @target_rcode: reason code for this PERR
160 * @ra: node this frame is addressed to 198 * @ra: node this frame is addressed to
161 */ 199 */
162int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, 200int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
201 __le16 target_rcode, u8 *ra,
163 struct ieee80211_sub_if_data *sdata) 202 struct ieee80211_sub_if_data *sdata)
164{ 203{
165 struct ieee80211_local *local = sdata->local; 204 struct ieee80211_local *local = sdata->local;
@@ -184,18 +223,30 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
184 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 223 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
185 /* BSSID is left zeroed, wildcard value */ 224 /* BSSID is left zeroed, wildcard value */
186 mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; 225 mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
187 mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; 226 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
188 ie_len = 12; 227 ie_len = 15;
189 pos = skb_put(skb, 2 + ie_len); 228 pos = skb_put(skb, 2 + ie_len);
190 *pos++ = WLAN_EID_PERR; 229 *pos++ = WLAN_EID_PERR;
191 *pos++ = ie_len; 230 *pos++ = ie_len;
192 /* mode flags, reserved */ 231 /* ttl */
193 *pos++ = 0; 232 *pos++ = MESH_TTL;
194 /* number of destinations */ 233 /* number of destinations */
195 *pos++ = 1; 234 *pos++ = 1;
196 memcpy(pos, dst, ETH_ALEN); 235 /*
236 * flags bit, bit 1 is unset if we know the sequence number and
237 * bit 2 is set if we have a reason code
238 */
239 *pos = 0;
240 if (!target_sn)
241 *pos |= MP_F_USN;
242 if (target_rcode)
243 *pos |= MP_F_RCODE;
244 pos++;
245 memcpy(pos, target, ETH_ALEN);
197 pos += ETH_ALEN; 246 pos += ETH_ALEN;
198 memcpy(pos, &dst_dsn, 4); 247 memcpy(pos, &target_sn, 4);
248 pos += 4;
249 memcpy(pos, &target_rcode, 2);
199 250
200 ieee80211_tx_skb(sdata, skb, 1); 251 ieee80211_tx_skb(sdata, skb, 1);
201 return 0; 252 return 0;
@@ -269,18 +320,17 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local,
269 */ 320 */
270static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, 321static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
271 struct ieee80211_mgmt *mgmt, 322 struct ieee80211_mgmt *mgmt,
272 u8 *hwmp_ie) 323 u8 *hwmp_ie, enum mpath_frame_type action)
273{ 324{
274 struct ieee80211_local *local = sdata->local; 325 struct ieee80211_local *local = sdata->local;
275 struct mesh_path *mpath; 326 struct mesh_path *mpath;
276 struct sta_info *sta; 327 struct sta_info *sta;
277 bool fresh_info; 328 bool fresh_info;
278 u8 *orig_addr, *ta; 329 u8 *orig_addr, *ta;
279 u32 orig_dsn, orig_metric; 330 u32 orig_sn, orig_metric;
280 unsigned long orig_lifetime, exp_time; 331 unsigned long orig_lifetime, exp_time;
281 u32 last_hop_metric, new_metric; 332 u32 last_hop_metric, new_metric;
282 bool process = true; 333 bool process = true;
283 u8 action = mgmt->u.action.u.mesh_action.action_code;
284 334
285 rcu_read_lock(); 335 rcu_read_lock();
286 sta = sta_info_get(local, mgmt->sa); 336 sta = sta_info_get(local, mgmt->sa);
@@ -296,7 +346,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
296 switch (action) { 346 switch (action) {
297 case MPATH_PREQ: 347 case MPATH_PREQ:
298 orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie); 348 orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
299 orig_dsn = PREQ_IE_ORIG_DSN(hwmp_ie); 349 orig_sn = PREQ_IE_ORIG_SN(hwmp_ie);
300 orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie); 350 orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
301 orig_metric = PREQ_IE_METRIC(hwmp_ie); 351 orig_metric = PREQ_IE_METRIC(hwmp_ie);
302 break; 352 break;
@@ -309,7 +359,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
309 * information from both PREQ and PREP frames. 359 * information from both PREQ and PREP frames.
310 */ 360 */
311 orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie); 361 orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie);
312 orig_dsn = PREP_IE_ORIG_DSN(hwmp_ie); 362 orig_sn = PREP_IE_ORIG_SN(hwmp_ie);
313 orig_lifetime = PREP_IE_LIFETIME(hwmp_ie); 363 orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
314 orig_metric = PREP_IE_METRIC(hwmp_ie); 364 orig_metric = PREP_IE_METRIC(hwmp_ie);
315 break; 365 break;
@@ -335,9 +385,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
335 if (mpath->flags & MESH_PATH_FIXED) 385 if (mpath->flags & MESH_PATH_FIXED)
336 fresh_info = false; 386 fresh_info = false;
337 else if ((mpath->flags & MESH_PATH_ACTIVE) && 387 else if ((mpath->flags & MESH_PATH_ACTIVE) &&
338 (mpath->flags & MESH_PATH_DSN_VALID)) { 388 (mpath->flags & MESH_PATH_SN_VALID)) {
339 if (DSN_GT(mpath->dsn, orig_dsn) || 389 if (SN_GT(mpath->sn, orig_sn) ||
340 (mpath->dsn == orig_dsn && 390 (mpath->sn == orig_sn &&
341 action == MPATH_PREQ && 391 action == MPATH_PREQ &&
342 new_metric > mpath->metric)) { 392 new_metric > mpath->metric)) {
343 process = false; 393 process = false;
@@ -356,9 +406,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
356 406
357 if (fresh_info) { 407 if (fresh_info) {
358 mesh_path_assign_nexthop(mpath, sta); 408 mesh_path_assign_nexthop(mpath, sta);
359 mpath->flags |= MESH_PATH_DSN_VALID; 409 mpath->flags |= MESH_PATH_SN_VALID;
360 mpath->metric = new_metric; 410 mpath->metric = new_metric;
361 mpath->dsn = orig_dsn; 411 mpath->sn = orig_sn;
362 mpath->exp_time = time_after(mpath->exp_time, exp_time) 412 mpath->exp_time = time_after(mpath->exp_time, exp_time)
363 ? mpath->exp_time : exp_time; 413 ? mpath->exp_time : exp_time;
364 mesh_path_activate(mpath); 414 mesh_path_activate(mpath);
@@ -397,7 +447,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
397 447
398 if (fresh_info) { 448 if (fresh_info) {
399 mesh_path_assign_nexthop(mpath, sta); 449 mesh_path_assign_nexthop(mpath, sta);
400 mpath->flags &= ~MESH_PATH_DSN_VALID; 450 mpath->flags &= ~MESH_PATH_SN_VALID;
401 mpath->metric = last_hop_metric; 451 mpath->metric = last_hop_metric;
402 mpath->exp_time = time_after(mpath->exp_time, exp_time) 452 mpath->exp_time = time_after(mpath->exp_time, exp_time)
403 ? mpath->exp_time : exp_time; 453 ? mpath->exp_time : exp_time;
@@ -419,44 +469,47 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
419{ 469{
420 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 470 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
421 struct mesh_path *mpath; 471 struct mesh_path *mpath;
422 u8 *dst_addr, *orig_addr; 472 u8 *target_addr, *orig_addr;
423 u8 dst_flags, ttl; 473 u8 target_flags, ttl;
424 u32 orig_dsn, dst_dsn, lifetime; 474 u32 orig_sn, target_sn, lifetime;
425 bool reply = false; 475 bool reply = false;
426 bool forward = true; 476 bool forward = true;
427 477
428 /* Update destination DSN, if present */ 478 /* Update target SN, if present */
429 dst_addr = PREQ_IE_DST_ADDR(preq_elem); 479 target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
430 orig_addr = PREQ_IE_ORIG_ADDR(preq_elem); 480 orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
431 dst_dsn = PREQ_IE_DST_DSN(preq_elem); 481 target_sn = PREQ_IE_TARGET_SN(preq_elem);
432 orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); 482 orig_sn = PREQ_IE_ORIG_SN(preq_elem);
433 dst_flags = PREQ_IE_DST_F(preq_elem); 483 target_flags = PREQ_IE_TARGET_F(preq_elem);
434 484
435 if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { 485 mhwmp_dbg("received PREQ from %pM\n", orig_addr);
486
487 if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) {
488 mhwmp_dbg("PREQ is for us\n");
436 forward = false; 489 forward = false;
437 reply = true; 490 reply = true;
438 metric = 0; 491 metric = 0;
439 if (time_after(jiffies, ifmsh->last_dsn_update + 492 if (time_after(jiffies, ifmsh->last_sn_update +
440 net_traversal_jiffies(sdata)) || 493 net_traversal_jiffies(sdata)) ||
441 time_before(jiffies, ifmsh->last_dsn_update)) { 494 time_before(jiffies, ifmsh->last_sn_update)) {
442 dst_dsn = ++ifmsh->dsn; 495 target_sn = ++ifmsh->sn;
443 ifmsh->last_dsn_update = jiffies; 496 ifmsh->last_sn_update = jiffies;
444 } 497 }
445 } else { 498 } else {
446 rcu_read_lock(); 499 rcu_read_lock();
447 mpath = mesh_path_lookup(dst_addr, sdata); 500 mpath = mesh_path_lookup(target_addr, sdata);
448 if (mpath) { 501 if (mpath) {
449 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || 502 if ((!(mpath->flags & MESH_PATH_SN_VALID)) ||
450 DSN_LT(mpath->dsn, dst_dsn)) { 503 SN_LT(mpath->sn, target_sn)) {
451 mpath->dsn = dst_dsn; 504 mpath->sn = target_sn;
452 mpath->flags |= MESH_PATH_DSN_VALID; 505 mpath->flags |= MESH_PATH_SN_VALID;
453 } else if ((!(dst_flags & MP_F_DO)) && 506 } else if ((!(target_flags & MP_F_DO)) &&
454 (mpath->flags & MESH_PATH_ACTIVE)) { 507 (mpath->flags & MESH_PATH_ACTIVE)) {
455 reply = true; 508 reply = true;
456 metric = mpath->metric; 509 metric = mpath->metric;
457 dst_dsn = mpath->dsn; 510 target_sn = mpath->sn;
458 if (dst_flags & MP_F_RF) 511 if (target_flags & MP_F_RF)
459 dst_flags |= MP_F_DO; 512 target_flags |= MP_F_DO;
460 else 513 else
461 forward = false; 514 forward = false;
462 } 515 }
@@ -467,13 +520,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
467 if (reply) { 520 if (reply) {
468 lifetime = PREQ_IE_LIFETIME(preq_elem); 521 lifetime = PREQ_IE_LIFETIME(preq_elem);
469 ttl = ifmsh->mshcfg.dot11MeshTTL; 522 ttl = ifmsh->mshcfg.dot11MeshTTL;
470 if (ttl != 0) 523 if (ttl != 0) {
471 mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, 524 mhwmp_dbg("replying to the PREQ\n");
472 cpu_to_le32(dst_dsn), 0, orig_addr, 525 mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr,
473 cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, 526 cpu_to_le32(target_sn), 0, orig_addr,
527 cpu_to_le32(orig_sn), mgmt->sa, 0, ttl,
474 cpu_to_le32(lifetime), cpu_to_le32(metric), 528 cpu_to_le32(lifetime), cpu_to_le32(metric),
475 0, sdata); 529 0, sdata);
476 else 530 } else
477 ifmsh->mshstats.dropped_frames_ttl++; 531 ifmsh->mshstats.dropped_frames_ttl++;
478 } 532 }
479 533
@@ -487,13 +541,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
487 ifmsh->mshstats.dropped_frames_ttl++; 541 ifmsh->mshstats.dropped_frames_ttl++;
488 return; 542 return;
489 } 543 }
544 mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr);
490 --ttl; 545 --ttl;
491 flags = PREQ_IE_FLAGS(preq_elem); 546 flags = PREQ_IE_FLAGS(preq_elem);
492 preq_id = PREQ_IE_PREQ_ID(preq_elem); 547 preq_id = PREQ_IE_PREQ_ID(preq_elem);
493 hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; 548 hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
494 mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, 549 mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
495 cpu_to_le32(orig_dsn), dst_flags, dst_addr, 550 cpu_to_le32(orig_sn), target_flags, target_addr,
496 cpu_to_le32(dst_dsn), sdata->dev->broadcast, 551 cpu_to_le32(target_sn), sdata->dev->broadcast,
497 hopcount, ttl, cpu_to_le32(lifetime), 552 hopcount, ttl, cpu_to_le32(lifetime),
498 cpu_to_le32(metric), cpu_to_le32(preq_id), 553 cpu_to_le32(metric), cpu_to_le32(preq_id),
499 sdata); 554 sdata);
@@ -508,10 +563,12 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
508 u8 *prep_elem, u32 metric) 563 u8 *prep_elem, u32 metric)
509{ 564{
510 struct mesh_path *mpath; 565 struct mesh_path *mpath;
511 u8 *dst_addr, *orig_addr; 566 u8 *target_addr, *orig_addr;
512 u8 ttl, hopcount, flags; 567 u8 ttl, hopcount, flags;
513 u8 next_hop[ETH_ALEN]; 568 u8 next_hop[ETH_ALEN];
514 u32 dst_dsn, orig_dsn, lifetime; 569 u32 target_sn, orig_sn, lifetime;
570
571 mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem));
515 572
516 /* Note that we divert from the draft nomenclature and denominate 573 /* Note that we divert from the draft nomenclature and denominate
517 * destination to what the draft refers to as origininator. So in this 574 * destination to what the draft refers to as origininator. So in this
@@ -519,8 +576,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
519 * which corresponds with the originator of the PREQ which this PREP 576 * which corresponds with the originator of the PREQ which this PREP
520 * replies 577 * replies
521 */ 578 */
522 dst_addr = PREP_IE_DST_ADDR(prep_elem); 579 target_addr = PREP_IE_TARGET_ADDR(prep_elem);
523 if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) 580 if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0)
524 /* destination, no forwarding required */ 581 /* destination, no forwarding required */
525 return; 582 return;
526 583
@@ -531,7 +588,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
531 } 588 }
532 589
533 rcu_read_lock(); 590 rcu_read_lock();
534 mpath = mesh_path_lookup(dst_addr, sdata); 591 mpath = mesh_path_lookup(target_addr, sdata);
535 if (mpath) 592 if (mpath)
536 spin_lock_bh(&mpath->state_lock); 593 spin_lock_bh(&mpath->state_lock);
537 else 594 else
@@ -547,13 +604,13 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
547 lifetime = PREP_IE_LIFETIME(prep_elem); 604 lifetime = PREP_IE_LIFETIME(prep_elem);
548 hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1; 605 hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
549 orig_addr = PREP_IE_ORIG_ADDR(prep_elem); 606 orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
550 dst_dsn = PREP_IE_DST_DSN(prep_elem); 607 target_sn = PREP_IE_TARGET_SN(prep_elem);
551 orig_dsn = PREP_IE_ORIG_DSN(prep_elem); 608 orig_sn = PREP_IE_ORIG_SN(prep_elem);
552 609
553 mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, 610 mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
554 cpu_to_le32(orig_dsn), 0, dst_addr, 611 cpu_to_le32(orig_sn), 0, target_addr,
555 cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl, 612 cpu_to_le32(target_sn), mpath->next_hop->sta.addr, hopcount,
556 cpu_to_le32(lifetime), cpu_to_le32(metric), 613 ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
557 0, sdata); 614 0, sdata);
558 rcu_read_unlock(); 615 rcu_read_unlock();
559 616
@@ -570,25 +627,39 @@ fail:
570static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, 627static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
571 struct ieee80211_mgmt *mgmt, u8 *perr_elem) 628 struct ieee80211_mgmt *mgmt, u8 *perr_elem)
572{ 629{
630 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
573 struct mesh_path *mpath; 631 struct mesh_path *mpath;
574 u8 *ta, *dst_addr; 632 u8 ttl;
575 u32 dst_dsn; 633 u8 *ta, *target_addr;
634 u8 target_flags;
635 u32 target_sn;
636 u16 target_rcode;
576 637
577 ta = mgmt->sa; 638 ta = mgmt->sa;
578 dst_addr = PERR_IE_DST_ADDR(perr_elem); 639 ttl = PERR_IE_TTL(perr_elem);
579 dst_dsn = PERR_IE_DST_DSN(perr_elem); 640 if (ttl <= 1) {
641 ifmsh->mshstats.dropped_frames_ttl++;
642 return;
643 }
644 ttl--;
645 target_flags = PERR_IE_TARGET_FLAGS(perr_elem);
646 target_addr = PERR_IE_TARGET_ADDR(perr_elem);
647 target_sn = PERR_IE_TARGET_SN(perr_elem);
648 target_rcode = PERR_IE_TARGET_RCODE(perr_elem);
649
580 rcu_read_lock(); 650 rcu_read_lock();
581 mpath = mesh_path_lookup(dst_addr, sdata); 651 mpath = mesh_path_lookup(target_addr, sdata);
582 if (mpath) { 652 if (mpath) {
583 spin_lock_bh(&mpath->state_lock); 653 spin_lock_bh(&mpath->state_lock);
584 if (mpath->flags & MESH_PATH_ACTIVE && 654 if (mpath->flags & MESH_PATH_ACTIVE &&
585 memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && 655 memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 &&
586 (!(mpath->flags & MESH_PATH_DSN_VALID) || 656 (!(mpath->flags & MESH_PATH_SN_VALID) ||
587 DSN_GT(dst_dsn, mpath->dsn))) { 657 SN_GT(target_sn, mpath->sn))) {
588 mpath->flags &= ~MESH_PATH_ACTIVE; 658 mpath->flags &= ~MESH_PATH_ACTIVE;
589 mpath->dsn = dst_dsn; 659 mpath->sn = target_sn;
590 spin_unlock_bh(&mpath->state_lock); 660 spin_unlock_bh(&mpath->state_lock);
591 mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), 661 mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn),
662 cpu_to_le16(target_rcode),
592 sdata->dev->broadcast, sdata); 663 sdata->dev->broadcast, sdata);
593 } else 664 } else
594 spin_unlock_bh(&mpath->state_lock); 665 spin_unlock_bh(&mpath->state_lock);
@@ -596,6 +667,56 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
596 rcu_read_unlock(); 667 rcu_read_unlock();
597} 668}
598 669
670static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
671 struct ieee80211_mgmt *mgmt,
672 struct ieee80211_rann_ie *rann)
673{
674 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
675 struct mesh_path *mpath;
676 u8 *ta;
677 u8 ttl, flags, hopcount;
678 u8 *orig_addr;
679 u32 orig_sn, metric;
680
681 ta = mgmt->sa;
682 ttl = rann->rann_ttl;
683 if (ttl <= 1) {
684 ifmsh->mshstats.dropped_frames_ttl++;
685 return;
686 }
687 ttl--;
688 flags = rann->rann_flags;
689 orig_addr = rann->rann_addr;
690 orig_sn = rann->rann_seq;
691 hopcount = rann->rann_hopcount;
692 hopcount++;
693 metric = rann->rann_metric;
694 mhwmp_dbg("received RANN from %pM\n", orig_addr);
695
696 rcu_read_lock();
697 mpath = mesh_path_lookup(orig_addr, sdata);
698 if (!mpath) {
699 mesh_path_add(orig_addr, sdata);
700 mpath = mesh_path_lookup(orig_addr, sdata);
701 if (!mpath) {
702 rcu_read_unlock();
703 sdata->u.mesh.mshstats.dropped_frames_no_route++;
704 return;
705 }
706 mesh_queue_preq(mpath,
707 PREQ_Q_F_START | PREQ_Q_F_REFRESH);
708 }
709 if (mpath->sn < orig_sn) {
710 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
711 cpu_to_le32(orig_sn),
712 0, NULL, 0, sdata->dev->broadcast,
713 hopcount, ttl, 0,
714 cpu_to_le32(metric + mpath->metric),
715 0, sdata);
716 mpath->sn = orig_sn;
717 }
718 rcu_read_unlock();
719}
599 720
600 721
601void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, 722void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
@@ -614,34 +735,34 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
614 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, 735 ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
615 len - baselen, &elems); 736 len - baselen, &elems);
616 737
617 switch (mgmt->u.action.u.mesh_action.action_code) { 738 if (elems.preq) {
618 case MPATH_PREQ: 739 if (elems.preq_len != 37)
619 if (!elems.preq || elems.preq_len != 37)
620 /* Right now we support just 1 destination and no AE */ 740 /* Right now we support just 1 destination and no AE */
621 return; 741 return;
622 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); 742 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
623 if (!last_hop_metric) 743 MPATH_PREQ);
624 return; 744 if (last_hop_metric)
625 hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); 745 hwmp_preq_frame_process(sdata, mgmt, elems.preq,
626 break; 746 last_hop_metric);
627 case MPATH_PREP: 747 }
628 if (!elems.prep || elems.prep_len != 31) 748 if (elems.prep) {
749 if (elems.prep_len != 31)
629 /* Right now we support no AE */ 750 /* Right now we support no AE */
630 return; 751 return;
631 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); 752 last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
632 if (!last_hop_metric) 753 MPATH_PREP);
633 return; 754 if (last_hop_metric)
634 hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); 755 hwmp_prep_frame_process(sdata, mgmt, elems.prep,
635 break; 756 last_hop_metric);
636 case MPATH_PERR: 757 }
637 if (!elems.perr || elems.perr_len != 12) 758 if (elems.perr) {
759 if (elems.perr_len != 15)
638 /* Right now we support only one destination per PERR */ 760 /* Right now we support only one destination per PERR */
639 return; 761 return;
640 hwmp_perr_frame_process(sdata, mgmt, elems.perr); 762 hwmp_perr_frame_process(sdata, mgmt, elems.perr);
641 default:
642 return;
643 } 763 }
644 764 if (elems.rann)
765 hwmp_rann_frame_process(sdata, mgmt, elems.rann);
645} 766}
646 767
647/** 768/**
@@ -661,7 +782,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
661 782
662 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); 783 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
663 if (!preq_node) { 784 if (!preq_node) {
664 printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); 785 mhwmp_dbg("could not allocate PREQ node\n");
665 return; 786 return;
666 } 787 }
667 788
@@ -670,7 +791,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
670 spin_unlock(&ifmsh->mesh_preq_queue_lock); 791 spin_unlock(&ifmsh->mesh_preq_queue_lock);
671 kfree(preq_node); 792 kfree(preq_node);
672 if (printk_ratelimit()) 793 if (printk_ratelimit())
673 printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); 794 mhwmp_dbg("PREQ node queue full\n");
674 return; 795 return;
675 } 796 }
676 797
@@ -705,7 +826,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
705 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 826 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
706 struct mesh_preq_queue *preq_node; 827 struct mesh_preq_queue *preq_node;
707 struct mesh_path *mpath; 828 struct mesh_path *mpath;
708 u8 ttl, dst_flags; 829 u8 ttl, target_flags;
709 u32 lifetime; 830 u32 lifetime;
710 831
711 spin_lock_bh(&ifmsh->mesh_preq_queue_lock); 832 spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
@@ -747,11 +868,11 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
747 868
748 ifmsh->last_preq = jiffies; 869 ifmsh->last_preq = jiffies;
749 870
750 if (time_after(jiffies, ifmsh->last_dsn_update + 871 if (time_after(jiffies, ifmsh->last_sn_update +
751 net_traversal_jiffies(sdata)) || 872 net_traversal_jiffies(sdata)) ||
752 time_before(jiffies, ifmsh->last_dsn_update)) { 873 time_before(jiffies, ifmsh->last_sn_update)) {
753 ++ifmsh->dsn; 874 ++ifmsh->sn;
754 sdata->u.mesh.last_dsn_update = jiffies; 875 sdata->u.mesh.last_sn_update = jiffies;
755 } 876 }
756 lifetime = default_lifetime(sdata); 877 lifetime = default_lifetime(sdata);
757 ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; 878 ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
@@ -762,14 +883,14 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
762 } 883 }
763 884
764 if (preq_node->flags & PREQ_Q_F_REFRESH) 885 if (preq_node->flags & PREQ_Q_F_REFRESH)
765 dst_flags = MP_F_DO; 886 target_flags = MP_F_DO;
766 else 887 else
767 dst_flags = MP_F_RF; 888 target_flags = MP_F_RF;
768 889
769 spin_unlock_bh(&mpath->state_lock); 890 spin_unlock_bh(&mpath->state_lock);
770 mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, 891 mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr,
771 cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, 892 cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
772 cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, 893 cpu_to_le32(mpath->sn), sdata->dev->broadcast, 0,
773 ttl, cpu_to_le32(lifetime), 0, 894 ttl, cpu_to_le32(lifetime), 0,
774 cpu_to_le32(ifmsh->preq_id++), sdata); 895 cpu_to_le32(ifmsh->preq_id++), sdata);
775 mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); 896 mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
@@ -796,15 +917,15 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
796 struct sk_buff *skb_to_free = NULL; 917 struct sk_buff *skb_to_free = NULL;
797 struct mesh_path *mpath; 918 struct mesh_path *mpath;
798 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 919 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
799 u8 *dst_addr = hdr->addr3; 920 u8 *target_addr = hdr->addr3;
800 int err = 0; 921 int err = 0;
801 922
802 rcu_read_lock(); 923 rcu_read_lock();
803 mpath = mesh_path_lookup(dst_addr, sdata); 924 mpath = mesh_path_lookup(target_addr, sdata);
804 925
805 if (!mpath) { 926 if (!mpath) {
806 mesh_path_add(dst_addr, sdata); 927 mesh_path_add(target_addr, sdata);
807 mpath = mesh_path_lookup(dst_addr, sdata); 928 mpath = mesh_path_lookup(target_addr, sdata);
808 if (!mpath) { 929 if (!mpath) {
809 sdata->u.mesh.mshstats.dropped_frames_no_route++; 930 sdata->u.mesh.mshstats.dropped_frames_no_route++;
810 err = -ENOSPC; 931 err = -ENOSPC;
@@ -882,3 +1003,14 @@ void mesh_path_timer(unsigned long data)
882endmpathtimer: 1003endmpathtimer:
883 rcu_read_unlock(); 1004 rcu_read_unlock();
884} 1005}
1006
1007void
1008mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1009{
1010 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1011
1012 mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr,
1013 cpu_to_le32(++ifmsh->sn),
1014 0, NULL, 0, sdata->dev->broadcast,
1015 0, MESH_TTL, 0, 0, 0, sdata);
1016}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 751c4d0e2b36..5399e7a9ec6e 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 open80211s Ltd. 2 * Copyright (c) 2008, 2009 open80211s Ltd.
3 * Author: Luis Carlos Cobo <luisca@cozybit.com> 3 * Author: Luis Carlos Cobo <luisca@cozybit.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -463,10 +463,11 @@ void mesh_plink_broken(struct sta_info *sta)
463 mpath->flags & MESH_PATH_ACTIVE && 463 mpath->flags & MESH_PATH_ACTIVE &&
464 !(mpath->flags & MESH_PATH_FIXED)) { 464 !(mpath->flags & MESH_PATH_FIXED)) {
465 mpath->flags &= ~MESH_PATH_ACTIVE; 465 mpath->flags &= ~MESH_PATH_ACTIVE;
466 ++mpath->dsn; 466 ++mpath->sn;
467 spin_unlock_bh(&mpath->state_lock); 467 spin_unlock_bh(&mpath->state_lock);
468 mesh_path_error_tx(mpath->dst, 468 mesh_path_error_tx(MESH_TTL, mpath->dst,
469 cpu_to_le32(mpath->dsn), 469 cpu_to_le32(mpath->sn),
470 PERR_RCODE_DEST_UNREACH,
470 sdata->dev->broadcast, sdata); 471 sdata->dev->broadcast, sdata);
471 } else 472 } else
472 spin_unlock_bh(&mpath->state_lock); 473 spin_unlock_bh(&mpath->state_lock);
@@ -601,7 +602,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
601{ 602{
602 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 603 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
603 struct mesh_path *mpath; 604 struct mesh_path *mpath;
604 u32 dsn = 0; 605 u32 sn = 0;
605 606
606 if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { 607 if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) {
607 u8 *ra, *da; 608 u8 *ra, *da;
@@ -610,8 +611,9 @@ void mesh_path_discard_frame(struct sk_buff *skb,
610 ra = hdr->addr1; 611 ra = hdr->addr1;
611 mpath = mesh_path_lookup(da, sdata); 612 mpath = mesh_path_lookup(da, sdata);
612 if (mpath) 613 if (mpath)
613 dsn = ++mpath->dsn; 614 sn = ++mpath->sn;
614 mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata); 615 mesh_path_error_tx(MESH_TTL, skb->data, cpu_to_le32(sn),
616 PERR_RCODE_NO_ROUTE, ra, sdata);
615 } 617 }
616 618
617 kfree_skb(skb); 619 kfree_skb(skb);
@@ -646,7 +648,7 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
646{ 648{
647 spin_lock_bh(&mpath->state_lock); 649 spin_lock_bh(&mpath->state_lock);
648 mesh_path_assign_nexthop(mpath, next_hop); 650 mesh_path_assign_nexthop(mpath, next_hop);
649 mpath->dsn = 0xffff; 651 mpath->sn = 0xffff;
650 mpath->metric = 0; 652 mpath->metric = 0;
651 mpath->hop_count = 0; 653 mpath->hop_count = 0;
652 mpath->exp_time = 0; 654 mpath->exp_time = 0;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index ffcbad75e09b..f21329afdae3 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008 open80211s Ltd. 2 * Copyright (c) 2008, 2009 open80211s Ltd.
3 * Author: Luis Carlos Cobo <luisca@cozybit.com> 3 * Author: Luis Carlos Cobo <luisca@cozybit.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,8 @@
18#define mpl_dbg(fmt, args...) do { (void)(0); } while (0) 18#define mpl_dbg(fmt, args...) do { (void)(0); } while (0)
19#endif 19#endif
20 20
21#define PLINK_GET_FRAME_SUBTYPE(p) (p) 21#define PLINK_GET_LLID(p) (p + 4)
22#define PLINK_GET_LLID(p) (p + 1) 22#define PLINK_GET_PLID(p) (p + 6)
23#define PLINK_GET_PLID(p) (p + 3)
24 23
25#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ 24#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
26 jiffies + HZ * t / 1000)) 25 jiffies + HZ * t / 1000))
@@ -65,6 +64,7 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
65{ 64{
66 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); 65 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
67 mesh_accept_plinks_update(sdata); 66 mesh_accept_plinks_update(sdata);
67 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
68} 68}
69 69
70static inline 70static inline
@@ -72,12 +72,13 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
72{ 72{
73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); 73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
74 mesh_accept_plinks_update(sdata); 74 mesh_accept_plinks_update(sdata);
75 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
75} 76}
76 77
77/** 78/**
78 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine 79 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
79 * 80 *
80 * @sta: mes peer link to restart 81 * @sta: mesh peer link to restart
81 * 82 *
82 * Locking: this function must be called holding sta->lock 83 * Locking: this function must be called holding sta->lock
83 */ 84 */
@@ -152,6 +153,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
152 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); 153 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
153 struct ieee80211_mgmt *mgmt; 154 struct ieee80211_mgmt *mgmt;
154 bool include_plid = false; 155 bool include_plid = false;
156 static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A };
155 u8 *pos; 157 u8 *pos;
156 int ie_len; 158 int ie_len;
157 159
@@ -169,7 +171,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
169 memcpy(mgmt->da, da, ETH_ALEN); 171 memcpy(mgmt->da, da, ETH_ALEN);
170 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 172 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
171 /* BSSID is left zeroed, wildcard value */ 173 /* BSSID is left zeroed, wildcard value */
172 mgmt->u.action.category = PLINK_CATEGORY; 174 mgmt->u.action.category = MESH_PLINK_CATEGORY;
173 mgmt->u.action.u.plink_action.action_code = action; 175 mgmt->u.action.u.plink_action.action_code = action;
174 176
175 if (action == PLINK_CLOSE) 177 if (action == PLINK_CLOSE)
@@ -179,7 +181,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
179 if (action == PLINK_CONFIRM) { 181 if (action == PLINK_CONFIRM) {
180 pos = skb_put(skb, 4); 182 pos = skb_put(skb, 4);
181 /* two-byte status code followed by two-byte AID */ 183 /* two-byte status code followed by two-byte AID */
182 memset(pos, 0, 4); 184 memset(pos, 0, 2);
185 memcpy(pos + 2, &plid, 2);
183 } 186 }
184 mesh_mgmt_ies_add(skb, sdata); 187 mesh_mgmt_ies_add(skb, sdata);
185 } 188 }
@@ -187,18 +190,18 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
187 /* Add Peer Link Management element */ 190 /* Add Peer Link Management element */
188 switch (action) { 191 switch (action) {
189 case PLINK_OPEN: 192 case PLINK_OPEN:
190 ie_len = 3; 193 ie_len = 6;
191 break; 194 break;
192 case PLINK_CONFIRM: 195 case PLINK_CONFIRM:
193 ie_len = 5; 196 ie_len = 8;
194 include_plid = true; 197 include_plid = true;
195 break; 198 break;
196 case PLINK_CLOSE: 199 case PLINK_CLOSE:
197 default: 200 default:
198 if (!plid) 201 if (!plid)
199 ie_len = 5; 202 ie_len = 8;
200 else { 203 else {
201 ie_len = 7; 204 ie_len = 10;
202 include_plid = true; 205 include_plid = true;
203 } 206 }
204 break; 207 break;
@@ -207,7 +210,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
207 pos = skb_put(skb, 2 + ie_len); 210 pos = skb_put(skb, 2 + ie_len);
208 *pos++ = WLAN_EID_PEER_LINK; 211 *pos++ = WLAN_EID_PEER_LINK;
209 *pos++ = ie_len; 212 *pos++ = ie_len;
210 *pos++ = action; 213 memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto));
214 pos += 4;
211 memcpy(pos, &llid, 2); 215 memcpy(pos, &llid, 2);
212 if (include_plid) { 216 if (include_plid) {
213 pos += 2; 217 pos += 2;
@@ -395,6 +399,17 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
395 u8 ie_len; 399 u8 ie_len;
396 u8 *baseaddr; 400 u8 *baseaddr;
397 __le16 plid, llid, reason; 401 __le16 plid, llid, reason;
402#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
403 static const char *mplstates[] = {
404 [PLINK_LISTEN] = "LISTEN",
405 [PLINK_OPN_SNT] = "OPN-SNT",
406 [PLINK_OPN_RCVD] = "OPN-RCVD",
407 [PLINK_CNF_RCVD] = "CNF_RCVD",
408 [PLINK_ESTAB] = "ESTAB",
409 [PLINK_HOLDING] = "HOLDING",
410 [PLINK_BLOCKED] = "BLOCKED"
411 };
412#endif
398 413
399 /* need action_code, aux */ 414 /* need action_code, aux */
400 if (len < IEEE80211_MIN_ACTION_SIZE + 3) 415 if (len < IEEE80211_MIN_ACTION_SIZE + 3)
@@ -417,12 +432,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
417 return; 432 return;
418 } 433 }
419 434
420 ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link)); 435 ftype = mgmt->u.action.u.plink_action.action_code;
421 ie_len = elems.peer_link_len; 436 ie_len = elems.peer_link_len;
422 if ((ftype == PLINK_OPEN && ie_len != 3) || 437 if ((ftype == PLINK_OPEN && ie_len != 6) ||
423 (ftype == PLINK_CONFIRM && ie_len != 5) || 438 (ftype == PLINK_CONFIRM && ie_len != 8) ||
424 (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) { 439 (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) {
425 mpl_dbg("Mesh plink: incorrect plink ie length\n"); 440 mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
441 ftype, ie_len);
426 return; 442 return;
427 } 443 }
428 444
@@ -434,7 +450,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
434 * from the point of view of this host. 450 * from the point of view of this host.
435 */ 451 */
436 memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); 452 memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
437 if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7)) 453 if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10))
438 memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); 454 memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
439 455
440 rcu_read_lock(); 456 rcu_read_lock();
@@ -532,8 +548,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
532 } 548 }
533 } 549 }
534 550
535 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %d %d %d %d\n", 551 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
536 mgmt->sa, sta->plink_state, 552 mgmt->sa, mplstates[sta->plink_state],
537 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), 553 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
538 event); 554 event);
539 reason = 0; 555 reason = 0;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dcc14e99227c..2af306f67d78 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1898,7 +1898,6 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1898 fc = le16_to_cpu(mgmt->frame_control); 1898 fc = le16_to_cpu(mgmt->frame_control);
1899 1899
1900 switch (fc & IEEE80211_FCTL_STYPE) { 1900 switch (fc & IEEE80211_FCTL_STYPE) {
1901 case IEEE80211_STYPE_PROBE_REQ:
1902 case IEEE80211_STYPE_PROBE_RESP: 1901 case IEEE80211_STYPE_PROBE_RESP:
1903 case IEEE80211_STYPE_BEACON: 1902 case IEEE80211_STYPE_BEACON:
1904 case IEEE80211_STYPE_AUTH: 1903 case IEEE80211_STYPE_AUTH:
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 28316b2a585f..6bce97ee2534 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -507,7 +507,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
507 507
508 if (ieee80211_is_action(hdr->frame_control)) { 508 if (ieee80211_is_action(hdr->frame_control)) {
509 mgmt = (struct ieee80211_mgmt *)hdr; 509 mgmt = (struct ieee80211_mgmt *)hdr;
510 if (mgmt->u.action.category != PLINK_CATEGORY) 510 if (mgmt->u.action.category != MESH_PLINK_CATEGORY)
511 return RX_DROP_MONITOR; 511 return RX_DROP_MONITOR;
512 return RX_CONTINUE; 512 return RX_CONTINUE;
513 } 513 }
@@ -1181,6 +1181,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1181{ 1181{
1182 struct net_device *dev = rx->dev; 1182 struct net_device *dev = rx->dev;
1183 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1183 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1184 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1185
1186 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr &&
1187 ieee80211_has_a4(hdr->frame_control))
1188 return -1;
1189 if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1))
1190 return -1;
1184 1191
1185 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); 1192 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
1186} 1193}
@@ -1229,7 +1236,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1229 if ((sdata->vif.type == NL80211_IFTYPE_AP || 1236 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
1230 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && 1237 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
1231 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && 1238 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
1232 (rx->flags & IEEE80211_RX_RA_MATCH)) { 1239 (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) {
1233 if (is_multicast_ether_addr(ehdr->h_dest)) { 1240 if (is_multicast_ether_addr(ehdr->h_dest)) {
1234 /* 1241 /*
1235 * send multicast frames both to higher layers in 1242 * send multicast frames both to higher layers in
@@ -1534,6 +1541,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1534{ 1541{
1535 struct net_device *dev = rx->dev; 1542 struct net_device *dev = rx->dev;
1536 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 1543 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1544 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1537 __le16 fc = hdr->frame_control; 1545 __le16 fc = hdr->frame_control;
1538 int err; 1546 int err;
1539 1547
@@ -1543,6 +1551,14 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1543 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 1551 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
1544 return RX_DROP_MONITOR; 1552 return RX_DROP_MONITOR;
1545 1553
1554 /*
1555 * Allow the cooked monitor interface of an AP to see 4-addr frames so
1556 * that a 4-addr station can be detected and moved into a separate VLAN
1557 */
1558 if (ieee80211_has_a4(hdr->frame_control) &&
1559 sdata->vif.type == NL80211_IFTYPE_AP)
1560 return RX_DROP_MONITOR;
1561
1546 err = __ieee80211_data_to_8023(rx); 1562 err = __ieee80211_data_to_8023(rx);
1547 if (unlikely(err)) 1563 if (unlikely(err))
1548 return RX_DROP_UNUSABLE; 1564 return RX_DROP_UNUSABLE;
@@ -1983,7 +1999,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
1983 1999
1984 switch (sdata->vif.type) { 2000 switch (sdata->vif.type) {
1985 case NL80211_IFTYPE_STATION: 2001 case NL80211_IFTYPE_STATION:
1986 if (!bssid) 2002 if (!bssid && !sdata->use_4addr)
1987 return 0; 2003 return 0;
1988 if (!multicast && 2004 if (!multicast &&
1989 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { 2005 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
@@ -2425,9 +2441,21 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
2425 goto drop; 2441 goto drop;
2426 2442
2427 if (status->flag & RX_FLAG_HT) { 2443 if (status->flag & RX_FLAG_HT) {
2428 /* rate_idx is MCS index */ 2444 /*
2429 if (WARN_ON(status->rate_idx < 0 || 2445 * rate_idx is MCS index, which can be [0-76] as documented on:
2430 status->rate_idx >= 76)) 2446 *
2447 * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
2448 *
2449 * Anything else would be some sort of driver or hardware error.
2450 * The driver should catch hardware errors.
2451 */
2452 if (WARN((status->rate_idx < 0 ||
2453 status->rate_idx > 76),
2454 "Rate marked as an HT rate but passed "
2455 "status->rate_idx is not "
2456 "an MCS index [0-76]: %d (0x%02x)\n",
2457 status->rate_idx,
2458 status->rate_idx))
2431 goto drop; 2459 goto drop;
2432 /* HT rates are not in the table - use the highest legacy rate 2460 /* HT rates are not in the table - use the highest legacy rate
2433 * for now since other parts of mac80211 may not yet be fully 2461 * for now since other parts of mac80211 may not yet be fully
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index be59456e8a42..396a94806de9 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -509,6 +509,9 @@ static void __sta_info_unlink(struct sta_info **sta)
509 local->num_sta--; 509 local->num_sta--;
510 local->sta_generation++; 510 local->sta_generation++;
511 511
512 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
513 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
514
512 if (local->ops->sta_notify) { 515 if (local->ops->sta_notify) {
513 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 516 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
514 sdata = container_of(sdata->bss, 517 sdata = container_of(sdata->bss,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bfaa43e096d2..3ad053f6de12 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1051,7 +1051,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1051 1051
1052 hdr = (struct ieee80211_hdr *) skb->data; 1052 hdr = (struct ieee80211_hdr *) skb->data;
1053 1053
1054 tx->sta = sta_info_get(local, hdr->addr1); 1054 if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr)
1055 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1056 if (!tx->sta)
1057 tx->sta = sta_info_get(local, hdr->addr1);
1055 1058
1056 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && 1059 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
1057 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { 1060 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1613,7 +1616,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1613 const u8 *encaps_data; 1616 const u8 *encaps_data;
1614 int encaps_len, skip_header_bytes; 1617 int encaps_len, skip_header_bytes;
1615 int nh_pos, h_pos; 1618 int nh_pos, h_pos;
1616 struct sta_info *sta; 1619 struct sta_info *sta = NULL;
1617 u32 sta_flags = 0; 1620 u32 sta_flags = 0;
1618 1621
1619 if (unlikely(skb->len < ETH_HLEN)) { 1622 if (unlikely(skb->len < ETH_HLEN)) {
@@ -1630,8 +1633,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1630 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); 1633 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
1631 1634
1632 switch (sdata->vif.type) { 1635 switch (sdata->vif.type) {
1633 case NL80211_IFTYPE_AP:
1634 case NL80211_IFTYPE_AP_VLAN: 1636 case NL80211_IFTYPE_AP_VLAN:
1637 rcu_read_lock();
1638 if (sdata->use_4addr)
1639 sta = rcu_dereference(sdata->u.vlan.sta);
1640 if (sta) {
1641 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1642 /* RA TA DA SA */
1643 memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
1644 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1645 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1646 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1647 hdrlen = 30;
1648 sta_flags = get_sta_flags(sta);
1649 }
1650 rcu_read_unlock();
1651 if (sta)
1652 break;
1653 /* fall through */
1654 case NL80211_IFTYPE_AP:
1635 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); 1655 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
1636 /* DA BSSID SA */ 1656 /* DA BSSID SA */
1637 memcpy(hdr.addr1, skb->data, ETH_ALEN); 1657 memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1705,12 +1725,21 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1705 break; 1725 break;
1706#endif 1726#endif
1707 case NL80211_IFTYPE_STATION: 1727 case NL80211_IFTYPE_STATION:
1708 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
1709 /* BSSID SA DA */
1710 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 1728 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1711 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 1729 if (sdata->use_4addr && ethertype != ETH_P_PAE) {
1712 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1730 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1713 hdrlen = 24; 1731 /* RA TA DA SA */
1732 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1733 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1734 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1735 hdrlen = 30;
1736 } else {
1737 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
1738 /* BSSID SA DA */
1739 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
1740 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1741 hdrlen = 24;
1742 }
1714 break; 1743 break;
1715 case NL80211_IFTYPE_ADHOC: 1744 case NL80211_IFTYPE_ADHOC:
1716 /* DA SA BSSID */ 1745 /* DA SA BSSID */
@@ -2119,7 +2148,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2119 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); 2148 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2120 memset(mgmt->da, 0xff, ETH_ALEN); 2149 memset(mgmt->da, 0xff, ETH_ALEN);
2121 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 2150 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
2122 /* BSSID is left zeroed, wildcard value */ 2151 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
2123 mgmt->u.beacon.beacon_int = 2152 mgmt->u.beacon.beacon_int =
2124 cpu_to_le16(sdata->vif.bss_conf.beacon_int); 2153 cpu_to_le16(sdata->vif.bss_conf.beacon_int);
2125 mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ 2154 mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index aedbaaa067e6..da86e1592f8c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -685,6 +685,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
685 elems->perr = pos; 685 elems->perr = pos;
686 elems->perr_len = elen; 686 elems->perr_len = elen;
687 break; 687 break;
688 case WLAN_EID_RANN:
689 if (elen >= sizeof(struct ieee80211_rann_ie))
690 elems->rann = (void *)pos;
691 break;
688 case WLAN_EID_CHANNEL_SWITCH: 692 case WLAN_EID_CHANNEL_SWITCH:
689 elems->ch_switch_elem = pos; 693 elems->ch_switch_elem = pos;
690 elems->ch_switch_elem_len = elen; 694 elems->ch_switch_elem_len = elen;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8ed62b6c172b..37264d56bace 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -138,6 +138,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
138 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, 138 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, 139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
140 [NL80211_ATTR_PID] = { .type = NLA_U32 }, 140 [NL80211_ATTR_PID] = { .type = NLA_U32 },
141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
141}; 142};
142 143
143/* policy for the attributes */ 144/* policy for the attributes */
@@ -151,6 +152,26 @@ nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
151 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 152 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
152}; 153};
153 154
155/* ifidx get helper */
156static int nl80211_get_ifidx(struct netlink_callback *cb)
157{
158 int res;
159
160 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
161 nl80211_fam.attrbuf, nl80211_fam.maxattr,
162 nl80211_policy);
163 if (res)
164 return res;
165
166 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
167 return -EINVAL;
168
169 res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
170 if (!res)
171 return -EINVAL;
172 return res;
173}
174
154/* IE validation */ 175/* IE validation */
155static bool is_valid_ie_attr(const struct nlattr *attr) 176static bool is_valid_ie_attr(const struct nlattr *attr)
156{ 177{
@@ -987,6 +1008,13 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
987 change = true; 1008 change = true;
988 } 1009 }
989 1010
1011 if (info->attrs[NL80211_ATTR_4ADDR]) {
1012 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1013 change = true;
1014 } else {
1015 params.use_4addr = -1;
1016 }
1017
990 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 1018 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
991 if (ntype != NL80211_IFTYPE_MONITOR) { 1019 if (ntype != NL80211_IFTYPE_MONITOR) {
992 err = -EINVAL; 1020 err = -EINVAL;
@@ -1053,6 +1081,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1053 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1081 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1054 } 1082 }
1055 1083
1084 if (info->attrs[NL80211_ATTR_4ADDR])
1085 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1086
1056 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1087 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1057 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1088 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
1058 &flags); 1089 &flags);
@@ -1682,20 +1713,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
1682 int sta_idx = cb->args[1]; 1713 int sta_idx = cb->args[1];
1683 int err; 1714 int err;
1684 1715
1685 if (!ifidx) { 1716 if (!ifidx)
1686 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1717 ifidx = nl80211_get_ifidx(cb);
1687 nl80211_fam.attrbuf, nl80211_fam.maxattr, 1718 if (ifidx < 0)
1688 nl80211_policy); 1719 return ifidx;
1689 if (err)
1690 return err;
1691
1692 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1693 return -EINVAL;
1694
1695 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1696 if (!ifidx)
1697 return -EINVAL;
1698 }
1699 1720
1700 rtnl_lock(); 1721 rtnl_lock();
1701 1722
@@ -1800,7 +1821,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1800} 1821}
1801 1822
1802/* 1823/*
1803 * Get vlan interface making sure it is on the right wiphy. 1824 * Get vlan interface making sure it is running and on the right wiphy.
1804 */ 1825 */
1805static int get_vlan(struct genl_info *info, 1826static int get_vlan(struct genl_info *info,
1806 struct cfg80211_registered_device *rdev, 1827 struct cfg80211_registered_device *rdev,
@@ -1818,6 +1839,8 @@ static int get_vlan(struct genl_info *info,
1818 return -EINVAL; 1839 return -EINVAL;
1819 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) 1840 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1820 return -EINVAL; 1841 return -EINVAL;
1842 if (!netif_running(*vlan))
1843 return -ENETDOWN;
1821 } 1844 }
1822 return 0; 1845 return 0;
1823} 1846}
@@ -2105,9 +2128,9 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
2105 if (pinfo->filled & MPATH_INFO_FRAME_QLEN) 2128 if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
2106 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, 2129 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
2107 pinfo->frame_qlen); 2130 pinfo->frame_qlen);
2108 if (pinfo->filled & MPATH_INFO_DSN) 2131 if (pinfo->filled & MPATH_INFO_SN)
2109 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN, 2132 NLA_PUT_U32(msg, NL80211_MPATH_INFO_SN,
2110 pinfo->dsn); 2133 pinfo->sn);
2111 if (pinfo->filled & MPATH_INFO_METRIC) 2134 if (pinfo->filled & MPATH_INFO_METRIC)
2112 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, 2135 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
2113 pinfo->metric); 2136 pinfo->metric);
@@ -2145,20 +2168,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
2145 int path_idx = cb->args[1]; 2168 int path_idx = cb->args[1];
2146 int err; 2169 int err;
2147 2170
2148 if (!ifidx) { 2171 if (!ifidx)
2149 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 2172 ifidx = nl80211_get_ifidx(cb);
2150 nl80211_fam.attrbuf, nl80211_fam.maxattr, 2173 if (ifidx < 0)
2151 nl80211_policy); 2174 return ifidx;
2152 if (err)
2153 return err;
2154
2155 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
2156 return -EINVAL;
2157
2158 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
2159 if (!ifidx)
2160 return -EINVAL;
2161 }
2162 2175
2163 rtnl_lock(); 2176 rtnl_lock();
2164 2177
@@ -2605,6 +2618,8 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2605 cur_params.dot11MeshHWMPpreqMinInterval); 2618 cur_params.dot11MeshHWMPpreqMinInterval);
2606 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 2619 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2607 cur_params.dot11MeshHWMPnetDiameterTraversalTime); 2620 cur_params.dot11MeshHWMPnetDiameterTraversalTime);
2621 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
2622 cur_params.dot11MeshHWMPRootMode);
2608 nla_nest_end(msg, pinfoattr); 2623 nla_nest_end(msg, pinfoattr);
2609 genlmsg_end(msg, hdr); 2624 genlmsg_end(msg, hdr);
2610 err = genlmsg_reply(msg, info); 2625 err = genlmsg_reply(msg, info);
@@ -2715,6 +2730,10 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2715 dot11MeshHWMPnetDiameterTraversalTime, 2730 dot11MeshHWMPnetDiameterTraversalTime,
2716 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 2731 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2717 nla_get_u16); 2732 nla_get_u16);
2733 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
2734 dot11MeshHWMPRootMode, mask,
2735 NL80211_MESHCONF_HWMP_ROOTMODE,
2736 nla_get_u8);
2718 2737
2719 /* Apply changes */ 2738 /* Apply changes */
2720 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); 2739 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
@@ -3181,21 +3200,11 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3181 int start = cb->args[1], idx = 0; 3200 int start = cb->args[1], idx = 0;
3182 int err; 3201 int err;
3183 3202
3184 if (!ifidx) { 3203 if (!ifidx)
3185 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 3204 ifidx = nl80211_get_ifidx(cb);
3186 nl80211_fam.attrbuf, nl80211_fam.maxattr, 3205 if (ifidx < 0)
3187 nl80211_policy); 3206 return ifidx;
3188 if (err) 3207 cb->args[0] = ifidx;
3189 return err;
3190
3191 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
3192 return -EINVAL;
3193
3194 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
3195 if (!ifidx)
3196 return -EINVAL;
3197 cb->args[0] = ifidx;
3198 }
3199 3208
3200 dev = dev_get_by_index(sock_net(skb->sk), ifidx); 3209 dev = dev_get_by_index(sock_net(skb->sk), ifidx);
3201 if (!dev) 3210 if (!dev)
@@ -3238,6 +3247,106 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3238 return err; 3247 return err;
3239} 3248}
3240 3249
3250static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
3251 int flags, struct net_device *dev,
3252 struct survey_info *survey)
3253{
3254 void *hdr;
3255 struct nlattr *infoattr;
3256
3257 /* Survey without a channel doesn't make sense */
3258 if (!survey->channel)
3259 return -EINVAL;
3260
3261 hdr = nl80211hdr_put(msg, pid, seq, flags,
3262 NL80211_CMD_NEW_SURVEY_RESULTS);
3263 if (!hdr)
3264 return -ENOMEM;
3265
3266 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
3267
3268 infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO);
3269 if (!infoattr)
3270 goto nla_put_failure;
3271
3272 NLA_PUT_U32(msg, NL80211_SURVEY_INFO_FREQUENCY,
3273 survey->channel->center_freq);
3274 if (survey->filled & SURVEY_INFO_NOISE_DBM)
3275 NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE,
3276 survey->noise);
3277
3278 nla_nest_end(msg, infoattr);
3279
3280 return genlmsg_end(msg, hdr);
3281
3282 nla_put_failure:
3283 genlmsg_cancel(msg, hdr);
3284 return -EMSGSIZE;
3285}
3286
3287static int nl80211_dump_survey(struct sk_buff *skb,
3288 struct netlink_callback *cb)
3289{
3290 struct survey_info survey;
3291 struct cfg80211_registered_device *dev;
3292 struct net_device *netdev;
3293 int ifidx = cb->args[0];
3294 int survey_idx = cb->args[1];
3295 int res;
3296
3297 if (!ifidx)
3298 ifidx = nl80211_get_ifidx(cb);
3299 if (ifidx < 0)
3300 return ifidx;
3301 cb->args[0] = ifidx;
3302
3303 rtnl_lock();
3304
3305 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
3306 if (!netdev) {
3307 res = -ENODEV;
3308 goto out_rtnl;
3309 }
3310
3311 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
3312 if (IS_ERR(dev)) {
3313 res = PTR_ERR(dev);
3314 goto out_rtnl;
3315 }
3316
3317 if (!dev->ops->dump_survey) {
3318 res = -EOPNOTSUPP;
3319 goto out_err;
3320 }
3321
3322 while (1) {
3323 res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
3324 &survey);
3325 if (res == -ENOENT)
3326 break;
3327 if (res)
3328 goto out_err;
3329
3330 if (nl80211_send_survey(skb,
3331 NETLINK_CB(cb->skb).pid,
3332 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3333 netdev,
3334 &survey) < 0)
3335 goto out;
3336 survey_idx++;
3337 }
3338
3339 out:
3340 cb->args[1] = survey_idx;
3341 res = skb->len;
3342 out_err:
3343 cfg80211_unlock_rdev(dev);
3344 out_rtnl:
3345 rtnl_unlock();
3346
3347 return res;
3348}
3349
3241static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) 3350static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
3242{ 3351{
3243 return auth_type <= NL80211_AUTHTYPE_MAX; 3352 return auth_type <= NL80211_AUTHTYPE_MAX;
@@ -4315,6 +4424,11 @@ static struct genl_ops nl80211_ops[] = {
4315 .policy = nl80211_policy, 4424 .policy = nl80211_policy,
4316 .flags = GENL_ADMIN_PERM, 4425 .flags = GENL_ADMIN_PERM,
4317 }, 4426 },
4427 {
4428 .cmd = NL80211_CMD_GET_SURVEY,
4429 .policy = nl80211_policy,
4430 .dumpit = nl80211_dump_survey,
4431 },
4318}; 4432};
4319static struct genl_multicast_group nl80211_mlme_mcgrp = { 4433static struct genl_multicast_group nl80211_mlme_mcgrp = {
4320 .name = "mlme", 4434 .name = "mlme",
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3fc2df86278f..5aa39f7cf9b9 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -320,7 +320,9 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
320 break; 320 break;
321 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): 321 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
322 if (unlikely(iftype != NL80211_IFTYPE_WDS && 322 if (unlikely(iftype != NL80211_IFTYPE_WDS &&
323 iftype != NL80211_IFTYPE_MESH_POINT)) 323 iftype != NL80211_IFTYPE_MESH_POINT &&
324 iftype != NL80211_IFTYPE_AP_VLAN &&
325 iftype != NL80211_IFTYPE_STATION))
324 return -1; 326 return -1;
325 if (iftype == NL80211_IFTYPE_MESH_POINT) { 327 if (iftype == NL80211_IFTYPE_MESH_POINT) {
326 struct ieee80211s_hdr *meshdr = 328 struct ieee80211s_hdr *meshdr =