[PATCH] ACS: cover not-offloaded-ACS with hw_mode=any

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Neo Jou <neojou@xxxxxxxxx>

This patch is to extend the existing hw_mode=any to cover
the not-offloaded-ACS case.

In wpa_driver_nl80211_postprocess_modes, the approach, similar
to the one for 80211.b is used for the mode
HOSTAPD_MODE_IEEE80211ANY. it is for hostapd_select_hw_mode()
to get the support configured mode.

And after ACS computed, the current_mode is changed back to B/G/A/AD,
depends on the frequency ACS decided.

By this way, "hw_mode=any" can be used for not-offloaded-ACS case.

Signed-off-by: Neo Jou <neojou@xxxxxxxxx>
---
 src/ap/hw_features.c              | 35 +++++++++++++++++++++++++++++
 src/drivers/driver_nl80211_capa.c | 47 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index ba10752..2db65c5 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -963,6 +963,39 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err)
 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
 			ACS_EVENT_COMPLETED "freq=%d channel=%d",
 			iface->freq, iface->conf->channel);
+
+		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211ANY) {
+			int i;
+			enum hostapd_hw_mode target_mode;
+
+			if (iface->freq < 4000) {
+				target_mode = HOSTAPD_MODE_IEEE80211B;
+				for (i = 0; i < iface->current_mode->num_rates; i++) {
+					if (iface->current_mode->rates[i] > 200) {
+						target_mode = HOSTAPD_MODE_IEEE80211G;
+						break;
+					}
+				}
+			} else if (iface->freq > 50000)
+				target_mode = HOSTAPD_MODE_IEEE80211AD;
+			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_IEEE80211ANY) {
+				wpa_printf(MSG_ERROR, "ACS error - cannot decide 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");
@@ -1070,6 +1103,8 @@ const char * hostapd_hw_mode_txt(int mode)
 		return "IEEE 802.11g";
 	case HOSTAPD_MODE_IEEE80211AD:
 		return "IEEE 802.11ad";
+	case HOSTAPD_MODE_IEEE80211ANY:
+		return "IEEE 802.11any";
 	default:
 		return "UNKNOWN";
 	}
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index e1cf9f7..908d1fd 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1808,6 +1808,53 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
 			modes[m].mode = HOSTAPD_MODE_IEEE80211A;
 	}
 
+	/* Add HOSTAPD_MODE_IEEE80211ANY */
+	nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
+	if (nmodes == NULL)
+		return modes; /* Could not add mode ANY */
+
+	mode = &nmodes[*num_modes];
+	os_memset(mode, 0, sizeof(*mode));
+	modes = nmodes;
+	mode->mode = HOSTAPD_MODE_IEEE80211ANY;
+
+	for (m = 0; m < *num_modes; m++) {
+		struct hostapd_channel_data *m_channels;
+		int *m_rates;
+
+		if (!modes[m].num_channels)
+			continue;
+
+		/* add channels */
+		m_channels = os_realloc_array(mode->channels,
+						  mode->num_channels + modes[m].num_channels,
+						  sizeof(struct hostapd_channel_data));
+		if (m_channels == NULL)
+			return modes;
+
+		mode->channels = m_channels;
+
+		memcpy(&(mode->channels[mode->num_channels]),
+		       modes[m].channels,
+		       modes[m].num_channels * sizeof(struct hostapd_channel_data));
+
+		mode->num_channels += modes[m].num_channels;
+
+		/* add rates */
+		m_rates = os_realloc_array(mode->rates,
+					   mode->num_rates + modes[m].num_rates,
+					   sizeof(int));
+		if (m_rates == NULL)
+			return modes;
+		mode->rates = m_rates;
+		memcpy(&(mode->rates[mode->num_rates]),
+		       modes[m].rates,
+		       modes[m].num_rates * sizeof(int));
+		mode->num_rates += modes[m].num_rates;
+	}
+
+	(*num_modes)++;
+
 	/* If only 802.11g mode is included, use it to construct matching
 	 * 802.11b mode data. */
 
-- 
2.7.4


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux