mac80211: backport MBSSID support
Required for an upcoming mt76 update Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -0,0 +1,144 @@ | |||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Wed, 15 Sep 2021 19:54:35 -0700 | ||||||
|  | Subject: [PATCH] mac80211: MBSSID support in interface handling | ||||||
|  |  | ||||||
|  | Configure multiple BSSID and enhanced multi-BSSID advertisement (EMA) | ||||||
|  | parameters in mac80211 for AP mode. | ||||||
|  |  | ||||||
|  | For each interface, 'mbssid_tx_vif' points to the transmitting interface of | ||||||
|  | the MBSSID set. The pointer is set to NULL if MBSSID is disabled. | ||||||
|  |  | ||||||
|  | Function ieee80211_stop() is modified to always bring down all the | ||||||
|  | non-transmitting interfaces first and the transmitting interface last. | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | Co-developed-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Link: https://lore.kernel.org/r/20210916025437.29138-3-alokad@codeaurora.org | ||||||
|  | [slightly change logic to be more obvious] | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/net/mac80211.h | ||||||
|  | +++ b/include/net/mac80211.h | ||||||
|  | @@ -1719,6 +1719,7 @@ enum ieee80211_offload_flags { | ||||||
|  |   *	write-protected by sdata_lock and local->mtx so holding either is fine | ||||||
|  |   *	for read access. | ||||||
|  |   * @color_change_color: the bss color that will be used after the change. | ||||||
|  | + * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled. | ||||||
|  |   */ | ||||||
|  |  struct ieee80211_vif { | ||||||
|  |  	enum nl80211_iftype type; | ||||||
|  | @@ -1750,6 +1751,8 @@ struct ieee80211_vif { | ||||||
|  |  	bool color_change_active; | ||||||
|  |  	u8 color_change_color; | ||||||
|  |   | ||||||
|  | +	struct ieee80211_vif *mbssid_tx_vif; | ||||||
|  | + | ||||||
|  |  	/* must be last */ | ||||||
|  |  	u8 drv_priv[] __aligned(sizeof(void *)); | ||||||
|  |  }; | ||||||
|  | --- a/net/mac80211/cfg.c | ||||||
|  | +++ b/net/mac80211/cfg.c | ||||||
|  | @@ -112,6 +112,36 @@ static int ieee80211_set_mon_options(str | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, | ||||||
|  | +					   struct cfg80211_mbssid_config params) | ||||||
|  | +{ | ||||||
|  | +	struct ieee80211_sub_if_data *tx_sdata; | ||||||
|  | + | ||||||
|  | +	sdata->vif.mbssid_tx_vif = NULL; | ||||||
|  | +	sdata->vif.bss_conf.bssid_index = 0; | ||||||
|  | +	sdata->vif.bss_conf.nontransmitted = false; | ||||||
|  | +	sdata->vif.bss_conf.ema_ap = false; | ||||||
|  | + | ||||||
|  | +	if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	tx_sdata = IEEE80211_WDEV_TO_SUB_IF(params.tx_wdev); | ||||||
|  | +	if (!tx_sdata) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	if (tx_sdata == sdata) { | ||||||
|  | +		sdata->vif.mbssid_tx_vif = &sdata->vif; | ||||||
|  | +	} else { | ||||||
|  | +		sdata->vif.mbssid_tx_vif = &tx_sdata->vif; | ||||||
|  | +		sdata->vif.bss_conf.nontransmitted = true; | ||||||
|  | +		sdata->vif.bss_conf.bssid_index = params.index; | ||||||
|  | +	} | ||||||
|  | +	if (params.ema) | ||||||
|  | +		sdata->vif.bss_conf.ema_ap = true; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, | ||||||
|  |  						const char *name, | ||||||
|  |  						unsigned char name_assign_type, | ||||||
|  | @@ -1107,6 +1137,14 @@ static int ieee80211_start_ap(struct wip | ||||||
|  |  			changed |= BSS_CHANGED_HE_BSS_COLOR; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (sdata->vif.type == NL80211_IFTYPE_AP && | ||||||
|  | +	    params->mbssid_config.tx_wdev) { | ||||||
|  | +		err = ieee80211_set_ap_mbssid_options(sdata, | ||||||
|  | +						      params->mbssid_config); | ||||||
|  | +		if (err) | ||||||
|  | +			return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	mutex_lock(&local->mtx); | ||||||
|  |  	err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, | ||||||
|  |  					IEEE80211_CHANCTX_SHARED); | ||||||
|  | --- a/net/mac80211/iface.c | ||||||
|  | +++ b/net/mac80211/iface.c | ||||||
|  | @@ -632,17 +632,46 @@ static void ieee80211_do_stop(struct iee | ||||||
|  |  		ieee80211_add_virtual_monitor(local); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) | ||||||
|  | +{ | ||||||
|  | +	struct ieee80211_sub_if_data *tx_sdata, *non_tx_sdata, *tmp_sdata; | ||||||
|  | +	struct ieee80211_vif *tx_vif = sdata->vif.mbssid_tx_vif; | ||||||
|  | + | ||||||
|  | +	if (!tx_vif) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	tx_sdata = vif_to_sdata(tx_vif); | ||||||
|  | +	sdata->vif.mbssid_tx_vif = NULL; | ||||||
|  | + | ||||||
|  | +	list_for_each_entry_safe(non_tx_sdata, tmp_sdata, | ||||||
|  | +				 &tx_sdata->local->interfaces, list) { | ||||||
|  | +		if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata && | ||||||
|  | +		    non_tx_sdata->vif.mbssid_tx_vif == tx_vif && | ||||||
|  | +		    ieee80211_sdata_running(non_tx_sdata)) { | ||||||
|  | +			non_tx_sdata->vif.mbssid_tx_vif = NULL; | ||||||
|  | +			dev_close(non_tx_sdata->wdev.netdev); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) { | ||||||
|  | +		tx_sdata->vif.mbssid_tx_vif = NULL; | ||||||
|  | +		dev_close(tx_sdata->wdev.netdev); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int ieee80211_stop(struct net_device *dev) | ||||||
|  |  { | ||||||
|  |  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||||||
|  |   | ||||||
|  | -	/* close all dependent VLAN interfaces before locking wiphy */ | ||||||
|  | +	/* close dependent VLAN and MBSSID interfaces before locking wiphy */ | ||||||
|  |  	if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||||||
|  |  		struct ieee80211_sub_if_data *vlan, *tmpsdata; | ||||||
|  |   | ||||||
|  |  		list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | ||||||
|  |  					 u.vlan.list) | ||||||
|  |  			dev_close(vlan->dev); | ||||||
|  | + | ||||||
|  | +		ieee80211_stop_mbssid(sdata); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	wiphy_lock(sdata->local->hw.wiphy); | ||||||
| @@ -0,0 +1,326 @@ | |||||||
|  | From: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Date: Thu, 24 Feb 2022 12:54:58 +0100 | ||||||
|  | Subject: [PATCH] mac80211: MBSSID beacon handling in AP mode | ||||||
|  |  | ||||||
|  | Add new fields in struct beacon_data to store all MBSSID elements. | ||||||
|  | Generate a beacon template which includes all MBSSID elements. | ||||||
|  | Move CSA offset to reflect the MBSSID element length. | ||||||
|  |  | ||||||
|  | Co-developed-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Co-developed-by: John Crispin <john@phrozen.org> | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Tested-by: Money Wang <money.wang@mediatek.com> | ||||||
|  | Link: https://lore.kernel.org/r/5322db3c303f431adaf191ab31c45e151dde5465.1645702516.git.lorenzo@kernel.org | ||||||
|  | [small cleanups] | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/net/mac80211.h | ||||||
|  | +++ b/include/net/mac80211.h | ||||||
|  | @@ -4938,12 +4938,14 @@ void ieee80211_report_low_ack(struct iee | ||||||
|  |   * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets | ||||||
|  |   *	to countdown counters.  This array can contain zero values which | ||||||
|  |   *	should be ignored. | ||||||
|  | + * @mbssid_off: position of the multiple bssid element | ||||||
|  |   */ | ||||||
|  |  struct ieee80211_mutable_offsets { | ||||||
|  |  	u16 tim_offset; | ||||||
|  |  	u16 tim_length; | ||||||
|  |   | ||||||
|  |  	u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; | ||||||
|  | +	u16 mbssid_off; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | --- a/net/mac80211/cfg.c | ||||||
|  | +++ b/net/mac80211/cfg.c | ||||||
|  | @@ -989,11 +989,29 @@ static int ieee80211_set_ftm_responder_p | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int | ||||||
|  | +ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst, | ||||||
|  | +			     struct cfg80211_mbssid_elems *src) | ||||||
|  | +{ | ||||||
|  | +	int i, offset = 0; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < src->cnt; i++) { | ||||||
|  | +		memcpy(pos + offset, src->elem[i].data, src->elem[i].len); | ||||||
|  | +		dst->elem[i].len = src->elem[i].len; | ||||||
|  | +		dst->elem[i].data = pos + offset; | ||||||
|  | +		offset += dst->elem[i].len; | ||||||
|  | +	} | ||||||
|  | +	dst->cnt = src->cnt; | ||||||
|  | + | ||||||
|  | +	return offset; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | ||||||
|  |  				   struct cfg80211_beacon_data *params, | ||||||
|  |  				   const struct ieee80211_csa_settings *csa, | ||||||
|  |  				   const struct ieee80211_color_change_settings *cca) | ||||||
|  |  { | ||||||
|  | +	struct cfg80211_mbssid_elems *mbssid = NULL; | ||||||
|  |  	struct beacon_data *new, *old; | ||||||
|  |  	int new_head_len, new_tail_len; | ||||||
|  |  	int size, err; | ||||||
|  | @@ -1021,6 +1039,17 @@ static int ieee80211_assign_beacon(struc | ||||||
|  |   | ||||||
|  |  	size = sizeof(*new) + new_head_len + new_tail_len; | ||||||
|  |   | ||||||
|  | +	/* new or old multiple BSSID elements? */ | ||||||
|  | +	if (params->mbssid_ies) { | ||||||
|  | +		mbssid = params->mbssid_ies; | ||||||
|  | +		size += struct_size(new->mbssid_ies, elem, mbssid->cnt); | ||||||
|  | +		size += ieee80211_get_mbssid_beacon_len(mbssid); | ||||||
|  | +	} else if (old && old->mbssid_ies) { | ||||||
|  | +		mbssid = old->mbssid_ies; | ||||||
|  | +		size += struct_size(new->mbssid_ies, elem, mbssid->cnt); | ||||||
|  | +		size += ieee80211_get_mbssid_beacon_len(mbssid); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	new = kzalloc(size, GFP_KERNEL); | ||||||
|  |  	if (!new) | ||||||
|  |  		return -ENOMEM; | ||||||
|  | @@ -1029,12 +1058,20 @@ static int ieee80211_assign_beacon(struc | ||||||
|  |   | ||||||
|  |  	/* | ||||||
|  |  	 * pointers go into the block we allocated, | ||||||
|  | -	 * memory is | beacon_data | head | tail | | ||||||
|  | +	 * memory is | beacon_data | head | tail | mbssid_ies | ||||||
|  |  	 */ | ||||||
|  |  	new->head = ((u8 *) new) + sizeof(*new); | ||||||
|  |  	new->tail = new->head + new_head_len; | ||||||
|  |  	new->head_len = new_head_len; | ||||||
|  |  	new->tail_len = new_tail_len; | ||||||
|  | +	/* copy in optional mbssid_ies */ | ||||||
|  | +	if (mbssid) { | ||||||
|  | +		u8 *pos = new->tail + new->tail_len; | ||||||
|  | + | ||||||
|  | +		new->mbssid_ies = (void *)pos; | ||||||
|  | +		pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); | ||||||
|  | +		ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	if (csa) { | ||||||
|  |  		new->cntdwn_current_counter = csa->count; | ||||||
|  | @@ -1329,8 +1366,11 @@ static int ieee80211_stop_ap(struct wiph | ||||||
|  |   | ||||||
|  |  	mutex_unlock(&local->mtx); | ||||||
|  |   | ||||||
|  | -	kfree(sdata->u.ap.next_beacon); | ||||||
|  | -	sdata->u.ap.next_beacon = NULL; | ||||||
|  | +	if (sdata->u.ap.next_beacon) { | ||||||
|  | +		kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +		kfree(sdata->u.ap.next_beacon); | ||||||
|  | +		sdata->u.ap.next_beacon = NULL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	/* turn off carrier for this interface and dependent VLANs */ | ||||||
|  |  	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||||||
|  | @@ -3126,12 +3166,24 @@ cfg80211_beacon_dup(struct cfg80211_beac | ||||||
|  |   | ||||||
|  |  	len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + | ||||||
|  |  	      beacon->proberesp_ies_len + beacon->assocresp_ies_len + | ||||||
|  | -	      beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; | ||||||
|  | +	      beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + | ||||||
|  | +	      ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); | ||||||
|  |   | ||||||
|  |  	new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); | ||||||
|  |  	if (!new_beacon) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | +	if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) { | ||||||
|  | +		new_beacon->mbssid_ies = | ||||||
|  | +			kzalloc(struct_size(new_beacon->mbssid_ies, | ||||||
|  | +					    elem, beacon->mbssid_ies->cnt), | ||||||
|  | +				GFP_KERNEL); | ||||||
|  | +		if (!new_beacon->mbssid_ies) { | ||||||
|  | +			kfree(new_beacon); | ||||||
|  | +			return NULL; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	pos = (u8 *)(new_beacon + 1); | ||||||
|  |  	if (beacon->head_len) { | ||||||
|  |  		new_beacon->head_len = beacon->head_len; | ||||||
|  | @@ -3169,6 +3221,10 @@ cfg80211_beacon_dup(struct cfg80211_beac | ||||||
|  |  		memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); | ||||||
|  |  		pos += beacon->probe_resp_len; | ||||||
|  |  	} | ||||||
|  | +	if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) | ||||||
|  | +		pos += ieee80211_copy_mbssid_beacon(pos, | ||||||
|  | +						    new_beacon->mbssid_ies, | ||||||
|  | +						    beacon->mbssid_ies); | ||||||
|  |   | ||||||
|  |  	/* might copy -1, meaning no changes requested */ | ||||||
|  |  	new_beacon->ftm_responder = beacon->ftm_responder; | ||||||
|  | @@ -3206,8 +3262,11 @@ static int ieee80211_set_after_csa_beaco | ||||||
|  |  	case NL80211_IFTYPE_AP: | ||||||
|  |  		err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, | ||||||
|  |  					      NULL, NULL); | ||||||
|  | -		kfree(sdata->u.ap.next_beacon); | ||||||
|  | -		sdata->u.ap.next_beacon = NULL; | ||||||
|  | +		if (sdata->u.ap.next_beacon) { | ||||||
|  | +			kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +			kfree(sdata->u.ap.next_beacon); | ||||||
|  | +			sdata->u.ap.next_beacon = NULL; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  |  		if (err < 0) | ||||||
|  |  			return err; | ||||||
|  | @@ -3362,8 +3421,12 @@ static int ieee80211_set_csa_beacon(stru | ||||||
|  |  		if ((params->n_counter_offsets_beacon > | ||||||
|  |  		     IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || | ||||||
|  |  		    (params->n_counter_offsets_presp > | ||||||
|  | -		     IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) | ||||||
|  | +		     IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { | ||||||
|  | +			kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +			kfree(sdata->u.ap.next_beacon); | ||||||
|  | +			sdata->u.ap.next_beacon = NULL; | ||||||
|  |  			return -EINVAL; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  |  		csa.counter_offsets_beacon = params->counter_offsets_beacon; | ||||||
|  |  		csa.counter_offsets_presp = params->counter_offsets_presp; | ||||||
|  | @@ -3373,7 +3436,9 @@ static int ieee80211_set_csa_beacon(stru | ||||||
|  |   | ||||||
|  |  		err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); | ||||||
|  |  		if (err < 0) { | ||||||
|  | +			kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  |  			kfree(sdata->u.ap.next_beacon); | ||||||
|  | +			sdata->u.ap.next_beacon = NULL; | ||||||
|  |  			return err; | ||||||
|  |  		} | ||||||
|  |  		*changed |= err; | ||||||
|  | @@ -3463,8 +3528,11 @@ static int ieee80211_set_csa_beacon(stru | ||||||
|  |  static void ieee80211_color_change_abort(struct ieee80211_sub_if_data  *sdata) | ||||||
|  |  { | ||||||
|  |  	sdata->vif.color_change_active = false; | ||||||
|  | -	kfree(sdata->u.ap.next_beacon); | ||||||
|  | -	sdata->u.ap.next_beacon = NULL; | ||||||
|  | +	if (sdata->u.ap.next_beacon) { | ||||||
|  | +		kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +		kfree(sdata->u.ap.next_beacon); | ||||||
|  | +		sdata->u.ap.next_beacon = NULL; | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	cfg80211_color_change_aborted_notify(sdata->dev); | ||||||
|  |  } | ||||||
|  | @@ -4202,8 +4270,11 @@ ieee80211_set_after_color_change_beacon( | ||||||
|  |   | ||||||
|  |  		ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, | ||||||
|  |  					      NULL, NULL); | ||||||
|  | -		kfree(sdata->u.ap.next_beacon); | ||||||
|  | -		sdata->u.ap.next_beacon = NULL; | ||||||
|  | +		if (sdata->u.ap.next_beacon) { | ||||||
|  | +			kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +			kfree(sdata->u.ap.next_beacon); | ||||||
|  | +			sdata->u.ap.next_beacon = NULL; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  |  		if (ret < 0) | ||||||
|  |  			return ret; | ||||||
|  | @@ -4246,7 +4317,11 @@ ieee80211_set_color_change_beacon(struct | ||||||
|  |  		err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, | ||||||
|  |  					      NULL, &color_change); | ||||||
|  |  		if (err < 0) { | ||||||
|  | -			kfree(sdata->u.ap.next_beacon); | ||||||
|  | +			if (sdata->u.ap.next_beacon) { | ||||||
|  | +				kfree(sdata->u.ap.next_beacon->mbssid_ies); | ||||||
|  | +				kfree(sdata->u.ap.next_beacon); | ||||||
|  | +				sdata->u.ap.next_beacon = NULL; | ||||||
|  | +			} | ||||||
|  |  			return err; | ||||||
|  |  		} | ||||||
|  |  		*changed |= err; | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -261,6 +261,7 @@ struct beacon_data { | ||||||
|  |  	struct ieee80211_meshconf_ie *meshconf; | ||||||
|  |  	u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; | ||||||
|  |  	u8 cntdwn_current_counter; | ||||||
|  | +	struct cfg80211_mbssid_elems *mbssid_ies; | ||||||
|  |  	struct rcu_head rcu_head; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -1063,6 +1064,20 @@ ieee80211_vif_get_shift(struct ieee80211 | ||||||
|  |  	return shift; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static inline int | ||||||
|  | +ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) | ||||||
|  | +{ | ||||||
|  | +	int i, len = 0; | ||||||
|  | + | ||||||
|  | +	if (!elems) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < elems->cnt; i++) | ||||||
|  | +		len += elems->elem[i].len; | ||||||
|  | + | ||||||
|  | +	return len; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  enum { | ||||||
|  |  	IEEE80211_RX_MSG	= 1, | ||||||
|  |  	IEEE80211_TX_STATUS_MSG	= 2, | ||||||
|  | --- a/net/mac80211/tx.c | ||||||
|  | +++ b/net/mac80211/tx.c | ||||||
|  | @@ -5041,6 +5041,19 @@ ieee80211_beacon_get_finish(struct ieee8 | ||||||
|  |  		       IEEE80211_TX_CTL_FIRST_FRAGMENT; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void | ||||||
|  | +ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon) | ||||||
|  | +{ | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	if (!beacon->mbssid_ies) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < beacon->mbssid_ies->cnt; i++) | ||||||
|  | +		skb_put_data(skb, beacon->mbssid_ies->elem[i].data, | ||||||
|  | +			     beacon->mbssid_ies->elem[i].len); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static struct sk_buff * | ||||||
|  |  ieee80211_beacon_get_ap(struct ieee80211_hw *hw, | ||||||
|  |  			struct ieee80211_vif *vif, | ||||||
|  | @@ -5054,6 +5067,7 @@ ieee80211_beacon_get_ap(struct ieee80211 | ||||||
|  |  	struct ieee80211_if_ap *ap = &sdata->u.ap; | ||||||
|  |  	struct sk_buff *skb = NULL; | ||||||
|  |  	u16 csa_off_base = 0; | ||||||
|  | +	int mbssid_len; | ||||||
|  |   | ||||||
|  |  	if (beacon->cntdwn_counter_offsets[0]) { | ||||||
|  |  		if (!is_template) | ||||||
|  | @@ -5063,11 +5077,12 @@ ieee80211_beacon_get_ap(struct ieee80211 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	/* headroom, head length, | ||||||
|  | -	 * tail length and maximum TIM length | ||||||
|  | +	 * tail length, maximum TIM length and multiple BSSID length | ||||||
|  |  	 */ | ||||||
|  | +	mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); | ||||||
|  |  	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + | ||||||
|  |  			    beacon->tail_len + 256 + | ||||||
|  | -			    local->hw.extra_beacon_tailroom); | ||||||
|  | +			    local->hw.extra_beacon_tailroom + mbssid_len); | ||||||
|  |  	if (!skb) | ||||||
|  |  		return NULL; | ||||||
|  |   | ||||||
|  | @@ -5081,6 +5096,11 @@ ieee80211_beacon_get_ap(struct ieee80211 | ||||||
|  |  		offs->tim_length = skb->len - beacon->head_len; | ||||||
|  |  		offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; | ||||||
|  |   | ||||||
|  | +		if (mbssid_len) { | ||||||
|  | +			ieee80211_beacon_add_mbssid(skb, beacon); | ||||||
|  | +			offs->mbssid_off = skb->len - mbssid_len; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		/* for AP the csa offsets are from tail */ | ||||||
|  |  		csa_off_base = skb->len; | ||||||
|  |  	} | ||||||
| @@ -0,0 +1,52 @@ | |||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 24 Feb 2022 12:54:59 +0100 | ||||||
|  | Subject: [PATCH] mac80211: MBSSID channel switch | ||||||
|  |  | ||||||
|  | Trigger ieee80211_csa_finish() on the non-transmitting interfaces | ||||||
|  | when channel switch concludes on the transmitting interface. | ||||||
|  |  | ||||||
|  | Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Co-developed-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | Link: https://lore.kernel.org/r/6fde4d7f9fa387494f46a7aa4a584478dcda06f1.1645702516.git.lorenzo@kernel.org | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/cfg.c | ||||||
|  | +++ b/net/mac80211/cfg.c | ||||||
|  | @@ -3247,9 +3247,31 @@ cfg80211_beacon_dup(struct cfg80211_beac | ||||||
|  |  void ieee80211_csa_finish(struct ieee80211_vif *vif) | ||||||
|  |  { | ||||||
|  |  	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||||||
|  | +	struct ieee80211_local *local = sdata->local; | ||||||
|  |   | ||||||
|  | -	ieee80211_queue_work(&sdata->local->hw, | ||||||
|  | -			     &sdata->csa_finalize_work); | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | + | ||||||
|  | +	if (vif->mbssid_tx_vif == vif) { | ||||||
|  | +		/* Trigger ieee80211_csa_finish() on the non-transmitting | ||||||
|  | +		 * interfaces when channel switch is received on | ||||||
|  | +		 * transmitting interface | ||||||
|  | +		 */ | ||||||
|  | +		struct ieee80211_sub_if_data *iter; | ||||||
|  | + | ||||||
|  | +		list_for_each_entry_rcu(iter, &local->interfaces, list) { | ||||||
|  | +			if (!ieee80211_sdata_running(iter)) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			if (iter == sdata || iter->vif.mbssid_tx_vif != vif) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			ieee80211_queue_work(&iter->local->hw, | ||||||
|  | +					     &iter->csa_finalize_work); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	ieee80211_queue_work(&local->hw, &sdata->csa_finalize_work); | ||||||
|  | + | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(ieee80211_csa_finish); | ||||||
|  |   | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | From: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Date: Thu, 24 Feb 2022 12:55:00 +0100 | ||||||
|  | Subject: [PATCH] mac80211: update bssid_indicator in | ||||||
|  |  ieee80211_assign_beacon | ||||||
|  |  | ||||||
|  | Update bssid_indicator in ieee80211_bss_conf according to the | ||||||
|  | number of bssid in the set. | ||||||
|  |  | ||||||
|  | Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> | ||||||
|  | Link: https://lore.kernel.org/r/f92317e002fca9933f05a445fcefb4f53291d601.1645702516.git.lorenzo@kernel.org | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/cfg.c | ||||||
|  | +++ b/net/mac80211/cfg.c | ||||||
|  | @@ -1071,6 +1071,9 @@ static int ieee80211_assign_beacon(struc | ||||||
|  |  		new->mbssid_ies = (void *)pos; | ||||||
|  |  		pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); | ||||||
|  |  		ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); | ||||||
|  | +		/* update bssid_indicator */ | ||||||
|  | +		sdata->vif.bss_conf.bssid_indicator = | ||||||
|  | +			ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (csa) { | ||||||
| @@ -57,7 +57,7 @@ | |||||||
|  	__NL80211_ATTR_AFTER_LAST, |  	__NL80211_ATTR_AFTER_LAST, | ||||||
| --- a/net/mac80211/cfg.c | --- a/net/mac80211/cfg.c | ||||||
| +++ b/net/mac80211/cfg.c | +++ b/net/mac80211/cfg.c | ||||||
| @@ -2764,6 +2764,19 @@ static int ieee80211_get_tx_power(struct | @@ -2845,6 +2845,19 @@ static int ieee80211_get_tx_power(struct | ||||||
|  	return 0; |  	return 0; | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -77,7 +77,7 @@ | |||||||
|  static void ieee80211_rfkill_poll(struct wiphy *wiphy) |  static void ieee80211_rfkill_poll(struct wiphy *wiphy) | ||||||
|  { |  { | ||||||
|  	struct ieee80211_local *local = wiphy_priv(wiphy); |  	struct ieee80211_local *local = wiphy_priv(wiphy); | ||||||
| @@ -4411,6 +4424,7 @@ const struct cfg80211_ops mac80211_confi | @@ -4549,6 +4562,7 @@ const struct cfg80211_ops mac80211_confi | ||||||
|  	.set_wiphy_params = ieee80211_set_wiphy_params, |  	.set_wiphy_params = ieee80211_set_wiphy_params, | ||||||
|  	.set_tx_power = ieee80211_set_tx_power, |  	.set_tx_power = ieee80211_set_tx_power, | ||||||
|  	.get_tx_power = ieee80211_get_tx_power, |  	.get_tx_power = ieee80211_get_tx_power, | ||||||
| @@ -87,7 +87,7 @@ | |||||||
|  	CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) |  	CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) | ||||||
| --- a/net/mac80211/ieee80211_i.h | --- a/net/mac80211/ieee80211_i.h | ||||||
| +++ b/net/mac80211/ieee80211_i.h | +++ b/net/mac80211/ieee80211_i.h | ||||||
| @@ -1429,6 +1429,7 @@ struct ieee80211_local { | @@ -1444,6 +1444,7 @@ struct ieee80211_local { | ||||||
|  	int dynamic_ps_forced_timeout; |  	int dynamic_ps_forced_timeout; | ||||||
|   |   | ||||||
|  	int user_power_level; /* in dBm, for all interfaces */ |  	int user_power_level; /* in dBm, for all interfaces */ | ||||||
| @@ -137,10 +137,11 @@ | |||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  /* policy for the key attributes */ |  /* policy for the key attributes */ | ||||||
| @@ -3375,6 +3376,22 @@ static int nl80211_set_wiphy(struct sk_b | @@ -3374,6 +3375,22 @@ static int nl80211_set_wiphy(struct sk_b | ||||||
|  |  		if (result) | ||||||
|  			goto out; |  			goto out; | ||||||
|  	} |  	} | ||||||
|   | + | ||||||
| +	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { | +	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { | ||||||
| +		int idx, dbi = 0; | +		int idx, dbi = 0; | ||||||
| + | + | ||||||
| @@ -156,7 +157,6 @@ | |||||||
| +		if (result) | +		if (result) | ||||||
| +			goto out; | +			goto out; | ||||||
| +	} | +	} | ||||||
| + |   | ||||||
|  	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { |  	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { | ||||||
|  		struct wireless_dev *txp_wdev = wdev; |  		struct wireless_dev *txp_wdev = wdev; | ||||||
|  		enum nl80211_tx_power_setting type; |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau