diff options
Diffstat (limited to 'net/mac80211/mesh.c')
| -rw-r--r-- | net/mac80211/mesh.c | 74 | 
1 files changed, 52 insertions, 22 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e5fbb7cf356..0675a2fec6a 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,21 @@ 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_HT20 && +	    sta_channel_type > NL80211_CHAN_HT20 && +	    local->_oper_channel_type != sta_channel_type)  		goto mismatch;  	return true; @@ -204,7 +215,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 +262,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 +384,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 +398,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 +587,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 +640,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 +674,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 +747,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 +790,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);  }  |