Skip to content

Commit

Permalink
mac80211: Implement mesh synchronization framework
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Javier Cardona authored and John W. Linville committed Apr 10, 2012
1 parent 9bdd3a6 commit dbf498f
Show file tree
Hide file tree
Showing 10 changed files with 392 additions and 8 deletions.
12 changes: 12 additions & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,18 @@ enum ieee80211_tdls_actioncode {
/* TDLS specific payload type in the LLC/SNAP header */
#define WLAN_TDLS_SNAP_RFTYPE 0x2

/**
* enum - mesh synchronization method identifier
*
* @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method
* @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method
* that will be specified in a vendor specific information element
*/
enum {
IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1,
IEEE80211_SYNC_METHOD_VENDOR = 255,
};

/**
* enum - mesh path selection protocol identifier
*
Expand Down
11 changes: 11 additions & 0 deletions net/mac80211/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ config MAC80211_VERBOSE_MHWMP_DEBUG

Do not select this option.

config MAC80211_VERBOSE_MESH_SYNC_DEBUG
bool "Verbose mesh mesh synchronization debugging"
depends on MAC80211_DEBUG_MENU
depends on MAC80211_MESH
---help---
Selecting this option causes mac80211 to print out very verbose mesh
synchronization debugging messages (when mac80211 is taking part in a
mesh network).

Do not select this option.

config MAC80211_VERBOSE_TDLS_DEBUG
bool "Verbose TDLS debugging"
depends on MAC80211_DEBUG_MENU
Expand Down
3 changes: 2 additions & 1 deletion net/mac80211/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
mesh.o \
mesh_pathtbl.o \
mesh_plink.o \
mesh_hwmp.o
mesh_hwmp.o \
mesh_sync.o

mac80211-$(CONFIG_PM) += pm.o

Expand Down
5 changes: 3 additions & 2 deletions net/mac80211/debugfs_sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,16 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""

int res = scnprintf(buf, sizeof(buf),
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
TEST(PS_DRIVER), TEST(AUTHORIZED),
TEST(SHORT_PREAMBLE),
TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
TEST(INSERTED), TEST(RATE_CONTROL));
TEST(INSERTED), TEST(RATE_CONTROL),
TEST(TOFFSET_KNOWN));
#undef TEST
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
Expand Down
23 changes: 23 additions & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,24 @@ struct ieee80211_if_ibss {
} state;
};

/**
* struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface
*
* these declarations define the interface, which enables
* vendor-specific mesh synchronization
*
*/
struct ieee802_11_elems;
struct ieee80211_mesh_sync_ops {
void (*rx_bcn_presp)(struct ieee80211_sub_if_data *sdata,
u16 stype,
struct ieee80211_mgmt *mgmt,
struct ieee802_11_elems *elems,
struct ieee80211_rx_status *rx_status);
void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata);
/* add other framework functions here */
};

struct ieee80211_if_mesh {
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
Expand Down Expand Up @@ -602,6 +620,11 @@ struct ieee80211_if_mesh {
IEEE80211_MESH_SEC_AUTHED = 0x1,
IEEE80211_MESH_SEC_SECURED = 0x2,
} security;
/* Extensible Synchronization Framework */
struct ieee80211_mesh_sync_ops *sync_ops;
s64 sync_offset_clockdrift_max;
spinlock_t sync_offset_lock;
bool adjusting_tbtt;
};

#ifdef CONFIG_MAC80211_MESH
Expand Down
21 changes: 16 additions & 5 deletions net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
#include "ieee80211_i.h"
#include "mesh.h"

#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01
#define MESHCONF_CAPAB_FORWARDING 0x08

#define TMR_RUNNING_HK 0
#define TMR_RUNNING_MP 1
#define TMR_RUNNING_MPR 2
Expand Down Expand Up @@ -251,8 +248,10 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
/* Mesh capability */
ifmsh->accepting_plinks = mesh_plink_availables(sdata);
*pos = MESHCONF_CAPAB_FORWARDING;
*pos++ |= ifmsh->accepting_plinks ?
*pos |= ifmsh->accepting_plinks ?
MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;
*pos++ |= ifmsh->adjusting_tbtt ?
MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00;
*pos++ = 0x00;

return 0;
Expand Down Expand Up @@ -573,8 +572,11 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
ieee80211_configure_filter(local);

ifmsh->mesh_cc_id = 0; /* Disabled */
ifmsh->mesh_sp_id = 0; /* Neighbor Offset */
ifmsh->mesh_auth_id = 0; /* Disabled */
/* register sync ops from extensible synchronization framework */
ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id);
ifmsh->adjusting_tbtt = false;
ifmsh->sync_offset_clockdrift_max = 0;
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
ieee80211_mesh_root_setup(ifmsh);
ieee80211_queue_work(&local->hw, &sdata->work);
Expand Down Expand Up @@ -616,6 +618,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee802_11_elems elems;
struct ieee80211_channel *channel;
u32 supp_rates = 0;
Expand Down Expand Up @@ -654,6 +657,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
supp_rates = ieee80211_sta_get_rates(local, &elems, band);
mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);
}

if (ifmsh->sync_ops)
ifmsh->sync_ops->rx_bcn_presp(sdata,
stype, mgmt, &elems, rx_status);
}

static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
Expand Down Expand Up @@ -721,6 +728,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)

if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags))
ieee80211_mesh_rootpath(sdata);

if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
mesh_sync_adjust_tbtt(sdata);
}

void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
Expand Down Expand Up @@ -761,4 +771,5 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
(unsigned long) sdata);
INIT_LIST_HEAD(&ifmsh->preq_queue.list);
spin_lock_init(&ifmsh->mesh_preq_queue_lock);
spin_lock_init(&ifmsh->sync_offset_lock);
}
19 changes: 19 additions & 0 deletions net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@

/* Data structures */

/**
* enum mesh_config_capab_flags - mesh config IE capability flags
*
* @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish
* additional mesh peerings with other mesh STAs
* @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
* @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing
*/
enum mesh_config_capab_flags {
MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0),
MESHCONF_CAPAB_FORWARDING = BIT(3),
MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5),
};

/**
* enum mesh_path_flags - mac80211 mesh path flags
*
Expand Down Expand Up @@ -56,12 +70,15 @@ enum mesh_path_flags {
* @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
* grow
* @MESH_WORK_ROOT: the mesh root station needs to send a frame
* @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other
* mesh nodes
*/
enum mesh_deferred_task_flags {
MESH_WORK_HOUSEKEEPING,
MESH_WORK_GROW_MPATH_TABLE,
MESH_WORK_GROW_MPP_TABLE,
MESH_WORK_ROOT,
MESH_WORK_DRIFT_ADJUST,
};

/**
Expand Down Expand Up @@ -234,6 +251,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);

/* Mesh paths */
int mesh_nexthop_lookup(struct sk_buff *skb,
Expand Down Expand Up @@ -327,6 +345,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
void mesh_plink_quiesce(struct sta_info *sta);
void mesh_plink_restart(struct sta_info *sta);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
#else
#define mesh_allocated 0
static inline void
Expand Down
Loading

0 comments on commit dbf498f

Please sign in to comment.