aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Ravi <sunilravi@google.com>2023-06-28 23:08:09 +0000
committerSunil Ravi <sunilravi@google.com>2023-08-04 16:23:08 +0000
commit640215c44f259e52a35981f70b18e97ae53a538e (patch)
tree68e92b0c037bd15f4eeafd297f34da2e7317d647
parentb6f94540c451270a44d28e782088421aaac5e31c (diff)
downloadwpa_supplicant_8-640215c44f259e52a35981f70b18e97ae53a538e.tar.gz
[wpa_supplicant] cumilative patch from commit d3ed34ba
Bug: 289287296 Test: Connect to open, WPA2, WPA3 and passpoint network Test: Establish P2P connection Test: Basic SoftAp tests Test: Regression test (b/289297084) BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from open source d3ed34bac Define a QCA vendor command to configure MLO link id for TDLS 8e16372cf Indicate link reconfiguration with QCA vendor interface 7b9070229 Indicate TID to link mapping changes with QCA vendor interface 4120f9d7a PASN: Introduce configuration option to allow/deny PASN-UNAUTH fc681995c Increase MAX_NL80211_NOISE_FREQS in survey dump handler for 6 GHz df2f22faf MLD STA: Use AP MLD address as previous BSSID for reassociation requests 199b44213 MLD STA: Allow auth frames without ML IE for failure status codes 57386a647 Add QCA vendor command to indicate STA MLD setup links removal 527cf095f Add QCA vendor command to notify TID-to-Link mapping changes a1601aaa6 WPS: Fix multi-ap fronthaul association 288566031 Store pmk_r1_name derived with wpa_ft_local_derive_pmk_r1() properly e978072ba Do prune_association only after the STA is authorized a2c09eb95 Define a QCA vendor attribute to update the CTS channel width e49c3df63 Add a new driver feature flag for enhanced audio experience over WLAN cc8a09a48 Add vendor attributes for forcing MLO power save and STR TX c0e12a518 Add vendor attributes for EHT OM control, EMLSR padding delay 386d59e00 Do not disconnect EAPOL-Logoff before authentication 733723220 wpa_supplicant: Skip scan before starting a BSS in AP mode f45cf609c wpa_supplicant: Fix compiling without IEEE8021X_EAPOL c62e94d79 Add missing driver entries to wpa_supplicant documentation 9122b60ff DPP: Remove argument requirement for DPP push button command 397d432f6 Add vendor attributes for MLO link active, EMLSR entry/exit 5d285040d Rename VHT elements to match the standard 8f8f68ba6 hostapd: Support channel switch to 320 MHz channels 4d0743d5e Fix file mode bits d930211bd Select 6 GHz mode correctly for ACS cases 927dbfb45 Fix 40 MHz channel bringup with ACS on the 6 GHz band 8bc84fcee Allow MLO disabled connection to legacy open/WPA2-Personal-only AP MLDs b9c3b57a9 Update AP RSNE/RSNXE to RSN state machine on driver-selected BSS cases 566ab39a7 tests: KDK derivation based on Secure LTF capability 6972b0fa2 OWE: Update transition mode information on selecting a new BSS f54ce7433 Fix determining mode for 6 GHz band when using hw_mode=any 5b568b21a Add support to fetch link layer stats per MLO link 6422b0d72 Fix vendor attribute numbering and relocate attribute accordingly c858a6360 Add a vendor specific roam status of background scan abort b171c5e4d Update QCA LL_STATS vendor command 6002fe87d SAE: Fix expected AP MLD address info in a debug print c70405cef MLD STA: Do not fail on unknown IEs in Authentication frames f8931fcba hostapd: Restore the flow of set beacon and WPA key init e8912452e Export wpa_supplicant config item 'he' for external configuration 9932ff30c Allowed frequency list configuration for AP operation 07a7bcd7e WMM: Advertise support for 16 PTKSA replay counters for non-AP STA ac54b6127 nl80211: Support for RNR elements 5d06acefd RNR: Add elements by default for EMA AP 8f1d38419 RNR: Skip interfaces on the same radio for MBSSID 921f82cf1 Sync with wireless-next.git include/uapi/linux/nl80211.h 302d761a8 Add QCA vendor feature flag for allowed frequency list 44c38af04 Add QCA vendor interface to get connected channels utilization bb4560252 Add QCA vendor attribute to configure list of allowed frequencies for AP Change-Id: Ibb944a0a4fbb2ac4abdec8fb09ce2dab3b551c27
-rw-r--r--hostapd/config_file.c2
-rw-r--r--hostapd/ctrl_iface.c30
-rw-r--r--hostapd/hostapd.conf5
-rw-r--r--hostapd/hostapd_cli.c2
-rw-r--r--src/ap/ap_config.c1
-rw-r--r--src/ap/ap_config.h3
-rw-r--r--src/ap/ap_drv_ops.c12
-rw-r--r--src/ap/ap_drv_ops.h5
-rw-r--r--src/ap/beacon.c52
-rw-r--r--src/ap/drv_callbacks.c3
-rw-r--r--src/ap/hostapd.c18
-rw-r--r--src/ap/hw_features.c25
-rw-r--r--src/ap/ieee802_11.c121
-rw-r--r--src/ap/ieee802_11.h5
-rw-r--r--src/ap/ieee802_1x.c27
-rw-r--r--src/ap/sta_info.c20
-rw-r--r--src/ap/sta_info.h3
-rw-r--r--src/ap/wpa_auth_ft.c7
-rw-r--r--src/common/ieee802_11_common.c8
-rw-r--r--src/common/ieee802_11_common.h2
-rw-r--r--src/common/ieee802_11_defs.h12
-rw-r--r--src/common/qca-vendor.h580
-rw-r--r--src/common/wpa_common.c2
-rw-r--r--src/common/wpa_ctrl.h4
-rw-r--r--src/drivers/driver.h70
-rw-r--r--src/drivers/driver_common.c2
-rw-r--r--src/drivers/driver_nl80211.c101
-rw-r--r--src/drivers/driver_nl80211.h5
-rw-r--r--src/drivers/driver_nl80211_capa.c3
-rw-r--r--src/drivers/driver_nl80211_event.c211
-rw-r--r--src/drivers/driver_nl80211_scan.c2
-rw-r--r--src/drivers/nl80211_copy.h24
-rw-r--r--src/eapol_auth/eapol_auth_sm.c26
-rw-r--r--src/eapol_auth/eapol_auth_sm.h4
-rw-r--r--src/eapol_auth/eapol_auth_sm_i.h4
-rw-r--r--src/pasn/pasn_common.h3
-rw-r--r--src/pasn/pasn_responder.c6
-rw-r--r--src/rsn_supp/wpa.c3
-rw-r--r--src/rsn_supp/wpa.h1
-rw-r--r--src/rsn_supp/wpa_i.h2
-rw-r--r--src/rsn_supp/wpa_ie.c4
-rw-r--r--wpa_supplicant/README2
-rw-r--r--wpa_supplicant/config.c1
-rw-r--r--wpa_supplicant/doc/docbook/wpa_supplicant.sgml14
-rw-r--r--wpa_supplicant/events.c145
-rw-r--r--wpa_supplicant/mesh_mpm.c2
-rw-r--r--wpa_supplicant/sme.c69
-rw-r--r--wpa_supplicant/wpa_cli.c2
-rw-r--r--wpa_supplicant/wpa_supplicant.c31
49 files changed, 1511 insertions, 175 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 17b1b4a6..580e41c9 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4738,6 +4738,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
bss->pasn_comeback_after = atoi(pos);
+ } else if (os_strcmp(buf, "pasn_noauth") == 0) {
+ bss->pasn_noauth = atoi(pos);
#endif /* CONFIG_PASN */
} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index ea9c4444..b46d9210 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2550,6 +2550,36 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
return -1;
}
break;
+ case 320:
+ if (!params->center_freq1 || params->center_freq2 ||
+ !params->sec_channel_offset)
+ return -1;
+
+ switch (params->sec_channel_offset) {
+ case 1:
+ if (params->freq + 150 != params->center_freq1 &&
+ params->freq + 110 != params->center_freq1 &&
+ params->freq + 70 != params->center_freq1 &&
+ params->freq + 30 != params->center_freq1 &&
+ params->freq - 10 != params->center_freq1 &&
+ params->freq - 50 != params->center_freq1 &&
+ params->freq - 90 != params->center_freq1 &&
+ params->freq - 130 != params->center_freq1)
+ return -1;
+ break;
+ case -1:
+ if (params->freq + 130 != params->center_freq1 &&
+ params->freq + 90 != params->center_freq1 &&
+ params->freq + 50 != params->center_freq1 &&
+ params->freq + 10 != params->center_freq1 &&
+ params->freq - 30 != params->center_freq1 &&
+ params->freq - 70 != params->center_freq1 &&
+ params->freq - 110 != params->center_freq1 &&
+ params->freq - 150 != params->center_freq1)
+ return -1;
+ break;
+ }
+ break;
default:
return -1;
}
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index bc4a0f6e..5868bfde 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -2170,6 +2170,11 @@ own_ip_addr=127.0.0.1
# (default: 10 TUs)
#pasn_comeback_after=10
+# Unauthenticated PASN activated (dot11NoAuthPASNActivated)
+# This indicates whether PASN without mutual authentication is allowed.
+# (default: 1 = activated)
+#pasn_noauth=1
+
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 95edea87..646dfc59 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1529,7 +1529,7 @@ static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc,
static int hostapd_cli_cmd_dpp_push_button(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return hostapd_cli_cmd(ctrl, "DPP_PUSH_BUTTON", 1, argc, argv);
+ return hostapd_cli_cmd(ctrl, "DPP_PUSH_BUTTON", 0, argc, argv);
}
#endif /* CONFIG_DPP3 */
#endif /* CONFIG_DPP */
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index b5fcc383..c3ee5067 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -169,6 +169,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_PASN
/* comeback after 10 TUs */
bss->pasn_comeback_after = 10;
+ bss->pasn_noauth = 1;
#endif /* CONFIG_PASN */
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 07ee31c4..def5fd56 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -906,6 +906,9 @@ struct hostapd_bss_config {
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_PASN
+ /* Whether to allow PASN-UNAUTH */
+ int pasn_noauth;
+
#ifdef CONFIG_TESTING_OPTIONS
/*
* Normally, KDK should be derived if and only if both sides support
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index f77f738e..aa4dbe9e 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -883,10 +883,10 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
}
-static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
- struct hostapd_hw_modes *mode,
- int acs_ch_list_all,
- int **freq_list)
+void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
+ struct hostapd_hw_modes *mode,
+ int acs_ch_list_all, bool allow_disabled,
+ int **freq_list)
{
int i;
@@ -912,7 +912,7 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
(!hapd->iface->conf->ieee80211ax &&
!hapd->iface->conf->ieee80211be)))
continue;
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ if ((!(chan->flag & HOSTAPD_CHAN_DISABLED) || allow_disabled) &&
!(hapd->iface->conf->acs_exclude_dfs &&
(chan->flag & HOSTAPD_CHAN_RADAR)) &&
!(chan->max_tx_power < hapd->iface->conf->min_tx_power))
@@ -969,7 +969,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
selected_mode != mode->mode)
continue;
hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all,
- &freq_list);
+ false, &freq_list);
}
params.freq_list = freq_list;
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 93b22449..023cbf1f 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -156,6 +156,11 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set,
void hostapd_get_ext_capa(struct hostapd_iface *iface);
+void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
+ struct hostapd_hw_modes *mode,
+ int acs_ch_list_all, bool allow_disabled,
+ int **freq_list);
+
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
int enabled)
{
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index c25a5bbc..de944fed 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -468,8 +468,9 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
{
struct hostapd_iface *iface = hapd->iface;
struct hostapd_data *tx_bss;
- size_t len;
+ size_t len, rnr_len = 0;
u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
+ u8 rnr_elem_count = 0, *rnr_elem = NULL, **rnr_elem_offset = NULL;
if (!iface->mbssid_max_interfaces ||
iface->num_bss > iface->mbssid_max_interfaces ||
@@ -479,7 +480,7 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
tx_bss = hostapd_mbssid_get_tx_bss(hapd);
len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
- NULL, 0);
+ NULL, 0, &rnr_len);
if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
elem_count > iface->ema_max_periodicity))
goto fail;
@@ -492,8 +493,19 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
if (!elem_offset)
goto fail;
+ if (rnr_len) {
+ rnr_elem = os_zalloc(rnr_len);
+ if (!rnr_elem)
+ goto fail;
+
+ rnr_elem_offset = os_calloc(elem_count + 1, sizeof(u8 *));
+ if (!rnr_elem_offset)
+ goto fail;
+ }
+
end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
- elem_count, elem_offset, NULL, 0);
+ elem_count, elem_offset, NULL, 0, rnr_elem,
+ &rnr_elem_count, rnr_elem_offset, rnr_len);
params->mbssid_tx_iface = tx_bss->conf->iface;
params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
@@ -501,12 +513,19 @@ ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
params->mbssid_elem_len = end - elem;
params->mbssid_elem_count = elem_count;
params->mbssid_elem_offset = elem_offset;
+ params->rnr_elem = rnr_elem;
+ params->rnr_elem_len = rnr_len;
+ params->rnr_elem_count = rnr_elem_count;
+ params->rnr_elem_offset = rnr_elem_offset;
if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED)
params->ema = true;
return 0;
fail:
+ os_free(rnr_elem);
+ os_free(rnr_elem_offset);
+ os_free(elem_offset);
os_free(elem);
wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
return -1;
@@ -590,7 +609,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
#endif /* CONFIG_IEEE80211BE */
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
- known_bss, known_bss_len);
+ known_bss, known_bss_len, NULL);
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
buflen += hostapd_mbo_ie_len(hapd);
buflen += hostapd_eid_owe_trans_len(hapd);
@@ -658,7 +677,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_get_rsne(hapd, pos, epos - pos);
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
- NULL, known_bss, known_bss_len);
+ NULL, known_bss, known_bss_len, NULL, NULL,
+ NULL, 0);
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
pos = hostapd_get_mde(hapd, pos, epos - pos);
@@ -2026,6 +2046,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
params->mbssid_elem = NULL;
os_free(params->mbssid_elem_offset);
params->mbssid_elem_offset = NULL;
+ os_free(params->rnr_elem);
+ params->rnr_elem = NULL;
+ os_free(params->rnr_elem_offset);
+ params->rnr_elem_offset = NULL;
#ifdef CONFIG_FILS
os_free(params->fd_frame_tmpl);
params->fd_frame_tmpl = NULL;
@@ -2034,6 +2058,8 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
os_free(params->unsol_bcast_probe_resp_tmpl);
params->unsol_bcast_probe_resp_tmpl = NULL;
#endif /* CONFIG_IEEE80211AX */
+ os_free(params->allowed_freqs);
+ params->allowed_freqs = NULL;
}
@@ -2045,7 +2071,8 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
struct hostapd_config *iconf = iface->conf;
struct hostapd_hw_modes *cmode = iface->current_mode;
struct wpabuf *beacon, *proberesp, *assocresp;
- int res, ret = -1;
+ int res, ret = -1, i;
+ struct hostapd_hw_modes *mode;
if (!hapd->drv_priv) {
wpa_printf(MSG_ERROR, "Interface is disabled");
@@ -2120,6 +2147,19 @@ static int __ieee802_11_set_beacon(struct hostapd_data *hapd)
&cmode->eht_capab[IEEE80211_MODE_AP]) == 0)
params.freq = &freq;
+ for (i = 0; i < hapd->iface->num_hw_features; i++) {
+ mode = &hapd->iface->hw_features[i];
+
+ if (iconf->hw_mode != HOSTAPD_MODE_IEEE80211ANY &&
+ iconf->hw_mode != mode->mode)
+ continue;
+
+ hostapd_get_hw_mode_any_channels(hapd, mode,
+ !(iconf->acs_freq_list.num ||
+ iconf->acs_ch_list.num),
+ true, &params.allowed_freqs);
+ }
+
res = hostapd_drv_set_ap(hapd, &params);
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
if (res)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 8fc128e9..510a06c6 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -978,7 +978,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hapd->iconf->ch_switch_eht_config = 0;
if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
- width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160)
+ width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 ||
+ width == CHAN_WIDTH_320)
hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT)
hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 8b3fb404..112e6fad 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1476,11 +1476,11 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
return -1;
}
- if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ if (start_beacon && hostapd_start_beacon(hapd, flush_old_stations) < 0)
return -1;
- if (start_beacon)
- return hostapd_start_beacon(hapd, flush_old_stations);
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
return 0;
}
@@ -1756,16 +1756,15 @@ static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
static void hostapd_set_6ghz_sec_chan(struct hostapd_iface *iface)
{
- int bw, seg0;
+ int bw;
if (!is_6ghz_op_class(iface->conf->op_class))
return;
- seg0 = hostapd_get_oper_centr_freq_seg0_idx(iface->conf);
- bw = center_idx_to_bw_6ghz(seg0);
+ bw = op_class_to_bandwidth(iface->conf->op_class);
/* Assign the secondary channel if absent in config for
* bandwidths > 20 MHz */
- if (bw > 0 && !iface->conf->secondary_channel) {
+ if (bw >= 40 && !iface->conf->secondary_channel) {
if (((iface->conf->channel - 1) / 4) % 2)
iface->conf->secondary_channel = -1;
else
@@ -3340,7 +3339,6 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
return;
}
- hostapd_prune_associations(hapd, sta->addr);
ap_sta_clear_disconnect_timeouts(hapd, sta);
sta->post_csa_sa_query = 0;
@@ -3602,6 +3600,7 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
case 40:
case 80:
case 160:
+ case 320:
conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
break;
default:
@@ -3674,6 +3673,9 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
case 160:
bandwidth = CONF_OPER_CHWIDTH_160MHZ;
break;
+ case 320:
+ bandwidth = CONF_OPER_CHWIDTH_320MHZ;
+ break;
default:
bandwidth = CONF_OPER_CHWIDTH_USE_HT;
break;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 842d9f5b..f836be48 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -1001,6 +1001,24 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
}
+static bool skip_mode(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode)
+{
+ int chan;
+
+ if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan))
+ return true;
+
+ if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
+ (mode->mode != HOSTAPD_MODE_IEEE80211A ||
+ mode->num_channels == 0 ||
+ !is_6ghz_freq(mode->channels[0].freq)))
+ return true;
+
+ return false;
+}
+
+
static void hostapd_determine_mode(struct hostapd_iface *iface)
{
int i;
@@ -1022,6 +1040,9 @@ static void hostapd_determine_mode(struct hostapd_iface *iface)
mode = &iface->hw_features[i];
if (mode->mode == target_mode) {
+ if (skip_mode(iface, mode))
+ continue;
+
iface->current_mode = mode;
iface->conf->hw_mode = mode->mode;
break;
@@ -1152,11 +1173,9 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
iface->current_mode = NULL;
for (i = 0; i < iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode = &iface->hw_features[i];
- int chan;
if (mode->mode == iface->conf->hw_mode) {
- if (iface->freq > 0 &&
- !hw_mode_get_channel(mode, iface->freq, &chan))
+ if (skip_mode(iface, mode))
continue;
iface->current_mode = mode;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 0142ee44..93a6b4f5 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2527,6 +2527,7 @@ static void hapd_initialize_pasn(struct hostapd_data *hapd,
pasn->cb_ctx = hapd;
pasn->send_mgmt = hapd_pasn_send_mlme;
pasn->pasn_groups = hapd->conf->pasn_groups;
+ pasn->noauth = hapd->conf->pasn_noauth;
pasn->wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
pasn->rsn_pairwise = hapd->conf->rsn_pairwise;
pasn->derive_kdk = hapd->iface->drv_flags2 &
@@ -3696,7 +3697,7 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = set_sta_vht_opmode(hapd, sta, elems->vht_opmode_notif);
+ resp = set_sta_vht_opmode(hapd, sta, elems->opmode_notif);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
@@ -5758,7 +5759,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
sta->flags |= WLAN_STA_WDS;
}
- if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
+ /* WPS not supported on backhaul BSS. Disable 4addr mode on fronthaul */
+ if ((sta->flags & WLAN_STA_WDS) ||
+ (sta->flags & WLAN_STA_MULTI_AP &&
+ !(hapd->conf->multi_ap & FRONTHAUL_BSS) &&
+ !(sta->flags & WLAN_STA_WPS))) {
int ret;
char ifname_wds[IFNAMSIZ + 1];
@@ -6347,7 +6352,7 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
!hapd->cs_freq_params.eht_enabled))
return eid;
- /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */
+ /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80, 4: 320 */
switch (hapd->cs_freq_params.bandwidth) {
case 40:
bw = 0;
@@ -6362,6 +6367,9 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
case 160:
bw = 2;
break;
+ case 320:
+ bw = 4;
+ break;
default:
/* not valid VHT bandwidth or not in CSA */
return eid;
@@ -6379,9 +6387,9 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
&chan2) != HOSTAPD_MODE_IEEE80211A)
return eid;
- *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER;
+ *eid++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER;
*eid++ = 5; /* Length of Channel Switch Wrapper */
- *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH;
+ *eid++ = WLAN_EID_WIDE_BW_CHSWITCH;
*eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
*eid++ = bw; /* New Channel Width */
*eid++ = chan1; /* New Channel Center Frequency Segment 0 */
@@ -6421,9 +6429,16 @@ static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd,
}
-static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
- struct hostapd_data *reporting_hapd,
- size_t *current_len)
+struct mbssid_ie_profiles {
+ u8 start;
+ u8 end;
+};
+
+static size_t
+hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ size_t *current_len,
+ struct mbssid_ie_profiles *skip_profiles)
{
size_t total_len = 0, len = *current_len;
int tbtt_count = 0;
@@ -6449,6 +6464,10 @@ static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
bss->conf->ignore_broadcast_ssid)
continue;
+ if (skip_profiles &&
+ i >= skip_profiles->start && i < skip_profiles->end)
+ continue;
+
if (len + RNR_TBTT_INFO_LEN > 255 ||
tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
break;
@@ -6527,7 +6546,7 @@ static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
continue;
len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
- current_len);
+ current_len, NULL);
}
return len;
@@ -6550,15 +6569,18 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
total_len += hostapd_eid_rnr_colocation_len(
hapd, &current_len);
- if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ !hapd->iconf->mbssid)
total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
- &current_len);
+ &current_len,
+ NULL);
break;
case WLAN_FC_STYPE_ACTION:
if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
- &current_len);
+ &current_len,
+ NULL);
break;
default:
@@ -6626,7 +6648,8 @@ static u8 * hostapd_eid_nr_db(struct hostapd_data *hapd, u8 *eid,
static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
struct hostapd_data *reporting_hapd,
- u8 *eid, size_t *current_len)
+ u8 *eid, size_t *current_len,
+ struct mbssid_ie_profiles *skip_profiles)
{
struct hostapd_data *bss;
struct hostapd_iface *iface = hapd->iface;
@@ -6671,6 +6694,10 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
bss->conf->ignore_broadcast_ssid)
continue;
+ if (skip_profiles &&
+ i >= skip_profiles->start && i < skip_profiles->end)
+ continue;
+
if (len + RNR_TBTT_INFO_LEN > 255 ||
tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
break;
@@ -6687,7 +6714,7 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
if (iface->conf->mbssid != MBSSID_DISABLED &&
iface->num_bss > 1) {
bss_param |= RNR_BSS_PARAM_MULTIPLE_BSSID;
- if (i == 0)
+ if (bss == hostapd_mbssid_get_tx_bss(hapd))
bss_param |=
RNR_BSS_PARAM_TRANSMITTED_BSSID;
}
@@ -6735,7 +6762,7 @@ static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
continue;
eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
- current_len);
+ current_len, NULL);
}
return eid;
@@ -6759,15 +6786,16 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
eid = hostapd_eid_rnr_colocation(hapd, eid,
&current_len);
- if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ !hapd->iconf->mbssid)
eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
- &current_len);
+ &current_len, NULL);
break;
case WLAN_FC_STYPE_ACTION:
if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
- &current_len);
+ &current_len, NULL);
break;
default:
@@ -6856,7 +6884,7 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
u8 *elem_count, const u8 *known_bss,
- size_t known_bss_len)
+ size_t known_bss_len, size_t *rnr_len)
{
size_t len = 0, bss_index = 1;
@@ -6875,13 +6903,29 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
}
while (bss_index < hapd->iface->num_bss) {
+ size_t rnr_count = bss_index;
+
len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
&bss_index, known_bss,
known_bss_len);
if (frame_type == WLAN_FC_STYPE_BEACON)
*elem_count += 1;
+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED && rnr_len) {
+ size_t rnr_cur_len = 0;
+ struct mbssid_ie_profiles skip_profiles = {
+ rnr_count, bss_index
+ };
+
+ *rnr_len += hostapd_eid_rnr_iface_len(
+ hapd, hostapd_mbssid_get_tx_bss(hapd),
+ &rnr_cur_len, &skip_profiles);
+ }
}
+
+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED && rnr_len)
+ *rnr_len += hostapd_eid_rnr_len(hapd, frame_type);
+
return len;
}
@@ -6993,10 +7037,12 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
unsigned int frame_stype, u8 elem_count,
u8 **elem_offset,
- const u8 *known_bss, size_t known_bss_len)
+ const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
+ u8 *rnr_count, u8 **rnr_offset, size_t rnr_len)
{
- size_t bss_index = 1;
- u8 elem_index = 0;
+ size_t bss_index = 1, cur_len = 0;
+ u8 elem_index = 0, *rnr_start_eid = rnr_eid;
+ bool add_rnr;
if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
(frame_stype != WLAN_FC_STYPE_BEACON &&
@@ -7009,7 +7055,13 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
return eid;
}
+ add_rnr = hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
+ frame_stype == WLAN_FC_STYPE_BEACON &&
+ rnr_eid && rnr_count && rnr_offset && rnr_len;
+
while (bss_index < hapd->iface->num_bss) {
+ unsigned int rnr_start_count = bss_index;
+
if (frame_stype == WLAN_FC_STYPE_BEACON) {
if (elem_index == elem_count) {
wpa_printf(MSG_WARNING,
@@ -7024,6 +7076,31 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
hostapd_max_bssid_indicator(hapd),
&bss_index, elem_count,
known_bss, known_bss_len);
+
+ if (add_rnr) {
+ struct mbssid_ie_profiles skip_profiles = {
+ rnr_start_count, bss_index
+ };
+
+ rnr_offset[*rnr_count] = rnr_eid;
+ *rnr_count = *rnr_count + 1;
+ cur_len = 0;
+ rnr_eid = hostapd_eid_rnr_iface(
+ hapd, hostapd_mbssid_get_tx_bss(hapd),
+ rnr_eid, &cur_len, &skip_profiles);
+ }
+ }
+
+ if (add_rnr && (size_t) (rnr_eid - rnr_start_eid) < rnr_len) {
+ rnr_offset[*rnr_count] = rnr_eid;
+ *rnr_count = *rnr_count + 1;
+ cur_len = 0;
+
+ if (hapd->conf->rnr)
+ rnr_eid = hostapd_eid_nr_db(hapd, rnr_eid, &cur_len);
+ if (get_colocation_mode(hapd) == COLOCATED_LOWER_BAND)
+ rnr_eid = hostapd_eid_rnr_colocation(hapd, rnr_eid,
+ &cur_len);
}
return eid;
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 1e4c843f..1190a5ea 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -218,11 +218,12 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *eht_capab, size_t eht_capab_len);
size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
u8 *elem_count, const u8 *known_bss,
- size_t known_bss_len);
+ size_t known_bss_len, size_t *rnr_len);
u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
unsigned int frame_stype, u8 elem_count,
u8 **elem_offset,
- const u8 *known_bss, size_t known_bss_len);
+ const u8 *known_bss, size_t known_bss_len, u8 *rnr_eid,
+ u8 *rnr_count, u8 **rnr_offset, size_t rnr_len);
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 46a47d06..8b67669b 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -43,9 +43,9 @@
#ifdef CONFIG_HS20
static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_HS20 */
-static void ieee802_1x_finished(struct hostapd_data *hapd,
+static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
- int remediation);
+ int remediation, bool logoff);
static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
@@ -2287,16 +2287,18 @@ static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
}
-static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
- int preauth, int remediation)
+static bool _ieee802_1x_finished(void *ctx, void *sta_ctx, int success,
+ int preauth, int remediation, bool logoff)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
- if (preauth)
+ if (preauth) {
rsn_preauth_finished(hapd, sta, success);
- else
- ieee802_1x_finished(hapd, sta, success, remediation);
+ return false;
+ }
+
+ return ieee802_1x_finished(hapd, sta, success, remediation, logoff);
}
@@ -2977,9 +2979,9 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
#endif /* CONFIG_HS20 */
-static void ieee802_1x_finished(struct hostapd_data *hapd,
+static bool ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
- int remediation)
+ int remediation, bool logoff)
{
const u8 *key;
size_t len;
@@ -3039,6 +3041,11 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
* EAP-FAST with anonymous provisioning, may require another
* EAPOL authentication to be started to complete connection.
*/
- ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta);
+ ap_sta_delayed_1x_auth_fail_disconnect(hapd, sta,
+ logoff ? 0 : 10);
+ if (logoff && sta->wpa_sm)
+ return true;
}
+
+ return false;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 63f514c9..2fb6edf0 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -197,7 +197,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
ap_sta_set_authorized(hapd, sta, 0);
hostapd_set_sta_flags(hapd, sta);
- if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP))
+ if ((sta->flags & WLAN_STA_WDS) ||
+ (sta->flags & WLAN_STA_MULTI_AP &&
+ !(hapd->conf->multi_ap & FRONTHAUL_BSS) &&
+ !(sta->flags & WLAN_STA_WPS)))
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
if (sta->ipaddr)
@@ -1280,10 +1283,12 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return;
- if (authorized)
+ if (authorized) {
+ hostapd_prune_associations(hapd, sta->addr);
sta->flags |= WLAN_STA_AUTHORIZED;
- else
+ } else {
sta->flags &= ~WLAN_STA_AUTHORIZED;
+ }
#ifdef CONFIG_P2P
if (hapd->p2p_group == NULL) {
@@ -1536,11 +1541,12 @@ static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
- struct sta_info *sta)
+ struct sta_info *sta,
+ unsigned timeout)
{
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Force disconnection of " MACSTR
- " after EAP-Failure in 10 ms", MAC2STR(sta->addr));
+ " after EAP-Failure in %u ms", MAC2STR(sta->addr), timeout);
/*
* Add a small sleep to increase likelihood of previously requested
@@ -1548,8 +1554,8 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
* operations.
*/
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
- eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
- hapd, sta);
+ eloop_register_timeout(0, timeout * 1000,
+ ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index b59b7584..8433ff8d 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -373,7 +373,8 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
- struct sta_info *sta);
+ struct sta_info *sta,
+ unsigned timeout);
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 35585cd9..2402ad92 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -3085,7 +3085,7 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *req_pmk_r0_name,
- const u8 *req_pmk_r1_name,
+ u8 *out_pmk_r1_name,
u8 *out_pmk_r1, int *out_pairwise,
struct vlan_description *vlan,
const u8 **identity, size_t *identity_len,
@@ -3096,7 +3096,6 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
{
struct wpa_auth_config *conf = &wpa_auth->conf;
const struct wpa_ft_pmk_r0_sa *r0;
- u8 pmk_r1_name[WPA_PMK_NAME_LEN];
int expires_in = 0;
int session_timeout = 0;
struct os_reltime now;
@@ -3115,7 +3114,7 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
if (wpa_derive_pmk_r1(r0->pmk_r0, r0->pmk_r0_len, r0->pmk_r0_name,
conf->r1_key_holder,
- sm->addr, out_pmk_r1, pmk_r1_name) < 0)
+ sm->addr, out_pmk_r1, out_pmk_r1_name) < 0)
return -1;
os_get_reltime(&now);
@@ -3126,7 +3125,7 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
session_timeout = r0->session_timeout - now.sec;
wpa_ft_store_pmk_r1(wpa_auth, sm->addr, out_pmk_r1, r0->pmk_r0_len,
- pmk_r1_name,
+ out_pmk_r1_name,
sm->pairwise, r0->vlan, expires_in, session_timeout,
r0->identity, r0->identity_len,
r0->radius_cui, r0->radius_cui_len);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index cd1b198f..abe3a6a0 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -550,10 +550,10 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len,
break;
elems->vht_operation = pos;
break;
- case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
+ case WLAN_EID_OPERATING_MODE_NOTIFICATION:
if (elen != 1)
break;
- elems->vht_opmode_notif = pos;
+ elems->opmode_notif = pos;
break;
case WLAN_EID_LINK_ID:
if (elen < 18)
@@ -777,8 +777,8 @@ void ieee802_11_elems_clear_ids(struct ieee802_11_elems *elems,
case WLAN_EID_VHT_OPERATION:
elems->vht_operation = NULL;
break;
- case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
- elems->vht_opmode_notif = NULL;
+ case WLAN_EID_OPERATING_MODE_NOTIFICATION:
+ elems->opmode_notif = NULL;
break;
case WLAN_EID_LINK_ID:
elems->link_id = NULL;
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index d1f72184..c7afd347 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -55,7 +55,7 @@ struct ieee802_11_elems {
const u8 *peer_mgmt;
const u8 *vht_capabilities;
const u8 *vht_operation;
- const u8 *vht_opmode_notif;
+ const u8 *opmode_notif;
const u8 *vendor_ht_cap;
const u8 *vendor_vht;
const u8 *p2p;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 9846fb48..b9bb2266 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -435,13 +435,13 @@
#define WLAN_EID_ANTENNA_SECTOR_ID_PATTERN 190
#define WLAN_EID_VHT_CAP 191
#define WLAN_EID_VHT_OPERATION 192
-#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
-#define WLAN_EID_VHT_WIDE_BW_CHSWITCH 194
+#define WLAN_EID_EXTENDED_BSS_LOAD 193
+#define WLAN_EID_WIDE_BW_CHSWITCH 194
#define WLAN_EID_TRANSMIT_POWER_ENVELOPE 195
-#define WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER 196
-#define WLAN_EID_VHT_AID 197
-#define WLAN_EID_VHT_QUIET_CHANNEL 198
-#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199
+#define WLAN_EID_CHANNEL_SWITCH_WRAPPER 196
+#define WLAN_EID_AID 197
+#define WLAN_EID_QUIET_CHANNEL 198
+#define WLAN_EID_OPERATING_MODE_NOTIFICATION 199
#define WLAN_EID_UPSIM 200
#define WLAN_EID_REDUCED_NEIGHBOR_REPORT 201
#define WLAN_EID_TVHT_OPERATION 202
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 6c25816b..2fcdfbe4 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -899,6 +899,61 @@ enum qca_radiotap_vendor_ids {
* configure and fetch the state information of the MLO links affiliated
* with the STA interface. The attributes used with this command are
* defined in enum qca_wlan_vendor_attr_mlo_link_state.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS: Userspace can use this
+ * vendor subcommand to trigger channel utilization measurement on entire
+ * channel width of the connected channel(s). For MLO connection, connected
+ * channel utilization measurement shall be done on all the MLO links.
+ * The driver may use regular scan or wideband energy detection feature
+ * based on the hardware capability for connected channel(s) utilization
+ * measurement. The driver indicates the connected channel(s) utilization
+ * measurement completion as an asynchronous event with this command ID to
+ * userspace. Upon receiving this event, userspace can use
+ * %NL80211_CMD_GET_INTERFACE to determine the channel width of the current
+ * connected channel(s) and can derive the channel utilization percentage
+ * (CU) of each 20 MHz sub-channel of the entire connected channel using
+ * %NL80211_CMD_GET_SURVEY response.
+ * CU = %NL80211_SURVEY_INFO_TIME_BUSY * 100 / %NL80211_SURVEY_INFO_TIME.
+ * This command is only used for STA mode.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP: This vendor subcommand is
+ * used as an event to notify the userspace of TID-to-link map changes
+ * negotiated by the driver or updated by associated AP MLD with Beacon,
+ * Probe Response, or Action frames. The attributes used with this command
+ * are defined in enum qca_wlan_vendor_attr_tid_to_link_map.
+ *
+ * Note that the attribute
+ * %QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR may not correspond to
+ * the current connected AP MLD address.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG: Notify userspace about the removal
+ * of STA MLD setup links due to the AP MLD removing the corresponding
+ * affiliated APs with Multi-Link reconfiguration. If all the STA MLD setup
+ * links are removed during Multi-Link reconfiguration, the driver shall
+ * use %NL80211_CMD_DISCONNECT instead of this command since it is a
+ * connection drop. The attributes used with this command are defined in
+ * enum qca_wlan_vendor_attr_link_reconfig.
+ * Note that the attribute
+ * %QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR may not correspond to
+ * the current connected AP MLD address.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_TDLS_DISC_RSP_EXT: Vendor command to configure
+ * the driver with MLO link id information on which to transmit the TDLS
+ * discovery response frame on the configured MLO BSS link when the
+ * local station is connected in MLO mode. This command is sent to the
+ * driver prior to the TDLS discovery response management transmit
+ * operation and is followed immediately by the TDLS discovery response
+ * management frame transmit command.
+ *
+ * The driver saves the configured MLO link id information and uses it for
+ * the following TDLS discovery response frame transmission on the
+ * configured MLO BSS link and the link id information is cleared in the
+ * driver after the TDLS discovery response frame is successfully
+ * transmitted. This behavior is indepent of the TDLS peer STA connection
+ * mode (MLO or non-MLO).
+ *
+ * Uses the attributes defined in
+ * enum qca_wlan_vendor_attr_tdls_disc_rsp_ext.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -1110,6 +1165,10 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_GET_MONITOR_MODE = 225,
QCA_NL80211_VENDOR_SUBCMD_ROAM_STATS = 226,
QCA_NL80211_VENDOR_SUBCMD_MLO_LINK_STATE = 227,
+ QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS = 228,
+ QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP = 229,
+ QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG = 230,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_DISC_RSP_EXT = 231,
};
/* Compatibility defines for previously used subcmd names.
@@ -1787,6 +1846,11 @@ enum qca_wlan_vendor_acs_hw_mode {
* measurement management frames. If
* NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE is set, then
* QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP will be ignored.
+ * @QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST: Flag indicates that the device
+ * in AP mode supports configuring allowed frequency list for AP operation
+ * with %QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST.
+ * @QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN: Flag indicates
+ * that the device supports enhanced audio experience over WLAN feature.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
@@ -1812,6 +1876,8 @@ enum qca_wlan_vendor_features {
QCA_WLAN_VENDOR_FEATURE_SECURE_RTT_AP = 19,
QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_STA = 20,
QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP = 21,
+ QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST = 22,
+ QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN = 23,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@@ -2839,6 +2905,9 @@ enum qca_wlan_vendor_attr_config {
* 8-bit unsigned value. This attribute can be used to configure the
* data path mode to be followed for audio traffic. Possible values
* are defined in enum qca_wlan_audio_data_path.
+ *
+ * This attribute is used only when the driver advertises support for
+ * QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN.
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_AUDIO_DATA_PATH = 82,
@@ -2917,6 +2986,57 @@ enum qca_wlan_vendor_attr_config {
*/
QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE = 90,
+ /* Nested attribute with frequencies in u32 attributes to configure a
+ * list of allowed 20 MHz channel center frequencies in MHz for AP
+ * operation. Whenever performing a channel selection operation, the
+ * driver shall generate a new list based on this provided list by
+ * filtering out channels that cannot be used at that time due to
+ * regulatory or other constraints. The resulting list is used as the
+ * list of all allowed channels, i.e., operation on any channel that is
+ * not included is not allowed, whenever performing operations like ACS
+ * and DFS.
+ *
+ * Userspace shall configure this before starting the AP and the
+ * configuration is valid only from the next BSS start and until the
+ * BSS is stopped. The driver shall clear this configuration when the
+ * AP is stopped and fall back to the default behavior for subsequent
+ * AP operation.
+ *
+ * The default behavior when this configuration is not applicable is the
+ * driver can choose any of the channels supported by the hardware
+ * except the channels that cannot be used due to regulatory or other
+ * constraints.
+ *
+ * The driver shall reject this configuration if done after the AP is
+ * started. This attribute can be used to specify user's choice of
+ * frequencies and static puncture channel list, etc.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST = 91,
+
+ /* Nested attribute to indicate EHT MLO links to be forced active.
+ * It contains link MAC address attributes. These nested attributes are
+ * of the type NL80211_ATTR_MAC and are used to force enabling of the
+ * MLO links corresponding to the indicated link MAC addresses.
+ * Subsequently, the links corresponding to the link MAC addresses that
+ * are not indicated are forced inactive.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS = 92,
+
+ /* 8-bit unsigned value to configure EMLSR mode entry or exit.
+ * Uses enum qca_wlan_emlsr_mode values.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH = 93,
+
+ /* 8-bit unsigned value to configure the channel bandwidth
+ * for CTS frame transmission during the dymamic bandwidth
+ * signaling CTS procedure referred in IEEE Std 802.11-2020,
+ * 10.3.2.9 CTS and DMG CTS procedure.
+ * This configuration is used for testing purposes.
+ *
+ * This uses values defined in enum nl80211_chan_width.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CTS_CHANNEL_WIDTH = 94,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
@@ -3999,18 +4119,55 @@ enum qca_wlan_vendor_attr_ll_stats_set {
QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST - 1,
};
+/**
+ * qca_wlan_ll_stats_clr_req_bitmap - Represents the bitmap to clear LL STATS
+ * values for %QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO: Clear all radio statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO_CCA: Clear cca_busy_time within
+ * radio statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO_CHANNEL: Clear all channel
+ * statistics within radio statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_SCAN: Clear all scan statistics within
+ * radio statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE: Clear all interface statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_TXRATE: Clear all TX rate statistics
+ * within interface statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_AC: Clear all AC statistics within
+ * interface statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_CONTENTION: Clear all contention
+ * (min, max, avg) statistics within AC statistics.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_ALL_PEER: Clear all peer statistics
+ * on this interface.
+ *
+ * @QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_PER_PEER: Clear particular peer
+ * statistics depending on the peer_mac.
+ */
+enum qca_wlan_ll_stats_clr_req_bitmap {
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO = BIT(0),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO_CCA = BIT(1),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO_CHANNELS = BIT(2),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_RADIO_SCAN = BIT(3),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE = BIT(4),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_TXRATE = BIT(5),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_AC = BIT(6),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_CONTENTION = BIT(7),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_ALL_PEER = BIT(8),
+ QCA_WLAN_LL_STATS_CLR_REQ_BITMAP_IFACE_PER_PEER = BIT(9),
+};
+
enum qca_wlan_vendor_attr_ll_stats_clr {
QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID = 0,
- /* Unsigned 32bit bitmap for clearing statistics
- * All radio statistics 0x00000001
- * cca_busy_time (within radio statistics) 0x00000002
- * All channel stats (within radio statistics) 0x00000004
- * All scan statistics (within radio statistics) 0x00000008
- * All interface statistics 0x00000010
- * All tx rate statistics (within interface statistics) 0x00000020
- * All ac statistics (with in interface statistics) 0x00000040
- * All contention (min, max, avg) statistics (within ac statisctics)
- * 0x00000080.
+ /* Unsigned 32bit bitmap for clearing statistics, specified
+ * in the enum qca_wlan_ll_stats_clr_req_bitmap.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK = 1,
/* Unsigned 8 bit value: Request to stop statistics collection */
@@ -4030,6 +4187,25 @@ enum qca_wlan_vendor_attr_ll_stats_clr {
QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST - 1,
};
+/**
+ * qca_wlan_ll_stats_get_req_bitmap - Represents the bitmap to request LL STATS
+ * values for %QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK.
+ *
+ * @QCA_WLAN_LL_STATS_GET_REQ_BITMAP_RADIO: Request all radio statistics.
+ *
+ * @QCA_WLAN_LL_STATS_GET_REQ_BITMAP_IFACE: Request interface statistics.
+ *
+ * @QCA_WLAN_LL_STATS_GET_REQ_BITMAP_ALL_PEER: Request all peer statistics.
+ *
+ * @QCA_WLAN_LL_STATS_GET_REQ_BITMAP_PER_PEER: Request per peer statistics.
+ */
+enum qca_wlan_ll_stats_get_req_bitmap {
+ QCA_WLAN_LL_STATS_GET_REQ_BITMAP_RADIO = BIT(0),
+ QCA_WLAN_LL_STATS_GET_REQ_BITMAP_IFACE = BIT(1),
+ QCA_WLAN_LL_STATS_GET_REQ_BITMAP_ALL_PEER = BIT(2),
+ QCA_WLAN_LL_STATS_GET_REQ_BITMAP_PER_PEER = BIT(3),
+};
+
enum qca_wlan_vendor_attr_ll_stats_get {
QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0,
/* Unsigned 32 bit value provided by the caller issuing the GET stats
@@ -4038,11 +4214,8 @@ enum qca_wlan_vendor_attr_ll_stats_get {
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID = 1,
/* Unsigned 32 bit value - bit mask to identify what statistics are
- * requested for retrieval.
- * Radio Statistics 0x00000001
- * Interface Statistics 0x00000020
- * All Peer Statistics 0x00000040
- * Peer Statistics 0x00000080
+ * requested for retrieval specified in the enum
+ * qca_wlan_ll_stats_get_req_bitmap
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK = 2,
/* keep last */
@@ -4053,24 +4226,65 @@ enum qca_wlan_vendor_attr_ll_stats_get {
enum qca_wlan_vendor_attr_ll_stats_results {
QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0,
+
+ /*
+ * For Multi Link Operation (MLO) connection, per-link statistics will
+ * be sent inside of %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and
+ * cumulative statistics will be sent outside of
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK to maintain backward
+ * compatibility with legacy user space. Attributes which don't have
+ * explicit documentation for MLO will be sent only outside of
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK, such attributes values
+ * don't depend on whether the connection is MLO capable or not, e.g.,
+ * radio and channel specific attributes.
+ */
+
/* Unsigned 32bit value. Used by the driver; must match the request id
* provided with the QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET command.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX = 2,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX = 3,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX = 4,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX = 5,
- /* Signed 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT = 6,
- /* Signed 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA = 7,
- /* Signed 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK = 8,
/* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are
@@ -4094,7 +4308,8 @@ enum qca_wlan_vendor_attr_ll_stats_results {
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES = 13,
/* NULL terminated SSID. An array of 33 Unsigned 8bit values */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID = 14,
- /* BSSID. An array of 6 unsigned 8 bit values */
+ /* For non-MLO connection, BSSID of the AP. For MLO connection, MLD
+ * address of the AP. An array of 6 unsigned 8 bit values */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID = 15,
/* Country string advertised by AP. An array of 3 unsigned 8 bit
* values.
@@ -4107,6 +4322,15 @@ enum qca_wlan_vendor_attr_ll_stats_results {
/* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could
* be nested within the interface stats.
+ * For an MLO connection, all %QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_*
+ * attributes except %QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_*
+ * indicate the aggregate of all links outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_* attributes
+ * indicate value of the MLO link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ * These attributes indicate the link specific value inside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
*/
/* Type = enum wifi_traffic_ac, e.g., V0, VI, BE and BK */
@@ -4209,6 +4433,12 @@ enum qca_wlan_vendor_attr_ll_stats_results {
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG = 48,
+ /* Unsigned 32 bit value. This is used to indicate radio ID of the radio
+ * statistics when %QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE is
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO. This is also used
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK to indicate radio ID
+ * of the MLO link.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID = 49,
/* Unsigned 32 bit value. Total number of msecs the radio is awake
* accruing over time.
@@ -4255,7 +4485,13 @@ enum qca_wlan_vendor_attr_ll_stats_results {
/* Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80 */
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH = 60,
- /* Unsigned 32 bit value. Primary 20 MHz channel. */
+ /* Unsigned 32 bit value. Primary 20 MHz channel. This is used to
+ * indicate the primary frequency of the channel when
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE is
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO. This is also used inside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK to indicate the frequency
+ * on which the MLO link is operating.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ = 61,
/* Unsigned 32 bit value. Center frequency (MHz) first segment. */
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 = 62,
@@ -4285,7 +4521,9 @@ enum qca_wlan_vendor_attr_ll_stats_results {
QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67,
/* Signifies the nested list of peer info attributes
- * QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_*
+ * QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_*. For MLO connection,
+ * this also contains %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK_ID to
+ * indicate on which link the peer is connected.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO = 68,
@@ -4306,16 +4544,32 @@ enum qca_wlan_vendor_attr_ll_stats_results {
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA = 71,
- /* Unsigned 64 bit value */
+ /* Unsigned 64 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET = 72,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED = 73,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED = 74,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME = 75,
/* Unsigned 32 bit value */
@@ -4328,13 +4582,29 @@ enum qca_wlan_vendor_attr_ll_stats_results {
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL = 78,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_SUCC_CNT = 79,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_FAIL_CNT = 80,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81,
- /* Unsigned 32 bit value */
+ /* Unsigned 32 bit value. For an MLO connection, indicates the value of
+ * the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
+ */
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82,
/* Unsigned int 32 value.
@@ -4358,12 +4628,18 @@ enum qca_wlan_vendor_attr_ll_stats_results {
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86,
/* u8 value representing the time slicing duty cycle percentage.
- * Possible values are 0-100.
+ * Possible values are 0-100. For an MLO connection, indicates the value
+ * of the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87,
/* Unsigned 32 bit value. The number of Beacon frames which are received
* from the associated AP and indicate buffered unicast frame(s) for us
- * in the TIM element.
+ * in the TIM element. For an MLO connection, indicates the value of the
+ * link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_TIM_BEACON = 88,
/* Unsigned 32 bit value. The total number of Beacon frames received
@@ -4374,16 +4650,46 @@ enum qca_wlan_vendor_attr_ll_stats_results {
* doesn’t receive any unicast data after this beacon.
* 2) The related TIM element is still set in the beacon for STA
* after STA has indicated power save exit by QoS Null Data frame.
+ * For an MLO connection, indicates the value of the link with the best
+ * RSSI outside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link
+ * specific value inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_TIM_BEACON_ERR = 89,
- /* Attribute used for padding for 64-bit alignment */
- QCA_WLAN_VENDOR_ATTR_LL_STATS_PAD = 90,
/* Signed 32 bit value. It represents the noise floor calibration value.
- * Possible values are -120~-50 dBm.
+ * Possible values are -120~-50 dBm. For an MLO connection, indicates
+ * the value of the link with the best RSSI outside
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK and the link specific value
+ * inside %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK.
*/
QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NF_CAL_VAL = 90,
+ /* Attribute used for padding for 64-bit alignment */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_PAD = 91,
+
+ /* Unsigned u8 value, link ID of an MLO link. Used inside nested
+ * attribute %QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK to represent the
+ * link ID of the MLO link for which the statistics are embedded in the
+ * nested attribute. Used inside nested attribute
+ * %QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO to represent the connected
+ * link ID of the peer.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK_ID = 92,
+
+ /* A nested array of attributes for each MLO link, each containing
+ * per-link statistics of a multi link connection. The attributes used
+ * inside this nested attribute are defined in enum
+ * qca_wlan_vendor_attr_ll_stats_results.
+ *
+ * For non-MLO connection, this attribute is not present and the
+ * statistics will be sent outside this attribute (without nesting).
+ *
+ * For MLO connection, this attribute is present and also cumulative
+ * statistics of all the links will be sent outside of this attribute
+ * to be compatible with legacy user space.
+ */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_MLO_LINK = 93,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX =
@@ -4865,6 +5171,8 @@ enum qca_vendor_roam_triggers {
* @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT: WPA3-SAE pre-authentication times
* out.
* @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL: WPA3-SAE pre-authentication fails.
+ * @QCA_ROAM_FAIL_REASON_CURR_AP_STILL_OK: Roam scan did not happen since the
+ * current network conditions are fine.
*/
enum qca_vendor_roam_fail_reasons {
QCA_ROAM_FAIL_REASON_NONE = 0,
@@ -4897,6 +5205,7 @@ enum qca_vendor_roam_fail_reasons {
QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID = 27,
QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT = 28,
QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL = 29,
+ QCA_ROAM_FAIL_REASON_CURR_AP_STILL_OK = 30,
};
/*
@@ -8558,9 +8867,19 @@ enum qca_wlan_eht_mlo_mode {
};
/**
- * enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for
- * HE operating mode control transmit request. These attributes are
- * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and
+ * enum qca_wlan_emlsr_mode: Enhanced Multi-link Single Radio mode configuration
+ * @QCA_WLAN_EMLSR_MODE_ENTER: Enter EMLSR mode
+ * @QCA_WLAN_EMLSR_MODE_EXIT: Exit EMLSR mode
+ */
+enum qca_wlan_emlsr_mode {
+ QCA_WLAN_EMLSR_MODE_ENTER = 0,
+ QCA_WLAN_EMLSR_MODE_EXIT = 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_omi_tx: Represents attributes for HE and
+ * EHT operating mode control transmit request. These attributes are
+ * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX and
* QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION.
*
* @QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS: Mandatory 8-bit unsigned value
@@ -8590,21 +8909,48 @@ enum qca_wlan_eht_mlo_mode {
* 1 - Determine which HE TB PPDU types are allowed by the STA if UL MU disable
* bit is not set, else UL MU Tx is suspended.
*
+ * @QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN: 8-bit unsigned value in the EHT OM
+ * Control subfield combined with the Rx NSS subfield in the OM Control subfield
+ * indicates NSS - 1, where NSS is the maximum number of spatial streams that
+ * STA supports in reception for PPDU bandwidths less than or equal to 80 MHz.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN: 8-bit unsigned value indicates
+ * 320 MHz operating channel width supported by the EHT STA for both reception
+ * and transmission.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN: 8-bit unsigned value in the EHT OM
+ * Control subfield combined with the Tx NSTS subfield in OM Control subfield
+ * indicates NSTS - 1, where NSTS is the maximum number of space-time streams
+ * that the STA supports in transmission for PPDU bandwidths less than or equal
+ * to 80 MHz.
*/
-enum qca_wlan_vendor_attr_he_omi_tx {
+enum qca_wlan_vendor_attr_omi_tx {
QCA_WLAN_VENDOR_ATTR_HE_OMI_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS = 1,
QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW = 2,
QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE = 3,
QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS = 4,
QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE = 5,
+ QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN = 6,
+ QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN = 7,
+ QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN = 8,
/* keep last */
- QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST,
- QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX =
- QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1,
+ QCA_WLAN_VENDOR_ATTR_OMI_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OMI_MAX =
+ QCA_WLAN_VENDOR_ATTR_OMI_AFTER_LAST - 1,
};
+/* deprecated legacy names */
+#define QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX \
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX
+#define qca_wlan_vendor_attr_he_omi_tx \
+ qca_wlan_vendor_attr_omi_tx
+#define QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST \
+ QCA_WLAN_VENDOR_ATTR_OMI_AFTER_LAST
+#define QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX \
+ QCA_WLAN_VENDOR_ATTR_OMI_MAX
+
/**
* enum qca_wlan_vendor_phy_mode - Different PHY modes
* These values are used with %QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE.
@@ -8922,10 +9268,10 @@ enum qca_wlan_vendor_attr_wifi_test_config {
* channel bandwidth, Tx Nsts and UL MU disable attributes.
* These nested attributes are used to send HE operating mode control
* with configured values.
- * Uses the enum qca_wlan_vendor_attr_he_omi_tx attributes.
+ * Uses the enum qca_wlan_vendor_attr_omi_tx attributes.
* This attribute is used to configure the testbed device.
*/
- QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX = 33,
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX = 33,
/* 8-bit unsigned value to configure +HTC_HE support to indicate the
* support for the reception of a frame that carries an HE variant
@@ -9207,6 +9553,46 @@ enum qca_wlan_vendor_attr_wifi_test_config {
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL = 66,
+ /* 8-bit unsigned value to configure the support for receiving an MPDU
+ * that contains an EHT operating mode control subfield.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT = 67,
+
+ /* 8-bit unsigned value to configure the driver with EMLSR padding delay
+ * subfield value.
+ *
+ * 0 - 0 us
+ * 1 - 32 us
+ * 2 - 64 us
+ * 3 - 128 us
+ * 4 - 256 us
+ * 5-255 - Reserved
+ *
+ * This attribute is used for testing purposes.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY = 68,
+
+ /*
+ * 8-bit unsigned value to indicate the firmware to force the active MLO
+ * links to power save mode for the configured number of beacon periods.
+ * This allows the firmware to suspend STA links for X beacon periods
+ * and remain asleep even if the AP advertises TIM as opposed to regular
+ * power save mode where STA links wake up if the AP indicates that it
+ * has buffered data to send.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD = 69,
+
+ /*
+ * 8-bit unsigned value to indicate the firmware to be in STR MLMR mode
+ * to enable simultaneous transmission of PPDUs on all active links.
+ * 0 - Default behavior
+ * 1 - Enter STR mode for simultaneous data transmission on all links
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX = 70,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -12194,9 +12580,13 @@ enum qca_wlan_concurrent_sta_policy_config {
*
* @QCA_WLAN_CONCURRENT_AP_POLICY_GAMING_AUDIO: Select interface concurrencies
* to meet gaming audio latency requirements.
+ * This policy is used only when the driver advertises support for
+ * QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN.
*
* @QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING: Select interface
* concurrencies to meet lossless audio streaming requirements.
+ * This policy is used only when the driver advertises support for
+ * QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN.
*
* @QCA_WLAN_CONCURRENT_AP_POLICY_XR: Select interface concurrencies to meet
* XR (eXtended Reality) requirements.
@@ -15117,4 +15507,100 @@ enum qca_wlan_vendor_attr_mlo_link_state {
QCA_WLAN_VENDOR_ATTR_LINK_STATE_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_vendor_attr_tid_link_map_status - Definition of attributes used
+ * inside nested attribute %QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK: Required u16 attribute
+ * within nested attribute %QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS.
+ * Indicates the link mapping bitmap of a TID for uplink traffic. It is a
+ * bitmask of the link IDs in which a bit set means that the TID is mapped with
+ * that link ID in uplink traffic. Otherwise, the TID is not mapped to uplink
+ * traffic for that link.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK: Required u16 attribute
+ * within nested attribute %QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS.
+ * Indicates the link mapping bitmap of a TID for downlink traffic. It is a
+ * bitmask of the link IDs in which a bit set means that the TID is mapped with
+ * that link ID in downlink traffic. Otherwise, the TID is not mapped to
+ * downlink traffic for that link.
+ */
+enum qca_wlan_vendor_attr_tid_link_map_status {
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK = 1,
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_MAX =
+ QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_AFTER_LAST - 1,
+};
+
+/*
+ * enum qca_wlan_vendor_attr_tid_to_link_map: Definition of attributes used with
+ * %QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR: Required attribute. 6-byte
+ * AP MLD address with which this TID-to-link negotiation mapping is
+ * established/updated.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS: Optional attribute. Array of
+ * nested attributes containing TID-to-links mapping information. This will have
+ * TID-to-link mapping for TID0 to TID7, each containing the uplink and downlink
+ * map information. If this attribute is not present the default TID-to-link
+ * mapping is in use, i.e., all TIDs are mapped to all links for both uplink and
+ * downlink traffic.
+ * See enum qca_wlan_vendor_attr_tid_link_map_status for the nested attributes.
+ */
+enum qca_wlan_vendor_attr_tid_to_link_map {
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_MAX =
+ QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_link_reconfig: Definition of attributes used
+ * with %QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG event.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR: Required attribute.
+ * 6-byte AP MLD address of the AP which indicated the link reconfiguration.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS: Required u16 attribute.
+ * A bitmap of the removed setup links link IDs.
+ */
+enum qca_wlan_vendor_attr_link_reconfig {
+
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR = 1,
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS = 2,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_tdls_disc_rsp_ext - Attributes used by
+ * %QCA_NL80211_VENDOR_SUBCMD_TDLS_DISC_RSP_EXT vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_TX_LINK: u8 attribute.
+ * Indicates the MLO link id on which the TDLS discovery response
+ * frame is to be transmitted.
+ */
+enum qca_wlan_vendor_attr_tdls_disc_rsp_ext {
+ QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_TX_LINK = 1,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_MAX =
+ QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 15ebcabb..367af8f6 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -3567,7 +3567,7 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
} else if (*pos == WLAN_EID_HT_CAP &&
pos[1] >= sizeof(struct ieee80211_ht_capabilities)) {
ie->ht_capabilities = pos + 2;
- } else if (*pos == WLAN_EID_VHT_AID) {
+ } else if (*pos == WLAN_EID_AID) {
if (pos[1] >= 2)
ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff;
} else if (*pos == WLAN_EID_VHT_CAP &&
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 4ab2a1b6..06149ecc 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -110,6 +110,10 @@ extern "C" {
#define WPA_EVENT_DO_ROAM "CTRL-EVENT-DO-ROAM "
/** Decision made to skip a within-ESS roam */
#define WPA_EVENT_SKIP_ROAM "CTRL-EVENT-SKIP-ROAM "
+/** TID-to-link mapping response event */
+#define WPA_EVENT_T2LM_UPDATE "CTRL-EVENT-T2LM-UPDATE "
+/** MLO link reconfiguration event */
+#define WPA_EVENT_LINK_RECONFIG "CTRL-EVENT-LINK-RECONFIG "
/** IP subnet status change notification
*
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 1477eccf..3c4de7a2 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -430,6 +430,18 @@ struct wpa_driver_scan_ssid {
size_t ssid_len;
};
+struct t2lm_mapping {
+ /**
+ * downlink - Bitmap of TIDs mapped with a link in downlink direction
+ */
+ u8 downlink;
+
+ /**
+ * uplink - Bitmap of TIDs mapped with a link in uplink direction
+ */
+ u8 uplink;
+};
+
/**
* struct wpa_driver_scan_params - Scan parameters
* Data for struct wpa_driver_ops::scan2().
@@ -1733,6 +1745,38 @@ struct wpa_driver_ap_params {
* subchannel is punctured, otherwise active.
*/
u16 punct_bitmap;
+
+ /**
+ * rnr_elem - This buffer contains all of reduced neighbor report (RNR)
+ * elements
+ */
+ u8 *rnr_elem;
+
+ /**
+ * rnr_elem_len - Length of rnr_elem buffer
+ */
+ size_t rnr_elem_len;
+
+ /**
+ * rnr_elem_count - Number of RNR elements
+ */
+ unsigned int rnr_elem_count;
+
+ /**
+ * rnr_elem_offset - The offsets to the elements in rnr_elem.
+ * The driver will use these to include RNR elements in EMA beacons.
+ */
+ u8 **rnr_elem_offset;
+
+ /**
+ * allowed_freqs - List of allowed 20 MHz channel center frequencies in
+ * MHz for AP operation. Drivers which support this parameter will
+ * generate a new list based on this provided list by filtering out
+ * channels that cannot be used at that time due to regulatory or other
+ * constraints. The resulting list is used as the list of all allowed
+ * channels whenever performing operations like ACS and DFS.
+ */
+ int *allowed_freqs;
};
struct wpa_driver_mesh_bss_params {
@@ -2889,6 +2933,7 @@ struct weighted_pcl {
};
struct driver_sta_mlo_info {
+ bool default_map;
u16 req_links; /* bitmap of requested link IDs */
u16 valid_links; /* bitmap of accepted link IDs */
u8 assoc_link_id;
@@ -2897,6 +2942,7 @@ struct driver_sta_mlo_info {
u8 addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
unsigned int freq;
+ struct t2lm_mapping t2lmap;
} links[MAX_NUM_MLD_LINKS];
};
@@ -5618,6 +5664,21 @@ enum wpa_event_type {
* Described in wpa_event_data.ch_switch.
*/
EVENT_LINK_CH_SWITCH_STARTED,
+
+ /**
+ * EVENT_TID_LINK_MAP - MLD event to set TID-to-link mapping
+ *
+ * This event is used by the driver to indicate the received TID-to-link
+ * mapping response from the associated AP MLD.
+ *
+ * Described in wpa_event_data.t2l_map_info.
+ */
+ EVENT_TID_LINK_MAP,
+
+ /**
+ * EVENT_LINK_RECONFIG - Notification that AP links removed
+ */
+ EVENT_LINK_RECONFIG,
};
@@ -6542,6 +6603,15 @@ union wpa_event_data {
const u8 *td_bitmap;
size_t td_bitmap_len;
} port_authorized;
+
+ /**
+ * struct tid_link_map_info - Data for EVENT_TID_LINK_MAP
+ */
+ struct tid_link_map_info {
+ bool default_map;
+ u8 valid_links;
+ struct t2lm_mapping t2lmap[MAX_NUM_MLD_LINKS];
+ } t2l_map_info;
};
/**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index bbd1a7ce..f3625e8c 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -98,6 +98,8 @@ const char * event_to_string(enum wpa_event_type event)
E2S(PASN_AUTH);
E2S(LINK_CH_SWITCH);
E2S(LINK_CH_SWITCH_STARTED);
+ E2S(TID_LINK_MAP);
+ E2S(LINK_RECONFIG);
}
return "UNKNOWN";
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index cc87e72d..5f39e804 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -283,6 +283,10 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
#ifdef CONFIG_DRIVER_NL80211_QCA
os_free(drv->pending_roam_data);
drv->pending_roam_data = NULL;
+ os_free(drv->pending_t2lm_data);
+ drv->pending_t2lm_data = NULL;
+ os_free(drv->pending_link_reconfig_data);
+ drv->pending_link_reconfig_data = NULL;
#endif /* CONFIG_DRIVER_NL80211_QCA */
drv->auth_mld = false;
@@ -4838,12 +4842,80 @@ static int nl80211_mbssid(struct nl_msg *msg,
nla_nest_end(msg, elems);
}
+ if (!params->ema)
+ return 0;
+
+ if (params->rnr_elem_count && params->rnr_elem_len &&
+ params->rnr_elem_offset && *params->rnr_elem_offset) {
+ u8 i, **offs = params->rnr_elem_offset;
+
+ elems = nla_nest_start(msg, NL80211_ATTR_EMA_RNR_ELEMS);
+ if (!elems)
+ return -1;
+
+ for (i = 0; i < params->rnr_elem_count - 1; i++) {
+ if (nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]))
+ return -1;
+ }
+
+ if (nla_put(msg, i + 1, *offs + params->rnr_elem_len - offs[i],
+ offs[i]))
+ return -1;
+ nla_nest_end(msg, elems);
+ }
+
return 0;
}
#endif /* CONFIG_IEEE80211AX */
+#ifdef CONFIG_DRIVER_NL80211_QCA
+static void qca_set_allowed_ap_freqs(struct wpa_driver_nl80211_data *drv,
+ const int *freqs, int num_freqs)
+{
+ struct nl_msg *msg;
+ struct nlattr *params, *freqs_list;
+ int i, ret;
+
+ if (!drv->set_wifi_conf_vendor_cmd_avail || !drv->qca_ap_allowed_freqs)
+ return;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Set AP allowed frequency list");
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)))
+ goto err;
+
+ freqs_list = nla_nest_start(
+ msg, QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST);
+ if (!freqs_list)
+ goto err;
+
+ for (i = 0; i < num_freqs; i++) {
+ if (nla_put_u32(msg, i, freqs[i]))
+ goto err;
+ }
+
+ nla_nest_end(msg, freqs_list);
+ nla_nest_end(msg, params);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed set AP alllowed frequency list: %d (%s)",
+ ret, strerror(-ret));
+
+ return;
+err:
+ nlmsg_free(msg);
+}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -5166,6 +5238,12 @@ static int wpa_driver_nl80211_set_ap(void *priv,
goto fail;
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
+ if (cmd == NL80211_CMD_NEW_BEACON && params->allowed_freqs)
+ qca_set_allowed_ap_freqs(drv, params->allowed_freqs,
+ int_array_len(params->allowed_freqs));
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
@@ -9618,6 +9696,11 @@ static int nl80211_set_param(void *priv, const char *param)
}
}
+ if (os_strstr(param, "secure_ltf=1")) {
+ drv->capa.flags2 |= WPA_DRIVER_FLAGS2_SEC_LTF_STA |
+ WPA_DRIVER_FLAGS2_SEC_LTF_AP;
+ }
+
return 0;
}
@@ -10662,8 +10745,10 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
struct driver_sta_mlo_info *mlo = &drv->sta_mlo_info;
res = os_snprintf(pos, end - pos,
- "ap_mld_addr=" MACSTR "\n",
- MAC2STR(mlo->ap_mld_addr));
+ "ap_mld_addr=" MACSTR "\n"
+ "default_map=%d\n",
+ MAC2STR(mlo->ap_mld_addr),
+ mlo->default_map);
if (os_snprintf_error(end - pos, res))
return pos - buf;
pos += res;
@@ -10682,6 +10767,18 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
if (os_snprintf_error(end - pos, res))
return pos - buf;
pos += res;
+
+ if (!mlo->default_map) {
+ res = os_snprintf(
+ pos, end - pos,
+ "uplink_map[%u]=%x\n"
+ "downlink_map[%u]=%x\n",
+ i, mlo->links[i].t2lmap.uplink,
+ i, mlo->links[i].t2lmap.downlink);
+ if (os_snprintf_error(end - pos, res))
+ return pos - buf;
+ pos += res;
+ }
}
}
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index bd35e52c..c5972956 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -199,6 +199,7 @@ struct wpa_driver_nl80211_data {
unsigned int uses_6ghz:1;
unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
unsigned int puncturing:1;
+ unsigned int qca_ap_allowed_freqs:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
@@ -257,6 +258,10 @@ struct wpa_driver_nl80211_data {
bool roam_indication_done;
u8 *pending_roam_data;
size_t pending_roam_data_len;
+ u8 *pending_t2lm_data;
+ size_t pending_t2lm_data_len;
+ u8 *pending_link_reconfig_data;
+ size_t pending_link_reconfig_data_len;
#endif /* CONFIG_DRIVER_NL80211_QCA */
};
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 31525297..09771bba 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1414,6 +1414,9 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
QCA_WLAN_VENDOR_FEATURE_PROT_RANGE_NEGO_AND_MEASURE_AP,
&info))
drv->capa.flags2 |= WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP;
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST,
+ &info))
+ drv->qca_ap_allowed_freqs = 1;
os_free(info.flags);
}
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 14d78427..e99afdca 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -421,6 +421,78 @@ convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes
}
+static void qca_nl80211_link_reconfig_event(struct wpa_driver_nl80211_data *drv,
+ u8 *data, size_t len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_MAX + 1];
+ u16 removed_links;
+ u8 *ap_mld;
+ int i;
+
+ if (!data)
+ return;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR])
+ return;
+
+ ap_mld = nla_data(tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_AP_MLD_ADDR]);
+ wpa_printf(MSG_DEBUG, "nl80211: AP MLD address " MACSTR
+ " received in link reconfig event", MAC2STR(ap_mld));
+ if (!drv->sta_mlo_info.valid_links ||
+ os_memcmp(drv->sta_mlo_info.ap_mld_addr, ap_mld, ETH_ALEN) != 0) {
+ if (drv->pending_link_reconfig_data == data) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Drop pending link reconfig event since AP MLD not matched even after new connect/roam event");
+ os_free(drv->pending_link_reconfig_data);
+ drv->pending_link_reconfig_data = NULL;
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Cache new link reconfig event till next connect/roam event");
+ if (drv->pending_link_reconfig_data) {
+ wpa_printf(MSG_DEBUG, "nl80211: Override old link reconfig event data");
+ os_free(drv->pending_link_reconfig_data);
+ }
+ drv->pending_link_reconfig_data = os_memdup(data, len);
+ if (!drv->pending_link_reconfig_data)
+ return;
+ drv->pending_link_reconfig_data_len = len;
+ return;
+ }
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS])
+ return;
+ removed_links = nla_get_u16(
+ tb[QCA_WLAN_VENDOR_ATTR_LINK_RECONFIG_REMOVED_LINKS]);
+
+ drv->sta_mlo_info.valid_links &= ~removed_links;
+
+ /*
+ * Set default BSSID to the BSSID of the lowest link ID of remaining
+ * links when the link used for (re)association is removed.
+ */
+ if (removed_links & BIT(drv->sta_mlo_info.assoc_link_id)) {
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+ continue;
+
+ os_memcpy(drv->bssid, drv->sta_mlo_info.links[i].bssid,
+ ETH_ALEN);
+ drv->sta_mlo_info.assoc_link_id = i;
+ break;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "nl80211: Removed MLO links bitmap: 0x%x",
+ removed_links);
+
+ wpa_supplicant_event(drv->ctx, EVENT_LINK_RECONFIG, NULL);
+}
+
+
static void
nl80211_parse_qca_vendor_mlo_link_info(struct driver_sta_mlo_info *mlo,
struct nlattr *mlo_links)
@@ -713,6 +785,126 @@ static void nl80211_parse_mlo_info(struct wpa_driver_nl80211_data *drv,
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
+static void
+qca_nl80211_tid_to_link_map_event(struct wpa_driver_nl80211_data *drv,
+ u8 *data, size_t len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_MAX + 1];
+ struct nlattr *tids;
+ union wpa_event_data event;
+ u8 *ap_mld;
+ int i, rem, tidnum = 0;
+
+ os_memset(&event, 0, sizeof(event));
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR])
+ return;
+
+ ap_mld = nla_data(tb[QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: AP MLD address " MACSTR
+ " received in TID to link mapping event", MAC2STR(ap_mld));
+ if (!drv->sta_mlo_info.valid_links ||
+ os_memcmp(drv->sta_mlo_info.ap_mld_addr, ap_mld, ETH_ALEN) != 0) {
+ if (drv->pending_t2lm_data == data) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Drop pending TID-to-link mapping event since AP MLD not matched even after new connect/roam event");
+ os_free(drv->pending_t2lm_data);
+ drv->pending_t2lm_data = NULL;
+ return;
+ }
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Cache new TID-to-link map event until the next connect/roam event");
+ if (drv->pending_t2lm_data) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Override old TID-to-link map event data");
+ os_free(drv->pending_t2lm_data);
+ }
+ drv->pending_t2lm_data = os_memdup(data, len);
+ if (!drv->pending_t2lm_data)
+ return;
+ drv->pending_t2lm_data_len = len;
+ return;
+ }
+
+ if (!tb[QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS]) {
+ wpa_printf(MSG_DEBUG, "nl80211: Default TID-to-link map");
+ event.t2l_map_info.default_map = true;
+ goto out;
+ }
+
+ event.t2l_map_info.default_map = false;
+
+ nla_for_each_nested(tids,
+ tb[QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS],
+ rem) {
+ u16 uplink, downlink;
+ struct nlattr *tid[QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_MAX + 1];
+
+ if (nla_parse_nested(
+ tid, QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_MAX,
+ tids, NULL)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: TID-to-link: nla_parse_nested() failed");
+ return;
+ }
+
+ if (!tid[QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK]) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: TID-to-link: uplink not present for tid: %d",
+ tidnum);
+ return;
+ }
+ uplink = nla_get_u16(tid[QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK]);
+
+ if (!tid[QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK]) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: TID-to-link: downlink not present for tid: %d",
+ tidnum);
+ return;
+ }
+ downlink = nla_get_u16(tid[QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK]);
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: TID-to-link: Received uplink %x downlink %x",
+ uplink, downlink);
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+ continue;
+ if (uplink & BIT(i))
+ event.t2l_map_info.t2lmap[i].uplink |=
+ BIT(tidnum);
+ if (downlink & BIT(i))
+ event.t2l_map_info.t2lmap[i].downlink |=
+ BIT(tidnum);
+ }
+
+ tidnum++;
+ }
+
+out:
+ drv->sta_mlo_info.default_map = event.t2l_map_info.default_map;
+
+ event.t2l_map_info.valid_links = drv->sta_mlo_info.valid_links;
+ for (i = 0; i < MAX_NUM_MLD_LINKS && !drv->sta_mlo_info.default_map;
+ i++) {
+ if (!(drv->sta_mlo_info.valid_links & BIT(i)))
+ continue;
+
+ drv->sta_mlo_info.links[i].t2lmap.uplink =
+ event.t2l_map_info.t2lmap[i].uplink;
+ drv->sta_mlo_info.links[i].t2lmap.downlink =
+ event.t2l_map_info.t2lmap[i].downlink;
+ }
+
+ wpa_supplicant_event(drv->ctx, EVENT_TID_LINK_MAP, &event);
+}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+
static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
enum nl80211_commands cmd, bool qca_roam_auth,
struct nlattr *status,
@@ -912,6 +1104,19 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
* operation that happened in parallel with the disconnection request.
*/
drv->ignore_next_local_disconnect = 0;
+
+#ifdef CONFIG_DRIVER_NL80211_QCA
+ if (drv->pending_t2lm_data)
+ qca_nl80211_tid_to_link_map_event(drv, drv->pending_t2lm_data,
+ drv->pending_t2lm_data_len);
+ else
+ drv->sta_mlo_info.default_map = true;
+
+ if (drv->pending_link_reconfig_data)
+ qca_nl80211_link_reconfig_event(
+ drv, drv->pending_link_reconfig_data,
+ drv->pending_link_reconfig_data_len);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
}
@@ -2861,6 +3066,12 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
qca_nl80211_pasn_auth(drv, data, len);
break;
#endif /* CONFIG_PASN */
+ case QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP:
+ qca_nl80211_tid_to_link_map_event(drv, data, len);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG:
+ qca_nl80211_link_reconfig_event(drv, data, len);
+ break;
#endif /* CONFIG_DRIVER_NL80211_QCA */
default:
wpa_printf(MSG_DEBUG,
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 7a7890c7..4d33b149 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -21,7 +21,7 @@
#include "driver_nl80211.h"
-#define MAX_NL80211_NOISE_FREQS 50
+#define MAX_NL80211_NOISE_FREQS 100
struct nl80211_noise_info {
u32 freq[MAX_NL80211_NOISE_FREQS];
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 9a0ac036..c59fec40 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -2794,6 +2794,17 @@ enum nl80211_commands {
* @NL80211_ATTR_HW_TIMESTAMP_ENABLED: Indicates whether HW timestamping should
* be enabled or not (flag attribute).
*
+ * @NL80211_ATTR_EMA_RNR_ELEMS: Optional nested attribute for
+ * reduced neighbor report (RNR) elements. This attribute can be used
+ * only when NL80211_MBSSID_CONFIG_ATTR_EMA is enabled.
+ * Userspace is responsible for splitting the RNR into multiple
+ * elements such that each element excludes the non-transmitting
+ * profiles already included in the MBSSID element
+ * (%NL80211_ATTR_MBSSID_ELEMS) at the same index. Each EMA beacon
+ * will be generated by adding MBSSID and RNR elements at the same
+ * index. If the userspace includes more RNR elements than number of
+ * MBSSID elements then these will be added in every EMA beacon.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3328,6 +3339,8 @@ enum nl80211_attrs {
NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS,
NL80211_ATTR_HW_TIMESTAMP_ENABLED,
+ NL80211_ATTR_EMA_RNR_ELEMS,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4048,6 +4061,10 @@ enum nl80211_band_iftype_attr {
* @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
* the allowed channel bandwidth configurations.
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+ * @NL80211_BAND_ATTR_S1G_MCS_NSS_SET: S1G capabilities, supported S1G-MCS and NSS
+ * set subfield, as in the S1G information IE, 5 bytes
+ * @NL80211_BAND_ATTR_S1G_CAPA: S1G capabilities information subfield as in the
+ * S1G information IE, 10 bytes
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
@@ -4068,6 +4085,9 @@ enum nl80211_band_attr {
NL80211_BAND_ATTR_EDMG_CHANNELS,
NL80211_BAND_ATTR_EDMG_BW_CONFIG,
+ NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
+ NL80211_BAND_ATTR_S1G_CAPA,
+
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
@@ -6544,7 +6564,9 @@ enum nl80211_timeout_reason {
* channels on which APs are expected to be found. Note that when not set,
* the scan logic would scan all 6GHz channels, but since transmission of
* probe requests on non PSC channels is limited, it is highly likely that
- * these channels would passively be scanned.
+ * these channels would passively be scanned. Also note that when the flag
+ * is set, in addition to the colocated APs, PSC channels would also be
+ * scanned if the user space has asked for it.
*/
enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c
index 1c11cb61..e1b82ebe 100644
--- a/src/eapol_auth/eapol_auth_sm.c
+++ b/src/eapol_auth/eapol_auth_sm.c
@@ -217,6 +217,9 @@ SM_STATE(AUTH_PAE, INITIALIZE)
SM_STATE(AUTH_PAE, DISCONNECTED)
{
int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
+ bool pre_auth_logoff = sm->auth_pae_state == AUTH_PAE_ABORTING &&
+ sm->eapolLogoff && !sm->authenticated;
+ bool logoff = sm->eapolLogoff;
if (sm->eapolLogoff) {
if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
@@ -231,10 +234,14 @@ SM_STATE(AUTH_PAE, DISCONNECTED)
setPortUnauthorized();
sm->reAuthCount = 0;
sm->eapolLogoff = false;
- if (!from_initialize) {
- sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
- sm->flags & EAPOL_SM_PREAUTH,
- sm->remediation);
+ if (!from_initialize && !pre_auth_logoff) {
+ if (sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
+ sm->flags & EAPOL_SM_PREAUTH,
+ sm->remediation, logoff)) {
+ wpa_printf(MSG_DEBUG,
+ "EAPOL: Do not restart since lower layers will disconnect the port after EAPOL-Logoff");
+ sm->stopped = true;
+ }
}
}
@@ -291,7 +298,8 @@ SM_STATE(AUTH_PAE, HELD)
eap_server_get_name(0, sm->eap_type_supp));
}
sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
- sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
+ sm->flags & EAPOL_SM_PREAUTH, sm->remediation,
+ false);
}
@@ -316,8 +324,11 @@ SM_STATE(AUTH_PAE, AUTHENTICATED)
sm->eap_type_authsrv,
eap_server_get_name(0, sm->eap_type_authsrv),
extra);
+ if (sm->authSuccess)
+ sm->authenticated++;
sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
- sm->flags & EAPOL_SM_PREAUTH, sm->remediation);
+ sm->flags & EAPOL_SM_PREAUTH, sm->remediation,
+ false);
}
@@ -397,7 +408,8 @@ SM_STEP(AUTH_PAE)
SM_ENTER(AUTH_PAE, DISCONNECTED);
break;
case AUTH_PAE_DISCONNECTED:
- SM_ENTER(AUTH_PAE, RESTART);
+ if (!sm->stopped)
+ SM_ENTER(AUTH_PAE, RESTART);
break;
case AUTH_PAE_RESTART:
if (!sm->eap_if->eapRestart)
diff --git a/src/eapol_auth/eapol_auth_sm.h b/src/eapol_auth/eapol_auth_sm.h
index 61b7039d..7296a3ac 100644
--- a/src/eapol_auth/eapol_auth_sm.h
+++ b/src/eapol_auth/eapol_auth_sm.h
@@ -46,8 +46,8 @@ struct eapol_auth_cb {
size_t datalen);
void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data,
size_t datalen);
- void (*finished)(void *ctx, void *sta_ctx, int success, int preauth,
- int remediation);
+ bool (*finished)(void *ctx, void *sta_ctx, int success, int preauth,
+ int remediation, bool logoff);
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
int phase2, struct eap_user *user);
int (*sta_entry_alive)(void *ctx, const u8 *addr);
diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h
index 3c689831..a0cef0f8 100644
--- a/src/eapol_auth/eapol_auth_sm_i.h
+++ b/src/eapol_auth/eapol_auth_sm_i.h
@@ -171,6 +171,10 @@ struct eapol_state_machine {
int remediation;
u64 acct_multi_session_id;
+
+ unsigned int authenticated; /* The number of times authentication has
+ * been completed successfully. */
+ bool stopped;
};
#endif /* EAPOL_AUTH_SM_I_H */
diff --git a/src/pasn/pasn_common.h b/src/pasn/pasn_common.h
index 9c2f397e..a4850a28 100644
--- a/src/pasn/pasn_common.h
+++ b/src/pasn/pasn_common.h
@@ -95,7 +95,8 @@ struct pasn_data {
u8 wrapped_data_format;
struct wpabuf *secret;
- /* Reponder */
+ /* Responder */
+ bool noauth; /* Whether PASN without mutual authentication is enabled */
int wpa_key_mgmt;
int rsn_pairwise;
bool derive_kdk;
diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c
index 3b1912df..78a9dd7d 100644
--- a/src/pasn/pasn_responder.c
+++ b/src/pasn/pasn_responder.c
@@ -743,6 +743,12 @@ int handle_auth_pasn_1(struct pasn_data *pasn,
goto send_resp;
}
+ if (!pasn->noauth && pasn->akmp == WPA_KEY_MGMT_PASN) {
+ wpa_printf(MSG_DEBUG, "PASN: Refuse PASN-UNAUTH");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
derive_keys = true;
if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
wrapped_data = ieee802_11_defrag(&elems,
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 3a398862..5a28ef57 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -4561,6 +4561,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
sm->dpp_pfs = value;
break;
#endif /* CONFIG_DPP2 */
+ case WPA_PARAM_WMM_ENABLED:
+ sm->wmm_enabled = value;
+ break;
default:
break;
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index cd3ef3e7..47d2344e 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -123,6 +123,7 @@ enum wpa_sm_conf_params {
WPA_PARAM_USE_EXT_KEY_ID,
WPA_PARAM_FT_RSNXE_USED,
WPA_PARAM_DPP_PFS,
+ WPA_PARAM_WMM_ENABLED,
WPA_PARAM_OCI_FREQ_EAPOL,
WPA_PARAM_OCI_FREQ_EAPOL_G2,
WPA_PARAM_OCI_FREQ_FT_ASSOC,
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index a3c13b11..300ef547 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -220,6 +220,8 @@ struct wpa_sm {
int dpp_pfs;
#endif /* CONFIG_DPP2 */
struct wpa_sm_mlo mlo;
+
+ bool wmm_enabled;
};
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 50bd2b27..2a6c79b2 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -109,6 +109,10 @@ u16 rsn_supp_capab(struct wpa_sm *sm)
{
u16 capab = 0;
+ if (sm->wmm_enabled) {
+ /* Advertise 16 PTKSA replay counters when using WMM */
+ capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
+ }
if (sm->mfp)
capab |= WPA_CAPABILITY_MFPC;
if (sm->mfp == 2)
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index c643b268..f8da7818 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -442,7 +442,9 @@ drivers:
nl80211 = Linux nl80211/cfg80211
wext = Linux wireless extensions (generic)
wired = wpa_supplicant wired Ethernet driver
+ macsec_linux = MACsec Ethernet driver for Linux
roboswitch = wpa_supplicant Broadcom switch driver
+ none = no driver (RADIUS server/WPS ER only)
bsd = BSD 802.11 support (Atheros, etc.)
ndis = Windows NDIS driver
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a5d4d815..c843cb00 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2501,6 +2501,7 @@ static const struct parse_data ssid_fields[] = {
{ FUNC(freq_list) },
{ INT_RANGE(ht, 0, 1) },
{ INT_RANGE(vht, 0, 1) },
+ { INT_RANGE(he, 0, 1) },
{ INT_RANGE(ht40, -1, 1) },
{ INT_RANGE(max_oper_chwidth, CONF_OPER_CHWIDTH_USE_HT,
CONF_OPER_CHWIDTH_80P80MHZ) },
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index 898765c9..df538e33 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -274,6 +274,13 @@
</varlistentry>
<varlistentry>
+ <term>macsec_linux</term>
+ <listitem>
+ <para>MACsec Ethernet driver for Linux</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>roboswitch</term>
<listitem>
<para>wpa_supplicant Broadcom switch driver</para>
@@ -281,6 +288,13 @@
</varlistentry>
<varlistentry>
+ <term>none</term>
+ <listitem>
+ <para>no driver (RADIUS server/WPS ER only)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>bsd</term>
<listitem>
<para>BSD 802.11 support (Atheros, etc.).</para>
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 09099613..e83d8772 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -60,6 +60,10 @@
static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
int new_scan, int own_request);
#endif /* CONFIG_NO_SCAN_PROCESSING */
+#ifdef CONFIG_OWE
+static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const u8 **ret_ssid, size_t *ret_ssid_len);
+#endif /* CONFIG_OWE */
int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
@@ -187,6 +191,7 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
struct wpa_ssid *ssid, *old_ssid;
+ struct wpa_bss *bss;
u8 drv_ssid[SSID_MAX_LEN];
size_t drv_ssid_len;
int res;
@@ -210,6 +215,14 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s,
return 0; /* current profile still in use */
#ifdef CONFIG_OWE
+ if (wpa_s->current_bss &&
+ !(wpa_s->current_bss->flags & WPA_BSS_OWE_TRANSITION)) {
+ const u8 *match_ssid;
+ size_t match_ssid_len;
+
+ owe_trans_ssid(wpa_s, wpa_s->current_bss,
+ &match_ssid, &match_ssid_len);
+ }
if ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
wpa_s->current_bss &&
(wpa_s->current_bss->flags & WPA_BSS_OWE_TRANSITION) &&
@@ -254,6 +267,7 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the "
"current AP");
+ bss = wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
u8 wpa_ie[80];
size_t wpa_ie_len = sizeof(wpa_ie);
@@ -263,7 +277,7 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s,
* driver indicated the actual values used in the
* (Re)Association Request frame. */
skip_default_rsne = data && data->assoc_info.req_ies;
- if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
wpa_ie, &wpa_ie_len,
skip_default_rsne) < 0)
wpa_dbg(wpa_s, MSG_DEBUG, "Could not set WPA suites");
@@ -276,8 +290,6 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s,
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
- wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
-
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid)
@@ -611,8 +623,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_WEP
int wep_ok;
#endif /* CONFIG_WEP */
- bool is_6ghz_bss_or_mld = is_6ghz_freq(bss->freq) ||
- !is_zero_ether_addr(bss->mld_addr);
+ bool is_6ghz_bss = is_6ghz_freq(bss->freq);
ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
if (ret >= 0)
@@ -627,10 +638,10 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_WEP */
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
- if (is_6ghz_bss_or_mld && !rsn_ie) {
+ if (is_6ghz_bss && !rsn_ie) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - 6 GHz/MLD BSS without RSNE");
+ " skip - 6 GHz BSS without RSNE");
return 0;
}
@@ -648,8 +659,8 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
if (!ie.has_group)
ie.group_cipher = wpa_default_rsn_cipher(bss->freq);
- if (is_6ghz_bss_or_mld) {
- /* WEP and TKIP are not allowed on 6 GHz */
+ if (is_6ghz_bss || !is_zero_ether_addr(bss->mld_addr)) {
+ /* WEP and TKIP are not allowed on 6 GHz/MLD */
ie.pairwise_cipher &= ~(WPA_CIPHER_WEP40 |
WPA_CIPHER_WEP104 |
WPA_CIPHER_TKIP);
@@ -699,12 +710,12 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
break;
}
- if (is_6ghz_bss_or_mld) {
+ if (is_6ghz_bss) {
/* MFPC must be supported on 6 GHz */
if (!(ie.capabilities & WPA_CAPABILITY_MFPC)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip RSNE - 6 GHz/MLD without MFPC");
+ " skip RSNE - 6 GHz without MFPC");
break;
}
@@ -744,10 +755,10 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
return 1;
}
- if (is_6ghz_bss_or_mld) {
+ if (is_6ghz_bss) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - 6 GHz/MLD BSS without matching RSNE");
+ " skip - 6 GHz BSS without matching RSNE");
return 0;
}
@@ -1828,6 +1839,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
struct wpa_bss *selected,
struct wpa_ssid *ssid)
{
+#ifdef IEEE8021X_EAPOL
if ((eap_is_wps_pbc_enrollee(&ssid->eap) &&
wpas_wps_partner_link_overlap_detect(wpa_s)) ||
wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
@@ -1850,6 +1862,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_WPS */
return -1;
}
+#endif /* IEEE8021X_EAPOL */
wpa_msg(wpa_s, MSG_DEBUG,
"Considering connect request: reassociate: %d selected: "
@@ -3793,7 +3806,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wpas_fst_update_mb_assoc(wpa_s, data);
#ifdef CONFIG_SME
- os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
+ /*
+ * Cache the current AP's BSSID (for non-MLO connection) or MLD address
+ * (for MLO connection) as the previous BSSID for subsequent
+ * reassociation requests handled by SME-in-wpa_supplicant.
+ */
+ os_memcpy(wpa_s->sme.prev_bssid,
+ wpa_s->valid_links ? wpa_s->ap_mld_addr : bssid, ETH_ALEN);
wpa_s->sme.prev_bssid_set = 1;
wpa_s->sme.last_unprot_disconnect.sec = 0;
#endif /* CONFIG_SME */
@@ -5383,6 +5402,97 @@ static void wpas_event_unprot_beacon(struct wpa_supplicant *wpa_s,
}
+static const char * bitmap_to_str(u8 value, char *buf)
+{
+ char *pos = buf;
+ int i, k = 0;
+
+ for (i = 7; i >= 0; i--)
+ pos[k++] = (value & BIT(i)) ? '1' : '0';
+
+ pos[8] = '\0';
+ return pos;
+}
+
+
+static void wpas_tid_link_map(struct wpa_supplicant *wpa_s,
+ struct tid_link_map_info *info)
+{
+ char map_info[1000], *pos, *end;
+ int res, i;
+
+ pos = map_info;
+ end = pos + sizeof(map_info);
+ res = os_snprintf(map_info, sizeof(map_info), "default=%d",
+ info->default_map);
+ if (os_snprintf_error(end - pos, res))
+ return;
+ pos += res;
+
+ if (!info->default_map) {
+ for (i = 0; i < MAX_NUM_MLD_LINKS && end > pos; i++) {
+ char uplink_map_str[9];
+ char downlink_map_str[9];
+
+ if (!(info->valid_links & BIT(i)))
+ continue;
+
+ bitmap_to_str(info->t2lmap[i].uplink, uplink_map_str);
+ bitmap_to_str(info->t2lmap[i].downlink,
+ downlink_map_str);
+
+ res = os_snprintf(pos, end - pos,
+ " link_id=%d up_link=%s down_link=%s",
+ i, uplink_map_str,
+ downlink_map_str);
+ if (os_snprintf_error(end - pos, res))
+ return;
+ pos += res;
+ }
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_T2LM_UPDATE "%s", map_info);
+}
+
+
+static void wpas_link_reconfig(struct wpa_supplicant *wpa_s)
+{
+ u8 bssid[ETH_ALEN];
+
+ if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+ wpa_printf(MSG_ERROR, "LINK_RECONFIG: Failed to get BSSID");
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ return;
+ }
+
+ if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
+ os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
+ wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid);
+ wpas_notify_bssid_changed(wpa_s);
+ }
+
+ if (wpa_drv_get_mlo_info(wpa_s) < 0) {
+ wpa_printf(MSG_ERROR,
+ "LINK_RECONFIG: Failed to get MLO connection info");
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ return;
+ }
+
+ if (wpa_sm_set_ml_info(wpa_s)) {
+ wpa_printf(MSG_ERROR,
+ "LINK_RECONFIG: Failed to set MLO connection info to wpa_sm");
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_LINK_RECONFIG "valid_links=0x%x",
+ wpa_s->valid_links);
+}
+
+
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -5482,6 +5592,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpas_event_deauth(wpa_s,
data ? &data->deauth_info : NULL);
break;
+ case EVENT_LINK_RECONFIG:
+ wpas_link_reconfig(wpa_s);
+ break;
case EVENT_MICHAEL_MIC_FAILURE:
wpa_supplicant_event_michael_mic_failure(wpa_s, data);
break;
@@ -6292,6 +6405,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpas_dpp_tx_wait_expire(wpa_s);
#endif /* CONFIG_DPP */
break;
+ case EVENT_TID_LINK_MAP:
+ if (data)
+ wpas_tid_link_map(wpa_s, &data->t2l_map_info);
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index da6d9db0..c9e14d5c 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -771,7 +771,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211AC
copy_sta_vht_capab(data, sta, elems->vht_capabilities);
copy_sta_vht_oper(data, sta, elems->vht_operation);
- set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
+ set_sta_vht_opmode(data, sta, elems->opmode_notif);
#endif /* CONFIG_IEEE80211AC */
#ifdef CONFIG_IEEE80211AX
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index ea4023c8..8068f1ef 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -378,10 +378,12 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
}
-static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ struct wpa_ssid *ssid)
{
struct wpabuf *mlbuf;
- const u8 *rnr_ie, *pos;
+ const u8 *rnr_ie, *pos, *rsn_ie;
+ struct wpa_ie_data ie;
u8 ml_ie_len, rnr_ie_len;
const struct ieee80211_eht_ml *eht_ml;
const struct eht_ml_basic_common_info *ml_basic_common_info;
@@ -402,6 +404,26 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
return false;
}
+ rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+ goto out;
+ }
+
+ if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
+ wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "MLD: No management frame protection");
+ goto out;
+ }
+
+ ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256);
+ if (!(ie.key_mgmt & ssid->key_mgmt)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
+ goto out;
+ }
+
ml_ie_len = wpabuf_len(mlbuf);
/* control + common info len + MLD address + MLD link information */
@@ -525,20 +547,28 @@ static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
{
struct ieee802_11_elems elems;
const u8 *mld_addr;
+ u16 status_code = data->auth.status_code;
if (!wpa_s->valid_links)
return;
if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
data->auth.ies_len - ie_offset,
- &elems, 0) != ParseOK) {
+ &elems, 0) == ParseFailed) {
wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
goto out;
}
if (!elems.basic_mle || !elems.basic_mle_len) {
wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
- goto out;
+ if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
+ status_code == WLAN_STATUS_SUCCESS ||
+ status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK)
+ goto out;
+ /* Accept missing Multi-Link element in failed authentication
+ * cases. */
+ return;
}
mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
@@ -604,7 +634,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
params.ssid_len = bss->ssid_len;
params.p2p = ssid->p2p_group;
- if (wpas_ml_element(wpa_s, bss)) {
+ if (wpas_ml_element(wpa_s, bss, ssid)) {
wpa_printf(MSG_DEBUG, "MLD: In authentication");
params.mld = true;
params.mld_link_id = wpa_s->mlo_assoc_link_id;
@@ -1596,20 +1626,28 @@ static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
- const u8 *data, size_t len, int ie_offset)
+ const u8 *data, size_t len, int ie_offset,
+ u16 status_code)
{
struct ieee802_11_elems elems;
const u8 *mld_addr;
if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
- &elems, 0) != ParseOK) {
+ &elems, 0) == ParseFailed) {
wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
return -1;
}
if (!elems.basic_mle || !elems.basic_mle_len) {
wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
- return -1;
+ if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
+ status_code == WLAN_STATUS_SUCCESS ||
+ status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK)
+ return -1;
+ /* Accept missing Multi-Link element in failed authentication
+ * cases. */
+ return 0;
}
mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
@@ -1623,7 +1661,8 @@ static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
0) {
wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
- MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
+ MACSTR ")",
+ MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
return -1;
}
@@ -1714,7 +1753,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
wpa_s->current_ssid, 2);
} else {
if (wpa_s->sme.ext_ml_auth &&
- sme_external_ml_auth(wpa_s, data, len, *ie_offset))
+ sme_external_ml_auth(wpa_s, data, len, *ie_offset,
+ status_code))
return -1;
sme_external_auth_send_sae_commit(
@@ -1741,7 +1781,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
wpa_s->current_ssid, 1);
} else {
if (wpa_s->sme.ext_ml_auth &&
- sme_external_ml_auth(wpa_s, data, len, *ie_offset))
+ sme_external_ml_auth(wpa_s, data, len, *ie_offset,
+ status_code))
return -1;
sme_external_auth_send_sae_commit(
@@ -1840,7 +1881,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
wpa_s->current_ssid, 0);
} else {
if (wpa_s->sme.ext_ml_auth &&
- sme_external_ml_auth(wpa_s, data, len, *ie_offset))
+ sme_external_ml_auth(wpa_s, data, len, *ie_offset,
+ status_code))
return -1;
sme_external_auth_send_sae_confirm(wpa_s, sa);
@@ -1856,7 +1898,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
ie_offset) < 0)
return -1;
if (external && wpa_s->sme.ext_ml_auth &&
- sme_external_ml_auth(wpa_s, data, len, *ie_offset))
+ sme_external_ml_auth(wpa_s, data, len, *ie_offset,
+ status_code))
return -1;
wpa_s->sme.sae.state = SAE_ACCEPTED;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index f808ac42..effc7b3b 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1427,7 +1427,7 @@ static const char *network_fields[] = {
"bssid_accept", "psk", "proto", "key_mgmt",
"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
"freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
- "vht_center_freq2", "ht", "edmg",
+ "vht_center_freq2", "ht", "edmg", "he",
#ifdef IEEE8021X_EAPOL
"eap", "identity", "anonymous_identity", "password", "ca_cert",
"ca_path", "client_cert", "private_key", "private_key_passwd",
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 287bc9e6..71ffa69e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1587,6 +1587,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
int sel, proto;
enum sae_pwe sae_pwe;
const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
+ bool wmm;
if (bss) {
bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
@@ -1983,6 +1984,22 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0);
}
+ /* Mark WMM enabled for any HT/VHT/HE/EHT association to get more
+ * appropriate advertisement of the supported number of PTKSA receive
+ * counters. In theory, this could be based on a driver capability, but
+ * in practice all cases using WMM support at least eight replay
+ * counters, so use a hardcoded value for now since there is no explicit
+ * driver capability indication for this.
+ *
+ * In addition, claim WMM to be enabled if the AP supports it since it
+ * is far more likely for any current device to support WMM. */
+ wmm = wpa_s->connection_set &&
+ (wpa_s->connection_ht || wpa_s->connection_vht ||
+ wpa_s->connection_he || wpa_s->connection_eht);
+ if (!wmm && bss)
+ wmm = wpa_bss_get_vendor_ie(bss, WMM_IE_VENDOR_TYPE);
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_WMM_ENABLED, wmm);
+
if (!skip_default_rsne) {
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie,
wpa_ie_len)) {
@@ -3975,7 +3992,16 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
return;
}
- os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
+ /*
+ * Set the current AP's BSSID (for non-MLO connection) or MLD address
+ * (for MLO connection) as the previous BSSID for reassociation requests
+ * handled by SME-in-driver. If wpa_supplicant is in disconnected state,
+ * prev_bssid will be zero as both wpa_s->valid_links and wpa_s->bssid
+ * will be zero.
+ */
+ os_memcpy(prev_bssid,
+ wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid,
+ ETH_ALEN);
os_memset(&params, 0, sizeof(params));
wpa_s->reassociate = 0;
wpa_s->eap_expected_failure = 0;
@@ -4829,7 +4855,8 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpa_s->current_ssid = ssid;
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_s->connect_without_scan =
- (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
+ (ssid->mode == WPAS_MODE_MESH ||
+ ssid->mode == WPAS_MODE_AP) ? ssid : NULL;
/*
* Don't optimize next scan freqs since a new ESS has been