diff options
author | Rui Paulo <rpaulo@gmail.com> | 2009-11-09 18:46:56 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-13 17:43:56 -0500 |
commit | e304bfd30f356f7b75d30cad0029ecca705fd590 (patch) | |
tree | 64b466a5d6b70dba13605d5ec1ae656801caa212 /net | |
parent | d19b3bf6384e66ac6e11a61ee31ed2cfe149f4d8 (diff) |
mac80211: implement a timer to send RANN action frames
RANN (Root Annoucement) frame TX. Send an action frame every second
trying to build a path to all nodes on the mesh.
Signed-off-by: Rui Paulo <rpaulo@gmail.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Reviewed-by: Andrey Yurovsky <andrey@cozybit.com>
Tested-by: Brian Cavagnolo <brian@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 39 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 11 |
4 files changed, 54 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fb54ddb9b27d..b63b99fb2fd3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -355,6 +355,7 @@ struct ieee80211_if_mesh { | |||
355 | struct work_struct work; | 355 | struct work_struct work; |
356 | struct timer_list housekeeping_timer; | 356 | struct timer_list housekeeping_timer; |
357 | struct timer_list mesh_path_timer; | 357 | struct timer_list mesh_path_timer; |
358 | struct timer_list mesh_path_root_timer; | ||
358 | struct sk_buff_head skb_queue; | 359 | struct sk_buff_head skb_queue; |
359 | 360 | ||
360 | unsigned long timers_running; | 361 | unsigned long timers_running; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 0f3e1147ec4f..88dcfe3030b1 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | 15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) |
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | 16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
17 | #define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) | ||
17 | 18 | ||
18 | #define MESHCONF_PP_OFFSET 0 /* Path Selection Protocol */ | 19 | #define MESHCONF_PP_OFFSET 0 /* Path Selection Protocol */ |
19 | #define MESHCONF_PM_OFFSET 1 /* Path Selection Metric */ | 20 | #define MESHCONF_PM_OFFSET 1 /* Path Selection Metric */ |
@@ -26,6 +27,7 @@ | |||
26 | 27 | ||
27 | #define TMR_RUNNING_HK 0 | 28 | #define TMR_RUNNING_HK 0 |
28 | #define TMR_RUNNING_MP 1 | 29 | #define TMR_RUNNING_MP 1 |
30 | #define TMR_RUNNING_MPR 2 | ||
29 | 31 | ||
30 | int mesh_allocated; | 32 | int mesh_allocated; |
31 | static struct kmem_cache *rm_cache; | 33 | static struct kmem_cache *rm_cache; |
@@ -354,6 +356,23 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
354 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 356 | ieee80211_queue_work(&local->hw, &ifmsh->work); |
355 | } | 357 | } |
356 | 358 | ||
359 | static void ieee80211_mesh_path_root_timer(unsigned long data) | ||
360 | { | ||
361 | struct ieee80211_sub_if_data *sdata = | ||
362 | (struct ieee80211_sub_if_data *) data; | ||
363 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
364 | struct ieee80211_local *local = sdata->local; | ||
365 | |||
366 | set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags); | ||
367 | |||
368 | if (local->quiescing) { | ||
369 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | ieee80211_queue_work(&local->hw, &ifmsh->work); | ||
374 | } | ||
375 | |||
357 | /** | 376 | /** |
358 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame | 377 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame |
359 | * @hdr: 802.11 frame header | 378 | * @hdr: 802.11 frame header |
@@ -447,6 +466,15 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
447 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 466 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); |
448 | } | 467 | } |
449 | 468 | ||
469 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | ||
470 | { | ||
471 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
472 | |||
473 | mesh_path_tx_root_frame(sdata); | ||
474 | mod_timer(&ifmsh->mesh_path_root_timer, | ||
475 | round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); | ||
476 | } | ||
477 | |||
450 | #ifdef CONFIG_PM | 478 | #ifdef CONFIG_PM |
451 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | 479 | void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) |
452 | { | 480 | { |
@@ -461,6 +489,8 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | |||
461 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); | 489 | set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); |
462 | if (del_timer_sync(&ifmsh->mesh_path_timer)) | 490 | if (del_timer_sync(&ifmsh->mesh_path_timer)) |
463 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); | 491 | set_bit(TMR_RUNNING_MP, &ifmsh->timers_running); |
492 | if (del_timer_sync(&ifmsh->mesh_path_root_timer)) | ||
493 | set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running); | ||
464 | } | 494 | } |
465 | 495 | ||
466 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | 496 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) |
@@ -471,6 +501,8 @@ void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | |||
471 | add_timer(&ifmsh->housekeeping_timer); | 501 | add_timer(&ifmsh->housekeeping_timer); |
472 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) | 502 | if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running)) |
473 | add_timer(&ifmsh->mesh_path_timer); | 503 | add_timer(&ifmsh->mesh_path_timer); |
504 | if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running)) | ||
505 | add_timer(&ifmsh->mesh_path_root_timer); | ||
474 | } | 506 | } |
475 | #endif | 507 | #endif |
476 | 508 | ||
@@ -490,6 +522,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
490 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 522 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
491 | { | 523 | { |
492 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 524 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
525 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | ||
493 | /* | 526 | /* |
494 | * If the timer fired while we waited for it, it will have | 527 | * If the timer fired while we waited for it, it will have |
495 | * requeued the work. Now the work will be running again | 528 | * requeued the work. Now the work will be running again |
@@ -627,6 +660,9 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
627 | 660 | ||
628 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 661 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
629 | ieee80211_mesh_housekeeping(sdata, ifmsh); | 662 | ieee80211_mesh_housekeeping(sdata, ifmsh); |
663 | |||
664 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | ||
665 | ieee80211_mesh_rootpath(sdata); | ||
630 | } | 666 | } |
631 | 667 | ||
632 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | 668 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) |
@@ -683,6 +719,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
683 | setup_timer(&ifmsh->mesh_path_timer, | 719 | setup_timer(&ifmsh->mesh_path_timer, |
684 | ieee80211_mesh_path_timer, | 720 | ieee80211_mesh_path_timer, |
685 | (unsigned long) sdata); | 721 | (unsigned long) sdata); |
722 | setup_timer(&ifmsh->mesh_path_root_timer, | ||
723 | ieee80211_mesh_path_root_timer, | ||
724 | (unsigned long) sdata); | ||
686 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 725 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
687 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 726 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
688 | } | 727 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index ee687add3927..00ee84258196 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -53,11 +53,13 @@ enum mesh_path_flags { | |||
53 | * to grow. | 53 | * to grow. |
54 | * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to | 54 | * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to |
55 | * grow | 55 | * grow |
56 | * @MESH_WORK_ROOT: the mesh root station needs to send a frame | ||
56 | */ | 57 | */ |
57 | enum mesh_deferred_task_flags { | 58 | enum mesh_deferred_task_flags { |
58 | MESH_WORK_HOUSEKEEPING, | 59 | MESH_WORK_HOUSEKEEPING, |
59 | MESH_WORK_GROW_MPATH_TABLE, | 60 | MESH_WORK_GROW_MPATH_TABLE, |
60 | MESH_WORK_GROW_MPP_TABLE, | 61 | MESH_WORK_GROW_MPP_TABLE, |
62 | MESH_WORK_ROOT, | ||
61 | }; | 63 | }; |
62 | 64 | ||
63 | /** | 65 | /** |
@@ -294,6 +296,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
294 | struct ieee80211_sub_if_data *sdata); | 296 | struct ieee80211_sub_if_data *sdata); |
295 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | 297 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); |
296 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | 298 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); |
299 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | ||
297 | 300 | ||
298 | extern int mesh_paths_generation; | 301 | extern int mesh_paths_generation; |
299 | 302 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index f03a27dfd616..7483894a3960 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -1003,3 +1003,14 @@ void mesh_path_timer(unsigned long data) | |||
1003 | endmpathtimer: | 1003 | endmpathtimer: |
1004 | rcu_read_unlock(); | 1004 | rcu_read_unlock(); |
1005 | } | 1005 | } |
1006 | |||
1007 | void | ||
1008 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | ||
1009 | { | ||
1010 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
1011 | |||
1012 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, | ||
1013 | cpu_to_le32(++ifmsh->sn), | ||
1014 | 0, NULL, 0, sdata->dev->broadcast, | ||
1015 | 0, MESH_TTL, 0, 0, 0, sdata); | ||
1016 | } | ||