diff options
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r-- | net/mac80211/mesh_plink.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index ffcbad75e09b..0f7c6e6a4248 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 | ||
70 | static inline | 70 | static 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; |
@@ -218,7 +222,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
218 | memcpy(pos, &reason, 2); | 222 | memcpy(pos, &reason, 2); |
219 | } | 223 | } |
220 | 224 | ||
221 | ieee80211_tx_skb(sdata, skb, 1); | 225 | ieee80211_tx_skb(sdata, skb); |
222 | return 0; | 226 | return 0; |
223 | } | 227 | } |
224 | 228 | ||
@@ -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; |