From 41cac481a889e27cca73038e6c922624dfe2d07a Mon Sep 17 00:00:00 2001 From: Ankita Bajaj Date: Mon, 18 Nov 2019 14:39:04 +0530 Subject: [PATCH] ACS: Use frequency params in ACS (offload) completed event interface Replace channel fields with frequency fields in ACS completed event interface from the driver layer. Use QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY and QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY attributes if the driver includes them in the QCA_NL80211_VENDOR_SUBCMD_DO_ACS event, otherwise use QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL and QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL attributes to maintain backwards compatibility with old drivers. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 25 +++++++++++---- src/drivers/driver.h | 8 ++--- src/drivers/driver_nl80211_event.c | 49 ++++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index e5ce76d11..49f4a0e36 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -17,6 +17,7 @@ #include "common/wpa_ctrl.h" #include "common/dpp.h" #include "common/sae.h" +#include "common/hw_features_common.h" #include "crypto/random.h" #include "p2p/p2p.h" #include "wps/wps.h" @@ -935,6 +936,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, { int ret, i; int err = 0; + struct hostapd_channel_data *pri_chan; if (hapd->iconf->channel) { wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", @@ -961,24 +963,35 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, } } - hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); + hapd->iface->freq = acs_res->pri_freq; - if (!acs_res->pri_channel) { + if (!acs_res->pri_freq) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, "driver switched to bad channel"); err = 1; goto out; } + pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode, + acs_res->pri_freq, NULL, + hapd->iface->hw_features, + hapd->iface->num_hw_features); + if (!pri_chan) { + wpa_printf(MSG_ERROR, + "ACS: Could not determine primary channel number from pri_freq %u", + acs_res->pri_freq); + err = 1; + goto out; + } - hapd->iconf->channel = acs_res->pri_channel; + hapd->iconf->channel = pri_chan->chan; hapd->iconf->acs = 1; - if (acs_res->sec_channel == 0) + if (acs_res->sec_freq == 0) hapd->iconf->secondary_channel = 0; - else if (acs_res->sec_channel < acs_res->pri_channel) + else if (acs_res->sec_freq < acs_res->pri_freq) hapd->iconf->secondary_channel = -1; - else if (acs_res->sec_channel > acs_res->pri_channel) + else if (acs_res->sec_freq > acs_res->pri_freq) hapd->iconf->secondary_channel = 1; else { wpa_printf(MSG_ERROR, "Invalid secondary channel!"); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index c6b7db8c2..f0e2a6f26 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -5607,8 +5607,8 @@ union wpa_event_data { /** * struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED - * @pri_channel: Selected primary channel - * @sec_channel: Selected secondary channel + * @pri_freq: Selected primary frequency + * @sec_freq: Selected secondary frequency * @vht_seg0_center_ch: VHT mode Segment0 center channel * @vht_seg1_center_ch: VHT mode Segment1 center channel * @ch_width: Selected Channel width by driver. Driver may choose to @@ -5617,8 +5617,8 @@ union wpa_event_data { * hw_mode: Selected band (used with hw_mode=any) */ struct acs_selected_channels { - u8 pri_channel; - u8 sec_channel; + unsigned int pri_freq; + unsigned int sec_freq; u8 vht_seg0_center_ch; u8 vht_seg1_center_ch; u16 ch_width; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 809d8a8da..2aecc7492 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1740,26 +1740,57 @@ static enum hostapd_hw_mode get_qca_hw_mode(u8 hw_mode) } +static unsigned int chan_2ghz_or_5ghz_to_freq(u8 chan) +{ + if (chan >= 1 && chan <= 13) + return 2407 + 5 * chan; + if (chan == 14) + return 2484; + if (chan >= 36 && chan <= 169) + return 5000 + 5 * chan; + + return 0; +} + + static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, const u8 *data, size_t len) { struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1]; union wpa_event_data event; + u8 chan; wpa_printf(MSG_DEBUG, "nl80211: ACS channel selection vendor event received"); if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, (struct nlattr *) data, len, NULL) || - !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL] || - !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]) + (!tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY] && + !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]) || + (!tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY] && + !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL])) return; os_memset(&event, 0, sizeof(event)); - event.acs_selected_channels.pri_channel = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); - event.acs_selected_channels.sec_channel = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) { + event.acs_selected_channels.pri_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]); + } else { + chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); + event.acs_selected_channels.pri_freq = + chan_2ghz_or_5ghz_to_freq(chan); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) { + event.acs_selected_channels.sec_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]); + } else { + chan = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); + event.acs_selected_channels.sec_freq = + chan_2ghz_or_5ghz_to_freq(chan); + } + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) event.acs_selected_channels.vht_seg0_center_ch = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); @@ -1784,9 +1815,9 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, } wpa_printf(MSG_INFO, - "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d", - event.acs_selected_channels.pri_channel, - event.acs_selected_channels.sec_channel, + "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d", + event.acs_selected_channels.pri_freq, + event.acs_selected_channels.sec_freq, event.acs_selected_channels.ch_width, event.acs_selected_channels.vht_seg0_center_ch, event.acs_selected_channels.vht_seg1_center_ch,