From: Neo Jou <neojou@xxxxxxxxx> A new hw_mode HOSTAPD_MODE_IEEE80211AG is proposed for ACS to compute 2.4G's and 5G's channels. At before, in hostapd.conf, hw_mode=a is set for 5G only, and hw_mode=g is set for 2.4G only. Also hw_mode=any is special case only with drivers with which offloaded ACS is used. So we would like to suggest a new hw_mode for ACS to compute 2.4G and 5G band both when the driver doesn't support offloaded ACS. In this patch: 1. A new hw_mode, HOSTAPD_MODE_IEEE80211AG is proposed, and conf->hw will be set to this mode when "hw_mode=ag" is set in hostapd.conf. 2. If the driver supports 2.4G (g) and 5G (a) band, then the hw_mode HOSTAPD_MODE_IEEE80211AG is added by wpa_driver_nl80211_postprocess_mode() with all channels/rates which the driver supports in 2.4G and 5G bands. (If this interface only supports 2.4G or 5G single band, not dual band, then this hw mode won't be created for the interface) 3. After ACS process is completed, iface->current_mode will be set again to HOSTAPD_MODE_IEEE80211G or HOSTAPD_MODE_IEEE80211A, depends on the computed ideal channel. This HOSTAPD_MODE_IEEE80211AG is only for ACS, so it fails to intiailize interface when hw_mode=ag and channel is not 0 (not ACS) in hostapd.conf. Signed-off-by: Neo Jou <neojou@xxxxxxxxx> --- hostapd/config_file.c | 2 ++ src/ap/hw_features.c | 24 +++++++++++++ src/common/defs.h | 1 + src/drivers/driver_nl80211_capa.c | 71 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0d340d2..88b5a99 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3112,6 +3112,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; else if (os_strcmp(pos, "any") == 0) conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; + else if (os_strcmp(pos, "ag") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211AG; else { wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'", line, pos); diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index c1f19e2..285ccfe 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -832,6 +832,30 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err) hostapd_hw_get_freq(iface->bss[0], iface->conf->channel), iface->conf->channel); + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AG) { + int i; + enum hostapd_hw_mode target_mode; + + if (iface->conf->channel<=14) + target_mode = HOSTAPD_MODE_IEEE80211G; + else + target_mode = HOSTAPD_MODE_IEEE80211A; + + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = &iface->hw_features[i]; + if (mode->mode == target_mode) { + iface->current_mode = mode; + break; + } + } + + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AG) { + wpa_printf(MSG_ERROR, "ACS error - can not decide A band or G band"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + } + } break; case HOSTAPD_CHAN_ACS: wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); diff --git a/src/common/defs.h b/src/common/defs.h index 4faf1c8..b531bc0 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -349,6 +349,7 @@ enum hostapd_hw_mode { HOSTAPD_MODE_IEEE80211A, HOSTAPD_MODE_IEEE80211AD, HOSTAPD_MODE_IEEE80211ANY, + HOSTAPD_MODE_IEEE80211AG, NUM_HOSTAPD_MODES }; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 8318b10..afc1570 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1743,6 +1743,43 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) return NL_SKIP; } +static int +wpa_driver_nl80211_hw_mode_append(struct hostapd_hw_modes *mode, + struct hostapd_hw_modes *mode11) +{ + struct hostapd_channel_data *new_channels; + int *new_rates; + + if ((mode11->num_channels == 0) || (mode11->num_rates == 0)) { + wpa_printf(MSG_ERROR, "%s: num_channels or num_rates is 0", __func__); + return -1; + } + + new_channels = os_realloc_array(mode->channels, + mode->num_channels + mode11->num_channels, + sizeof(struct hostapd_channel_data)); + if (new_channels == NULL) + return -1; + + memcpy(&new_channels[mode->num_channels], mode11->channels, + mode11->num_channels * sizeof(struct hostapd_channel_data)); + mode->channels = new_channels; + mode->num_channels += mode11->num_channels; + + new_rates = os_realloc_array(mode->rates, mode->num_rates + mode11->num_rates, + sizeof(int)); + if ( new_rates == NULL) { + os_free(mode->channels); + return -1; + } + + memcpy(&new_rates[mode->num_rates], mode11->rates, + mode11->num_rates * sizeof(int)); + mode->rates = new_rates; + mode->num_rates += mode11->num_rates; + + return 0; +} static struct hostapd_hw_modes * wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, @@ -1751,6 +1788,8 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, u16 m; struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; int i, mode11g_idx = -1; + struct hostapd_hw_modes *mode11a = NULL; + int mode11a_idx = -1; /* heuristic to set up modes */ for (m = 0; m < *num_modes; m++) { @@ -1778,6 +1817,8 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, return modes; /* 802.11b already included */ if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) mode11g_idx = m; + if (modes[m].mode == HOSTAPD_MODE_IEEE80211A) + mode11a_idx = m; } if (mode11g_idx < 0) @@ -1832,6 +1873,36 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g " "information"); + if (mode11a_idx < 0) { + wpa_printf(MSG_DEBUG, "nl80211: NO 5G band"); + return modes; /* 5GHz band not supported at all */ + } + + /* add AG mode if 2.4GHz and 5GHz are all supported */ + nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes)); + if (nmodes == NULL) + return modes; /* Could not add 802.11b mode */ + + mode = &nmodes[*num_modes]; + os_memset(mode, 0, sizeof(*mode)); + (*num_modes)++; + modes = nmodes; + mode11g = &modes[mode11g_idx]; + mode11a = &modes[mode11a_idx]; + + mode->mode = HOSTAPD_MODE_IEEE80211AG; + mode->num_channels = 0; + mode->num_rates = 0; + if ((wpa_driver_nl80211_hw_mode_append(mode, mode11g) < 0) || + (wpa_driver_nl80211_hw_mode_append(mode, mode11a) < 0)) { + wpa_printf(MSG_ERROR, "nl80211: Added 802.11a+g failed"); + (*num_modes)--; + return modes; /* Could not add 802.11g mode */ + } + + wpa_printf(MSG_DEBUG, "nl80211: Added 802.11a+g mode based on 802.11g/a " + "information"); + return modes; } -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap