aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c165
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
30int mesh_allocated; 27int mesh_allocated;
31static struct kmem_cache *rm_cache; 28static 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 */
103bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) 100bool 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
129void mesh_ids_set_default(struct ieee80211_if_mesh *sta) 127void 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
145int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) 136int 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
353static 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
370void 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 */
368int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char 391int 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
475static 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
452void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) 485void 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
467void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) 502void 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)
491void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 530void 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
633void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) 676void 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);