From e3e68668c1f6729348538844bbba289820783756 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 30 Nov 2022 15:09:26 +0200 Subject: [PATCH] ctrl_iface: Report RNR and ML in BSS command Add the required ML and RNR definitions and report the information in BSS command. Signed-off-by: Ilan Peer Signed-off-by: Andrei Otcheretianski --- src/common/ieee802_11_defs.h | 96 ++++++++++++++ src/common/wpa_ctrl.h | 2 + wpa_supplicant/ctrl_iface.c | 250 +++++++++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index dbb0691af..6ded79dec 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2570,6 +2570,92 @@ struct ieee80211_eht_capabilities { #define BASIC_MLE_STA_PROF_STA_MAC_IDX 3 +/* IEEE P802.11be/D2.2, 9.4.2.312.2.3 - Common Info field of the Basic + * Multi-Link element */ +struct eht_ml_basic_common_info { + u8 len; + u8 mld_addr[ETH_ALEN]; + + /* + * Followed by optional fields based on the multi link basic presence + * bitmap + * + * Link ID Info: 1 octet + * BSS Parameters Change Count: 1 octet + * Medium Synchronization Delay Information: 2 octets + * EML Capabilities: 2 octets + * MLD Capabilities and Operations: 2 octets + * AP MLD ID: 1 octet + */ + u8 variable[]; +} STRUCT_PACKED; + +#define EHT_ML_LINK_ID_MSK 0x0f + +#define EHT_ML_MEDIUM_SYNC_DELAY_DURATION 0x00ff +#define EHT_ML_MEDIUM_SYNC_DELAY_OFDM_ED_TH 0x0f00 +#define EHT_ML_MEDIUM_SYNC_DELAY_MAX_TXOP 0xf000 + +#define EHT_ML_EML_CAPA_EMLSR_SUPP 0x0001 +#define EHT_ML_EML_CAPA_EMLSR_PADDING_DELAY_MASK 0x000e +#define EHT_ML_EML_CAPA_EMLSR_TRANS_DELAY_MASK 0x0070 +#define EHT_ML_EML_CAPA_EMLMR_SUPP 0x0080 +#define EHT_ML_EML_CAPA_EMLMR_DELAY_MASK 0x0700 +#define EHT_ML_EML_CAPA_TRANSITION_TIMEOUT_MASK 0x7800 + +#define EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK 0x000f +#define EHT_ML_MLD_CAPA_SRS_SUPP 0x0010 +#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_ALL_TO_ALL 0x0020 +#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_ALL_TO_ONE 0x0040 +#define EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK 0x0060 +#define EHT_ML_MLD_CAPA_FREQ_SEP_FOR_STR_MASK 0x0f80 +#define EHT_ML_MLD_CAPA_AAR_SUPP 0x1000 + +/* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */ +struct ieee80211_eht_per_sta_profile { + le16 sta_control; + + /* Followed by STA Info and STA Profile fields */ + u8 variable[]; +} STRUCT_PACKED; + +/* IEEE P802.11be/D2.0, 9.4.2.312.3 - Probe Request Multi-Link element */ + +#define EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID 0x0001 + +struct eht_ml_probe_req_common_info { + u8 len; + + /* + * Followed by optional fields based on the multi link basic presence + * bitmap + * + * AP MLD ID: 1 octet + */ + u8 variable[]; +} STRUCT_PACKED; + +/* IEEE P802.11be/D2.0, 9.4.2.312.4 - Reconfiguration Multi-Link element */ + +#define EHT_ML_PRES_BM_RECONFIGURE_MLD_ADDRESS 0x0001 + +/* IEEE P802.11be/D2.0, 9.4.2.312.1 - Multi-Link element / General */ + +struct ieee80211_eht_ml { + le16 ml_control; + + /* Followed by Common Info and Link Info fields */ + u8 variable[]; +} STRUCT_PACKED; + +/* Table 9-401c - Optional subelement IDs for Link Info field of the + * Multi-Link element */ +enum ieee80211_eht_ml_sub_elem { + EHT_ML_SUB_ELEM_PER_STA_PROFILE = 0, + EHT_ML_SUB_ELEM_VENDOR = 221, + EHT_ML_SUB_ELEM_FRAGMENT = 254, +}; + /* IEEE P802.11ay/D4.0, 9.4.2.251 - EDMG Operation element */ #define EDMG_BSS_OPERATING_CHANNELS_OFFSET 6 #define EDMG_OPERATING_CHANNEL_WIDTH_OFFSET 7 @@ -2711,4 +2797,14 @@ enum dscp_policy_request_type { #define WFA_CAPA_QM_DSCP_POLICY BIT(0) #define WFA_CAPA_QM_UNSOLIC_DSCP BIT(1) +struct ieee80211_neighbor_ap_info { + u8 tbtt_info_hdr; + u8 tbtt_info_len; + u8 op_class; + u8 channel; + + /* Followed by the rest of the TBTT Information field contents */ + u8 data[0]; +} STRUCT_PACKED; + #endif /* IEEE802_11_DEFS_H */ diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index ba54da544..4ab2a1b63 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -466,6 +466,8 @@ extern "C" { #define WPA_BSS_MASK_UPDATE_IDX BIT(22) #define WPA_BSS_MASK_BEACON_IE BIT(23) #define WPA_BSS_MASK_FILS_INDICATION BIT(24) +#define WPA_BSS_MASK_RNR BIT(25) +#define WPA_BSS_MASK_ML BIT(26) /* VENDOR_ELEM_* frame id values */ diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index cf2f4b821..d34d4a777 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5001,6 +5001,250 @@ static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) #endif /* CONFIG_FILS */ +static int print_rnr(struct wpa_bss *bss, char *pos, char *end) +{ + char *start = pos; + const u8 *ie, *ie_end; + unsigned int n = 0; + int ret; + + ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT); + if (!ie) + return 0; + + ie_end = ie + 2 + ie[1]; + ie += 2; + + while (ie < ie_end) { + const struct ieee80211_neighbor_ap_info *info = + (const struct ieee80211_neighbor_ap_info *) ie; + const u8 *tbtt_start; + size_t left = ie_end - ie; + + if (left < sizeof(struct ieee80211_neighbor_ap_info)) + return 0; + + left -= sizeof(struct ieee80211_neighbor_ap_info); + if (left < info->tbtt_info_len) + return 0; + + ret = os_snprintf(pos, end - pos, + "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ", + n, *ie, info->tbtt_info_len, + info->op_class, info->channel); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + ie += sizeof(struct ieee80211_neighbor_ap_info); + tbtt_start = ie; + if (info->tbtt_info_len >= 1) { + ret = os_snprintf(pos, end - pos, + "tbtt_offset=%u, ", *ie); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie++; + pos += ret; + } + + if (info->tbtt_info_len >= 7) { + ret = os_snprintf(pos, end - pos, + "bssid=" MACSTR ", ", + MAC2STR(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie += ETH_ALEN; + pos += ret; + } + + if (info->tbtt_info_len >= 11) { + ret = os_snprintf(pos, end - pos, + "short SSID=0x%x, ", + WPA_GET_LE32(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie += 4; + pos += ret; + } + + if (info->tbtt_info_len >= 12) { + ret = os_snprintf(pos, end - pos, + "bss_params=0x%x, ", *ie); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie++; + pos += ret; + } + + if (info->tbtt_info_len >= 13) { + ret = os_snprintf(pos, end - pos, + "PSD=0x%x, ", *ie); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie++; + pos += ret; + } + + if (info->tbtt_info_len >= 16) { + ret = os_snprintf(pos, end - pos, + "mld ID=%u, link ID=%u", + *ie, *(ie + 1) & 0xF); + if (os_snprintf_error(end - pos, ret)) + return 0; + + ie += 3; + pos += ret; + } + + ie = tbtt_start + info->tbtt_info_len; + + ret = os_snprintf(pos, end - pos, "\n"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + n++; + } + + return pos - start; +} + + +static int print_ml(struct wpa_bss *bss, char *pos, char *end) +{ + const struct ieee80211_eht_ml *ml; + char *start = pos; + const u8 *ie, *ie_end; + u16 ml_control; + u8 common_info_length; + int ret; + + ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len, + MULTI_LINK_CONTROL_TYPE_BASIC); + if (!ie) + return 0; + + ie_end = ie + 2 + ie[1]; + ie += 3; + ml = (const struct ieee80211_eht_ml *) ie; + + /* control + common info length + MLD MAC Address */ + if (ie_end - ie < 2 + 1 + ETH_ALEN) + return 0; + + ml_control = le_to_host16(ml->ml_control); + + common_info_length = *(ie + 2); + ret = os_snprintf(pos, end - pos, + "multi-link: control=0x%x, common info len=%u", + ml_control, common_info_length); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + ie += 2; + if (ie_end - ie < common_info_length) + return 0; + + ie++; + common_info_length--; + + if (common_info_length < ETH_ALEN) + return 0; + + ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + ie += ETH_ALEN; + common_info_length -= ETH_ALEN; + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) { + if (common_info_length < 1) + return 0; + + ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie++; + common_info_length--; + } + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) { + if (common_info_length < 1) + return 0; + + ret = os_snprintf(pos, end - pos, + ", BSS change parameters=0x%x", *ie); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie++; + common_info_length--; + } + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) { + if (common_info_length < 2) + return 0; + + ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x", + WPA_GET_LE16(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += 2; + common_info_length -= 2; + } + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) { + if (common_info_length < 2) + return 0; + + ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x", + WPA_GET_LE16(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += 2; + common_info_length -= 2; + } + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) { + if (common_info_length < 2) + return 0; + + ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x", + WPA_GET_LE16(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += 2; + common_info_length -= 2; + } + + if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) { + if (common_info_length < 1) + return 0; + + ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x\n", *ie); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += 1; + common_info_length--; + } + + return pos - start; +} + + static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, unsigned long mask, char *buf, size_t buflen) { @@ -5451,6 +5695,12 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos += ret; } + if (mask & WPA_BSS_MASK_RNR) + pos += print_rnr(bss, pos, end); + + if (mask & WPA_BSS_MASK_ML) + pos += print_ml(bss, pos, end); + if (mask & WPA_BSS_MASK_DELIM) { ret = os_snprintf(pos, end - pos, "====\n"); if (os_snprintf_error(end - pos, ret))