WNM: Collocated Interference Reporting
Add support for negotiating WNM Collocated Interference Reporting. This allows hostapd to request associated STAs to report their collocated interference information and wpa_supplicant to process such request and reporting. The actual values (Collocated Interference Report Elements) are out of scope of hostapd and wpa_supplicant, i.e., external components are expected to generated and process these. For hostapd/AP, this mechanism is enabled by setting coloc_intf_reporting=1 in configuration. STAs are requested to perform reporting with "COLOC_INTF_REQ <addr> <Automatic Report Enabled> <Report Timeout>" control interface command. The received reports are indicated as control interface events "COLOC-INTF-REPORT <addr> <dialog token> <hexdump of report elements>". For wpa_supplicant/STA, this mechanism is enabled by setting coloc_intf_reporting=1 in configuration and setting Collocated Interference Report Elements as a hexdump with "SET coloc_intf_elems <hexdump>" control interface command. The hexdump can contain one or more Collocated Interference Report Elements (each including the information element header). For additional testing purposes, received requests are reported with "COLOC-INTF-REQ <dialog token> <automatic report enabled> <report timeout>" control interface events and unsolicited reports can be sent with "COLOC_INTF_REPORT <hexdump>". This commit adds support for reporting changes in the collocated interference (Automatic Report Enabled == 1 and partial 3), but not for periodic reports (2 and other part of 3). Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
224eddb03b
commit
d514b50265
18 changed files with 324 additions and 1 deletions
|
@ -4108,6 +4108,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
line, pos);
|
line, pos);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
|
||||||
|
bss->coloc_intf_reporting = atoi(pos);
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
|
|
|
@ -992,6 +992,42 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
|
||||||
|
const char *cmd)
|
||||||
|
{
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
struct sta_info *sta;
|
||||||
|
const char *pos;
|
||||||
|
unsigned int auto_report, timeout;
|
||||||
|
|
||||||
|
if (hwaddr_aton(cmd, addr)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sta = ap_get_sta(hapd, addr);
|
||||||
|
if (!sta) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Station " MACSTR
|
||||||
|
" not found for Collocated Interference Request",
|
||||||
|
MAC2STR(addr));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = cmd + 17;
|
||||||
|
if (*pos != ' ')
|
||||||
|
return -1;
|
||||||
|
pos++;
|
||||||
|
auto_report = atoi(pos);
|
||||||
|
pos = os_strchr(pos, ' ');
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
pos++;
|
||||||
|
timeout = atoi(pos);
|
||||||
|
|
||||||
|
return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WNM_AP */
|
#endif /* CONFIG_WNM_AP */
|
||||||
|
|
||||||
|
|
||||||
|
@ -2961,6 +2997,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
|
} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
|
||||||
if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
|
if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
|
||||||
|
if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_WNM_AP */
|
#endif /* CONFIG_WNM_AP */
|
||||||
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
|
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
|
||||||
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
|
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
|
||||||
|
|
|
@ -684,6 +684,8 @@ struct hostapd_bss_config {
|
||||||
char owe_transition_ifname[IFNAMSIZ + 1];
|
char owe_transition_ifname[IFNAMSIZ + 1];
|
||||||
int *owe_groups;
|
int *owe_groups;
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
|
int coloc_intf_reporting;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -178,6 +178,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
||||||
case 1: /* Bits 8-15 */
|
case 1: /* Bits 8-15 */
|
||||||
if (hapd->conf->proxy_arp)
|
if (hapd->conf->proxy_arp)
|
||||||
*pos |= 0x10; /* Bit 12 - Proxy ARP */
|
*pos |= 0x10; /* Bit 12 - Proxy ARP */
|
||||||
|
if (hapd->conf->coloc_intf_reporting) {
|
||||||
|
/* Bit 13 - Collocated Interference Reporting */
|
||||||
|
*pos |= 0x20;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2: /* Bits 16-23 */
|
case 2: /* Bits 16-23 */
|
||||||
if (hapd->conf->wnm_sleep_mode)
|
if (hapd->conf->wnm_sleep_mode)
|
||||||
|
|
|
@ -453,6 +453,48 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ieee802_11_rx_wnm_coloc_intf_report(struct hostapd_data *hapd,
|
||||||
|
const u8 *addr, const u8 *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 dialog_token;
|
||||||
|
char *hex;
|
||||||
|
size_t hex_len;
|
||||||
|
|
||||||
|
if (!hapd->conf->coloc_intf_reporting) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Ignore unexpected Collocated Interference Report from "
|
||||||
|
MACSTR, MAC2STR(addr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < 1) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Ignore too short Collocated Interference Report from "
|
||||||
|
MACSTR, MAC2STR(addr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog_token = *buf++;
|
||||||
|
len--;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Received Collocated Interference Report frame from "
|
||||||
|
MACSTR " (dialog_token=%u)",
|
||||||
|
MAC2STR(addr), dialog_token);
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "WNM: Collocated Interference Report Elements",
|
||||||
|
buf, len);
|
||||||
|
|
||||||
|
hex_len = 2 * len + 1;
|
||||||
|
hex = os_malloc(hex_len);
|
||||||
|
if (!hex)
|
||||||
|
return;
|
||||||
|
wpa_snprintf_hex(hex, hex_len, buf, len);
|
||||||
|
wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, COLOC_INTF_REPORT MACSTR " %d %s",
|
||||||
|
MAC2STR(addr), dialog_token, hex);
|
||||||
|
os_free(hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -483,6 +525,10 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
|
||||||
ieee802_11_rx_wnm_notification_req(hapd, mgmt->sa, payload,
|
ieee802_11_rx_wnm_notification_req(hapd, mgmt->sa, payload,
|
||||||
plen);
|
plen);
|
||||||
return 0;
|
return 0;
|
||||||
|
case WNM_COLLOCATED_INTERFERENCE_REPORT:
|
||||||
|
ieee802_11_rx_wnm_coloc_intf_report(hapd, mgmt->sa, payload,
|
||||||
|
plen);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
|
||||||
|
@ -681,3 +727,40 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
unsigned int auto_report, unsigned int timeout)
|
||||||
|
{
|
||||||
|
u8 buf[100], *pos;
|
||||||
|
struct ieee80211_mgmt *mgmt;
|
||||||
|
u8 dialog_token = 1;
|
||||||
|
|
||||||
|
if (auto_report > 3 || timeout > 63)
|
||||||
|
return -1;
|
||||||
|
os_memset(buf, 0, sizeof(buf));
|
||||||
|
mgmt = (struct ieee80211_mgmt *) buf;
|
||||||
|
mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
||||||
|
WLAN_FC_STYPE_ACTION);
|
||||||
|
os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
|
||||||
|
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
|
||||||
|
os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
|
||||||
|
mgmt->u.action.category = WLAN_ACTION_WNM;
|
||||||
|
mgmt->u.action.u.coloc_intf_req.action =
|
||||||
|
WNM_COLLOCATED_INTERFERENCE_REQ;
|
||||||
|
mgmt->u.action.u.coloc_intf_req.dialog_token = dialog_token;
|
||||||
|
mgmt->u.action.u.coloc_intf_req.req_info = auto_report | (timeout << 2);
|
||||||
|
pos = &mgmt->u.action.u.coloc_intf_req.req_info;
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
|
||||||
|
MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
|
||||||
|
MAC2STR(sta->addr), dialog_token, auto_report, timeout);
|
||||||
|
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Failed to send Collocated Interference Request frame");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -24,5 +24,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
const u8 *nei_rep, size_t nei_rep_len,
|
const u8 *nei_rep, size_t nei_rep_len,
|
||||||
const u8 *mbo_attrs, size_t mbo_len);
|
const u8 *mbo_attrs, size_t mbo_len);
|
||||||
void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx);
|
void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx);
|
||||||
|
int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
unsigned int auto_report, unsigned int timeout);
|
||||||
|
|
||||||
#endif /* WNM_AP_H */
|
#endif /* WNM_AP_H */
|
||||||
|
|
|
@ -921,6 +921,16 @@ struct ieee80211_mgmt {
|
||||||
* Entries (optional) */
|
* Entries (optional) */
|
||||||
u8 variable[];
|
u8 variable[];
|
||||||
} STRUCT_PACKED bss_tm_query;
|
} STRUCT_PACKED bss_tm_query;
|
||||||
|
struct {
|
||||||
|
u8 action; /* 11 */
|
||||||
|
u8 dialog_token;
|
||||||
|
u8 req_info;
|
||||||
|
} STRUCT_PACKED coloc_intf_req;
|
||||||
|
struct {
|
||||||
|
u8 action; /* 12 */
|
||||||
|
u8 dialog_token;
|
||||||
|
u8 variable[];
|
||||||
|
} STRUCT_PACKED coloc_intf_report;
|
||||||
struct {
|
struct {
|
||||||
u8 action; /* 15 */
|
u8 action; /* 15 */
|
||||||
u8 variable[];
|
u8 variable[];
|
||||||
|
|
|
@ -332,6 +332,13 @@ extern "C" {
|
||||||
/* BSS Transition Management Response frame received */
|
/* BSS Transition Management Response frame received */
|
||||||
#define BSS_TM_RESP "BSS-TM-RESP "
|
#define BSS_TM_RESP "BSS-TM-RESP "
|
||||||
|
|
||||||
|
/* Collocated Interference Request frame received;
|
||||||
|
* parameters: <dialog token> <automatic report enabled> <report timeout> */
|
||||||
|
#define COLOC_INTF_REQ "COLOC-INTF-REQ "
|
||||||
|
/* Collocated Interference Report frame received;
|
||||||
|
* parameters: <STA address> <dialog token> <hexdump of report elements> */
|
||||||
|
#define COLOC_INTF_REPORT "COLOC-INTF-REPORT "
|
||||||
|
|
||||||
/* MBO IE with cellular data connection preference received */
|
/* MBO IE with cellular data connection preference received */
|
||||||
#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
|
#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
|
||||||
|
|
||||||
|
|
|
@ -2200,6 +2200,11 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
|
||||||
/* WNM-Sleep Mode Response */
|
/* WNM-Sleep Mode Response */
|
||||||
if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
|
if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
/* WNM - Collocated Interference Request */
|
||||||
|
if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x0b", 2) < 0)
|
||||||
|
ret = -1;
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
#ifdef CONFIG_HS20
|
#ifdef CONFIG_HS20
|
||||||
/* WNM-Notification */
|
/* WNM-Notification */
|
||||||
|
|
|
@ -4755,6 +4755,7 @@ static const struct global_parse_data global_fields[] = {
|
||||||
{ INT(gas_rand_addr_lifetime), 0 },
|
{ INT(gas_rand_addr_lifetime), 0 },
|
||||||
{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
|
{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
|
||||||
{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
|
{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
|
||||||
|
{ INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef FUNC
|
#undef FUNC
|
||||||
|
|
|
@ -1469,6 +1469,15 @@ struct wpa_config {
|
||||||
* profile automatically
|
* profile automatically
|
||||||
*/
|
*/
|
||||||
int dpp_config_processing;
|
int dpp_config_processing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* coloc_intf_reporting - Colocated interference reporting
|
||||||
|
*
|
||||||
|
* dot11CoLocIntfReportingActivated
|
||||||
|
* 0 = disabled (false)
|
||||||
|
* 1 = enabled (true)
|
||||||
|
*/
|
||||||
|
int coloc_intf_reporting;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1511,7 +1511,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
|
||||||
if (config->dpp_config_processing)
|
if (config->dpp_config_processing)
|
||||||
fprintf(f, "dpp_config_processing=%d\n",
|
fprintf(f, "dpp_config_processing=%d\n",
|
||||||
config->dpp_config_processing);
|
config->dpp_config_processing);
|
||||||
|
if (config->coloc_intf_reporting)
|
||||||
|
fprintf(f, "coloc_intf_reporting=%d\n",
|
||||||
|
config->coloc_intf_reporting);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NO_CONFIG_WRITE */
|
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||||
|
|
|
@ -750,6 +750,15 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
||||||
ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
|
ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
|
||||||
} else if (os_strcasecmp(cmd, "roaming") == 0) {
|
} else if (os_strcasecmp(cmd, "roaming") == 0) {
|
||||||
ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
|
ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
} else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
|
||||||
|
struct wpabuf *elems;
|
||||||
|
|
||||||
|
elems = wpabuf_parse_bin(value);
|
||||||
|
if (!elems)
|
||||||
|
return -1;
|
||||||
|
wnm_set_coloc_intf_elems(wpa_s, elems);
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
} else {
|
} else {
|
||||||
value[-1] = '=';
|
value[-1] = '=';
|
||||||
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
|
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
|
||||||
|
@ -7437,6 +7446,22 @@ static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd
|
||||||
list);
|
list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
|
||||||
|
char *cmd)
|
||||||
|
{
|
||||||
|
struct wpabuf *elems;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
elems = wpabuf_parse_bin(cmd);
|
||||||
|
if (!elems)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
|
||||||
|
wpabuf_free(elems);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
|
|
||||||
|
@ -10423,6 +10448,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
|
} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
|
||||||
if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
|
if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
|
||||||
|
if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
} else if (os_strcmp(buf, "FLUSH") == 0) {
|
} else if (os_strcmp(buf, "FLUSH") == 0) {
|
||||||
wpa_supplicant_ctrl_iface_flush(wpa_s);
|
wpa_supplicant_ctrl_iface_flush(wpa_s);
|
||||||
|
|
|
@ -317,6 +317,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
|
||||||
|
|
||||||
wpas_rrm_reset(wpa_s);
|
wpas_rrm_reset(wpa_s);
|
||||||
wpa_s->wnmsleep_used = 0;
|
wpa_s->wnmsleep_used = 0;
|
||||||
|
wnm_clear_coloc_intf_reporting(wpa_s);
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
wpa_s->last_tk_alg = WPA_ALG_NONE;
|
wpa_s->last_tk_alg = WPA_ALG_NONE;
|
||||||
|
@ -4339,6 +4340,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
|
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
|
||||||
|
wnm_clear_coloc_intf_reporting(wpa_s);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_AP
|
#ifdef CONFIG_AP
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
|
|
|
@ -338,6 +338,9 @@ void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
|
||||||
wpa_s->wnm_num_neighbor_report = 0;
|
wpa_s->wnm_num_neighbor_report = 0;
|
||||||
os_free(wpa_s->wnm_neighbor_report_elements);
|
os_free(wpa_s->wnm_neighbor_report_elements);
|
||||||
wpa_s->wnm_neighbor_report_elements = NULL;
|
wpa_s->wnm_neighbor_report_elements = NULL;
|
||||||
|
|
||||||
|
wpabuf_free(wpa_s->coloc_intf_elems);
|
||||||
|
wpa_s->coloc_intf_elems = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1717,6 +1720,46 @@ static void ieee802_11_rx_wnm_notif_req(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ieee802_11_rx_wnm_coloc_intf_req(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *sa, const u8 *frm,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
u8 dialog_token, req_info, auto_report, timeout;
|
||||||
|
|
||||||
|
if (!wpa_s->conf->coloc_intf_reporting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Dialog Token [1] | Request Info [1] */
|
||||||
|
|
||||||
|
if (len < 2)
|
||||||
|
return;
|
||||||
|
dialog_token = frm[0];
|
||||||
|
req_info = frm[1];
|
||||||
|
auto_report = req_info & 0x03;
|
||||||
|
timeout = req_info >> 2;
|
||||||
|
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"WNM: Received Collocated Interference Request (dialog_token %u auto_report %u timeout %u sa " MACSTR ")",
|
||||||
|
dialog_token, auto_report, timeout, MAC2STR(sa));
|
||||||
|
|
||||||
|
if (dialog_token == 0)
|
||||||
|
return; /* only nonzero values are used for request */
|
||||||
|
|
||||||
|
if (wpa_s->wpa_state != WPA_COMPLETED ||
|
||||||
|
os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"WNM: Collocated Interference Request frame not from current AP - ignore it");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, COLOC_INTF_REQ "%u %u %u",
|
||||||
|
dialog_token, auto_report, timeout);
|
||||||
|
wpa_s->coloc_intf_dialog_token = dialog_token;
|
||||||
|
wpa_s->coloc_intf_auto_report = auto_report;
|
||||||
|
wpa_s->coloc_intf_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -1750,8 +1793,75 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
|
||||||
case WNM_NOTIFICATION_REQ:
|
case WNM_NOTIFICATION_REQ:
|
||||||
ieee802_11_rx_wnm_notif_req(wpa_s, mgmt->sa, pos, end - pos);
|
ieee802_11_rx_wnm_notif_req(wpa_s, mgmt->sa, pos, end - pos);
|
||||||
break;
|
break;
|
||||||
|
case WNM_COLLOCATED_INTERFERENCE_REQ:
|
||||||
|
ieee802_11_rx_wnm_coloc_intf_req(wpa_s, mgmt->sa, pos,
|
||||||
|
end - pos);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_ERROR, "WNM: Unknown request");
|
wpa_printf(MSG_ERROR, "WNM: Unknown request");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
|
||||||
|
const struct wpabuf *elems)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (wpa_s->wpa_state < WPA_ASSOCIATED || !elems)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Send Collocated Interference Report to "
|
||||||
|
MACSTR " (dialog token %u)",
|
||||||
|
MAC2STR(wpa_s->bssid), dialog_token);
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(3 + wpabuf_len(elems));
|
||||||
|
if (!buf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
|
||||||
|
wpabuf_put_u8(buf, WNM_COLLOCATED_INTERFERENCE_REPORT);
|
||||||
|
wpabuf_put_u8(buf, dialog_token);
|
||||||
|
wpabuf_put_buf(buf, elems);
|
||||||
|
|
||||||
|
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
|
||||||
|
wpa_s->own_addr, wpa_s->bssid,
|
||||||
|
wpabuf_head_u8(buf), wpabuf_len(buf), 0);
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpabuf *elems)
|
||||||
|
{
|
||||||
|
wpabuf_free(wpa_s->coloc_intf_elems);
|
||||||
|
if (elems && wpabuf_len(elems) == 0) {
|
||||||
|
wpabuf_free(elems);
|
||||||
|
elems = NULL;
|
||||||
|
}
|
||||||
|
wpa_s->coloc_intf_elems = elems;
|
||||||
|
|
||||||
|
if (wpa_s->conf->coloc_intf_reporting && wpa_s->coloc_intf_elems &&
|
||||||
|
wpa_s->coloc_intf_dialog_token &&
|
||||||
|
(wpa_s->coloc_intf_auto_report == 1 ||
|
||||||
|
wpa_s->coloc_intf_auto_report == 3)) {
|
||||||
|
/* TODO: Check that there has not been less than
|
||||||
|
* wpa_s->coloc_intf_timeout * 200 TU from the last report.
|
||||||
|
*/
|
||||||
|
wnm_send_coloc_intf_report(wpa_s,
|
||||||
|
wpa_s->coloc_intf_dialog_token,
|
||||||
|
wpa_s->coloc_intf_elems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
wpa_s->coloc_intf_dialog_token = 0;
|
||||||
|
wpa_s->coloc_intf_auto_report = 0;
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
}
|
||||||
|
|
|
@ -65,11 +65,16 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
|
||||||
int cand_list);
|
int cand_list);
|
||||||
|
|
||||||
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
|
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
|
||||||
|
int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
|
||||||
|
const struct wpabuf *elems);
|
||||||
|
void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpabuf *elems);
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM
|
||||||
|
|
||||||
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
|
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
|
||||||
|
void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
#else /* CONFIG_WNM */
|
#else /* CONFIG_WNM */
|
||||||
|
|
||||||
|
@ -79,6 +84,10 @@ static inline int wnm_scan_process(struct wpa_supplicant *wpa_s,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
#endif /* WNM_STA_H */
|
#endif /* WNM_STA_H */
|
||||||
|
|
|
@ -1645,6 +1645,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
|
||||||
case 0: /* Bits 0-7 */
|
case 0: /* Bits 0-7 */
|
||||||
break;
|
break;
|
||||||
case 1: /* Bits 8-15 */
|
case 1: /* Bits 8-15 */
|
||||||
|
if (wpa_s->conf->coloc_intf_reporting) {
|
||||||
|
/* Bit 13 - Collocated Interference Reporting */
|
||||||
|
*pos |= 0x20;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2: /* Bits 16-23 */
|
case 2: /* Bits 16-23 */
|
||||||
#ifdef CONFIG_WNM
|
#ifdef CONFIG_WNM
|
||||||
|
|
|
@ -1059,6 +1059,10 @@ struct wpa_supplicant {
|
||||||
struct neighbor_report *wnm_neighbor_report_elements;
|
struct neighbor_report *wnm_neighbor_report_elements;
|
||||||
struct os_reltime wnm_cand_valid_until;
|
struct os_reltime wnm_cand_valid_until;
|
||||||
u8 wnm_cand_from_bss[ETH_ALEN];
|
u8 wnm_cand_from_bss[ETH_ALEN];
|
||||||
|
struct wpabuf *coloc_intf_elems;
|
||||||
|
u8 coloc_intf_dialog_token;
|
||||||
|
u8 coloc_intf_auto_report;
|
||||||
|
u8 coloc_intf_timeout;
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
unsigned int wnm_mbo_trans_reason_present:1;
|
unsigned int wnm_mbo_trans_reason_present:1;
|
||||||
u8 wnm_mbo_transition_reason;
|
u8 wnm_mbo_transition_reason;
|
||||||
|
|
Loading…
Reference in a new issue