Unified the callback for 'channel_switch' and 'channel_switch_started' as they both use the same code and only differ in the event type and message sent to the control interface. the 'channel_switch_started' is raised before the kernel starts the actual channel switch process i.e. right after 'pre_channel_switch' callback, the 'channel_switch' event is raised after the process has already finished in the kernel and driver. Signed-off-by: Omer Dagan <omer.dagan@xxxxxxxxxxx> --- src/ap/drv_callbacks.c | 111 +++++------------------------ src/ap/hostapd.h | 2 +- src/drivers/driver.h | 7 ++ src/drivers/driver_nl80211_event.c | 90 +++++------------------ wpa_supplicant/ap.c | 4 +- wpa_supplicant/ap.h | 2 +- wpa_supplicant/events.c | 76 ++++++++++---------- 7 files changed, 81 insertions(+), 211 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 455be8a71..e813dc16d 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -737,9 +737,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, } } - -void hostapd_event_ch_switch_started(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2) +void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, + int offset, int width, int cf1, int cf2, enum ch_switch_state state) { /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ @@ -748,95 +747,19 @@ void hostapd_event_ch_switch_started(struct hostapd_data *hapd, int freq, int ht u8 seg0_idx = 0, seg1_idx = 0; size_t i; - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + if ( state == CH_SW_STARTED ) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, - "driver starting channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + "driver had channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", freq, ht, hapd->iconf->ch_switch_vht_config, offset, width, channel_width_to_string(width), cf1, cf2); - - hapd->iface->freq = freq; - - channel = hostapd_hw_get_channel(hapd, freq); - if (!channel) { + } else { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "driver switched to bad channel!"); - } - - switch (width) { - case CHAN_WIDTH_80: - chwidth = VHT_CHANWIDTH_80MHZ; - break; - case CHAN_WIDTH_80P80: - chwidth = VHT_CHANWIDTH_80P80MHZ; - break; - case CHAN_WIDTH_160: - chwidth = VHT_CHANWIDTH_160MHZ; - break; - case CHAN_WIDTH_20_NOHT: - case CHAN_WIDTH_20: - case CHAN_WIDTH_40: - default: - chwidth = VHT_CHANWIDTH_USE_HT; - break; - } - - switch (hapd->iface->current_mode->mode) { - case HOSTAPD_MODE_IEEE80211A: - if (cf1 > 5000) - seg0_idx = (cf1 - 5000) / 5; - if (cf2 > 5000) - seg1_idx = (cf2 - 5000) / 5; - break; - default: - ieee80211_freq_to_chan(cf1, &seg0_idx); - ieee80211_freq_to_chan(cf2, &seg1_idx); - break; - } - - hapd->iconf->channel = channel; - hapd->iconf->ieee80211n = ht; - if (!ht) { - hapd->iconf->ieee80211ac = 0; - } else if (hapd->iconf->ch_switch_vht_config) { - /* CHAN_SWITCH VHT config */ - if (hapd->iconf->ch_switch_vht_config & - CH_SWITCH_VHT_ENABLED) - hapd->iconf->ieee80211ac = 1; - else if (hapd->iconf->ch_switch_vht_config & - CH_SWITCH_VHT_DISABLED) - hapd->iconf->ieee80211ac = 0; - } - hapd->iconf->ch_switch_vht_config = 0; - - hapd->iconf->secondary_channel = offset; - hapd->iconf->vht_oper_chwidth = chwidth; - hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx; - hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx; - - is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features, - hapd->iface->num_hw_features); - - wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED - "freq=%d dfs=%d", freq, is_dfs); - -#endif /* NEED_AP_MLME */ -} -void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, - int offset, int width, int cf1, int cf2) -{ - /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ - -#ifdef NEED_AP_MLME - int channel, chwidth, is_dfs; - u8 seg0_idx = 0, seg1_idx = 0; - size_t i; - - 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 starting channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", freq, ht, hapd->iconf->ch_switch_vht_config, offset, width, channel_width_to_string(width), cf1, cf2); + } hapd->iface->freq = freq; @@ -902,6 +825,12 @@ 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); + if ( state == CH_SW_STARTED ) { + wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED + "freq=%d dfs=%d", freq, is_dfs); + return; + } + if (hapd->csa_in_progress && freq == hapd->cs_freq_params.freq) { hostapd_cleanup_cs_params(hapd); @@ -1741,15 +1670,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, hostapd_notif_auth(hapd, &data->auth); break; case EVENT_CH_SWITCH_STARTED: - if (!data) - break; - hostapd_event_ch_switch_started(hapd, data->ch_switch.freq, - data->ch_switch.ht_enabled, - data->ch_switch.ch_offset, - data->ch_switch.ch_width, - data->ch_switch.cf1, - data->ch_switch.cf2); - break; case EVENT_CH_SWITCH: if (!data) break; @@ -1758,7 +1678,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, + data->ch_switch.state); break; case EVENT_CONNECT_FAILED_REASON: if (!data) diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index b8637c46a..6cc873a9f 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -609,7 +609,7 @@ 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, enum ch_switch_state state); struct survey_results; void hostapd_event_get_survey(struct hostapd_iface *iface, struct survey_results *survey_results); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 5d3c15b4f..de5519e8f 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; @@ -5388,6 +5393,7 @@ union wpa_event_data { * @ch_width: Channel width * @cf1: Center frequency 1 * @cf2: Center frequency 2 + * @state: Whether the switch has just started or has already finished */ struct ch_switch { int freq; @@ -5396,6 +5402,7 @@ union wpa_event_data { enum chan_width ch_width; int cf1; int cf2; + enum ch_switch_state state; } ch_switch; /** diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index a02ed3cf6..97d894494 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -528,78 +528,11 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2) return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1; } -static void mlme_event_ch_switch_started(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 i802_bss *bss; - union wpa_event_data data; - int ht_enabled = 1; - int chan_offset = 0; - int ifidx; - - wpa_printf(MSG_DEBUG, "nl80211: Channel switch started event"); - - if (!freq) - return; - - ifidx = nla_get_u32(ifindex); - bss = get_bss_ifindex(drv, ifidx); - if (bss == NULL) { - wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch started, ignoring", - ifidx); - return; - } - - if (type) { - enum nl80211_channel_type ch_type = nla_get_u32(type); - - wpa_printf(MSG_DEBUG, "nl80211: Channel type: %d", ch_type); - switch (ch_type) { - case NL80211_CHAN_NO_HT: - ht_enabled = 0; - break; - case NL80211_CHAN_HT20: - break; - case NL80211_CHAN_HT40PLUS: - chan_offset = 1; - break; - case NL80211_CHAN_HT40MINUS: - chan_offset = -1; - break; - } - } else if (bw && cf1) { - /* This can happen for example with VHT80 ch switch */ - chan_offset = calculate_chan_offset(nla_get_u32(bw), - nla_get_u32(freq), - nla_get_u32(cf1), - cf2 ? nla_get_u32(cf2) : 0); - } else { - wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail"); - } - - os_memset(&data, 0, sizeof(data)); - data.ch_switch.freq = nla_get_u32(freq); - data.ch_switch.ht_enabled = ht_enabled; - data.ch_switch.ch_offset = chan_offset; - if (bw) - data.ch_switch.ch_width = convert2width(nla_get_u32(bw)); - if (cf1) - data.ch_switch.cf1 = nla_get_u32(cf1); - if (cf2) - data.ch_switch.cf2 = nla_get_u32(cf2); - - bss->freq = data.ch_switch.freq; - drv->assoc_freq = data.ch_switch.freq; - - wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH_STARTED, &data); -} - 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, + enum ch_switch_state state) { struct i802_bss *bss; union wpa_event_data data; @@ -607,7 +540,10 @@ 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"); + if ( state == CH_SW_STARTED ) + wpa_printf(MSG_DEBUG, "nl80211: Channel switch started event"); + else + wpa_printf(MSG_DEBUG, "nl80211: Channel switch event"); if (!freq) return; @@ -658,10 +594,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, if (cf2) data.ch_switch.cf2 = nla_get_u32(cf2); + data.ch_switch.state = state; bss->freq = data.ch_switch.freq; drv->assoc_freq = data.ch_switch.freq; - wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data); + if ( state == CH_SW_STARTED ) + wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH_STARTED, &data); + else + wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data); } @@ -2569,13 +2509,14 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_PMKID]); break; case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: - mlme_event_ch_switch_started(drv, + 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]); + tb[NL80211_ATTR_CENTER_FREQ2], + (enum ch_switch_state)CH_SW_STARTED); break; case NL80211_CMD_CH_SWITCH_NOTIFY: mlme_event_ch_switch(drv, @@ -2584,7 +2525,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], + (enum ch_switch_state)CH_SW_FINISHED); 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 453c99dd5..5f1637a62 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1384,7 +1384,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, enum ch_switch_state state) { struct hostapd_iface *iface = wpa_s->ap_iface; @@ -1396,7 +1396,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, state); } diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index 447b55186..89efc801e 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, enum ch_switch_state state); 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 d4452cf7a..2c884a33e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4440,54 +4440,54 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_AP */ case EVENT_CH_SWITCH_STARTED: - if (!data || !wpa_s->current_ssid) - break; - - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED - "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d", - 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); - break; 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", - 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); - - wpa_s->assoc_freq = data->ch_switch.freq; - wpa_s->current_ssid->frequency = data->ch_switch.freq; + if ( data->ch_switch.state == CH_SW_STARTED ) { + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED + "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d", + 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); + } else { + 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", + 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); + + wpa_s->assoc_freq = data->ch_switch.freq; + wpa_s->current_ssid->frequency = data->ch_switch.freq; #ifdef CONFIG_AP - if (wpa_s->current_ssid->mode == WPAS_MODE_AP || - wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO || - wpa_s->current_ssid->mode == WPAS_MODE_MESH || - wpa_s->current_ssid->mode == - WPAS_MODE_P2P_GROUP_FORMATION) { - wpas_ap_ch_switch(wpa_s, data->ch_switch.freq, - data->ch_switch.ht_enabled, - data->ch_switch.ch_offset, - data->ch_switch.ch_width, - data->ch_switch.cf1, - data->ch_switch.cf2); - } + if (wpa_s->current_ssid->mode == WPAS_MODE_AP || + wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO || + wpa_s->current_ssid->mode == WPAS_MODE_MESH || + wpa_s->current_ssid->mode == + WPAS_MODE_P2P_GROUP_FORMATION) { + wpas_ap_ch_switch(wpa_s, data->ch_switch.freq, + data->ch_switch.ht_enabled, + data->ch_switch.ch_offset, + data->ch_switch.ch_width, + data->ch_switch.cf1, + data->ch_switch.cf2, + data->ch_switch.state); + } #endif /* CONFIG_AP */ #ifdef CONFIG_IEEE80211W - sme_event_ch_switch(wpa_s); + sme_event_ch_switch(wpa_s); #endif /* CONFIG_IEEE80211W */ - wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); - wnm_clear_coloc_intf_reporting(wpa_s); + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); + wnm_clear_coloc_intf_reporting(wpa_s); + } break; #ifdef CONFIG_AP #ifdef NEED_AP_MLME -- 2.17.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap