diff options
-rw-r--r-- | include/linux/ieee80211.h | 4 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 20 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 12 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 61 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 5 |
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 @@ | |||
27 | int mesh_allocated; | 23 | int mesh_allocated; |
28 | static struct kmem_cache *rm_cache; | 24 | static struct kmem_cache *rm_cache; |
29 | 25 | ||
26 | #ifdef CONFIG_MAC80211_MESH | ||
27 | bool 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 | ||
33 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | ||
34 | { return false; } | ||
35 | #endif | ||
36 | |||
30 | void ieee80211s_init(void) | 37 | void 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 */ |
190 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 185 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
@@ -276,6 +271,7 @@ void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | |||
276 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | 271 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); |
277 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 272 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
278 | 273 | ||
274 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); | ||
279 | extern int mesh_paths_generation; | 275 | extern 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 | |||
1006 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | 1018 | mesh_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 | } |