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.c76
1 files changed, 54 insertions, 22 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index e5fbb7cf3562..2913113c5833 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -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
@@ -67,16 +64,19 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
/**
* mesh_matches_local - check if the config of a mesh point matches ours
*
- * @ie: information elements of a management frame from the mesh peer
* @sdata: local mesh subif
+ * @ie: information elements of a management frame from the mesh peer
*
* This function checks if the mesh configuration of a mesh point matches the
* local mesh configuration, i.e. if both nodes belong to the same mesh network.
*/
-bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata)
+bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
+ struct ieee802_11_elems *ie)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
+ u32 basic_rates = 0;
+ enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT;
/*
* As support for each feature is added, check for matching
@@ -97,10 +97,23 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
(ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
goto mismatch;
- /* disallow peering with mismatched channel types for now */
- if (ie->ht_info_elem &&
- (local->_oper_channel_type !=
- ieee80211_ht_info_to_channel_type(ie->ht_info_elem)))
+ ieee80211_sta_get_rates(local, ie, local->oper_channel->band,
+ &basic_rates);
+
+ if (sdata->vif.bss_conf.basic_rates != basic_rates)
+ goto mismatch;
+
+ if (ie->ht_operation)
+ sta_channel_type =
+ ieee80211_ht_oper_to_channel_type(ie->ht_operation);
+
+ /* Disallow HT40+/- mismatch */
+ if (ie->ht_operation &&
+ (local->_oper_channel_type == NL80211_CHAN_HT40MINUS ||
+ local->_oper_channel_type == NL80211_CHAN_HT40PLUS) &&
+ (sta_channel_type == NL80211_CHAN_HT40MINUS ||
+ sta_channel_type == NL80211_CHAN_HT40PLUS) &&
+ local->_oper_channel_type != sta_channel_type)
goto mismatch;
return true;
@@ -204,7 +217,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
kmem_cache_free(rm_cache, p);
--entries;
} else if ((seqnum == p->seqnum) &&
- (compare_ether_addr(sa, p->sa) == 0))
+ (ether_addr_equal(sa, p->sa)))
return -1;
}
@@ -251,8 +264,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;
@@ -371,7 +386,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
return 0;
}
-int mesh_add_ht_info_ie(struct sk_buff *skb,
+int mesh_add_ht_oper_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
@@ -385,11 +400,12 @@ int mesh_add_ht_info_ie(struct sk_buff *skb,
if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
return 0;
- if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info))
+ if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation))
return -ENOMEM;
- pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info));
- ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type);
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
+ ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type,
+ sdata->vif.bss_conf.ht_operation_mode);
return 0;
}
@@ -573,14 +589,24 @@ 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);
+ sdata->vif.bss_conf.ht_operation_mode =
+ ifmsh->mshcfg.ht_opmode;
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
+ sdata->vif.bss_conf.basic_rates =
+ ieee80211_mandatory_rates(sdata->local,
+ sdata->local->hw.conf.channel->band);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_HT |
+ BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT);
}
@@ -616,16 +642,16 @@ 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;
size_t baselen;
int freq;
enum ieee80211_band band = rx_status->band;
/* ignore ProbeResp to foreign address */
if (stype == IEEE80211_STYPE_PROBE_RESP &&
- compare_ether_addr(mgmt->da, sdata->vif.addr))
+ !ether_addr_equal(mgmt->da, sdata->vif.addr))
return;
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
@@ -650,10 +676,12 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
return;
if (elems.mesh_id && elems.mesh_config &&
- mesh_matches_local(&elems, sdata)) {
- supp_rates = ieee80211_sta_get_rates(local, &elems, band);
- mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);
- }
+ mesh_matches_local(sdata, &elems))
+ mesh_neighbour_update(sdata, mgmt->sa, &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,
@@ -721,6 +749,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)
@@ -761,4 +792,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);
}