From 95f556f3c77d32c46fb98437bf929ffe39a41ce8 Mon Sep 17 00:00:00 2001 From: Omer Dagan Date: Mon, 8 Apr 2019 06:44:57 +0000 Subject: [PATCH] Make channel switch started event available over control interface This makes it easier to upper layer components to manage operating channels in cases where the same radio is shared for both station and AP mode virtual interfaces. Signed-off-by: Omer Dagan --- src/ap/drv_callbacks.c | 19 ++++++++++++++++--- src/ap/hostapd.h | 3 ++- src/common/wpa_ctrl.h | 3 +++ src/drivers/driver.h | 14 ++++++++++++++ src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211_event.c | 22 ++++++++++++++++++---- wpa_supplicant/ap.c | 4 ++-- wpa_supplicant/ap.h | 2 +- wpa_supplicant/events.c | 13 ++++++++++--- 9 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 8ddf754f6..58753e55a 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -772,7 +772,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2) + int offset, int width, int cf1, int cf2, + int finished) { /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ @@ -783,7 +784,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, - "driver had channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + finished ? "had" : "starting", freq, ht, hapd->iconf->ch_switch_vht_config, offset, width, channel_width_to_string(width), cf1, cf2); @@ -851,6 +853,15 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features, hapd->iface->num_hw_features); + wpa_msg(hapd->msg_ctx, MSG_INFO, + "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", + finished ? WPA_EVENT_CHANNEL_SWITCH : + WPA_EVENT_CHANNEL_SWITCH_STARTED, + freq, ht, offset, channel_width_to_string(width), + cf1, cf2, is_dfs); + if (!finished) + return; + if (hapd->csa_in_progress && freq == hapd->cs_freq_params.freq) { hostapd_cleanup_cs_params(hapd); @@ -1689,6 +1700,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_AUTH: hostapd_notif_auth(hapd, &data->auth); break; + case EVENT_CH_SWITCH_STARTED: case EVENT_CH_SWITCH: if (!data) break; @@ -1697,7 +1709,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->ch_switch.ch_offset, data->ch_switch.ch_width, data->ch_switch.cf1, - data->ch_switch.cf2); + data->ch_switch.cf2, + event == EVENT_CH_SWITCH); break; case EVENT_CONNECT_FAILED_REASON: if (!data) diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 790d37754..0f76cd6c8 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -607,7 +607,8 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, const u8 *bssid, const u8 *ie, size_t ie_len, int ssi_signal); void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2); + int offset, int width, int cf1, int cf2, + int finished); struct survey_results; void hostapd_event_get_survey(struct hostapd_iface *iface, struct survey_results *survey_results); diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index f65077e04..b24ae63e5 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -87,6 +87,9 @@ extern "C" { #define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS " /** Regulatory domain channel */ #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " +/** Channel switch started (followed by freq= and other channel parameters) + */ +#define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH " /** Channel switch (followed by freq= and other channel parameters) */ #define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH " /** SAE authentication failed due to unknown password identifier */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index cb561acba..095bfd96a 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1122,6 +1122,11 @@ enum hide_ssid { HIDDEN_SSID_ZERO_CONTENTS }; +enum ch_switch_state { + CH_SW_STARTED, + CH_SW_FINISHED +}; + struct wowlan_triggers { u8 any; u8 disconnect; @@ -4540,6 +4545,15 @@ enum wpa_event_type { * */ EVENT_CH_SWITCH, + /** + * EVENT_CH_SWITCH_STARTED - AP or GO started to switch channels + * + * This is a pre-switch event indicating the shortly following switch + * of operating channels. + * + * Described in wpa_event_data.ch_switch + */ + EVENT_CH_SWITCH_STARTED, /** * EVENT_WNM - Request WNM operation * diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index e55e6cd2b..b52e8baba 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -67,6 +67,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(DRIVER_CLIENT_POLL_OK); E2S(EAPOL_TX_STATUS); E2S(CH_SWITCH); + E2S(CH_SWITCH_STARTED); E2S(WNM); E2S(CONNECT_FAILED_REASON); E2S(DFS_RADAR_DETECTED); diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index ee7b4da38..7abbafcd8 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -534,7 +534,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2) static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, struct nlattr *ifindex, struct nlattr *freq, struct nlattr *type, struct nlattr *bw, - struct nlattr *cf1, struct nlattr *cf2) + struct nlattr *cf1, struct nlattr *cf2, + int finished) { struct i802_bss *bss; union wpa_event_data data; @@ -542,7 +543,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, int chan_offset = 0; int ifidx; - wpa_printf(MSG_DEBUG, "nl80211: Channel switch event"); + wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event", + finished ? "" : " started"); if (!freq) return; @@ -596,7 +598,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, bss->freq = data.ch_switch.freq; drv->assoc_freq = data.ch_switch.freq; - wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data); + wpa_supplicant_event(bss->ctx, finished ? + EVENT_CH_SWITCH : EVENT_CH_SWITCH_STARTED, &data); } @@ -2508,6 +2511,16 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_PMK], tb[NL80211_ATTR_PMKID]); break; + case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: + mlme_event_ch_switch(drv, + tb[NL80211_ATTR_IFINDEX], + tb[NL80211_ATTR_WIPHY_FREQ], + tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], + tb[NL80211_ATTR_CHANNEL_WIDTH], + tb[NL80211_ATTR_CENTER_FREQ1], + tb[NL80211_ATTR_CENTER_FREQ2], + 0); + break; case NL80211_CMD_CH_SWITCH_NOTIFY: mlme_event_ch_switch(drv, tb[NL80211_ATTR_IFINDEX], @@ -2515,7 +2528,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], - tb[NL80211_ATTR_CENTER_FREQ2]); + tb[NL80211_ATTR_CENTER_FREQ2], + 1); break; case NL80211_CMD_DISCONNECT: mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE], diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 4e1916942..7a3ec3067 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1387,7 +1387,7 @@ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos) void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, - int offset, int width, int cf1, int cf2) + int offset, int width, int cf1, int cf2, int finished) { struct hostapd_iface *iface = wpa_s->ap_iface; @@ -1399,7 +1399,7 @@ void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, if (wpa_s->current_ssid) wpa_s->current_ssid->frequency = freq; hostapd_event_ch_switch(iface->bss[0], freq, ht, - offset, width, cf1, cf2); + offset, width, cf1, cf2, finished); } diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index 447b55186..6c6e94cdf 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -54,7 +54,7 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s, struct csa_settings *settings); int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *txtaddr); void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, - int offset, int width, int cf1, int cf2); + int offset, int width, int cf1, int cf2, int finished); struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s, int ndef); #ifdef CONFIG_AP diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 3ff8ba92d..cab0a6d9a 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4462,18 +4462,24 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->rx_from_unknown.wds); break; #endif /* CONFIG_AP */ + + case EVENT_CH_SWITCH_STARTED: case EVENT_CH_SWITCH: if (!data || !wpa_s->current_ssid) break; - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH - "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d", + wpa_msg(wpa_s, MSG_INFO, + "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d", + event == EVENT_CH_SWITCH ? WPA_EVENT_CHANNEL_SWITCH : + WPA_EVENT_CHANNEL_SWITCH_STARTED, data->ch_switch.freq, data->ch_switch.ht_enabled, data->ch_switch.ch_offset, channel_width_to_string(data->ch_switch.ch_width), data->ch_switch.cf1, data->ch_switch.cf2); + if (event == EVENT_CH_SWITCH_STARTED) + break; wpa_s->assoc_freq = data->ch_switch.freq; wpa_s->current_ssid->frequency = data->ch_switch.freq; @@ -4489,7 +4495,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->ch_switch.ch_offset, data->ch_switch.ch_width, data->ch_switch.cf1, - data->ch_switch.cf2); + data->ch_switch.cf2, + 1); } #endif /* CONFIG_AP */