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 <omer.dagan@tandemg.com>
This commit is contained in:
Omer Dagan 2019-04-08 06:44:57 +00:00 committed by Jouni Malinen
parent 9c95124418
commit 95f556f3c7
9 changed files with 67 additions and 14 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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=<MHz> and other channel parameters)
*/
#define WPA_EVENT_CHANNEL_SWITCH_STARTED "CTRL-EVENT-STARTED-CHANNEL-SWITCH "
/** Channel switch (followed by freq=<MHz> and other channel parameters) */
#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
/** SAE authentication failed due to unknown password identifier */

View File

@ -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
*

View File

@ -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);

View File

@ -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],

View File

@ -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);
}

View File

@ -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

View File

@ -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 */