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 <jouni@codeaurora.org>
This commit is contained in:
Ankita Bajaj 2019-11-18 14:39:04 +05:30 committed by Jouni Malinen
parent 840532aea5
commit 41cac481a8
3 changed files with 63 additions and 19 deletions

View file

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

View file

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

View file

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