diff options
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r-- | net/mac80211/mesh.c | 165 |
1 files changed, 104 insertions, 61 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index f7364e56f1ee..859ee5f3d941 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 | * |
@@ -8,24 +8,21 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/slab.h> | ||
11 | #include <asm/unaligned.h> | 12 | #include <asm/unaligned.h> |
12 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
13 | #include "mesh.h" | 14 | #include "mesh.h" |
14 | 15 | ||
15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | 16 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) |
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | 17 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
18 | #define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) | ||
17 | 19 | ||
18 | #define PP_OFFSET 1 /* Path Selection Protocol */ | 20 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 |
19 | #define PM_OFFSET 5 /* Path Selection Metric */ | 21 | #define MESHCONF_CAPAB_FORWARDING 0x08 |
20 | #define CC_OFFSET 9 /* Congestion Control Mode */ | ||
21 | #define SP_OFFSET 13 /* Synchronization Protocol */ | ||
22 | #define AUTH_OFFSET 17 /* Authentication Protocol */ | ||
23 | #define CAPAB_OFFSET 22 | ||
24 | #define CAPAB_ACCEPT_PLINKS 0x80 | ||
25 | #define CAPAB_FORWARDING 0x10 | ||
26 | 22 | ||
27 | #define TMR_RUNNING_HK 0 | 23 | #define TMR_RUNNING_HK 0 |
28 | #define TMR_RUNNING_MP 1 | 24 | #define TMR_RUNNING_MP 1 |
25 | #define TMR_RUNNING_MPR 2 | ||
29 | 26 | ||
30 | int mesh_allocated; | 27 | int mesh_allocated; |
31 | static struct kmem_cache *rm_cache; | 28 | static struct kmem_cache *rm_cache; |
@@ -50,7 +47,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
50 | struct ieee80211_local *local = sdata->local; | 47 | struct ieee80211_local *local = sdata->local; |
51 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 48 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
52 | 49 | ||
53 | ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING; | 50 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
54 | 51 | ||
55 | if (local->quiescing) { | 52 | if (local->quiescing) { |
56 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 53 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
@@ -85,11 +82,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
85 | */ | 82 | */ |
86 | if (ifmsh->mesh_id_len == ie->mesh_id_len && | 83 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
87 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 84 | 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 && | 85 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && |
89 | memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && | 86 | (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) && |
90 | memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0 && | 87 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && |
91 | memcmp(ifmsh->mesh_sp_id, ie->mesh_config + SP_OFFSET, 4) == 0 && | 88 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && |
92 | memcmp(ifmsh->mesh_auth_id, ie->mesh_config + AUTH_OFFSET, 4) == 0) | 89 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)) |
93 | return true; | 90 | return true; |
94 | 91 | ||
95 | return false; | 92 | return false; |
@@ -102,7 +99,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
102 | */ | 99 | */ |
103 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 100 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
104 | { | 101 | { |
105 | return (*(ie->mesh_config + CAPAB_OFFSET) & CAPAB_ACCEPT_PLINKS) != 0; | 102 | return (ie->mesh_config->meshconf_cap & |
103 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | /** | 106 | /** |
@@ -128,18 +126,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
128 | 126 | ||
129 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) | 127 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) |
130 | { | 128 | { |
131 | u8 oui[3] = {0x00, 0x0F, 0xAC}; | 129 | sta->mesh_pp_id = 0; /* HWMP */ |
132 | 130 | sta->mesh_pm_id = 0; /* Airtime */ | |
133 | memcpy(sta->mesh_pp_id, oui, sizeof(oui)); | 131 | sta->mesh_cc_id = 0; /* Disabled */ |
134 | memcpy(sta->mesh_pm_id, oui, sizeof(oui)); | 132 | sta->mesh_sp_id = 0; /* Neighbor Offset */ |
135 | memcpy(sta->mesh_cc_id, oui, sizeof(oui)); | 133 | 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 | } | 134 | } |
144 | 135 | ||
145 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 136 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
@@ -205,8 +196,8 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
205 | list_del(&p->list); | 196 | list_del(&p->list); |
206 | kmem_cache_free(rm_cache, p); | 197 | kmem_cache_free(rm_cache, p); |
207 | --entries; | 198 | --entries; |
208 | } else if ((seqnum == p->seqnum) | 199 | } else if ((seqnum == p->seqnum) && |
209 | && (memcmp(sa, p->sa, ETH_ALEN) == 0)) | 200 | (memcmp(sa, p->sa, ETH_ALEN) == 0)) |
210 | return -1; | 201 | return -1; |
211 | } | 202 | } |
212 | 203 | ||
@@ -228,6 +219,7 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
228 | struct ieee80211_supported_band *sband; | 219 | struct ieee80211_supported_band *sband; |
229 | u8 *pos; | 220 | u8 *pos; |
230 | int len, i, rate; | 221 | int len, i, rate; |
222 | u8 neighbors; | ||
231 | 223 | ||
232 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 224 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
233 | len = sband->n_bitrates; | 225 | len = sband->n_bitrates; |
@@ -251,46 +243,49 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
251 | } | 243 | } |
252 | } | 244 | } |
253 | 245 | ||
246 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
247 | pos = skb_put(skb, 2 + 1); | ||
248 | *pos++ = WLAN_EID_DS_PARAMS; | ||
249 | *pos++ = 1; | ||
250 | *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); | ||
251 | } | ||
252 | |||
254 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); | 253 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
255 | *pos++ = WLAN_EID_MESH_ID; | 254 | *pos++ = WLAN_EID_MESH_ID; |
256 | *pos++ = sdata->u.mesh.mesh_id_len; | 255 | *pos++ = sdata->u.mesh.mesh_id_len; |
257 | if (sdata->u.mesh.mesh_id_len) | 256 | if (sdata->u.mesh.mesh_id_len) |
258 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); | 257 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
259 | 258 | ||
260 | pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN); | 259 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); |
261 | *pos++ = WLAN_EID_MESH_CONFIG; | 260 | *pos++ = WLAN_EID_MESH_CONFIG; |
262 | *pos++ = IEEE80211_MESH_CONFIG_LEN; | 261 | *pos++ = sizeof(struct ieee80211_meshconf_ie); |
263 | /* Version */ | ||
264 | *pos++ = 1; | ||
265 | 262 | ||
266 | /* Active path selection protocol ID */ | 263 | /* Active path selection protocol ID */ |
267 | memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); | 264 | *pos++ = sdata->u.mesh.mesh_pp_id; |
268 | pos += 4; | ||
269 | 265 | ||
270 | /* Active path selection metric ID */ | 266 | /* Active path selection metric ID */ |
271 | memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); | 267 | *pos++ = sdata->u.mesh.mesh_pm_id; |
272 | pos += 4; | ||
273 | 268 | ||
274 | /* Congestion control mode identifier */ | 269 | /* Congestion control mode identifier */ |
275 | memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); | 270 | *pos++ = sdata->u.mesh.mesh_cc_id; |
276 | pos += 4; | ||
277 | 271 | ||
278 | /* Synchronization protocol identifier */ | 272 | /* Synchronization protocol identifier */ |
279 | memcpy(pos, sdata->u.mesh.mesh_sp_id, 4); | 273 | *pos++ = sdata->u.mesh.mesh_sp_id; |
280 | pos += 4; | ||
281 | 274 | ||
282 | /* Authentication Protocol identifier */ | 275 | /* Authentication Protocol identifier */ |
283 | memcpy(pos, sdata->u.mesh.mesh_auth_id, 4); | 276 | *pos++ = sdata->u.mesh.mesh_auth_id; |
284 | pos += 4; | ||
285 | 277 | ||
286 | /* Mesh Formation Info */ | 278 | /* Mesh Formation Info - number of neighbors */ |
287 | memset(pos, 0x00, 1); | 279 | neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); |
288 | pos += 1; | 280 | /* Number of neighbor mesh STAs or 15 whichever is smaller */ |
281 | neighbors = (neighbors > 15) ? 15 : neighbors; | ||
282 | *pos++ = neighbors << 1; | ||
289 | 283 | ||
290 | /* Mesh capability */ | 284 | /* Mesh capability */ |
291 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); | 285 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
292 | *pos = CAPAB_FORWARDING; | 286 | *pos = MESHCONF_CAPAB_FORWARDING; |
293 | *pos++ |= sdata->u.mesh.accepting_plinks ? CAPAB_ACCEPT_PLINKS : 0x00; | 287 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | ||
294 | *pos++ = 0x00; | 289 | *pos++ = 0x00; |
295 | 290 | ||
296 | return; | 291 | return; |
@@ -355,6 +350,34 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
355 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 350 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
356 | } | 351 | } |
357 | 352 | ||
353 | static void ieee80211_mesh_path_root_timer(unsigned long data) | ||
354 | { | ||
355 | struct ieee80211_sub_if_data *sdata = | ||
356 | (struct ieee80211_sub_if_data *) data; | ||
357 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
358 | struct ieee80211_local *local = sdata->local; | ||
359 | |||
360 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | ||
361 | |||
362 | if (local->quiescing) { | ||
363 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | ieee80211_queue_work(&local->hw, &ifmsh->work); | ||
368 | } | ||
369 | |||
370 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | ||
371 | { | ||
372 | if (ifmsh->mshcfg.dot11MeshHWMPRootMode) | ||
373 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | ||
374 | else { | ||
375 | clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | ||
376 | /* stop running timer */ | ||
377 | del_timer_sync(&ifmsh->mesh_path_root_timer); | ||
378 | } | ||
379 | } | ||
380 | |||
358 | /** | 381 | /** |
359 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame | 382 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame |
360 | * @hdr: 802.11 frame header | 383 | * @hdr: 802.11 frame header |
@@ -365,8 +388,9 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
365 | * | 388 | * |
366 | * Return the length of the 802.11 (does not include a mesh control header) | 389 | * Return the length of the 802.11 (does not include a mesh control header) |
367 | */ | 390 | */ |
368 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char | 391 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
369 | *meshda, char *meshsa) { | 392 | const u8 *meshda, const u8 *meshsa) |
393 | { | ||
370 | if (is_multicast_ether_addr(meshda)) { | 394 | if (is_multicast_ether_addr(meshda)) { |
371 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 395 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
372 | /* DA TA SA */ | 396 | /* DA TA SA */ |
@@ -404,7 +428,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
404 | char *addr5, char *addr6) | 428 | char *addr5, char *addr6) |
405 | { | 429 | { |
406 | int aelen = 0; | 430 | int aelen = 0; |
407 | memset(meshhdr, 0, sizeof(meshhdr)); | 431 | memset(meshhdr, 0, sizeof(*meshhdr)); |
408 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 432 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
409 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 433 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
410 | sdata->u.mesh.mesh_seqnum++; | 434 | sdata->u.mesh.mesh_seqnum++; |
@@ -434,7 +458,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
434 | 458 | ||
435 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 459 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
436 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 460 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", |
437 | sdata->dev->name); | 461 | sdata->name); |
438 | #endif | 462 | #endif |
439 | 463 | ||
440 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 464 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
@@ -448,6 +472,15 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
448 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 472 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); |
449 | } | 473 | } |
450 | 474 | ||
475 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | ||
476 | { | ||
477 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
478 | |||
479 | mesh_path_tx_root_frame(sdata); | ||
480 | mod_timer(&ifmsh->mesh_path_root_timer, | ||
481 | round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); | ||
482 | } | ||
483 | |||
451 | #ifdef CONFIG_PM | 484 | #ifdef CONFIG_PM |
452 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | 485 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) |
453 | { | 486 | { |
@@ -462,6 +495,8 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | |||
462 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 495 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
463 | if (del_timer_sync(&ifmsh->mesh_path_timer)) | 496 | if (del_timer_sync(&ifmsh->mesh_path_timer)) |
464 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | 497 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); |
498 | if (del_timer_sync(&ifmsh->mesh_path_root_timer)) | ||
499 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
465 | } | 500 | } |
466 | 501 | ||
467 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | 502 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) |
@@ -472,6 +507,9 @@ void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | |||
472 | add_timer(&ifmsh->housekeeping_timer); | 507 | add_timer(&ifmsh->housekeeping_timer); |
473 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) | 508 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) |
474 | add_timer(&ifmsh->mesh_path_timer); | 509 | add_timer(&ifmsh->mesh_path_timer); |
510 | if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) | ||
511 | add_timer(&ifmsh->mesh_path_root_timer); | ||
512 | ieee80211_mesh_root_setup(ifmsh); | ||
475 | } | 513 | } |
476 | #endif | 514 | #endif |
477 | 515 | ||
@@ -480,7 +518,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
480 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 518 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
481 | struct ieee80211_local *local = sdata->local; | 519 | struct ieee80211_local *local = sdata->local; |
482 | 520 | ||
483 | ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING; | 521 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
522 | ieee80211_mesh_root_setup(ifmsh); | ||
484 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 523 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
485 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 524 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
486 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 525 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
@@ -491,6 +530,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
491 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 530 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
492 | { | 531 | { |
493 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 532 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
533 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | ||
494 | /* | 534 | /* |
495 | * If the timer fired while we waited for it, it will have | 535 | * If the timer fired while we waited for it, it will have |
496 | * requeued the work. Now the work will be running again | 536 | * requeued the work. Now the work will be running again |
@@ -526,7 +566,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
526 | 566 | ||
527 | /* ignore ProbeResp to foreign address */ | 567 | /* ignore ProbeResp to foreign address */ |
528 | if (stype == IEEE80211_STYPE_PROBE_RESP && | 568 | if (stype == IEEE80211_STYPE_PROBE_RESP && |
529 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | 569 | compare_ether_addr(mgmt->da, sdata->vif.addr)) |
530 | return; | 570 | return; |
531 | 571 | ||
532 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 572 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -561,7 +601,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
561 | struct ieee80211_rx_status *rx_status) | 601 | struct ieee80211_rx_status *rx_status) |
562 | { | 602 | { |
563 | switch (mgmt->u.action.category) { | 603 | switch (mgmt->u.action.category) { |
564 | case PLINK_CATEGORY: | 604 | case MESH_PLINK_CATEGORY: |
565 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 605 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); |
566 | break; | 606 | break; |
567 | case MESH_PATH_SEL_CATEGORY: | 607 | case MESH_PATH_SEL_CATEGORY: |
@@ -606,7 +646,7 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
606 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 646 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
607 | struct sk_buff *skb; | 647 | struct sk_buff *skb; |
608 | 648 | ||
609 | if (!netif_running(sdata->dev)) | 649 | if (!ieee80211_sdata_running(sdata)) |
610 | return; | 650 | return; |
611 | 651 | ||
612 | if (local->scanning) | 652 | if (local->scanning) |
@@ -628,6 +668,9 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
628 | 668 | ||
629 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 669 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
630 | ieee80211_mesh_housekeeping(sdata, ifmsh); | 670 | ieee80211_mesh_housekeeping(sdata, ifmsh); |
671 | |||
672 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | ||
673 | ieee80211_mesh_rootpath(sdata); | ||
631 | } | 674 | } |
632 | 675 | ||
633 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | 676 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) |
@@ -673,7 +716,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
673 | MESH_MIN_DISCOVERY_TIMEOUT; | 716 | MESH_MIN_DISCOVERY_TIMEOUT; |
674 | ifmsh->accepting_plinks = true; | 717 | ifmsh->accepting_plinks = true; |
675 | ifmsh->preq_id = 0; | 718 | ifmsh->preq_id = 0; |
676 | ifmsh->dsn = 0; | 719 | ifmsh->sn = 0; |
677 | atomic_set(&ifmsh->mpaths, 0); | 720 | atomic_set(&ifmsh->mpaths, 0); |
678 | mesh_rmc_init(sdata); | 721 | mesh_rmc_init(sdata); |
679 | ifmsh->last_preq = jiffies; | 722 | ifmsh->last_preq = jiffies; |
@@ -684,6 +727,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
684 | setup_timer(&ifmsh->mesh_path_timer, | 727 | setup_timer(&ifmsh->mesh_path_timer, |
685 | ieee80211_mesh_path_timer, | 728 | ieee80211_mesh_path_timer, |
686 | (unsigned long) sdata); | 729 | (unsigned long) sdata); |
730 | setup_timer(&ifmsh->mesh_path_root_timer, | ||
731 | ieee80211_mesh_path_root_timer, | ||
732 | (unsigned long) sdata); | ||
687 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 733 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
688 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 734 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
689 | } | 735 | } |
@@ -704,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
704 | 750 | ||
705 | switch (fc & IEEE80211_FCTL_STYPE) { | 751 | switch (fc & IEEE80211_FCTL_STYPE) { |
706 | case IEEE80211_STYPE_ACTION: | 752 | case IEEE80211_STYPE_ACTION: |
707 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
708 | return RX_DROP_MONITOR; | ||
709 | /* fall through */ | ||
710 | case IEEE80211_STYPE_PROBE_RESP: | 753 | case IEEE80211_STYPE_PROBE_RESP: |
711 | case IEEE80211_STYPE_BEACON: | 754 | case IEEE80211_STYPE_BEACON: |
712 | skb_queue_tail(&ifmsh->skb_queue, skb); | 755 | skb_queue_tail(&ifmsh->skb_queue, skb); |