I'm giving up on this for now, but the patches I was trying
are attached in case someone else wants to try it someday.
It compiles now, but AP won't start...I have no idea why.
Thanks,
Ben
On 05/14/2016 09:18 AM, Ben Greear wrote:
On 05/14/2016 07:13 AM, Jouni Malinen wrote:
On Sat, May 14, 2016 at 06:38:23AM -0700, Ben Greear wrote:
This patch does not compile....looks like I have to pass chwidth into a lot
more places. But, I'm curious if anyone has any opinions on whether this is
even remotely the right way to go about doing this?
What is your use case for this? 5 and 10 MHz channel widths are not
really used very commonly today and only in quite special use cases..
Seems they are used in the 4.9Ghz band, at least. That is what my user
is interested in...
Thanks,
Ben
--
Ben Greear <greearb@xxxxxxxxxxxxxxx>
Candela Technologies Inc http://www.candelatech.com
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 8030feb..4fb8328 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2895,6 +2895,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->require_vht = atoi(pos);
} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
conf->vht_oper_chwidth = atoi(pos);
+ } else if (os_strcmp(buf, "ht_oper_chwidth") == 0) {
+ conf->ht_oper_chwidth = atoi(pos);
} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 33819ab..26338e5 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -751,7 +751,8 @@ static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
- wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_head(buf), wpabuf_len(buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(buf);
return ret;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2d07c67..552f740 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -665,6 +665,8 @@ struct hostapd_config {
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+ u8 ht_oper_chwidth;
+
/* Use driver-generated interface addresses when adding multiple BSSs */
u8 use_driver_iface_addr;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index b89f60e..828198d 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -485,7 +485,7 @@ int hostapd_flush(struct hostapd_data *hapd)
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
- int center_segment0, int center_segment1)
+ int center_segment0, int center_segment1, int ht_oper_chwidth)
{
struct hostapd_freq_params data;
@@ -494,7 +494,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
vht_oper_chwidth,
center_segment0, center_segment1,
hapd->iface->current_mode ?
- hapd->iface->current_mode->vht_capab : 0))
+ hapd->iface->current_mode->vht_capab : 0,
+ ht_oper_chwidth))
return -1;
if (hapd->driver == NULL)
@@ -623,7 +624,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
- NULL, 0);
+ NULL, 0, 0);
}
@@ -634,7 +635,7 @@ int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
- csa_offs, csa_offs_len);
+ csa_offs, csa_offs_len, 0);
}
@@ -670,13 +671,13 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
- size_t len)
+ size_t len, int chwidth)
{
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
return 0;
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
hapd->own_addr, hapd->own_addr, data,
- len, 0);
+ len, 0, chwidth);
}
@@ -684,7 +685,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
enum hostapd_hw_mode mode, int freq,
int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
- int center_segment0, int center_segment1)
+ int center_segment0, int center_segment1,
+ int ht_oper_chwidth)
{
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_freq_params data;
@@ -703,7 +705,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
vht_enabled, sec_channel_offset,
vht_oper_chwidth, center_segment0,
center_segment1,
- iface->current_mode->vht_capab)) {
+ iface->current_mode->vht_capab,
+ ht_oper_chwidth)) {
wpa_printf(MSG_ERROR, "Can't set freq params");
return -1;
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 757a706..d7f0c27 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -61,7 +61,7 @@ int hostapd_flush(struct hostapd_data *hapd);
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
- int center_segment0, int center_segment1);
+ int center_segment0, int center_segment1, int ht_oper_chwidth);
int hostapd_set_rts(struct hostapd_data *hapd, int rts);
int hostapd_set_frag(struct hostapd_data *hapd, int frag);
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
@@ -97,7 +97,7 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
unsigned int wait, const u8 *dst, const u8 *data,
- size_t len);
+ size_t len, int chwidth);
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg);
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
@@ -110,7 +110,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
enum hostapd_hw_mode mode, int freq,
int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
- int center_segment0, int center_segment1);
+ int center_segment0, int center_segment1, int ht_oper_chwidth);
int hostapd_drv_do_acs(struct hostapd_data *hapd);
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 0720e14..3ab6060 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1279,7 +1279,8 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
iconf->vht_oper_chwidth,
iconf->vht_oper_centr_freq_seg0_idx,
iconf->vht_oper_centr_freq_seg1_idx,
- iface->current_mode->vht_capab) == 0)
+ iface->current_mode->vht_capab,
+ iconf->ht_oper_chwidth) == 0)
params.freq = &freq;
res = hostapd_drv_set_ap(hapd, ¶ms);
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 9f249d7..a478b3f 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -443,6 +443,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
"num_sta_ht_20_mhz=%d\n"
"num_sta_ht40_intolerant=%d\n"
"olbc_ht=%d\n"
+ "ht_oper_chwidth=%d\n"
"ht_op_mode=0x%x\n",
hostapd_state_text(iface->state),
iface->phy,
@@ -456,6 +457,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
iface->num_sta_ht_20mhz,
iface->num_sta_ht40_intolerant,
iface->olbc_ht,
+ iface->conf->ht_oper_chwidth,
iface->ht_op_mode);
if (os_snprintf_error(buflen - len, ret))
return len;
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 47adba7..6bf0825 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -515,6 +515,8 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
/* Seems cf1 and chan_width is enough here */
switch (chan_width) {
+ case CHAN_WIDTH_5:
+ case CHAN_WIDTH_10:
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
n_chans = 1;
@@ -571,6 +573,8 @@ static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
/* Reported via radar event */
switch (chan_width) {
+ case CHAN_WIDTH_5:
+ case CHAN_WIDTH_10:
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
radar_n_chans = 1;
@@ -736,7 +740,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
iface->conf->secondary_channel,
iface->conf->vht_oper_chwidth,
iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx);
+ iface->conf->vht_oper_centr_freq_seg1_idx,
+ iface->conf->ht_oper_chwidth);
if (res) {
wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
@@ -897,7 +902,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
iface->conf->vht_oper_chwidth,
vht_oper_centr_freq_seg0_idx,
vht_oper_centr_freq_seg1_idx,
- iface->current_mode->vht_capab);
+ iface->current_mode->vht_capab,
+ iface->conf->ht_oper_chwidth);
if (err) {
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index f54d1ad..cd6420a 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -502,6 +502,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
case CHAN_WIDTH_160:
chwidth = VHT_CHANWIDTH_160MHZ;
break;
+ case CHAN_WIDTH_5:
+ case CHAN_WIDTH_10:
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
case CHAN_WIDTH_40:
@@ -532,6 +534,11 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
+ if (width == CHAN_WIDTH_5)
+ hapd->iconf->ht_oper_chwidth = 5;
+ else if (width == CHAN_WIDTH_10)
+ hapd->iconf->ht_oper_chwidth = 10;
+
is_dfs = ieee80211_is_dfs(freq);
if (hapd->csa_in_progress &&
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index 179dc7a..9c9512e 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -1228,7 +1228,8 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd,
if (prot)
convert_to_protected_dual(tx_buf);
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(tx_buf), wpabuf_len(tx_buf));
+ wpabuf_head(tx_buf), wpabuf_len(tx_buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(tx_buf);
}
@@ -1288,7 +1289,8 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
if (prot)
convert_to_protected_dual(buf);
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_head(buf), wpabuf_len(buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(buf);
return;
}
@@ -1421,7 +1423,8 @@ send_resp:
if (prot)
convert_to_protected_dual(tx_buf);
hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(tx_buf), wpabuf_len(tx_buf));
+ wpabuf_head(tx_buf), wpabuf_len(tx_buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(tx_buf);
}
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 55ca9e8..cb656f8 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -188,6 +188,7 @@ int hostapd_reload_config(struct hostapd_iface *iface)
hapd->iconf->ht_capab = oldconf->ht_capab;
hapd->iconf->vht_capab = oldconf->vht_capab;
hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
+ hapd->iconf->ht_oper_chwidth = oldconf->ht_oper_chwidth;
hapd->iconf->vht_oper_centr_freq_seg0_idx =
oldconf->vht_oper_centr_freq_seg0_idx;
hapd->iconf->vht_oper_centr_freq_seg1_idx =
@@ -1436,7 +1437,8 @@ static int fst_hostapd_send_action_cb(void *ctx, const u8 *da,
struct hostapd_data *hapd = ctx;
return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, da,
- wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_head(buf), wpabuf_len(buf),
+ hapd->iconf->ht_oper_chwidth);
}
@@ -1595,7 +1597,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
hapd->iconf->secondary_channel,
hapd->iconf->vht_oper_chwidth,
hapd->iconf->vht_oper_centr_freq_seg0_idx,
- hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
+ hapd->iconf->vht_oper_centr_freq_seg1_idx,
+ hapd->iconf->ht_oper_chwidth)) {
wpa_printf(MSG_ERROR, "Could not set channel for "
"kernel driver");
goto fail;
@@ -2879,11 +2882,14 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
conf->vht_oper_chwidth,
conf->vht_oper_centr_freq_seg0_idx,
conf->vht_oper_centr_freq_seg1_idx,
- conf->vht_capab))
+ conf->vht_capab,
+ conf->ht_oper_chwidth))
return -1;
switch (params->bandwidth) {
case 0:
+ case 5:
+ case 10:
case 20:
case 40:
conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
@@ -3051,6 +3057,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
switch (freq_params->bandwidth) {
case 0:
+ case 5:
+ case 10:
case 20:
case 40:
vht_bw = VHT_CHANWIDTH_USE_HT;
diff --git a/src/ap/hs20.c b/src/ap/hs20.c
index d7909fa..05871f2 100644
--- a/src/ap/hs20.c
+++ b/src/ap/hs20.c
@@ -134,7 +134,8 @@ int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
}
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
- wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_head(buf), wpabuf_len(buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(buf);
@@ -169,7 +170,8 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
wpabuf_put_buf(buf, payload);
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
- wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_head(buf), wpabuf_len(buf),
+ hapd->iconf->ht_oper_chwidth);
wpabuf_free(buf);
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 41d50ce..cd684ed 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -145,7 +145,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd,
/* In driver, response frame should be forced to sent when STA is in
* PS mode */
res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
- mgmt->da, &mgmt->u.action.category, len);
+ mgmt->da, &mgmt->u.action.category, len,
+ hapd->iconf->ht_oper_chwidth);
if (!res) {
wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response "
@@ -295,7 +296,8 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
len = pos - &mgmt->u.action.category;
res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
- mgmt->da, &mgmt->u.action.category, len);
+ mgmt->da, &mgmt->u.action.category, len,
+ hapd->iconf->ht_oper_chwidth);
os_free(mgmt);
return res;
}
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 9c37ea6..49eaf87 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -354,7 +354,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int freq, int channel, int ht_enabled,
int vht_enabled, int sec_channel_offset,
int vht_oper_chwidth, int center_segment0,
- int center_segment1, u32 vht_caps)
+ int center_segment1, u32 vht_caps,
+ int ht_oper_chwidth)
{
os_memset(data, 0, sizeof(*data));
data->mode = mode;
@@ -367,6 +368,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
data->center_freq2 = 0;
data->bandwidth = sec_channel_offset ? 40 : 20;
+ if (ht_oper_chwidth) {
+ if (!sec_channel_offset)
+ data->bandwidth = ht_oper_chwidth; /* user-override */
+ }
+
if (data->vht_enabled) switch (vht_oper_chwidth) {
case VHT_CHANWIDTH_USE_HT:
if (center_segment1 ||
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index 7360b4e..ae2e9a1 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -34,6 +34,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int freq, int channel, int ht_enabled,
int vht_enabled, int sec_channel_offset,
int vht_oper_chwidth, int center_segment0,
- int center_segment1, u32 vht_caps);
+ int center_segment1, u32 vht_caps,
+ int ht_oper_chwidth);
#endif /* HW_FEATURES_COMMON_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index adfcdb4..3e0f1c4 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1587,6 +1587,8 @@ enum chan_width {
CHAN_WIDTH_80,
CHAN_WIDTH_80P80,
CHAN_WIDTH_160,
+ CHAN_WIDTH_5,
+ CHAN_WIDTH_10,
CHAN_WIDTH_UNKNOWN
};
@@ -2067,7 +2069,7 @@ struct wpa_driver_ops {
*/
int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
int noack, unsigned int freq, const u16 *csa_offs,
- size_t csa_offs_len);
+ size_t csa_offs_len, int chwidth);
/**
* update_ft_ies - Update FT (IEEE 802.11r) IEs
@@ -2652,7 +2654,8 @@ struct wpa_driver_ops {
* @bssid: BSSID (Address 3)
* @data: Frame body
* @data_len: data length in octets
- @ @no_cck: Whether CCK rates must not be used to transmit this frame
+ * @no_cck: Whether CCK rates must not be used to transmit this frame
+ * @chwidth: Specify channel width, or use 0 for default.
* Returns: 0 on success, -1 on failure
*
* This command can be used to request the driver to transmit an action
@@ -2670,7 +2673,8 @@ struct wpa_driver_ops {
*/
int (*send_action)(void *priv, unsigned int freq, unsigned int wait,
const u8 *dst, const u8 *src, const u8 *bssid,
- const u8 *data, size_t data_len, int no_cck);
+ const u8 *data, size_t data_len, int no_cck,
+ int chwidth);
/**
* send_action_cancel_wait - Cancel action frame TX wait
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index b32d35f..443f56d 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -90,6 +90,10 @@ const char * event_to_string(enum wpa_event_type event)
const char * channel_width_to_string(enum chan_width width)
{
switch (width) {
+ case CHAN_WIDTH_5:
+ return "5 MHz";
+ case CHAN_WIDTH_10:
+ return "10 MHz";
case CHAN_WIDTH_20_NOHT:
return "20 MHz (no HT)";
case CHAN_WIDTH_20:
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 014bde3..db14674 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -37,6 +37,7 @@
#include "radiotap_iter.h"
#include "rfkill.h"
#include "driver_nl80211.h"
+#include <assert.h>
#ifndef CONFIG_LIBNL20
@@ -177,7 +178,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len, u64 *cookie,
int no_cck, int no_ack, int offchanok,
- const u16 *csa_offs, size_t csa_offs_len);
+ const u16 *csa_offs, size_t csa_offs_len,
+ int chwidth);
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
int report);
@@ -210,6 +212,10 @@ static int nl80211_set_param(void *priv, const char *param);
enum chan_width convert2width(int width)
{
switch (width) {
+ case NL80211_CHAN_WIDTH_5:
+ return CHAN_WIDTH_5;
+ case NL80211_CHAN_WIDTH_10:
+ return CHAN_WIDTH_10;
case NL80211_CHAN_WIDTH_20_NOHT:
return CHAN_WIDTH_20_NOHT;
case NL80211_CHAN_WIDTH_20:
@@ -3186,7 +3192,7 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
unsigned int freq, int no_cck,
int offchanok, unsigned int wait_time,
const u16 *csa_offs,
- size_t csa_offs_len)
+ size_t csa_offs_len, int chwidth)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
u64 cookie;
@@ -3210,10 +3216,11 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
return nl80211_send_monitor(drv, data, len, encrypt, noack);
}
- wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
+ wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd freq:%d chwidth:%d",
+ freq, chwidth);
res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
&cookie, no_cck, noack, offchanok,
- csa_offs, csa_offs_len);
+ csa_offs, csa_offs_len, chwidth);
if (res == 0 && !noack) {
const struct ieee80211_mgmt *mgmt;
u16 fc;
@@ -3241,7 +3248,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
int offchanok,
unsigned int wait_time,
const u16 *csa_offs,
- size_t csa_offs_len)
+ size_t csa_offs_len, int chwidth)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct ieee80211_mgmt *mgmt;
@@ -3271,7 +3278,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
}
return nl80211_send_frame_cmd(bss, freq, 0,
data, data_len, NULL, 1, noack,
- 1, csa_offs, csa_offs_len);
+ 1, csa_offs, csa_offs_len, chwidth);
}
if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
@@ -3286,7 +3293,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
data, data_len,
&drv->send_action_cookie,
no_cck, noack, offchanok,
- csa_offs, csa_offs_len);
+ csa_offs, csa_offs_len, chwidth);
}
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@@ -3307,7 +3314,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
noack, freq, no_cck, offchanok,
wait_time, csa_offs,
- csa_offs_len);
+ csa_offs_len, chwidth);
}
@@ -3660,17 +3667,17 @@ fail:
static int nl80211_put_freq_params(struct nl_msg *msg,
const struct hostapd_freq_params *freq)
{
+ enum nl80211_chan_width cw;
+
wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq);
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
return -ENOBUFS;
wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled);
wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled);
+ wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth);
if (freq->vht_enabled) {
- enum nl80211_chan_width cw;
-
- wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth);
switch (freq->bandwidth) {
case 20:
cw = NL80211_CHAN_WIDTH_20;
@@ -3720,8 +3727,26 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
break;
}
+ switch (freq->bandwidth) {
+ case 5:
+ cw = NL80211_CHAN_WIDTH_5;
+ break;
+ case 10:
+ cw = NL80211_CHAN_WIDTH_10;
+ break;
+ case 40:
+ cw = NL80211_CHAN_WIDTH_40;
+ break;
+ case 20:
+ default:
+ cw = NL80211_CHAN_WIDTH_20;
+ break;
+ }
+
+ wpa_printf(MSG_DEBUG, " * channel_width=%d", cw);
wpa_printf(MSG_DEBUG, " * channel_type=%d", ct);
- if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
+ if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
return -ENOBUFS;
}
return 0;
@@ -4413,7 +4438,7 @@ static int wpa_driver_nl80211_hapd_send_eapol(
memcpy(pos, data, data_len);
res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
- 0, 0, 0, 0, NULL, 0);
+ 0, 0, 0, 0, NULL, 0, 0);
if (res < 0) {
wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
"failed: %d (%s)",
@@ -5635,7 +5660,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth), 0, 0, 0, 0,
- 0, NULL, 0);
+ 0, NULL, 0, 0);
}
@@ -5662,7 +5687,7 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
- 0, NULL, 0);
+ 0, NULL, 0, 0);
}
@@ -6366,7 +6391,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
const u8 *buf, size_t buf_len,
u64 *cookie_out, int no_cck, int no_ack,
int offchanok, const u16 *csa_offs,
- size_t csa_offs_len)
+ size_t csa_offs_len, int chwidth)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
@@ -6374,12 +6399,13 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
int ret = -1;
wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
- "no_ack=%d offchanok=%d",
- freq, wait, no_cck, no_ack, offchanok);
+ "no_ack=%d offchanok=%d chwidth=%d",
+ freq, wait, no_cck, no_ack, offchanok, chwidth);
wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
(freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
+ (chwidth && nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chwidth)) ||
(wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
(offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
drv->test_use_roc_tx) &&
@@ -6433,7 +6459,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
const u8 *dst, const u8 *src,
const u8 *bssid,
const u8 *data, size_t data_len,
- int no_cck)
+ int no_cck, int chwidth)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
int ret = -1;
@@ -6461,12 +6487,12 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
!drv->use_monitor))
ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
0, freq, no_cck, 1,
- wait_time, NULL, 0);
+ wait_time, NULL, 0, chwidth);
else
ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
24 + data_len,
&drv->send_action_cookie,
- no_cck, 0, 1, NULL, 0);
+ no_cck, 0, 1, NULL, 0, chwidth);
os_free(buf);
return ret;
@@ -7049,7 +7075,7 @@ static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
- 0, 0, 0, 0, NULL, 0);
+ 0, 0, 0, 0, NULL, 0, 0);
}
static void parse_ht_mask(u8 *mask, int mask_len, const char* input)
@@ -7531,7 +7557,7 @@ static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
- 0, 0, NULL, 0) < 0)
+ 0, 0, NULL, 0, 0) < 0)
wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
"send poll frame");
}
@@ -7852,12 +7878,13 @@ static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
size_t data_len, int noack,
unsigned int freq,
- const u16 *csa_offs, size_t csa_offs_len)
+ const u16 *csa_offs, size_t csa_offs_len,
+ int chwidth)
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
freq, 0, 0, 0, csa_offs,
- csa_offs_len);
+ csa_offs_len, chwidth);
}
@@ -7890,11 +7917,12 @@ static int driver_nl80211_send_action(void *priv, unsigned int freq,
const u8 *dst, const u8 *src,
const u8 *bssid,
const u8 *data, size_t data_len,
- int no_cck)
+ int no_cck, int chwidth)
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
- bssid, data, data_len, no_cck);
+ bssid, data, data_len, no_cck,
+ chwidth);
}
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index dae203a..74aaab2 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -427,6 +427,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
int freq1 = 0;
switch (convert2width(width)) {
+ case CHAN_WIDTH_5:
+ case CHAN_WIDTH_10:
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
return 0;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index cbad262..288f36b 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -297,7 +297,8 @@ static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
if (wpa_s->driver->send_mlme)
return wpa_s->driver->send_mlme(wpa_s->drv_priv,
data, data_len, noack,
- freq, NULL, 0);
+ freq, NULL, 0,
+ 0 /* TODO: Support configuring channel-width */);
return -1;
}
@@ -379,7 +380,8 @@ static inline int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
if (wpa_s->driver->send_action)
return wpa_s->driver->send_action(wpa_s->drv_priv, freq,
wait, dst, src, bssid,
- data, data_len, no_cck);
+ data, data_len, no_cck,
+ 0 /* TODO: Support specifying channel-width */);
return -1;
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index d6cc099..805a28b 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2118,7 +2118,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
freq->channel, freq->ht_enabled,
vht_freq.vht_enabled,
freq->sec_channel_offset,
- chwidth, seg0, seg1, vht_caps) != 0)
+ chwidth, seg0, seg1, vht_caps, 0) != 0)
return;
*freq = vht_freq;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 506c9f3..98d5f53 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1973,6 +1973,14 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
chantype);
return -EINVAL;
}
+
+ if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
+ chandef->width =
+ nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
+ }
+ pr_err("parse-chandef, ctype: width: %d addr-cwidth: %p\n",
+ chandef->width, info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
+ WARN_ON(chandef->width == 0);
} else if (info->attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
chandef->width =
nla_get_u32(info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
@@ -1986,6 +1994,9 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
info->attrs[NL80211_ATTR_CENTER_FREQ2]);
}
+ pr_err("parse-chandef: width: %d addr-cwidth: %p\n",
+ chandef->width, info->attrs[NL80211_ATTR_CHANNEL_WIDTH]);
+
if (!cfg80211_chandef_valid(chandef)) {
pr_err("parse-chandef: chandef is not valid\n");
return -EINVAL;
_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap