diff options
author | Javier Cardona <javier@cozybit.com> | 2012-03-31 14:31:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-10 15:20:31 -0400 |
commit | dbf498fbafa2c23139d5a990e94ed78bafbbea19 (patch) | |
tree | 723a2ed4575ab2178cbd210d85a19d5c968a95a1 /net/mac80211/mesh.c | |
parent | 9bdd3a6bf8513a0a9eda031d15b36e4677854243 (diff) |
mac80211: Implement mesh synchronization framework
This patch adds MBSS extensible synchronization framework (Sec.
13.13.2 of IEEE Std. 802.11-2012).
The framework is implemented via an ops table which defines the
following functions:
rx_bcn_presp() - this is called every time a mesh beacon is
received.
adjust_tbtt() - this is called immediately before a beacon is about
to be transmitted.
The default neighbor offset synchronization defined in the standard is
implemented. We also provide template functions for vendor specific
methods.
When neighbor offset synchronization is active (which is the default)
mesh neighbors in the same MBSS will track timing offsets to each other
and compensate clock drift.
In our tests we observed that this mesh synchronization implementation
successfully corrected drifts between stations of ~2PPM while
introducing a jitter of ~20us.
It is also possible to test this framework on mac80211_hwsim simulated
phys to see how it behaves under different topologies, over poor links,
etc.
Signed-off-by: Marco Porsch <marco.porsch@s2005.tu-chemnitz.de>
Signed-off-by: Pavel Zubarev <pavel.zubarev@gmail.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r-- | net/mac80211/mesh.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b05fa9ef866c..386dbca1eab3 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -13,9 +13,6 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 | ||
17 | #define MESHCONF_CAPAB_FORWARDING 0x08 | ||
18 | |||
19 | #define TMR_RUNNING_HK 0 | 16 | #define TMR_RUNNING_HK 0 |
20 | #define TMR_RUNNING_MP 1 | 17 | #define TMR_RUNNING_MP 1 |
21 | #define TMR_RUNNING_MPR 2 | 18 | #define TMR_RUNNING_MPR 2 |
@@ -251,8 +248,10 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
251 | /* Mesh capability */ | 248 | /* Mesh capability */ |
252 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); | 249 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); |
253 | *pos = MESHCONF_CAPAB_FORWARDING; | 250 | *pos = MESHCONF_CAPAB_FORWARDING; |
254 | *pos++ |= ifmsh->accepting_plinks ? | 251 | *pos |= ifmsh->accepting_plinks ? |
255 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 252 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
253 | *pos++ |= ifmsh->adjusting_tbtt ? | ||
254 | MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | ||
256 | *pos++ = 0x00; | 255 | *pos++ = 0x00; |
257 | 256 | ||
258 | return 0; | 257 | return 0; |
@@ -573,8 +572,11 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
573 | ieee80211_configure_filter(local); | 572 | ieee80211_configure_filter(local); |
574 | 573 | ||
575 | ifmsh->mesh_cc_id = 0; /* Disabled */ | 574 | ifmsh->mesh_cc_id = 0; /* Disabled */ |
576 | ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ | ||
577 | ifmsh->mesh_auth_id = 0; /* Disabled */ | 575 | ifmsh->mesh_auth_id = 0; /* Disabled */ |
576 | /* register sync ops from extensible synchronization framework */ | ||
577 | ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); | ||
578 | ifmsh->adjusting_tbtt = false; | ||
579 | ifmsh->sync_offset_clockdrift_max = 0; | ||
578 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 580 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
579 | ieee80211_mesh_root_setup(ifmsh); | 581 | ieee80211_mesh_root_setup(ifmsh); |
580 | ieee80211_queue_work(&local->hw, &sdata->work); | 582 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -616,6 +618,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
616 | struct ieee80211_rx_status *rx_status) | 618 | struct ieee80211_rx_status *rx_status) |
617 | { | 619 | { |
618 | struct ieee80211_local *local = sdata->local; | 620 | struct ieee80211_local *local = sdata->local; |
621 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
619 | struct ieee802_11_elems elems; | 622 | struct ieee802_11_elems elems; |
620 | struct ieee80211_channel *channel; | 623 | struct ieee80211_channel *channel; |
621 | u32 supp_rates = 0; | 624 | u32 supp_rates = 0; |
@@ -654,6 +657,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
654 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | 657 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); |
655 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); | 658 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); |
656 | } | 659 | } |
660 | |||
661 | if (ifmsh->sync_ops) | ||
662 | ifmsh->sync_ops->rx_bcn_presp(sdata, | ||
663 | stype, mgmt, &elems, rx_status); | ||
657 | } | 664 | } |
658 | 665 | ||
659 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | 666 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, |
@@ -721,6 +728,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
721 | 728 | ||
722 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | 729 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) |
723 | ieee80211_mesh_rootpath(sdata); | 730 | ieee80211_mesh_rootpath(sdata); |
731 | |||
732 | if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) | ||
733 | mesh_sync_adjust_tbtt(sdata); | ||
724 | } | 734 | } |
725 | 735 | ||
726 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | 736 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) |
@@ -761,4 +771,5 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
761 | (unsigned long) sdata); | 771 | (unsigned long) sdata); |
762 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 772 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
763 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 773 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
774 | spin_lock_init(&ifmsh->sync_offset_lock); | ||
764 | } | 775 | } |