MBSSID and EMA support in AP mode
Subsystems (2)
v12 cover MBSSID and EMA support in AP mode
This patchset adds support for multiple BSSID and enhanced multi-BSSID advertisements for AP mode. Individual patches describe the changes in this version.
John Crispin (4):
nl80211: MBSSID and EMA support in AP mode
mac80211: MBSSID support in interface handling
mac80211: MBSSID and EMA support in beacon handling
mac80211: MBSSID channel switch
include/net/cfg80211.h | 44 ++++++ include/net/mac80211.h | 92 ++++++++++++ include/uapi/linux/nl80211.h | 76 +++++++++- net/mac80211/cfg.c | 192 +++++++++++++++++++++--- net/mac80211/ieee80211_i.h | 2 + net/mac80211/iface.c | 29 +++- net/mac80211/tx.c | 173 +++++++++++++++++++--- net/wireless/nl80211.c | 277 ++++++++++++++++++++++++++++++----- 8 files changed, 805 insertions(+), 80 deletions(-)
base-commit: 339133f6c318612f9a4556c300753beda27abc01
Signature · 1 line
2.31.1
PATCH v12 1/4 nl80211: MBSSID and EMA support in AP mode
From: John Crispin <[email protected]>
This commit adds new attributes to configure support for multiple BSSID and advanced multi-BSSID advertisements (EMA) in AP mode.
- NL80211_ATTR_MBSSID_CONFIG used for per interface configuration.
- NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons.
Memory for the elements is allocated dynamically. This change frees the memory in existing functions which call nl80211_parse_beacon(), a comment is added to indicate the new references to do the same.
---
v12: Replaced __dev_get_by_index() with dev_get_by_index() and
added dev_put(). nl80211_parse_mbssid_elems()returns ERR_PTR() insead of NULL in case of error and the caller nl80211_parse_beacon() uses PTR_ERR() to return the same.
include/net/cfg80211.h | 44 ++++++ include/uapi/linux/nl80211.h | 76 +++++++++- net/wireless/nl80211.c | 277 ++++++++++++++++++++++++++++++----- 3 files changed, 358 insertions(+), 39 deletions(-)
include/net/cfg80211.h +44 -0
@@ -1040,6 +1040,36 @@ struct cfg80211_crypto_settings {enum nl80211_sae_pwe_mechanism sae_pwe; }; +/** +* struct cfg80211_mbssid_config - AP settings for multi bssid +* +* @tx_wdev: pointer to the transmitted interface in the MBSSID set +* @index: index of this AP in the multi bssid group. +* @ema: set to true if the beacons should be sent out in EMA mode. +*/ +struct cfg80211_mbssid_config { +struct wireless_dev *tx_wdev; +u8 index; +bool ema; +}; + +/** +* struct cfg80211_mbssid_elems - Multiple BSSID elements +* +* @cnt: Number of elements in array %elems. +* +* @elem: Array of multiple BSSID element(s) to be added into Beacon frames. +* @elem.data: Data for multiple BSSID elements. +* @elem.len: Length of data. +*/ +struct cfg80211_mbssid_elems { +u8 cnt; +struct { +u8 *data; +size_t len; + } elem[]; +}; +/** * struct cfg80211_beacon_data - beacon data * @head: head portion of beacon (before TIM IE)
@@ -1058,6 +1088,7 @@ struct cfg80211_crypto_settings {* @assocresp_ies_len: length of assocresp_ies in octets * @probe_resp_len: length of probe response template (@probe_resp) * @probe_resp: probe response template (AP mode only) +* @mbssid_ies: multiple BSSID elements * @ftm_responder: enable FTM responder functionality; -1 for no change * (which also implies no change in LCI/civic location data) * @lci: Measurement Report element content, starting with Measurement Token
@@ -1075,6 +1106,7 @@ struct cfg80211_beacon_data {const u8 *probe_resp;const u8 *lci;const u8 *civicloc; +struct cfg80211_mbssid_elems *mbssid_ies;s8 ftm_responder;size_t head_len, tail_len;
@@ -1189,6 +1221,7 @@ enum cfg80211_ap_settings_flags {* @he_oper: HE operation IE (or %NULL if HE isn't enabled) * @fils_discovery: FILS discovery transmission parameters * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters +* @mbssid_config: AP settings for multiple bssid */ struct cfg80211_ap_settings {struct cfg80211_chan_def chandef;
@@ -1221,6 +1254,7 @@ struct cfg80211_ap_settings {struct cfg80211_he_bss_color he_bss_color;struct cfg80211_fils_discovery fils_discovery;struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; +struct cfg80211_mbssid_config mbssid_config; };/**
@@ -4981,6 +5015,13 @@ struct wiphy_iftype_akm_suites {* %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes * @sar_capa: SAR control capabilities * @rfkill: a pointer to the rfkill structure +* +* @mbssid_max_interfaces: maximum number of interfaces supported by the driver +* in a multiple BSSID set. This field must be set to a non-zero value +* by the driver to advertise MBSSID support. +* @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by +* the driver. Setting this field to a non-zero value indicates that the +* driver supports enhanced multi-BSSID advertisements (EMA AP). */ struct wiphy {struct mutex mtx;
@@ -5125,6 +5166,9 @@ struct wiphy {struct rfkill *rfkill; +u8 mbssid_max_interfaces; +u8 ema_max_profile_periodicity; +char priv[]__aligned(NETDEV_ALIGN) ; };
include/uapi/linux/nl80211.h +75 -1
98 lines not on this page · raw message
net/wireless/nl80211.c +239 -38
444 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v12 2/4 mac80211: MBSSID support in interface handling
In reply to Aloka DixitFrom: John Crispin <[email protected]>
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.
---
v12: Only cosmetic changes.
v11: Moved dev_close() for non-transmitting interfaces
before locking wiphy->mtx.
Removed interface count, instead mac80211 passes pointer 'mbssid_tx_vif' to the driver for each interface. Removed dev_close() calls from ieee80211_del_iface(). Removed IEEE80211_HW_SUPPORTS_MBSSID_AP and IEEE80211_HW_SUPPORTS_EMA_AP.
Instead of new parameters in struct ieee80211_bss_conf, reused the existing ones which were used for STA mode.
include/net/mac80211.h | 3 +++ net/mac80211/cfg.c | 38 ++++++++++++++++++++++++++++++++++++++ net/mac80211/iface.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-)
include/net/mac80211.h +3 -0
@@ -1715,6 +1715,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;
@@ -1746,6 +1747,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 *)) ; };
net/mac80211/cfg.c +38 -0
@@ -111,6 +111,36 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,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,
@@ -1105,6 +1135,14 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, 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 );
net/mac80211/iface.c +28 -1
@@ -632,17 +632,44 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_doieee80211_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; + + 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); + +if (sdata->vif.mbssid_tx_vif) +ieee80211_stop_mbssid (sdata); }wiphy_lock (sdata->local->hw.wiphy);
Signature · 1 line
2.31.1
Re: [PATCH v12 2/4] mac80211: MBSSID support in interface handling
Quoted 8 lines · Aloka Dixit
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.
This has already been applied, but this has some apparent issues that are now showing up with mac80211_hwsim testing being available..
net/mac80211/cfg.c static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, · line 115
Quoted 3 lines
net/mac80211/cfg.c +2
-0+static int ieee80211_set_ap_mbssid_options (struct ieee80211_sub_if_data *sdata, +struct cfg80211_mbssid_config params)
While that does not really break behavior, why is that params argument passed by value instead of by reference? I see no point in copying struct cfg80211_mbssid_config members for this call since the function is only reading the value.
net/mac80211/cfg.c static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, · line 122
Quoted 4 lines
net/mac80211/cfg.c +4
-0+ 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;
This cleanup is important, but it is done only here in this helper function..
net/mac80211/cfg.c static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · line 1141
Quoted 8 lines
net/mac80211/cfg.c +7
-0@@ -1105,6 +1135,14 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, +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; + }
And that is the only place where the help function is called and this happens only under the params->mbssid_config.tx_wdev condition. In other words, those bssid_index/nontransmitted/ema_ap values are not cleared in all cases. This results in issue when the bss_conf (link_conf in the current kernel snapshot) is left in the previous mbssid configuration.
As an example, this will make the following mac80211_hwsim test case sequence fail:
hostap/tests/hwsim/vm$ ./vm-run.sh he_ap_ema p2p_group_cli_invalid
This happens because ema_ap is set to true in he_ap_ema and then it is left set true for p2p_group_cli_invalid and that test case does not actually end up sending Beacon frames.
This can be fixed by clearing something in the !params->mbssid_config.tx_wdev case in ieee80211_start_ap(). I'm not completely sure what is the correct way of doing this, but at least ema_ap needs to be cleared to false and likely some other cleanup needs to be done as well.
Signature · 1 line
Jouni Malinen PGP id EFC895FA
Re: [PATCH v12 2/4] mac80211: MBSSID support in interface handling
Quoted 13 lines · Jouni Malinen
Quoted 8 lines · Aloka Dixit
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.This has already been applied, but this has some apparent issues that are now showing up with
mac80211_hwsimtesting being available..
Quoted 9 lines
net/mac80211/cfg.c static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, · line 115
Quoted 3 lines
net/mac80211/cfg.c +2
-0+static int ieee80211_set_ap_mbssid_options (struct ieee80211_sub_if_data *sdata, +struct cfg80211_mbssid_config params)While that does not really break behavior, why is that params argument passed by value instead of by reference? I see no point in copying struct
cfg80211_mbssid_configmembers for this call since the function is only reading the value.
Hi Jouni, the only reason for value instead of reference is that this function does not need to change anything in 'params'. I didn't understand your question. Are you suggesting moving the assignments to ieee80211_start_ap() instead of this separate function?
Quoted 5 lines
net/mac80211/cfg.c static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, · line 122
Quoted 4 lines
net/mac80211/cfg.c +4
-0+ 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;
Quoted 8 lines
This cleanup is important, but it is done only here in this helper function..
And that is the only place where the help function is called and this happens only under theparams->mbssid_config.tx_wdevcondition. In other words, those bssid_index/nontransmitted/ema_ap values are not cleared in all cases. This results in issue when thebss_conf(link_confin the current kernel snapshot) is left in the previous mbssid configuration.
Will send a patch to fix this part.
Please let me know regarding the first question above so that I can include that in the same patch.
Thanks.
Re: [PATCH v12 2/4] mac80211: MBSSID support in interface handling
Quoted 11 lines · Aloka Dixit
Quoted 9 lines · Jouni Malinen
net/mac80211/cfg.c
Quoted 3 lines · Aloka Dixit
net/mac80211/cfg.c +2
-0+static int ieee80211_set_ap_mbssid_options (struct ieee80211_sub_if_data *sdata, +struct cfg80211_mbssid_config params)While that does not really break behavior, why is that params argument passed by value instead of by reference? I see no point in copying struct
cfg80211_mbssid_configmembers for this call since the function is only reading the value.
Quoted 4 lines
Hi Jouni, the only reason for value instead of reference is that this function does not need to change anything in 'params'. I didn't understand your question. Are you suggesting moving the assignments to
ieee80211_start_ap()instead of this separate function?
I would use a constant pointer (const struct cfg80211_mbssid_config *params) to avoid the need to copy the full contents of that struct whenever calling the function.
Maybe the following patch is a clearer way of showing what I was thinking of (and testing with):
net/mac80211/cfg.c +13 -6
@@ -138,7 +138,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, }static int ieee80211_set_ap_mbssid_options (struct ieee80211_sub_if_data *sdata, -struct cfg80211_mbssid_config params, +const struct cfg80211_mbssid_config *params,struct ieee80211_bss_conf *link_conf) {struct ieee80211_sub_if_data *tx_sdata;
@@ -148,10 +148,10 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, link_conf->nontransmitted = false; link_conf->ema_ap = false; -if (sdata->vif.type !=NL80211_IFTYPE_AP || !params.tx_wdev) +if (sdata->vif.type !=NL80211_IFTYPE_AP || !params->tx_wdev)return -EINVAL ; - tx_sdata =IEEE80211_WDEV_TO_SUB_IF (params.tx_wdev); + tx_sdata =IEEE80211_WDEV_TO_SUB_IF (params->tx_wdev);if (!tx_sdata)return -EINVAL ;
@@ -160,9 +160,9 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, }else { sdata->vif.mbssid_tx_vif = &tx_sdata->vif; link_conf->nontransmitted = true; - link_conf->bssid_index = params.index; + link_conf->bssid_index = params->index; } -if (params.ema) +if (params->ema) link_conf->ema_ap = true;return 0 ;
@@ -1268,10 +1268,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,if (sdata->vif.type ==NL80211_IFTYPE_AP && params->mbssid_config.tx_wdev) { err =ieee80211_set_ap_mbssid_options (sdata, - params->mbssid_config, + ¶ms->mbssid_config, link_conf);if (err)return err; + }else { +/* FIX: Is this the correct thing to do here and under which +* conditions? At least ema_ap needs to be cleared for AP mode +* if mbssid_config.tx_wdev is not set. */ + link_conf->bssid_index =0 ; + link_conf->nontransmitted = false; + link_conf->ema_ap = false; }mutex_lock (&local->mtx);
Quoted 10 lines
Quoted 8 lines
This cleanup is important, but it is done only here in this helper function..
And that is the only place where the help function is called and this happens only under theparams->mbssid_config.tx_wdevcondition. In other words, those bssid_index/nontransmitted/ema_ap values are not cleared in all cases. This results in issue when thebss_conf(link_confin the current kernel snapshot) is left in the previous mbssid configuration.Will send a patch to fix this part.
Thanks.
Quoted 2 lines
Please let me know regarding the first question above so that I can include that in the same patch.
That should not be in the same patch since it is just cleanup/optimization while the not clearing parameters in some cases is a visible bug that should be fixed on its own first.
Signature · 1 line
Jouni Malinen PGP id EFC895FA
Re: [PATCH v12 2/4] mac80211: MBSSID support in interface handling
Quoted 13 lines · Jouni Malinen
Quoted 6 lines · Aloka Dixit
Quoted 5 lines · Jouni Malinen
Quoted 3 lines · Aloka Dixit
net/mac80211/cfg.c +2
-0+static int ieee80211_set_ap_mbssid_options (struct ieee80211_sub_if_data *sdata, +struct cfg80211_mbssid_config params)net/mac80211/cfg.c +1
-1@@ -1268,10 +1268,17 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,if (sdata->vif.type ==NL80211_IFTYPE_AP && params->mbssid_config.tx_wdev) { err = ieee80211_set_ap_mbssid_options(sdata, - params->mbssid_config, + ¶ms->mbssid_config,
net/mac80211/cfg.c static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · line 1281
Quoted 10 lines
net/mac80211/cfg.c +7
-0link_conf);if (err)return err; + }else { +/* FIX: Is this the correct thing to do here and under which +* conditions? At least ema_ap needs to be cleared for AP mode +* if mbssid_config.tx_wdev is not set. */ + link_conf->bssid_index =0 ; + link_conf->nontransmitted = false; + link_conf->ema_ap = false;
Will need to clean MBSSID elements in stored beacon as well.
Would the two HWSIM testcases you mentioned earlier be sufficient for testing? I've never used P2P related tests, and in fact I only even ran one testcase at a time so stale configurations didn't show up.
Thanks.
PATCH v12 3/4 mac80211: MBSSID and EMA support in beacon handling
In reply to Aloka DixitFrom: John Crispin <[email protected]>
New fields added in struct beacon_data to store all MBSSID elements and the index of the next element to be included in beacon template.
For a non-EMA AP, a single beacon template is generated with all elements. For an EMA AP, multiple beacon templates are generated and each includes a single MBSSID element. EMA profile periodicity equals the count of elements.
This patch also generates and includes multiple BSSID configuration element in each beacon template for both EMA/non-EMA AP when MBSSID is enabled.
New field added in struct ieee80211_mutable_offsets to store offset of the first MBSSID element in beacons. Also the offset for channel switch announcement (CSA) is modified to account for MBSSID length.
Depending on the hardware support and the usecase, drivers should use following functions for beacon generation:
- ieee80211_beacon_get_template() - Existing function for legacy beacon generation for non-MBSSID APs. No change in prototype.
- ieee80211_beacon_get_template_ema_next() - Generate the next EMA beacon template using the 'ema_index' stored in beacon_data.
- ieee80211_beacon_get_template_ema_list() - Generate all EMA templates. Drivers must call ieee80211_beacon_free_ema_list() to free the memory.
This commit also adds a missing free() for sdata->u.ap.next_beacon in ieee80211_set_csa_beacon() and sets the pointer to NULL in case of error.
---
v12: No changes.
include/net/mac80211.h | 89 +++++++++++++++++++ net/mac80211/cfg.c | 139 +++++++++++++++++++++++++---- net/mac80211/ieee80211_i.h | 2 + net/mac80211/tx.c | 173 ++++++++++++++++++++++++++++++++----- 4 files changed, 365 insertions(+), 38 deletions(-)
include/net/mac80211.h +89 -0
@@ -4911,12 +4911,14 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);* @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_offset: 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_offset; };/**
@@ -4943,6 +4945,93 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw,struct ieee80211_vif *vif, struct ieee80211_mutable_offsets *offs); +/** +* enum ieee80211_bcn_tmpl_ema - EMA beacon generation type +* +* When enhanced multi-BSSID advertisements (EMA) mode is enabled, the +* non-transmitting profiles from the multiple BSSID set are split into more +* than one multiple BSSID elements if required. Each EMA beacon includes only +* one element to reduce the total size. The number of beacons required to +* cover all profiles is called as the profile periodicity of the set. +* +* In MAC80211, the multiple BSSID elements passed by the application are +* stored in a array and the index of the next element (starting from 0) to be +* included in the beacon template is tracked through the member ema_index of +* struct beacon_data. +* +* @IEEE80211_BCN_EMA_NONE: Used when EMA is disabled. Only one beacon +* template will be generated which includes all multiple BSSID elements. +* @IEEE80211_BCN_EMA_NEXT: Used when EMA is enabled. Includes the next +* multiple BSSID element while generating the beacon template. +* @IEEE80211_BCN_EMA_BASE: Used when EMA is enabled. Beacon template includes +* the multiple MBSSID element at a specified index which should be set +* to a value more than or equal to IEEE80211_BCN_EMA_BASE. +*/ +enum ieee80211_bcn_tmpl_ema { +IEEE80211_BCN_EMA_NONE =-2 , +IEEE80211_BCN_EMA_NEXT =-1 , +IEEE80211_BCN_EMA_BASE =0 , +}; + +/** +* ieee80211_beacon_get_template_ema_next - EMA beacon template generation +* function for drivers using the sw offload path. +* @hw: pointer obtained from ieee80211_alloc_hw(). +* @vif: &struct ieee80211_vif pointer from the add_interface callback. +* @offs: &struct ieee80211_mutable_offsets pointer to struct that will +* receive the offsets that may be updated by the driver. +* +* This function follows the same rules as ieee80211_beacon_get_template() +* but returns a beacon template which includes the next multiple BSSID +* element. +* +* Return: The beacon template. %NULL on error. +*/ +struct sk_buff *ieee80211_beacon_get_template_ema_next (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct ieee80211_mutable_offsets *offs); + +/** +* struct ieee80211_ema_bcn_list - list entry of an EMA beacon +* @list: the list pointer. +* @skb: the skb containing this specific beacon +* @offs: &struct ieee80211_mutable_offsets pointer to struct that will +* receive the offsets that may be updated by the driver. +*/ +struct ieee80211_ema_bcn_list { +struct list_head list; +struct sk_buff *skb; +struct ieee80211_mutable_offsets offs; +}; + +/** +* ieee80211_beacon_get_template_ema_list - EMA beacon template generation +* function for drivers using the hw offload. +* @hw: pointer obtained from ieee80211_alloc_hw(). +* @vif: &struct ieee80211_vif pointer from the add_interface callback. +* @head: linked list head that will get populated with +* &struct ieee80211_ema_bcn_list pointers. +* +* This function follows the same rules as ieee80211_beacon_get_template() +* but returns a linked list of all beacon templates required to cover all +* profiles in the multiple BSSID set. Each template includes only one multiple +* BSSID element. +* +* Return: The nuber of entries in the list or 0 on error. +*/ +int ieee80211_beacon_get_template_ema_list (struct ieee80211_hw *hw, +struct ieee80211_vif *vif, +struct list_head *head); + +/** +* ieee80211_beacon_free_ema_list - free an EMA beacon template list +* @head: linked list head containing &struct ieee80211_ema_bcn_list pointers. +* +* This function will free a list previously acquired by calling +* ieee80211_beacon_get_template_ema_list() +*/ +void ieee80211_beacon_free_ema_list (struct list_head *head); +/** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw().
net/mac80211/cfg.c +122 -17
263 lines not on this page · raw message
net/mac80211/ieee80211_i.h +2 -0
@@ -257,6 +257,8 @@ 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; +u16 ema_index;struct rcu_head rcu_head; };
net/mac80211/tx.c +152 -21
277 lines not on this page · raw message
Signature · 1 line
2.31.1
Johannes Berg
maintainerRe: [PATCH v12 3/4] mac80211: MBSSID and EMA support in beacon handling
Hi,
So I applied patches 1 and 2, but have some comments/questions here.
Quoted 17 lines
static struct
sk_buff* __ieee80211_beacon_get(structieee80211_hw*hw, structieee80211_vif*vif, structieee80211_mutable_offsets*offs,net/mac80211/tx.c +2
-1- bool is_template) +bool is_template, + int ema_index){
structieee80211_local*local =hw_to_local(hw); structbeacon_data*beacon = NULL;net/mac80211/tx.c +0
-0@@ -4995,13 +5038,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *chanctx_conf; int csa_off_base = 0;
net/mac80211/tx.c __ieee80211_beacon_get(struct ieee80211_hw *hw, · line 4998
Quoted 1 line
net/mac80211/tx.c +0
-1-rcu_read_lock ();
Why are you making this change that moves the RCU locking out? In two out of three places, you now have to
rcu_read_lock(); __ieee80211_beacon_get(...); rcu_read_unlock();
Not sure I see the point?
Review
Quoted 4 lines
if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
(quoted diff) +1
-1- goto out; + return NULL;
That also causes a lot of collateral changes that make it harder to read than it needs to be.
Maybe split the locking change to a separate patch, if at all necessary?
(but see below)
Review
Quoted 3 lines
(quoted diff) +2
-0+ rcu_read_lock(); + ema = kmalloc(sizeof(*ema), GFP_KERNEL);
This is obviously wrong - you should add a few more debug options to your test kernels :-)
net/mac80211/tx.c __ieee80211_beacon_get(struct ieee80211_hw *hw, · line 5287
Quoted 4 lines
net/mac80211/tx.c +4
-0+if (!ema) { +ieee80211_beacon_free_ema_list (head); + cnt =0 ; + goto out;
break would be enough, and you could save the 'out' label?
net/mac80211/tx.c __ieee80211_beacon_get(struct ieee80211_hw *hw, · line 5300
Quoted 13 lines
net/mac80211/tx.c +13
-0+ } + + ema->skb =__ieee80211_beacon_get (hw, vif, &ema->offs, true, + cnt); +if (!ema->skb) { +kfree (ema); +break ; + } +list_add_tail (&ema->list, head); + cnt++; + } +out: +rcu_read_unlock ();
This is also the only place that uses the rcu_read_lock()/unlock() not directly around the __ieee80211_beacon_get(), but there's absolutely no point in that?
I think what you intended here was correct, but it was done incorrectly.
Really what it seems you (should have) _wanted_ with the RCU locking here is that the
beacon = rcu_dereference(ap->beacon);
is only done *once*, so that you can really get a snapshot of *all* those MBSSID beacons, even if ap->beacon changed.
However, that's not what you implemented. By moving the rcu_read_lock() outside, you've achieved nothing, since you still do a dereference inside, and it can change.
It seems to me that to do this correctly you have to actually split __ieee80211_beacon_get() and do the dereference *outside* of it, then pass the 'beacon' pointer into it. Then, you can here do the dereference outside of the loop too (and in fact can do a much nicer for loop rather than the infinite loop).
As it is, you've penalized the other cases (they now need to do the rcu_read_lock() manually), but haven't actually gained anything (functionally, at least, you save a few cycles by having the RCU stuff outside the loop, but that doesn't really count).
johannes
PATCH v12 4/4 mac80211: MBSSID channel switch
In reply to Aloka DixitFrom: John Crispin <[email protected]>
Trigger ieee80211_csa_finish() on the non-transmitting interfaces when channel switch concludes on the transmitting interface.
---
v12: No changes.
net/mac80211/cfg.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
net/mac80211/cfg.c +13 -2
@@ -3271,8 +3271,19 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif) {struct ieee80211_sub_if_data *sdata =vif_to_sdata (vif); -ieee80211_queue_work (&sdata->local->hw, - &sdata->csa_finalize_work); +if (vif->mbssid_tx_vif == vif) { +struct ieee80211_sub_if_data *child, *tmp; + +list_for_each_entry_safe (child, tmp, + &sdata->local->interfaces, list) +if (child != sdata && child->vif.mbssid_tx_vif == vif && +ieee80211_sdata_running (child)) { +ieee80211_queue_work (&child->local->hw, + &child->csa_finalize_work); + } + } + +ieee80211_queue_work (&sdata->local->hw, &sdata->csa_finalize_work); }EXPORT_SYMBOL (ieee80211_csa_finish);
Signature · 1 line
2.31.1
Johannes Berg
maintainerRe: [PATCH v12 4/4] mac80211: MBSSID channel switch
Quoted 12 lines · Aloka Dixit
net/mac80211/cfg.c +0
-0@@ -3271,8 +3271,19 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
net/mac80211/cfg.c void ieee80211_csa_finish(struct ieee80211_vif *vif) · line 3278
Quoted 7 lines
net/mac80211/cfg.c +5
-2-ieee80211_queue_work (&sdata->local->hw, - &sdata->csa_finalize_work); +if (vif->mbssid_tx_vif == vif) { +struct ieee80211_sub_if_data *child, *tmp; + +list_for_each_entry_safe (child, tmp, + &sdata->local->interfaces, list)
I don't see any reason to believe that this list iteration should be safe?
johannes