Cumulative patch from commit ea18024d78bde140fb8f74d216d757816bfd6e9b
ea18024 dbus: Add PropertiesChanged signal to Peer object
36716ee P2P: Add a utility function to run a method on every known peer
bf03566 dbus: Remove GroupMember object type and use Peer instead
17a37d7 dbus: Add a Groups property to a Peer object on which it belongs
6f04642 P2P: Add utility functions to get GO/client interface
c6386e5 P2P Add a utility to run a callback on all available groups
8e76f48 P2P: Add a utility function to get the group configuration
37d8a27 TDLS: Clean up add/set peer operations
bcd2baa TDLS: Tear down connection on malformed Setup Confirm
8190540 TDLS: Abort local setup when failing to add STA
1dce7a2 TDLS: Update peer STA as soon as full peer info is available
819c943 TDLS: Remove peer from global peer-list on free
5841958 hostapd: Use channel switch fallback on error
8974620 hostapd: Perform multi-BSS CSA for DFS properly
ccac7c6 hostapd: Make chan_switch command per-interface not per-BSS
6782b68 hostapd: Move CSA parameters to hostapd_data
1de809e eapol_test: Fix -R option to not replace -s option value
3c5d34e Change channel before IBSS associations
ebffdbc nl80211: Refactor mode switch logic
Change-Id: I1cbdc4dce586ec69f693b3b04eb340a5332f6b40
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 4e09fa3..55b7ced 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2175,13 +2175,12 @@
}
-static int hostapd_build_beacon_data(struct hostapd_iface *iface,
+static int hostapd_build_beacon_data(struct hostapd_data *hapd,
struct beacon_data *beacon)
{
struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
struct wpa_driver_ap_params params;
int ret;
- struct hostapd_data *hapd = iface->bss[0];
os_memset(beacon, 0, sizeof(*beacon));
ret = ieee802_11_build_ap_params(hapd, ¶ms);
@@ -2281,13 +2280,13 @@
if (!params->channel) {
/* check if the new channel is supported by hw */
- channel = hostapd_hw_get_channel(hapd, params->freq);
- if (!channel)
- return -1;
- } else {
- channel = params->channel;
+ params->channel = hostapd_hw_get_channel(hapd, params->freq);
}
+ channel = params->channel;
+ if (!channel)
+ return -1;
+
/* if a pointer to old_params is provided we save previous state */
if (old_params) {
old_params->channel = conf->channel;
@@ -2305,14 +2304,15 @@
}
-static int hostapd_fill_csa_settings(struct hostapd_iface *iface,
+static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
struct csa_settings *settings)
{
+ struct hostapd_iface *iface = hapd->iface;
struct hostapd_freq_params old_freq;
int ret;
os_memset(&old_freq, 0, sizeof(old_freq));
- if (!iface || !iface->freq || iface->csa_in_progress)
+ if (!iface || !iface->freq || hapd->csa_in_progress)
return -1;
ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
@@ -2321,7 +2321,7 @@
if (ret)
return ret;
- ret = hostapd_build_beacon_data(iface, &settings->beacon_after);
+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
/* change back the configuration */
hostapd_change_config_freq(iface->bss[0], iface->conf,
@@ -2331,18 +2331,18 @@
return ret;
/* set channel switch parameters for csa ie */
- iface->cs_freq_params = settings->freq_params;
- iface->cs_count = settings->cs_count;
- iface->cs_block_tx = settings->block_tx;
+ hapd->cs_freq_params = settings->freq_params;
+ hapd->cs_count = settings->cs_count;
+ hapd->cs_block_tx = settings->block_tx;
- ret = hostapd_build_beacon_data(iface, &settings->beacon_csa);
+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa);
if (ret) {
free_beacon_data(&settings->beacon_after);
return ret;
}
- settings->counter_offset_beacon = iface->cs_c_off_beacon;
- settings->counter_offset_presp = iface->cs_c_off_proberesp;
+ settings->counter_offset_beacon = hapd->cs_c_off_beacon;
+ settings->counter_offset_presp = hapd->cs_c_off_proberesp;
return 0;
}
@@ -2350,13 +2350,12 @@
void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
{
- os_memset(&hapd->iface->cs_freq_params, 0,
- sizeof(hapd->iface->cs_freq_params));
- hapd->iface->cs_count = 0;
- hapd->iface->cs_block_tx = 0;
- hapd->iface->cs_c_off_beacon = 0;
- hapd->iface->cs_c_off_proberesp = 0;
- hapd->iface->csa_in_progress = 0;
+ os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params));
+ hapd->cs_count = 0;
+ hapd->cs_block_tx = 0;
+ hapd->cs_c_off_beacon = 0;
+ hapd->cs_c_off_proberesp = 0;
+ hapd->csa_in_progress = 0;
}
@@ -2364,7 +2363,7 @@
struct csa_settings *settings)
{
int ret;
- ret = hostapd_fill_csa_settings(hapd->iface, settings);
+ ret = hostapd_fill_csa_settings(hapd, settings);
if (ret)
return ret;
@@ -2378,8 +2377,64 @@
return ret;
}
- hapd->iface->csa_in_progress = 1;
+ hapd->csa_in_progress = 1;
return 0;
}
+
+void
+hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+ const struct hostapd_freq_params *freq_params)
+{
+ int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
+ unsigned int i;
+
+ wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
+
+ if (freq_params->center_freq1)
+ vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
+ if (freq_params->center_freq2)
+ vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
+
+ switch (freq_params->bandwidth) {
+ case 0:
+ case 20:
+ case 40:
+ vht_bw = VHT_CHANWIDTH_USE_HT;
+ break;
+ case 80:
+ if (freq_params->center_freq2)
+ vht_bw = VHT_CHANWIDTH_80P80MHZ;
+ else
+ vht_bw = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 160:
+ vht_bw = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
+ freq_params->bandwidth);
+ break;
+ }
+
+ iface->freq = freq_params->freq;
+ iface->conf->channel = freq_params->channel;
+ iface->conf->secondary_channel = freq_params->sec_channel_offset;
+ iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
+ iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
+ iface->conf->vht_oper_chwidth = vht_bw;
+ iface->conf->ieee80211n = freq_params->ht_enabled;
+ iface->conf->ieee80211ac = freq_params->vht_enabled;
+
+ /*
+ * cs_params must not be cleared earlier because the freq_params
+ * argument may actually point to one of these.
+ */
+ for (i = 0; i < iface->num_bss; i++)
+ hostapd_cleanup_cs_params(iface->bss[i]);
+
+ hostapd_disable_iface(iface);
+ hostapd_enable_iface(iface);
+}
+
#endif /* NEED_AP_MLME */