aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h4
-rw-r--r--net/mac80211/mesh.c20
-rw-r--r--net/mac80211/mesh.h12
-rw-r--r--net/mac80211/mesh_hwmp.c61
-rw-r--r--net/mac80211/mesh_pathtbl.c8
-rw-r--r--net/mac80211/rx.c5
6 files changed, 62 insertions, 48 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 58033c146dd3..03cfbf393a63 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -629,6 +629,7 @@ struct ieee80211_rann_ie {
629 u8 rann_ttl; 629 u8 rann_ttl;
630 u8 rann_addr[6]; 630 u8 rann_addr[6];
631 u32 rann_seq; 631 u32 rann_seq;
632 u32 rann_interval;
632 u32 rann_metric; 633 u32 rann_metric;
633} __attribute__ ((packed)); 634} __attribute__ ((packed));
634 635
@@ -1269,9 +1270,6 @@ enum ieee80211_category {
1269 WLAN_CATEGORY_MULTIHOP_ACTION = 14, 1270 WLAN_CATEGORY_MULTIHOP_ACTION = 14,
1270 WLAN_CATEGORY_SELF_PROTECTED = 15, 1271 WLAN_CATEGORY_SELF_PROTECTED = 15,
1271 WLAN_CATEGORY_WMM = 17, 1272 WLAN_CATEGORY_WMM = 17,
1272 /* TODO: remove MESH_PATH_SEL after mesh is updated
1273 * to current 802.11s draft */
1274 WLAN_CATEGORY_MESH_PATH_SEL = 32,
1275 WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, 1273 WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
1276 WLAN_CATEGORY_VENDOR_SPECIFIC = 127, 1274 WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
1277}; 1275};
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index da5e981c4833..ecdde6ce4df0 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -13,10 +13,6 @@
13#include "ieee80211_i.h" 13#include "ieee80211_i.h"
14#include "mesh.h" 14#include "mesh.h"
15 15
16#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
17#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
18#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)
19
20#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 16#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01
21#define MESHCONF_CAPAB_FORWARDING 0x08 17#define MESHCONF_CAPAB_FORWARDING 0x08
22 18
@@ -27,6 +23,17 @@
27int mesh_allocated; 23int mesh_allocated;
28static struct kmem_cache *rm_cache; 24static struct kmem_cache *rm_cache;
29 25
26#ifdef CONFIG_MAC80211_MESH
27bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
28{
29 return (mgmt->u.action.u.mesh_action.action_code ==
30 WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
31}
32#else
33bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
34{ return false; }
35#endif
36
30void ieee80211s_init(void) 37void ieee80211s_init(void)
31{ 38{
32 mesh_pathtbl_init(); 39 mesh_pathtbl_init();
@@ -671,8 +678,9 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
671 break; 678 break;
672 } 679 }
673 break; 680 break;
674 case WLAN_CATEGORY_MESH_PATH_SEL: 681 case WLAN_CATEGORY_MESH_ACTION:
675 mesh_rx_path_sel_frame(sdata, mgmt, len); 682 if (mesh_action_is_path_sel(mgmt))
683 mesh_rx_path_sel_frame(sdata, mgmt, len);
676 break; 684 break;
677 } 685 }
678} 686}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b794360d0dfb..3c7d0f8b376a 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -166,6 +166,9 @@ struct mesh_rmc {
166 u32 idx_mask; 166 u32 idx_mask;
167}; 167};
168 168
169#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
170#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
171#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)
169 172
170#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ 173#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
171 174
@@ -177,14 +180,6 @@ struct mesh_rmc {
177/* Maximum number of paths per interface */ 180/* Maximum number of paths per interface */
178#define MESH_MAX_MPATHS 1024 181#define MESH_MAX_MPATHS 1024
179 182
180/* Pending ANA approval */
181#define MESH_PATH_SEL_ACTION 0
182
183/* PERR reason codes */
184#define PEER_RCODE_UNSPECIFIED 11
185#define PERR_RCODE_NO_ROUTE 12
186#define PERR_RCODE_DEST_UNREACH 13
187
188/* Public interfaces */ 183/* Public interfaces */
189/* Various */ 184/* Various */
190int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, 185int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
@@ -276,6 +271,7 @@ void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
276void mesh_path_restart(struct ieee80211_sub_if_data *sdata); 271void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
277void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); 272void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
278 273
274bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
279extern int mesh_paths_generation; 275extern int mesh_paths_generation;
280 276
281#ifdef CONFIG_MAC80211_MESH 277#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 3d8e55ae6ab6..9c3c0b86a740 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -68,12 +68,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
68#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) 68#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
69#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) 69#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
70#define PREP_IE_TTL(x) PREQ_IE_TTL(x) 70#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
71#define PREP_IE_ORIG_ADDR(x) (x + 3) 71#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
72#define PREP_IE_ORIG_SN(x) u32_field_get(x, 9, 0) 72#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x))
73#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)) 73#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x))
74#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)) 74#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x))
75#define PREP_IE_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) 75#define PREP_IE_TARGET_ADDR(x) (x + 3)
76#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x)) 76#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0)
77 77
78#define PERR_IE_TTL(x) (*(x)) 78#define PERR_IE_TTL(x) (*(x))
79#define PERR_IE_TARGET_FLAGS(x) (*(x + 2)) 79#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
@@ -132,8 +132,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
132 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 132 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
133 /* BSSID == SA */ 133 /* BSSID == SA */
134 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 134 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
135 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 135 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
136 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 136 mgmt->u.action.u.mesh_action.action_code =
137 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
137 138
138 switch (action) { 139 switch (action) {
139 case MPATH_PREQ: 140 case MPATH_PREQ:
@@ -163,29 +164,37 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
163 *pos++ = flags; 164 *pos++ = flags;
164 *pos++ = hop_count; 165 *pos++ = hop_count;
165 *pos++ = ttl; 166 *pos++ = ttl;
166 if (action == MPATH_PREQ) { 167 if (action == MPATH_PREP) {
167 memcpy(pos, &preq_id, 4); 168 memcpy(pos, target, ETH_ALEN);
169 pos += ETH_ALEN;
170 memcpy(pos, &target_sn, 4);
168 pos += 4; 171 pos += 4;
169 } 172 } else {
170 memcpy(pos, orig_addr, ETH_ALEN); 173 if (action == MPATH_PREQ) {
171 pos += ETH_ALEN; 174 memcpy(pos, &preq_id, 4);
172 memcpy(pos, &orig_sn, 4); 175 pos += 4;
173 pos += 4; 176 }
174 if (action != MPATH_RANN) { 177 memcpy(pos, orig_addr, ETH_ALEN);
175 memcpy(pos, &lifetime, 4); 178 pos += ETH_ALEN;
179 memcpy(pos, &orig_sn, 4);
176 pos += 4; 180 pos += 4;
177 } 181 }
182 memcpy(pos, &lifetime, 4); /* interval for RANN */
183 pos += 4;
178 memcpy(pos, &metric, 4); 184 memcpy(pos, &metric, 4);
179 pos += 4; 185 pos += 4;
180 if (action == MPATH_PREQ) { 186 if (action == MPATH_PREQ) {
181 /* destination count */ 187 *pos++ = 1; /* destination count */
182 *pos++ = 1;
183 *pos++ = target_flags; 188 *pos++ = target_flags;
184 }
185 if (action != MPATH_RANN) {
186 memcpy(pos, target, ETH_ALEN); 189 memcpy(pos, target, ETH_ALEN);
187 pos += ETH_ALEN; 190 pos += ETH_ALEN;
188 memcpy(pos, &target_sn, 4); 191 memcpy(pos, &target_sn, 4);
192 pos += 4;
193 } else if (action == MPATH_PREP) {
194 memcpy(pos, orig_addr, ETH_ALEN);
195 pos += ETH_ALEN;
196 memcpy(pos, &orig_sn, 4);
197 pos += 4;
189 } 198 }
190 199
191 ieee80211_tx_skb(sdata, skb); 200 ieee80211_tx_skb(sdata, skb);
@@ -224,9 +233,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
224 233
225 memcpy(mgmt->da, ra, ETH_ALEN); 234 memcpy(mgmt->da, ra, ETH_ALEN);
226 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 235 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
227 /* BSSID is left zeroed, wildcard value */ 236 /* BSSID == SA */
228 mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; 237 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
229 mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; 238 mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
239 mgmt->u.action.u.mesh_action.action_code =
240 WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
230 ie_len = 15; 241 ie_len = 15;
231 pos = skb_put(skb, 2 + ie_len); 242 pos = skb_put(skb, 2 + ie_len);
232 *pos++ = WLAN_EID_PERR; 243 *pos++ = WLAN_EID_PERR;
@@ -683,6 +694,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
683 u8 ttl, flags, hopcount; 694 u8 ttl, flags, hopcount;
684 u8 *orig_addr; 695 u8 *orig_addr;
685 u32 orig_sn, metric; 696 u32 orig_sn, metric;
697 u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
686 698
687 ttl = rann->rann_ttl; 699 ttl = rann->rann_ttl;
688 if (ttl <= 1) { 700 if (ttl <= 1) {
@@ -715,7 +727,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
715 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, 727 mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
716 cpu_to_le32(orig_sn), 728 cpu_to_le32(orig_sn),
717 0, NULL, 0, broadcast_addr, 729 0, NULL, 0, broadcast_addr,
718 hopcount, ttl, 0, 730 hopcount, ttl, interval,
719 cpu_to_le32(metric + mpath->metric), 731 cpu_to_le32(metric + mpath->metric),
720 0, sdata); 732 0, sdata);
721 mpath->sn = orig_sn; 733 mpath->sn = orig_sn;
@@ -1006,10 +1018,11 @@ void
1006mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) 1018mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
1007{ 1019{
1008 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 1020 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
1021 u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
1009 1022
1010 mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, 1023 mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
1011 cpu_to_le32(++ifmsh->sn), 1024 cpu_to_le32(++ifmsh->sn),
1012 0, NULL, 0, broadcast_addr, 1025 0, NULL, 0, broadcast_addr,
1013 0, sdata->u.mesh.mshcfg.element_ttl, 1026 0, sdata->u.mesh.mshcfg.element_ttl,
1014 0, 0, 0, sdata); 1027 interval, 0, 0, sdata);
1015} 1028}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 068ee6518254..6ffcd53fe7d6 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -539,6 +539,7 @@ void mesh_plink_broken(struct sta_info *sta)
539 struct hlist_node *p; 539 struct hlist_node *p;
540 struct ieee80211_sub_if_data *sdata = sta->sdata; 540 struct ieee80211_sub_if_data *sdata = sta->sdata;
541 int i; 541 int i;
542 __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
542 543
543 rcu_read_lock(); 544 rcu_read_lock();
544 tbl = rcu_dereference(mesh_paths); 545 tbl = rcu_dereference(mesh_paths);
@@ -553,8 +554,7 @@ void mesh_plink_broken(struct sta_info *sta)
553 spin_unlock_bh(&mpath->state_lock); 554 spin_unlock_bh(&mpath->state_lock);
554 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, 555 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,
555 mpath->dst, cpu_to_le32(mpath->sn), 556 mpath->dst, cpu_to_le32(mpath->sn),
556 cpu_to_le16(PERR_RCODE_DEST_UNREACH), 557 reason, bcast, sdata);
557 bcast, sdata);
558 } else 558 } else
559 spin_unlock_bh(&mpath->state_lock); 559 spin_unlock_bh(&mpath->state_lock);
560 } 560 }
@@ -699,6 +699,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
699 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 699 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
700 struct mesh_path *mpath; 700 struct mesh_path *mpath;
701 u32 sn = 0; 701 u32 sn = 0;
702 __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);
702 703
703 if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { 704 if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {
704 u8 *ra, *da; 705 u8 *ra, *da;
@@ -709,8 +710,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
709 if (mpath) 710 if (mpath)
710 sn = ++mpath->sn; 711 sn = ++mpath->sn;
711 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, 712 mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data,
712 cpu_to_le32(sn), 713 cpu_to_le32(sn), reason, ra, sdata);
713 cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata);
714 } 714 }
715 715
716 kfree_skb(skb); 716 kfree_skb(skb);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3fb6dea36536..c4453fdd6e11 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2241,9 +2241,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2241 case WLAN_CATEGORY_MESH_ACTION: 2241 case WLAN_CATEGORY_MESH_ACTION:
2242 if (!ieee80211_vif_is_mesh(&sdata->vif)) 2242 if (!ieee80211_vif_is_mesh(&sdata->vif))
2243 break; 2243 break;
2244 goto queue; 2244 if (mesh_action_is_path_sel(mgmt) &&
2245 case WLAN_CATEGORY_MESH_PATH_SEL: 2245 (!mesh_path_sel_is_hwmp(sdata)))
2246 if (!mesh_path_sel_is_hwmp(sdata))
2247 break; 2246 break;
2248 goto queue; 2247 goto queue;
2249 } 2248 }