nl80211: Add VHT 160 MHz channel flags

This extends the previous design that covered only the VHT 80 MHz cases
for VHT channel flags. New functions are introduced to allow 160 MHz
bandwidth cases to determine the center channel and check availability
of a 160 MHz channel.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Ahmad Kholaif 2015-10-28 14:14:10 -07:00 committed by Jouni Malinen
parent 5e1da9c8fd
commit bee5d8e067
4 changed files with 119 additions and 2 deletions

View file

@ -45,6 +45,15 @@
#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000 #define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000 #define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
#define HOSTAPD_CHAN_VHT_10_150 0x00100000
#define HOSTAPD_CHAN_VHT_30_130 0x00200000
#define HOSTAPD_CHAN_VHT_50_110 0x00400000
#define HOSTAPD_CHAN_VHT_70_90 0x00800000
#define HOSTAPD_CHAN_VHT_90_70 0x01000000
#define HOSTAPD_CHAN_VHT_110_50 0x02000000
#define HOSTAPD_CHAN_VHT_130_30 0x04000000
#define HOSTAPD_CHAN_VHT_150_10 0x08000000
/** /**
* enum reg_change_initiator - Regulatory change initiator * enum reg_change_initiator - Regulatory change initiator
*/ */

View file

@ -1418,7 +1418,7 @@ static void nl80211_reg_rule_sec(struct nlattr *tb[],
static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start, static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
int end) int end, int max_bw)
{ {
int c; int c;
@ -1435,6 +1435,32 @@ static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
if (chan->freq - 70 >= start && chan->freq + 10 <= end) if (chan->freq - 70 >= start && chan->freq + 10 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_70_10; chan->flag |= HOSTAPD_CHAN_VHT_70_10;
if (max_bw >= 160) {
if (chan->freq - 10 >= start && chan->freq + 150 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_10_150;
if (chan->freq - 30 >= start && chan->freq + 130 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_30_130;
if (chan->freq - 50 >= start && chan->freq + 110 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_50_110;
if (chan->freq - 70 >= start && chan->freq + 90 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_70_90;
if (chan->freq - 90 >= start && chan->freq + 70 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_90_70;
if (chan->freq - 110 >= start && chan->freq + 50 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_110_50;
if (chan->freq - 130 >= start && chan->freq + 30 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_130_30;
if (chan->freq - 150 >= start && chan->freq + 10 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_150_10;
}
} }
} }
@ -1465,7 +1491,7 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[],
if (!results->modes[m].vht_capab) if (!results->modes[m].vht_capab)
continue; continue;
nl80211_set_vht_mode(&results->modes[m], start, end); nl80211_set_vht_mode(&results->modes[m], start, end, max_bw);
} }
} }

View file

@ -3417,6 +3417,75 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
} }
static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel)
{
u8 center_channels[] = { 50, 114 };
unsigned int i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
for (i = 0; i < ARRAY_SIZE(center_channels); i++)
/*
* In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
* so the center channel is 14 channels away from the start/end.
*/
if (channel >= center_channels[i] - 14 &&
channel <= center_channels[i] + 14)
return center_channels[i];
return 0;
}
static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel, u8 bw)
{
u8 center_chan;
int i, flags;
enum chan_allowed res, ret = ALLOWED;
center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
if (!center_chan)
return NOT_ALLOWED;
/* VHT 160 MHz uses DFS channels in most countries. */
/* Check all the channels are available */
for (i = 0; i < 8; i++) {
int adj_chan = center_chan - 14 + i * 4;
res = has_channel(wpa_s->global, mode, adj_chan, &flags);
if (res == NOT_ALLOWED)
return NOT_ALLOWED;
if (res == NO_IR)
ret = NO_IR;
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
return NOT_ALLOWED;
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
return NOT_ALLOWED;
if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
return NOT_ALLOWED;
if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
return NOT_ALLOWED;
if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
return NOT_ALLOWED;
if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
return NOT_ALLOWED;
if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
return NOT_ALLOWED;
if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
return NOT_ALLOWED;
}
return ret;
}
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, struct hostapd_hw_modes *mode,
u8 channel, u8 bw) u8 channel, u8 bw)
@ -3435,6 +3504,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
res2 = has_channel(wpa_s->global, mode, channel + 4, NULL); res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
} else if (bw == BW80) { } else if (bw == BW80) {
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw); res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
} else if (bw == BW160) {
res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
} }
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED) if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
@ -3548,6 +3619,15 @@ int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
} }
int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel)
{
if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW160))
return 0;
return wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
}
static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf, static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
size_t buf_len) size_t buf_len)
{ {

View file

@ -140,6 +140,8 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel); struct hostapd_hw_modes *mode, u8 channel);
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s, int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel); struct hostapd_hw_modes *mode, u8 channel);
int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s); unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr, void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
const u8 *p2p_dev_addr, const u8 *p2p_dev_addr,