hostapd: update mesh DFS patches and add mesh HE support

Drop outdated and by now broken patchset originally supplied by
Peter Oh in August 2018 but never merged upstream.
Instead add the more promissing rework recently submitted by
Markus Theil who picked up Peter's patchset, fixed and completed it
and added support for HE (802.11ax) in mesh mode.

This is only compile tested and needs some real-life testing.

Fixes: FS#3214
Fixes: 167028b750 ("hostapd: Update to version 2.9 (2019-08-08)")
Fixes: 0a3ec87a66 ("hostapd: update to latest Git hostap_2_9-1238-gdd2daf0848ed")
Fixes: 017320ead3 ("hostapd: bring back mesh patches")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2020-07-23 18:34:00 +01:00
parent 68ac3f2cdd
commit 34705946e2
34 changed files with 1441 additions and 191 deletions

View File

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=hostapd
PKG_RELEASE:=2
PKG_RELEASE:=3
PKG_SOURCE_URL:=http://w1.fi/hostap.git
PKG_SOURCE_PROTO:=git

View File

@ -0,0 +1,196 @@
From 91976250359b263a44861aebe553b20627fe487e Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:17 +0200
Subject: [PATCH 01/19] HE/VHT: fix frequency setup with HE enabled
Some places in the code base were not using the
wrappers like hostapd_set_oper_centr_freq_seg0_idx
and friends. This could lead to errors, for example when
joining 80 MHz mesh networks. Fix this, by enforcing
usage of these wrappers.
wpa_supplicant_conf_ap_ht now checks for HE capability
before dealing with VHT in order for these wrappers to work,
as they first check HE support in the config.
While doing these changes, I've noticed that the extra
channel setup code for mesh networks in wpa_supplicant/mesh.c
should not be necessary anymore and dropped it.
wpa_supplicant_conf_ap_ht should handle this setup already.
Acked-by: John Crispin <john@phrozen.org>
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
src/ap/dfs.c | 8 ++++----
wpa_supplicant/ap.c | 40 +++++++++++++++++++++++-----------------
wpa_supplicant/mesh.c | 24 ------------------------
3 files changed, 27 insertions(+), 45 deletions(-)
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1028,7 +1028,7 @@ static int hostapd_dfs_start_channel_swi
unsigned int i;
int err = 1;
struct hostapd_hw_modes *cmode = iface->current_mode;
- u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
__func__, iface->cac_started ? "yes" : "no",
@@ -1089,8 +1089,8 @@ static int hostapd_dfs_start_channel_swi
"freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel);
- new_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
- iface->conf->vht_oper_chwidth = current_vht_oper_chwidth;
+ new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+ hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
/* Setup CSA request */
os_memset(&csa_settings, 0, sizeof(csa_settings));
@@ -1130,7 +1130,7 @@ static int hostapd_dfs_start_channel_swi
iface->freq = channel->freq;
iface->conf->channel = channel->chan;
iface->conf->secondary_channel = secondary_channel;
- iface->conf->vht_oper_chwidth = new_vht_oper_chwidth;
+ hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
oper_centr_freq_seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -52,6 +52,7 @@ static void wpas_conf_ap_vht(struct wpa_
#ifdef CONFIG_P2P
u8 center_chan = 0;
u8 channel = conf->channel;
+ u8 freq_seg_idx;
#endif /* CONFIG_P2P */
if (!conf->secondary_channel)
@@ -59,19 +60,21 @@ static void wpas_conf_ap_vht(struct wpa_
/* Use the maximum oper channel width if it's given. */
if (ssid->max_oper_chwidth)
- conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+ hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
ieee80211_freq_to_chan(ssid->vht_center_freq2,
- &conf->vht_oper_centr_freq_seg1_idx);
+ &freq_seg_idx);
+ hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx);
if (!ssid->p2p_group) {
if (!ssid->vht_center_freq1 ||
- conf->vht_oper_chwidth == CHANWIDTH_USE_HT)
+ hostapd_get_oper_chwidth(conf) == CHANWIDTH_USE_HT)
goto no_vht;
ieee80211_freq_to_chan(ssid->vht_center_freq1,
- &conf->vht_oper_centr_freq_seg0_idx);
+ &freq_seg_idx);
+ hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx);
wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP",
- conf->vht_oper_centr_freq_seg0_idx);
+ hostapd_get_oper_centr_freq_seg0_idx(conf));
return;
}
@@ -96,14 +99,14 @@ static void wpas_conf_ap_vht(struct wpa_
* try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
* not supported.
*/
- conf->vht_oper_chwidth = CHANWIDTH_160MHZ;
+ hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ);
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
if (center_chan) {
wpa_printf(MSG_DEBUG,
"VHT center channel %u for auto-selected 160 MHz bandwidth",
center_chan);
} else {
- conf->vht_oper_chwidth = CHANWIDTH_80MHZ;
+ hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ);
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
channel);
wpa_printf(MSG_DEBUG,
@@ -115,9 +118,9 @@ static void wpas_conf_ap_vht(struct wpa_
if (!center_chan)
goto no_vht;
- conf->vht_oper_centr_freq_seg0_idx = center_chan;
+ hostapd_set_oper_centr_freq_seg0_idx(conf, center_chan);
wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO",
- conf->vht_oper_centr_freq_seg0_idx);
+ hostapd_get_oper_centr_freq_seg0_idx(conf));
return;
#endif /* CONFIG_P2P */
@@ -125,9 +128,9 @@ no_vht:
wpa_printf(MSG_DEBUG,
"No VHT higher bandwidth support for the selected channel %d",
conf->channel);
- conf->vht_oper_centr_freq_seg0_idx =
- conf->channel + conf->secondary_channel * 2;
- conf->vht_oper_chwidth = CHANWIDTH_USE_HT;
+ hostapd_set_oper_centr_freq_seg0_idx(conf,
+ conf->channel + conf->secondary_channel * 2);
+ hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT);
}
@@ -231,16 +234,19 @@ int wpa_supplicant_conf_ap_ht(struct wpa
HT_CAP_INFO_TX_STBC |
HT_CAP_INFO_MAX_AMSDU_SIZE);
+ /* check this before VHT, because setting oper chan
+ * width and friends is the same call for HE and VHT
+ * and checks if conf->ieee8021ax == 1 */
+ if (mode->he_capab[wpas_mode_to_ieee80211_mode(
+ ssid->mode)].he_supported &&
+ ssid->he)
+ conf->ieee80211ax = 1;
+
if (mode->vht_capab && ssid->vht) {
conf->ieee80211ac = 1;
conf->vht_capab |= mode->vht_capab;
wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
}
-
- if (mode->he_capab[wpas_mode_to_ieee80211_mode(
- ssid->mode)].he_supported &&
- ssid->he)
- conf->ieee80211ax = 1;
}
}
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -333,30 +333,6 @@ static int wpa_supplicant_mesh_init(stru
frequency);
goto out_free;
}
- if (ssid->ht40)
- conf->secondary_channel = ssid->ht40;
- if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
- if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH)
- conf->vht_oper_chwidth = ssid->max_oper_chwidth;
- switch (conf->vht_oper_chwidth) {
- case CHANWIDTH_80MHZ:
- case CHANWIDTH_80P80MHZ:
- ieee80211_freq_to_chan(
- frequency,
- &conf->vht_oper_centr_freq_seg0_idx);
- conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
- break;
- case CHANWIDTH_160MHZ:
- ieee80211_freq_to_chan(
- frequency,
- &conf->vht_oper_centr_freq_seg0_idx);
- conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
- conf->vht_oper_centr_freq_seg0_idx += 40 / 5;
- break;
- }
- ieee80211_freq_to_chan(ssid->vht_center_freq2,
- &conf->vht_oper_centr_freq_seg1_idx);
- }
if (ssid->mesh_basic_rates == NULL) {
/*

View File

@ -0,0 +1,126 @@
From d869c753b79a1423c2bd9b0afdfa0d89d55a930c Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:18 +0200
Subject: [PATCH 02/19] mesh: fix channel init order, disable pri/sec channel
switch
wpa_supplicant_conf_ap_ht has to happen before hostapd_setup_interface
in order for its configuration settings to have effect on interface
configuration.
Disable primary and secondary channel switch because of missing tie
breaking rule/frames in mesh networks. A rather long comment about
this issue is placed in mesh.c in the corresponding place.
In consequence, remove mesh coex test, which contradicts this change.
I was not able to reproduce the memory corruption during
mesh_secure_ocv_mix_legacy, which lead to a revert of a similar patch
in the past.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
tests/hwsim/test_wpas_mesh.py | 50 -----------------------------------
wpa_supplicant/mesh.c | 25 ++++++++++++++++--
2 files changed, 23 insertions(+), 52 deletions(-)
--- a/tests/hwsim/test_wpas_mesh.py
+++ b/tests/hwsim/test_wpas_mesh.py
@@ -933,56 +933,6 @@ def _test_wpas_mesh_open_5ghz(dev, apdev
dev[0].dump_monitor()
dev[1].dump_monitor()
-def test_wpas_mesh_open_5ghz_coex(dev, apdev):
- """Mesh network on 5 GHz band and 20/40 coex change"""
- try:
- _test_wpas_mesh_open_5ghz_coex(dev, apdev)
- finally:
- dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname)
- dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname)
- set_world_reg(apdev0=apdev[0], dev0=dev[0])
- dev[0].flush_scan_cache()
- dev[1].flush_scan_cache()
-
-def _test_wpas_mesh_open_5ghz_coex(dev, apdev):
- check_mesh_support(dev[0])
- subprocess.call(['iw', 'reg', 'set', 'US'])
-
- # Start a 20 MHz BSS on channel 40 that would be the secondary channel of
- # HT40+ mesh on channel 36.
- params = {"ssid": "test-ht40",
- "hw_mode": "a",
- "channel": "40",
- "country_code": "US"}
- hapd = hostapd.add_ap(apdev[0], params)
- bssid = hapd.own_addr()
-
- for i in range(2):
- for j in range(5):
- ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
- if ev is None:
- raise Exception("No regdom change event")
- if "alpha2=US" in ev:
- break
- dev[i].scan_for_bss(bssid, freq=5200)
- add_open_mesh_network(dev[i], freq="5180")
-
- check_mesh_joined_connected(dev)
-
- freq = dev[0].get_status_field("freq")
- if freq != "5200":
- raise Exception("Unexpected STATUS freq=" + freq)
- sig = dev[0].request("SIGNAL_POLL").splitlines()
- if "FREQUENCY=5200" not in sig:
- raise Exception("Unexpected SIGNAL_POLL output: " + str(sig))
-
- hapd.disable()
- dev[0].mesh_group_remove()
- dev[1].mesh_group_remove()
- check_mesh_group_removed(dev[0])
- check_mesh_group_removed(dev[1])
- dev[0].dump_monitor()
- dev[1].dump_monitor()
def test_wpas_mesh_open_ht40(dev, apdev):
"""Mesh and HT40 support difference"""
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -363,6 +363,29 @@ static int wpa_supplicant_mesh_init(stru
conf->basic_rates[rate_len] = -1;
}
+ /* While it can enhance performance to switch the primary channel, which
+ * is also the secondary channel of another network at the same time),
+ * to the other primary channel, problems exist with this in mesh networks.
+ *
+ * Example with problems:
+ * - 3 mesh nodes M1-M3, freq (5200, 5180)
+ * - other node O1, e.g. AP mode, freq (5180, 5200),
+ * Locations: O1 M1 M2 M3
+ *
+ * M3 can only send frames to M1 over M2, no direct connection is possible
+ * Start O1, M1 and M3 first, M1 or O1 will switch channels to align with
+ * each other. M3 does not swap, because M1 or O1 cannot be reached.
+ * M2 is started afterwards and can either connect to M3 or M1 because of
+ * this primary secondary channel switch.
+ *
+ * Solutions: (1) central coordination -> not always possible
+ * (2) disable pri/sec channel switch in mesh networks
+ *
+ * In AP mode, when all nodes can work independently, this poses of course
+ * no problem, therefore disable it only in mesh mode.`*/
+ conf->no_pri_sec_switch = 1;
+ wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+
if (wpa_drv_init_mesh(wpa_s)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
return -1;
@@ -374,8 +397,6 @@ static int wpa_supplicant_mesh_init(stru
return -1;
}
- wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
-
return 0;
out_free:
wpa_supplicant_mesh_deinit(wpa_s);

View File

@ -0,0 +1,102 @@
From 978a59514ccde994b5c06e1cbb49cc8cebe6381c Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:19 +0200
Subject: [PATCH 03/19] wpa_supplicant: handle HT40 and mode downgrade in AP
mode
This patch adds some missing pieces to the interface configuration
of AP/mesh mode in wpa_supplicant.
- check for secondary channel and HT40 capability
- try to downgrade to 11b if 11g is not available
Especially with the HT40 check, this code now performs all settings,
which the deleted/duplicated mesh code did.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/ap.c | 49 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 40 insertions(+), 9 deletions(-)
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -134,6 +134,23 @@ no_vht:
}
+static struct hostapd_hw_modes *wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s,
+ enum hostapd_hw_mode hw_mode)
+{
+ struct hostapd_hw_modes *mode = NULL;
+ int i;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].mode == hw_mode) {
+ mode = &wpa_s->hw.modes[i];
+ break;
+ }
+ }
+
+ return mode;
+}
+
+
int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_config *conf)
@@ -147,9 +164,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa
return -1;
}
- /* TODO: enable HT40 if driver supports it;
- * drop to 11b if driver does not support 11g */
-
/*
* Enable HT20 if the driver supports it, by setting conf->ieee80211n
* and a mask of allowed capabilities within conf->ht_capab.
@@ -158,17 +172,27 @@ int wpa_supplicant_conf_ap_ht(struct wpa
*/
if (wpa_s->hw.modes) {
struct hostapd_hw_modes *mode = NULL;
- int i, no_ht = 0;
+ int no_ht = 0;
wpa_printf(MSG_DEBUG,
"Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)",
ssid->frequency, conf->channel);
- for (i = 0; i < wpa_s->hw.num_modes; i++) {
- if (wpa_s->hw.modes[i].mode == conf->hw_mode) {
- mode = &wpa_s->hw.modes[i];
- break;
- }
+ mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode);
+
+ /* may drop drop to 11b if driver does not support 11g */
+ if (!mode && conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
+ conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
+ wpa_printf(MSG_INFO,
+ "Try downgrade to IEEE 802.11b as 802.11g is not "
+ "supported by the current hardware");
+ mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode);
+ }
+
+ if (!mode) {
+ wpa_printf(MSG_ERROR,
+ "No match between requested and supported hw modes found");
+ return -1;
}
#ifdef CONFIG_HT_OVERRIDES
@@ -193,6 +217,13 @@ int wpa_supplicant_conf_ap_ht(struct wpa
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET),
ssid->ht40);
conf->ieee80211n = 1;
+
+ if (ssid->ht40 &&
+ mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
+ conf->secondary_channel = ssid->ht40;
+ else
+ conf->secondary_channel = 0;
+
#ifdef CONFIG_P2P
if (ssid->p2p_group &&
conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&

View File

@ -0,0 +1,63 @@
From 7f7325dae1d03a3964d4e91940d8369f3fed7b43 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:20 +0200
Subject: [PATCH 04/19] wpa_supplicant: fix frequency config for non p2p vht/he
cases
Fix compile without CONFIG_P2P and only set secondary channel seg idx
if we use a mode supporting a sec channel for vht/he.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/ap.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -52,8 +52,8 @@ static void wpas_conf_ap_vht(struct wpa_
#ifdef CONFIG_P2P
u8 center_chan = 0;
u8 channel = conf->channel;
- u8 freq_seg_idx;
#endif /* CONFIG_P2P */
+ u8 freq_seg_idx;
if (!conf->secondary_channel)
goto no_vht;
@@ -62,24 +62,27 @@ static void wpas_conf_ap_vht(struct wpa_
if (ssid->max_oper_chwidth)
hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
- ieee80211_freq_to_chan(ssid->vht_center_freq2,
- &freq_seg_idx);
- hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx);
-
if (!ssid->p2p_group) {
- if (!ssid->vht_center_freq1 ||
- hostapd_get_oper_chwidth(conf) == CHANWIDTH_USE_HT)
+ if (!ssid->vht_center_freq1)
goto no_vht;
ieee80211_freq_to_chan(ssid->vht_center_freq1,
&freq_seg_idx);
hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx);
- wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP",
- hostapd_get_oper_centr_freq_seg0_idx(conf));
+
+ if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) {
+ ieee80211_freq_to_chan(ssid->vht_center_freq2,
+ &freq_seg_idx);
+ hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx);
+ }
+
+ wpa_printf(MSG_DEBUG, "VHT seg0 index %d and seg1 index %d for AP",
+ hostapd_get_oper_centr_freq_seg0_idx(conf),
+ hostapd_get_oper_centr_freq_seg1_idx(conf));
return;
}
#ifdef CONFIG_P2P
- switch (conf->vht_oper_chwidth) {
+ switch (hostapd_get_oper_chwidth(conf)) {
case CHANWIDTH_80MHZ:
case CHANWIDTH_80P80MHZ:
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);

View File

@ -0,0 +1,25 @@
From ff7fb3fa0831c8521327d777c5607a3b7d8736b8 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:21 +0200
Subject: [PATCH 05/19] wpa_supplicant: enable vht and he in default config
parameters
Enable VHT and HE as default config parameters in order for
wpa_supplicant AP mode to use it, if hw support is given.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/config.c | 2 ++
1 file changed, 2 insertions(+)
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3036,6 +3036,8 @@ void wpa_config_set_network_defaults(str
ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
ssid->ht = 1;
+ ssid->vht = 1;
+ ssid->he = 1;
#ifdef IEEE8021X_EAPOL
ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;

View File

@ -0,0 +1,83 @@
From 6522dcbbcf71abcb80cce84b93b4a9a5cfcd4fca Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:22 +0200
Subject: [PATCH 06/19] hw_features: better debug messages for some error cases
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
src/common/hw_features_common.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -540,13 +540,18 @@ int hostapd_set_freq_params(struct hosta
if (center_segment1 ||
(center_segment0 != 0 &&
5000 + center_segment0 * 5 != data->center_freq1 &&
- 2407 + center_segment0 * 5 != data->center_freq1))
+ 2407 + center_segment0 * 5 != data->center_freq1)) {
+ wpa_printf(MSG_ERROR, "20/40 MHz: center segment 0 (=%i) and center freq 1 (=%i) not in sync",
+ center_segment0, data->center_freq1);
return -1;
+ }
break;
case CHANWIDTH_80P80MHZ:
if (center_segment1 == center_segment0 + 4 ||
- center_segment1 == center_segment0 - 4)
+ center_segment1 == center_segment0 - 4) {
+ wpa_printf(MSG_ERROR, "80+80 MHz: center segment 1 only 20 MHz apart");
return -1;
+ }
data->center_freq2 = 5000 + center_segment1 * 5;
/* fall through */
case CHANWIDTH_80MHZ:
@@ -555,8 +560,10 @@ int hostapd_set_freq_params(struct hosta
center_segment1) ||
(oper_chwidth == CHANWIDTH_80P80MHZ &&
!center_segment1) ||
- !sec_channel_offset)
+ !sec_channel_offset) {
+ wpa_printf(MSG_ERROR, "80/80+80 MHz: center segment 1 wrong or no second channel offset");
return -1;
+ }
if (!center_segment0) {
if (channel <= 48)
center_segment0 = 42;
@@ -582,16 +589,22 @@ int hostapd_set_freq_params(struct hosta
center_segment0 == channel - 2 ||
center_segment0 == channel - 6)
data->center_freq1 = 5000 + center_segment0 * 5;
- else
+ else {
+ wpa_printf(MSG_ERROR, "Wrong coupling between HT and VHT/HE channel setting");
return -1;
+ }
}
break;
case CHANWIDTH_160MHZ:
data->bandwidth = 160;
- if (center_segment1)
+ if (center_segment1) {
+ wpa_printf(MSG_ERROR, "160 MHz: center segment 1 should not be set");
return -1;
- if (!sec_channel_offset)
+ }
+ if (!sec_channel_offset) {
+ wpa_printf(MSG_ERROR, "160 MHz: second channel offset not set");
return -1;
+ }
/*
* Note: HT/VHT config and params are coupled. Check if
* HT40 channel band is in VHT160 channel band configuration.
@@ -605,8 +618,10 @@ int hostapd_set_freq_params(struct hosta
center_segment0 == channel - 10 ||
center_segment0 == channel - 14)
data->center_freq1 = 5000 + center_segment0 * 5;
- else
+ else {
+ wpa_printf(MSG_ERROR, "160 MHz: HT40 channel band is not in 160 MHz band");
return -1;
+ }
break;
}

View File

@ -0,0 +1,27 @@
From 6eacc14904b6f09a1490e697c01adf5dc56c4905 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 13:53:23 +0200
Subject: [PATCH 07/19] dfs: use helper functions for vht/he parameters
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
src/ap/dfs.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -955,10 +955,12 @@ dfs_downgrade_bandwidth(struct hostapd_i
if (*skip_radar) {
*skip_radar = 0;
} else {
- if (iface->conf->vht_oper_chwidth == CHANWIDTH_USE_HT)
+ int oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
+
+ if (oper_chwidth == CHANWIDTH_USE_HT)
break;
*skip_radar = 1;
- iface->conf->vht_oper_chwidth--;
+ hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1);
}
}

View File

@ -1,47 +0,0 @@
From 2564184440d9d6041d11a8c7d50b31368634c3bd Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:40 -0700
Subject: [PATCH] mesh: Apply channel attributes before setup interface
This helps mesh interface initialization with correct channel
parameters.
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
wpa_supplicant/mesh.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -253,7 +253,7 @@ static int wpa_supplicant_mesh_init(stru
struct mesh_conf *mconf;
int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
int rate_len;
- int frequency;
+ int frequency, saved_freq;
if (!wpa_s->conf->user_mpm) {
/* not much for us to do here */
@@ -391,6 +391,13 @@ static int wpa_supplicant_mesh_init(stru
conf->basic_rates[rate_len] = -1;
}
+ /* Handle pri/sec switch frequency within AP configuration parameter
+ * generation without changing the stored network profile in the end. */
+ saved_freq = ssid->frequency;
+ ssid->frequency = frequency;
+ wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+ ssid->frequency = saved_freq;
+
if (wpa_drv_init_mesh(wpa_s)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
return -1;
@@ -402,8 +409,6 @@ static int wpa_supplicant_mesh_init(stru
return -1;
}
- wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
-
return 0;
out_free:
wpa_supplicant_mesh_deinit(wpa_s);

View File

@ -1,7 +1,8 @@
From c05ace7510ead96e72b97ce47b33f7b5865d6d36 Mon Sep 17 00:00:00 2001
From 11e5bbe58eebdb10793eec374b6c8ccc7daf7ec8 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:38 -0700
Subject: [PATCH 1/7] mesh: use setup completion callback to complete mesh join
Date: Tue, 30 Jun 2020 14:18:56 +0200
Subject: [PATCH 08/19] mesh: use setup completion callback to complete mesh
join
mesh join function is the last function to be called during
mesh join process, but it's been called a bit earlier than
@ -16,12 +17,11 @@ The callback will be called by hostapd_setup_interface_complete_sync.
There is possiblity that completing mesh init fails, so add error
handle codes.
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
src/ap/hostapd.c | 11 ++++++++++-
wpa_supplicant/mesh.c | 13 +++++++------
2 files changed, 17 insertions(+), 7 deletions(-)
wpa_supplicant/mesh.c | 12 ++++++++++--
2 files changed, 20 insertions(+), 3 deletions(-)
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@ -39,7 +39,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
+#ifdef CONFIG_MESH
+ if (delay_apply_cfg && !iface->mconf) {
+ if (delay_apply_cfg && iface->mconf == NULL) {
+ wpa_printf(MSG_ERROR, "Error while completing mesh init");
+ goto fail;
+ }
@ -53,51 +53,35 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
if (ret) {
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
- iface->bss[0]->conf->iface);
+ iface->conf ? iface->conf->bss[0]->iface : "N/A");
+ iface->conf ? iface->conf->bss[0]->iface : "N/A");
return -1;
}
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -194,8 +194,9 @@ static int wpas_mesh_init_rsn(struct wpa
@@ -193,7 +193,6 @@ static int wpas_mesh_init_rsn(struct wpa
return !wpa_s->mesh_rsn ? -1 : 0;
}
-static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
+static void wpas_mesh_complete_cb(void *ctx)
{
+ struct wpa_supplicant *wpa_s = ctx;
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
struct wpa_ssid *ssid = wpa_s->current_ssid;
@@ -204,7 +205,7 @@ static int wpas_mesh_complete(struct wpa
if (!params || !ssid || !ifmsh) {
wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
__func__);
- return -1;
+ return;
}
if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
@@ -213,7 +214,7 @@ static int wpas_mesh_complete(struct wpa
"mesh: RSN initialization failed - deinit mesh");
wpa_supplicant_mesh_deinit(wpa_s);
wpa_drv_leave_mesh(wpa_s);
- return -1;
+ return;
}
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
@@ -239,8 +240,6 @@ static int wpas_mesh_complete(struct wpa
if (!ret)
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
-
- return ret;
static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
{
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
@@ -244,6 +243,13 @@ static int wpas_mesh_complete(struct wpa
}
@@ -267,6 +266,7 @@ static int wpa_supplicant_mesh_init(stru
+static void wpas_mesh_complete_cb(void *arg)
+{
+ struct wpa_supplicant *wpa_s = arg;
+ wpas_mesh_complete(wpa_s);
+}
+
+
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
@@ -267,6 +273,7 @@ static int wpa_supplicant_mesh_init(stru
if (!ifmsh)
return -ENOMEM;
@ -105,7 +89,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
ifmsh->drv_flags = wpa_s->drv_flags;
ifmsh->drv_flags2 = wpa_s->drv_flags2;
ifmsh->num_bss = 1;
@@ -285,6 +285,8 @@ static int wpa_supplicant_mesh_init(stru
@@ -285,6 +292,8 @@ static int wpa_supplicant_mesh_init(stru
bss->drv_priv = wpa_s->drv_priv;
bss->iface = ifmsh;
bss->mesh_sta_free_cb = mesh_mpm_free_sta;
@ -114,7 +98,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
frequency = ssid->frequency;
if (frequency != freq->freq &&
frequency == freq->freq + freq->sec_channel_offset * 20) {
@@ -526,7 +528,6 @@ int wpa_supplicant_join_mesh(struct wpa_
@@ -523,7 +532,6 @@ int wpa_supplicant_join_mesh(struct wpa_
goto out;
}

View File

@ -1,7 +1,7 @@
From c56f18380d1d404a2abc0ea5373d294508ef1e54 Mon Sep 17 00:00:00 2001
From 87c5e8883898e7eb8e9637e212350c1925a22654 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:41 -0700
Subject: [PATCH 2/7] mesh: update ssid->frequency as pri/sec channel switch
Date: Tue, 30 Jun 2020 14:18:57 +0200
Subject: [PATCH 09/19] mesh: update ssid->frequency as pri/sec channel switch
ssid->frequency is one of variables used to gets channel
number from given frequency. Leave it as unchanged when
@ -16,7 +16,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -292,6 +292,7 @@ static int wpa_supplicant_mesh_init(stru
@@ -299,6 +299,7 @@ static int wpa_supplicant_mesh_init(stru
frequency == freq->freq + freq->sec_channel_offset * 20) {
wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
frequency = freq->freq;

View File

@ -1,15 +1,16 @@
From 89fa0d75fb1be82330258082ed3d7fd452eb6076 Mon Sep 17 00:00:00 2001
From 8de8cd8380af0c43d4fde67a668d79ef73b26b26 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:45 -0700
Subject: [PATCH 3/7] mesh: Allow DFS channels to be selected if dfs is enabled
Date: Tue, 30 Jun 2020 14:18:58 +0200
Subject: [PATCH 10/19] mesh: Allow DFS channels to be selected if dfs is
enabled
Note: DFS is assumed to be usable if a country code has been set
Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
wpa_supplicant/wpa_supplicant.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
wpa_supplicant/wpa_supplicant.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@ -18,7 +19,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
u32 vht_caps = 0;
int is_24ghz;
+ int dfs_enabled = wpa_s->conf->country[0] &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
freq->freq = ssid->frequency;
@ -61,7 +62,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
}
chwidth = CHANWIDTH_80MHZ;
@@ -2585,10 +2596,11 @@ skip_ht40:
@@ -2585,10 +2596,12 @@ skip_ht40:
if (!chan)
continue;
@ -70,7 +71,8 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
- HOSTAPD_CHAN_RADAR))
+ if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
+ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
+ if (chan->flag & (HOSTAPD_CHAN_RADAR |
+ HOSTAPD_CHAN_NO_IR))
+ if (!dfs_enabled)
+ continue;

View File

@ -1,7 +1,7 @@
From 71e9c65a7c8af90a5fd11072062b596421316452 Mon Sep 17 00:00:00 2001
From af8dcbc87466ed6472850a4f1cfe252652cb3d26 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:46 -0700
Subject: [PATCH 4/7] mesh: do not set offchanok on DFS channels in non-ETSI
Date: Tue, 30 Jun 2020 14:18:59 +0200
Subject: [PATCH 11/19] mesh: do not set offchanok on DFS channels in non-ETSI
mac80211 does not allow mgmt tx to use off channel on
DFS channels in non-ETSI domain, because it will invalidate
@ -12,19 +12,20 @@ in non-ETSI.
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
src/drivers/driver_nl80211.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
src/drivers/driver_nl80211.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -7789,6 +7789,10 @@ static int wpa_driver_nl80211_send_actio
@@ -7788,7 +7788,11 @@ static int wpa_driver_nl80211_send_actio
int ret = -1;
u8 *buf;
struct ieee80211_hdr *hdr;
int offchanok = 1;
+ struct hostapd_hw_modes *modes;
+ int i;
int offchanok = 1;
+ u16 num_modes, flags;
+ u8 dfs_domain;
+ int i;
if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq &&
bss->beacon_set)

View File

@ -1,7 +1,7 @@
From 5913d6e2a741683e7c747c046f72ca790bbe1337 Mon Sep 17 00:00:00 2001
From ab6995f15aae17af93507dd2344615f91672a31a Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:47 -0700
Subject: [PATCH 5/7] mesh: fix channel switch error during CAC
Date: Tue, 30 Jun 2020 14:19:00 +0200
Subject: [PATCH 12/19] mesh: fix channel switch error during CAC
Mesh interface has used its channel parameters that configured
during its initialization even after channel switched due to
@ -11,8 +11,8 @@ when channel's been changed from initial one.
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
wpa_supplicant/mesh.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
wpa_supplicant/mesh.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@ -24,8 +24,8 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
#include "ap/sta_info.h"
#include "ap/hostapd.h"
#include "ap/ieee802_11.h"
@@ -208,6 +209,34 @@ static void wpas_mesh_complete_cb(void *
return;
@@ -206,6 +207,39 @@ static int wpas_mesh_complete(struct wpa
return -1;
}
+ /*
@ -35,6 +35,11 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+ if (ifmsh->freq != params->freq.freq) {
+ wpa_s->assoc_freq = ifmsh->freq;
+ ssid->frequency = ifmsh->freq;
+ struct he_capabilities *he_capab = NULL;
+
+ if (ifmsh->current_mode)
+ he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
+
+ if (hostapd_set_freq_params(&params->freq,
+ ifmsh->conf->hw_mode,
+ ifmsh->freq,
@ -48,11 +53,11 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+ hostapd_get_oper_chwidth(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
+ ifmsh->current_mode->vht_capab,
+ &ifmsh->current_mode->he_capab[IEEE80211_MODE_AP])) {
+ ifmsh->conf->vht_capab,
+ he_capab)) {
+ wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
+ wpa_supplicant_mesh_deinit(wpa_s);
+ return;
+ return -1;
+ }
+ }
+

View File

@ -1,29 +0,0 @@
From 4f4a9b9e2e61fba334a21dadea749e4b440f42e6 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:48 -0700
Subject: [PATCH 6/7] mesh: don't allow pri/sec channel switch
This limitation isn't backed by standard, but it is known that
mesh doesn't have capability to handle 20/40 coex change in
current implementation and it will not able to establish
PLINK when channel switch between primary and secondary happens.
Since it's unknown when we will have the implementation of handling
20/40 coex change for mesh, it'd better to avoid them from happening
until standard based implementation is introduced.
Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
---
wpa_supplicant/mesh.c | 1 +
1 file changed, 1 insertion(+)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -391,6 +391,7 @@ static int wpa_supplicant_mesh_init(stru
conf->basic_rates[rate_len] = -1;
}
+ conf->no_pri_sec_switch = 1;
/* Handle pri/sec switch frequency within AP configuration parameter
* generation without changing the stored network profile in the end. */
saved_freq = ssid->frequency;

View File

@ -1,7 +1,7 @@
From 593602b7f14be5c2695979639764b1c50f01bbec Mon Sep 17 00:00:00 2001
From f1118eca5b1a63a4acb2a11ceea15dc4bc259c77 Mon Sep 17 00:00:00 2001
From: Peter Oh <peter.oh@bowerswilkins.com>
Date: Mon, 27 Aug 2018 14:28:49 -0700
Subject: [PATCH 7/7] mesh: inform kernel driver DFS handler in userspace
Date: Tue, 30 Jun 2020 14:19:01 +0200
Subject: [PATCH 13/19] mesh: inform kernel driver DFS handler in userspace
NL80211_ATTR_HANDLE_DFS is required by kerenel space
to enable DFS channels that indicates DFS handler
@ -26,7 +26,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
struct wpa_driver_set_key_params {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -10051,6 +10051,9 @@ static int nl80211_join_mesh(struct i802
@@ -10070,6 +10070,9 @@ static int nl80211_join_mesh(struct i802
wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
@ -38,7 +38,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
goto fail;
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -314,6 +314,7 @@ static int wpa_supplicant_mesh_init(stru
@@ -355,6 +355,7 @@ static int wpa_supplicant_mesh_init(stru
conf->country[0] = wpa_s->conf->country[0];
conf->country[1] = wpa_s->conf->country[1];
conf->country[2] = ' ';

View File

@ -0,0 +1,158 @@
From 30bdefd7559d57eae8c3c7e6f721ecf7be929bf2 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:02 +0200
Subject: [PATCH 14/19] mesh: fixes for mesh init/deinit
Send mesh group started notification after join completion
callback is called.
Implement outstanding TODO, to leave the mesh network on deinit.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/mesh.c | 32 ++++++++++++++++++++------------
wpa_supplicant/mesh.h | 6 ++++--
wpa_supplicant/wpa_supplicant.c | 8 ++------
3 files changed, 26 insertions(+), 20 deletions(-)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -30,20 +30,20 @@
static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
{
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
+ wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
wpa_s->ifmsh = NULL;
wpa_s->current_ssid = NULL;
os_free(wpa_s->mesh_rsn);
wpa_s->mesh_rsn = NULL;
os_free(wpa_s->mesh_params);
wpa_s->mesh_params = NULL;
- /* TODO: leave mesh (stop beacon). This will happen on link down
- * anyway, so it's not urgent */
+ wpa_supplicant_leave_mesh(wpa_s, false);
}
void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
- struct hostapd_iface *ifmsh)
+ struct hostapd_iface *ifmsh,
+ bool also_clear_hostapd)
{
if (!ifmsh)
return;
@@ -64,8 +64,10 @@ void wpa_supplicant_mesh_iface_deinit(st
}
/* take care of shared data */
- hostapd_interface_deinit(ifmsh);
- hostapd_interface_free(ifmsh);
+ if (also_clear_hostapd) {
+ hostapd_interface_deinit(ifmsh);
+ hostapd_interface_free(ifmsh);
+ }
}
@@ -244,8 +246,7 @@ static int wpas_mesh_complete(struct wpa
wpas_mesh_init_rsn(wpa_s)) {
wpa_printf(MSG_ERROR,
"mesh: RSN initialization failed - deinit mesh");
- wpa_supplicant_mesh_deinit(wpa_s);
- wpa_drv_leave_mesh(wpa_s);
+ wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false);
return -1;
}
@@ -270,9 +271,15 @@ static int wpas_mesh_complete(struct wpa
/* hostapd sets the interface down until we associate */
wpa_drv_set_operstate(wpa_s, 1);
- if (!ret)
+ if (!ret) {
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->id);
+ wpas_notify_mesh_group_started(wpa_s, ssid);
+ }
+
return ret;
}
@@ -563,7 +570,7 @@ int wpa_supplicant_join_mesh(struct wpa_
wpa_s->mesh_params = params;
if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
- wpa_drv_leave_mesh(wpa_s);
+ wpa_supplicant_leave_mesh(wpa_s, true);
ret = -1;
goto out;
}
@@ -573,14 +580,15 @@ out:
}
-int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit)
{
int ret = 0;
wpa_msg(wpa_s, MSG_INFO, "leaving mesh");
/* Need to send peering close messages first */
- wpa_supplicant_mesh_deinit(wpa_s);
+ if (need_deinit)
+ wpa_supplicant_mesh_deinit(wpa_s);
ret = wpa_drv_leave_mesh(wpa_s);
if (ret)
--- a/wpa_supplicant/mesh.h
+++ b/wpa_supplicant/mesh.h
@@ -11,9 +11,11 @@
int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
-int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s,
+ bool need_deinit);
void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
- struct hostapd_iface *ifmsh);
+ struct hostapd_iface *ifmsh,
+ bool also_clear_hostapd);
int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
char *end);
int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2225,10 +2225,6 @@ void wpa_supplicant_associate(struct wpa
return;
}
wpa_s->current_bss = bss;
- wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->id);
- wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
@@ -3938,7 +3934,7 @@ void wpa_supplicant_deauthenticate(struc
wpa_s->ifname);
wpas_notify_mesh_group_removed(wpa_s, mconf->meshid,
mconf->meshid_len, reason_code);
- wpa_supplicant_leave_mesh(wpa_s);
+ wpa_supplicant_leave_mesh(wpa_s, true);
}
#endif /* CONFIG_MESH */
@@ -6551,7 +6547,7 @@ static void wpa_supplicant_deinit_iface(
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
+ wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
wpa_s->ifmsh = NULL;
}
#endif /* CONFIG_MESH */

View File

@ -0,0 +1,262 @@
From d017f5d98a143c46c3c3fcb0e6507ca0b2bebdb0 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:03 +0200
Subject: [PATCH 15/19] mesh: fix DFS deinit/init
The hostapd DFS code deinitializes and initializes the
AP interface, if a clean channel switch is not possible.
In this case the AP code paths would deinit the driver, for
example nl80211, without wpa_supplicant code paths getting
notice of this.
Therefore add callbacks for wpa_supplicant mesh methods,
which are called on init/deinit of the AP bss. These
callbacks are then used to handle the reset in the mesh
code.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
src/ap/dfs.c | 2 +-
src/ap/hostapd.c | 17 ++++++--
src/ap/hostapd.h | 6 +++
wpa_supplicant/mesh.c | 90 +++++++++++++++++++++++++++++++++++++------
4 files changed, 100 insertions(+), 15 deletions(-)
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1112,7 +1112,7 @@ static int hostapd_dfs_start_channel_swi
oper_centr_freq_seg0_idx,
oper_centr_freq_seg1_idx,
cmode->vht_capab,
- &cmode->he_capab[IEEE80211_MODE_AP]);
+ &cmode->he_capab[iface->conf->hw_mode]);
if (err) {
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -354,7 +354,7 @@ static int hostapd_broadcast_wep_set(str
#endif /* CONFIG_WEP */
-static void hostapd_free_hapd_data(struct hostapd_data *hapd)
+void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
os_free(hapd->probereq_cb);
hapd->probereq_cb = NULL;
@@ -498,7 +498,7 @@ static void sta_track_deinit(struct host
}
-static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
+void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
#ifdef NEED_AP_MLME
@@ -626,7 +626,7 @@ static int hostapd_flush_old_stations(st
}
-static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
+void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
{
hostapd_free_stas(hapd);
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
@@ -2690,6 +2690,13 @@ int hostapd_enable_iface(struct hostapd_
{
size_t j;
+ if (hapd_iface == NULL)
+ return -1;
+
+ if (hapd_iface->enable_iface_cb != NULL) {
+ return hapd_iface->enable_iface_cb(hapd_iface);
+ }
+
if (hapd_iface->bss[0]->drv_priv != NULL) {
wpa_printf(MSG_ERROR, "Interface %s already enabled",
hapd_iface->conf->bss[0]->iface);
@@ -2751,6 +2758,10 @@ int hostapd_disable_iface(struct hostapd
if (hapd_iface == NULL)
return -1;
+ if (hapd_iface->disable_iface_cb != NULL) {
+ return hapd_iface->disable_iface_cb(hapd_iface);
+ }
+
if (hapd_iface->bss[0]->drv_priv == NULL) {
wpa_printf(MSG_INFO, "Interface %s already disabled",
hapd_iface->conf->bss[0]->iface);
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -589,6 +589,9 @@ struct hostapd_iface {
/* Previous WMM element information */
struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
};
/* hostapd.c */
@@ -617,6 +620,9 @@ void hostapd_interface_deinit_free(struc
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
+void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
+void hostapd_free_hapd_data(struct hostapd_data *hapd);
+void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -28,15 +28,20 @@
#include "mesh.h"
-static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
+static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, bool also_clear_hostapd)
{
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
- wpa_s->ifmsh = NULL;
- wpa_s->current_ssid = NULL;
+ wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, also_clear_hostapd);
+
+ if (also_clear_hostapd) {
+ wpa_s->ifmsh = NULL;
+ wpa_s->current_ssid = NULL;
+ os_free(wpa_s->mesh_params);
+ wpa_s->mesh_params = NULL;
+ }
+
os_free(wpa_s->mesh_rsn);
wpa_s->mesh_rsn = NULL;
- os_free(wpa_s->mesh_params);
- wpa_s->mesh_params = NULL;
+
wpa_supplicant_leave_mesh(wpa_s, false);
}
@@ -237,7 +242,7 @@ static int wpas_mesh_complete(struct wpa
ifmsh->conf->vht_capab,
he_capab)) {
wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
- wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_supplicant_mesh_deinit(wpa_s, true);
return -1;
}
}
@@ -246,7 +251,7 @@ static int wpas_mesh_complete(struct wpa
wpas_mesh_init_rsn(wpa_s)) {
wpa_printf(MSG_ERROR,
"mesh: RSN initialization failed - deinit mesh");
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false);
+ wpa_supplicant_mesh_deinit(wpa_s, false);
return -1;
}
@@ -291,6 +296,67 @@ static void wpas_mesh_complete_cb(void *
}
+static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
+{
+ struct wpa_supplicant *wpa_s = ifmsh->owner;
+ struct hostapd_data *bss;
+
+ ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
+
+ bss = ifmsh->bss[0];
+ bss->msg_ctx = wpa_s;
+ os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
+ bss->driver = wpa_s->driver;
+ bss->drv_priv = wpa_s->drv_priv;
+ bss->iface = ifmsh;
+ bss->mesh_sta_free_cb = mesh_mpm_free_sta;
+ bss->setup_complete_cb = wpas_mesh_complete_cb;
+ bss->setup_complete_cb_ctx = wpa_s;
+
+ bss->conf->start_disabled = 1;
+ bss->conf->mesh = MESH_ENABLED;
+ bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
+
+ if (wpa_drv_init_mesh(wpa_s)) {
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
+ return -1;
+ }
+
+ if (hostapd_setup_interface(ifmsh)) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize hostapd interface for mesh");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
+{
+ struct wpa_supplicant *wpa_s = ifmsh->owner;
+ int j;
+
+ wpa_supplicant_mesh_deinit(wpa_s, false);
+
+#ifdef NEED_AP_MLME
+ for (j = 0; j < ifmsh->num_bss; j++)
+ hostapd_cleanup_cs_params(ifmsh->bss[j]);
+#endif /* NEED_AP_MLME */
+
+ /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
+ for (j = 0; j < ifmsh->num_bss; j++) {
+ struct hostapd_data *hapd = ifmsh->bss[j];
+ hostapd_bss_deinit_no_free(hapd);
+ hostapd_free_hapd_data(hapd);
+ }
+
+ hostapd_cleanup_iface_partial(ifmsh);
+
+ return 0;
+}
+
+
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
@@ -318,6 +384,8 @@ static int wpa_supplicant_mesh_init(stru
ifmsh->drv_flags = wpa_s->drv_flags;
ifmsh->drv_flags2 = wpa_s->drv_flags2;
ifmsh->num_bss = 1;
+ ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
+ ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
sizeof(struct hostapd_data *));
if (!ifmsh->bss)
@@ -451,7 +519,7 @@ static int wpa_supplicant_mesh_init(stru
return 0;
out_free:
- wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_supplicant_mesh_deinit(wpa_s, true);
return -ENOMEM;
}
@@ -499,7 +567,7 @@ int wpa_supplicant_join_mesh(struct wpa_
goto out;
}
- wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_supplicant_mesh_deinit(wpa_s, true);
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
wpa_s->group_cipher = WPA_CIPHER_NONE;
@@ -588,7 +656,7 @@ int wpa_supplicant_leave_mesh(struct wpa
/* Need to send peering close messages first */
if (need_deinit)
- wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_supplicant_mesh_deinit(wpa_s, true);
ret = wpa_drv_leave_mesh(wpa_s);
if (ret)

View File

@ -0,0 +1,94 @@
From 6ee4e70d469b8ce05013ed524eea32ea303e6563 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:04 +0200
Subject: [PATCH 16/19] tests: DFS test for wpa_supplicant mesh
Add a test with uses a DFS channel, waits for CAC
afterwards successfull mesh join and then triggers
a radar event and check if the mesh comes up again
on the same device.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
tests/hwsim/test_wpas_mesh.py | 56 +++++++++++++++++++++++++++++++++--
1 file changed, 54 insertions(+), 2 deletions(-)
--- a/tests/hwsim/test_wpas_mesh.py
+++ b/tests/hwsim/test_wpas_mesh.py
@@ -80,8 +80,23 @@ def check_mesh_scan(dev, params, other_s
if '[MESH]' not in bss['flags']:
raise Exception("BSS output did not include MESH flag")
-def check_mesh_group_added(dev):
- ev = dev.wait_event(["MESH-GROUP-STARTED"])
+def check_dfs_started(dev, timeout=10):
+ ev = dev.wait_event(["DFS-CAC-START"], timeout=timeout)
+ if ev is None:
+ raise Exception("Test exception: CAC did not start")
+
+def check_dfs_finished(dev, timeout=70):
+ ev = dev.wait_event(["DFS-CAC-COMPLETED"], timeout=timeout)
+ if ev is None:
+ raise Exception("Test exception: CAC did not finish")
+
+def check_mesh_radar_handling_finished(dev, timeout=75):
+ ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH", "MESH-GROUP-STARTED"], timeout=timeout)
+ if ev is None:
+ raise Exception("Test exception: Couldn't join mesh")
+
+def check_mesh_group_added(dev, timeout=10):
+ ev = dev.wait_event(["MESH-GROUP-STARTED"], timeout=timeout)
if ev is None:
raise Exception("Test exception: Couldn't join mesh")
@@ -91,6 +106,10 @@ def check_mesh_group_removed(dev):
if ev is None:
raise Exception("Test exception: Couldn't leave mesh")
+def check_regdom_change(dev, timeout=10):
+ ev = dev.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=timeout)
+ if ev is None:
+ raise Exception("Test exception: No regdom change happened.")
def check_mesh_peer_connected(dev, timeout=10):
ev = dev.wait_event(["MESH-PEER-CONNECTED"], timeout=timeout)
@@ -167,6 +186,39 @@ def test_wpas_mesh_group_remove(dev):
check_mesh_group_removed(dev[0])
dev[0].mesh_group_remove()
+def dfs_simulate_radar(dev):
+ logger.info("Trigger a simulated radar event")
+ phyname = dev.get_driver_status_field("phyname")
+ radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar'
+ with open(radar_file, 'w') as f:
+ f.write('1')
+
+@long_duration_test
+def test_wpas_mesh_peer_connected_dfs(dev):
+ """wpa_supplicant MESH peer connected"""
+ dev[0].set("country", "DE")
+ dev[1].set("country", "DE")
+
+ check_regdom_change(dev[0])
+ check_regdom_change(dev[1])
+
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0], freq="5500", beacon_int=160)
+ add_open_mesh_network(dev[1], freq="5500", beacon_int=160)
+ check_dfs_started(dev[0])
+ check_dfs_finished(dev[0])
+ check_mesh_joined_connected(dev, timeout0=10)
+
+ dfs_simulate_radar(dev[0])
+
+ check_mesh_radar_handling_finished(dev[0], timeout=75)
+
+ dev[0].set("country", "00")
+ dev[1].set("country", "00")
+
+ check_regdom_change(dev[0])
+ check_regdom_change(dev[1])
+
def test_wpas_mesh_peer_connected(dev):
"""wpa_supplicant MESH peer connected"""
check_mesh_support(dev[0])

View File

@ -0,0 +1,24 @@
From 928da9a270deaf4409aee4d87a33a6f61b56c136 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:05 +0200
Subject: [PATCH 17/19] mesh: fix mesh_oom test
Only change freq params, if ifmsh->freq is set initially, which only
happens if hostapd_get_hw_features in setup_interface2 succeeds.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/mesh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -218,7 +218,7 @@ static int wpas_mesh_complete(struct wpa
* inspect if channel's been changed since initialized.
* i.e. DFS radar detection
*/
- if (ifmsh->freq != params->freq.freq) {
+ if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
wpa_s->assoc_freq = ifmsh->freq;
ssid->frequency = ifmsh->freq;
struct he_capabilities *he_capab = NULL;

View File

@ -0,0 +1,93 @@
From 1eab0e62920f443f8814bad846f6439843223b69 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:06 +0200
Subject: [PATCH 18/19] mesh: move mesh freq setting to own function
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
wpa_supplicant/mesh.c | 59 ++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 23 deletions(-)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -201,6 +201,40 @@ static int wpas_mesh_init_rsn(struct wpa
return !wpa_s->mesh_rsn ? -1 : 0;
}
+
+static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+ struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+ struct he_capabilities *he_capab = NULL;
+
+ if (ifmsh->current_mode)
+ he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
+
+ if (hostapd_set_freq_params(&params->freq,
+ ifmsh->conf->hw_mode,
+ ifmsh->freq,
+ ifmsh->conf->channel,
+ ifmsh->conf->enable_edmg,
+ ifmsh->conf->edmg_channel,
+ ifmsh->conf->ieee80211n,
+ ifmsh->conf->ieee80211ac,
+ ifmsh->conf->ieee80211ax,
+ ifmsh->conf->secondary_channel,
+ hostapd_get_oper_chwidth(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
+ ifmsh->conf->vht_capab,
+ he_capab)) {
+ wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
+ wpa_supplicant_mesh_deinit(wpa_s, true);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
{
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
@@ -221,30 +255,8 @@ static int wpas_mesh_complete(struct wpa
if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
wpa_s->assoc_freq = ifmsh->freq;
ssid->frequency = ifmsh->freq;
- struct he_capabilities *he_capab = NULL;
-
- if (ifmsh->current_mode)
- he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
-
- if (hostapd_set_freq_params(&params->freq,
- ifmsh->conf->hw_mode,
- ifmsh->freq,
- ifmsh->conf->channel,
- ifmsh->conf->enable_edmg,
- ifmsh->conf->edmg_channel,
- ifmsh->conf->ieee80211n,
- ifmsh->conf->ieee80211ac,
- ifmsh->conf->ieee80211ax,
- ifmsh->conf->secondary_channel,
- hostapd_get_oper_chwidth(ifmsh->conf),
- hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
- hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
- ifmsh->conf->vht_capab,
- he_capab)) {
- wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
- wpa_supplicant_mesh_deinit(wpa_s, true);
+ if (wpas_mesh_update_freq_params(wpa_s) != 0)
return -1;
- }
}
if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
@@ -518,6 +530,7 @@ static int wpa_supplicant_mesh_init(stru
}
return 0;
+
out_free:
wpa_supplicant_mesh_deinit(wpa_s, true);
return -ENOMEM;

View File

@ -0,0 +1,81 @@
From fc8ea40f6130ac18d9c66797de2cf1d5af55d496 Mon Sep 17 00:00:00 2001
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Tue, 30 Jun 2020 14:19:07 +0200
Subject: [PATCH 19/19] mesh: use deterministic channel on channel switch
This patch uses a deterministic channel on DFS channel switch
in mesh networks. Otherwise, when switching to a usable but not
available channel, no CSA can be sent and a random channel is choosen
without notification of other nodes. It is then quite likely, that
the mesh network gets disconnected.
Fix this by using a deterministic number, based on the sha256 hash
of the mesh ID, in order to use at least a different number in each
mesh network.
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
src/ap/dfs.c | 20 +++++++++++++++++++-
src/drivers/driver_nl80211.c | 4 ++++
2 files changed, 23 insertions(+), 1 deletion(-)
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -17,6 +17,7 @@
#include "ap_drv_ops.h"
#include "drivers/driver.h"
#include "dfs.h"
+#include "crypto/crypto.h"
static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
@@ -480,9 +481,14 @@ dfs_get_valid_channel(struct hostapd_ifa
int num_available_chandefs;
int chan_idx, chan_idx2;
int sec_chan_idx_80p80 = -1;
+ bool is_mesh = false;
int i;
u32 _rand;
+#ifdef CONFIG_MESH
+ is_mesh = iface->mconf;
+#endif
+
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
*secondary_channel = 0;
*oper_centr_freq_seg0_idx = 0;
@@ -502,8 +508,20 @@ dfs_get_valid_channel(struct hostapd_ifa
if (num_available_chandefs == 0)
return NULL;
- if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+ /* try to use deterministic channel in mesh, so that both sides
+ * have a chance to switch to the same channel */
+ if (is_mesh) {
+#ifdef CONFIG_MESH
+ u64 hash[4];
+ const u8 *meshid[1] = { &iface->mconf->meshid[0] };
+ const size_t meshid_len = iface->mconf->meshid_len;
+
+ sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]);
+ _rand = hash[0] + hash[1] + hash[2] + hash[3];
+#endif
+ } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
return NULL;
+
chan_idx = _rand % num_available_chandefs;
dfs_find_channel(iface, &chan, chan_idx, skip_radar);
if (!chan) {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9473,6 +9473,10 @@ static int nl80211_switch_channel(void *
if (ret)
goto error;
+ if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) {
+ nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS);
+ }
+
/* beacon_csa params */
beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
if (!beacon_csa)

View File

@ -59,7 +59,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -10019,6 +10019,9 @@ static int nl80211_put_mesh_config(struc
@@ -10023,6 +10023,9 @@ static int nl80211_put_mesh_config(struc
if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
params->auto_plinks)) ||
@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
{ INT_RANGE(mesh_rssi_threshold, -255, 1) },
#else /* CONFIG_MESH */
{ INT_RANGE(mode, 0, 4) },
@@ -3047,6 +3048,7 @@ void wpa_config_set_network_defaults(str
@@ -3049,6 +3050,7 @@ void wpa_config_set_network_defaults(str
ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
@ -87,7 +87,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
#endif /* CONFIG_MESH */
#ifdef CONFIG_HT_OVERRIDES
@@ -4274,6 +4276,7 @@ struct wpa_config * wpa_config_alloc_emp
@@ -4276,6 +4278,7 @@ struct wpa_config * wpa_config_alloc_emp
config->user_mpm = DEFAULT_USER_MPM;
config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
@ -95,7 +95,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
config->dot11RSNASAERetransPeriod =
DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
config->fast_reauth = DEFAULT_FAST_REAUTH;
@@ -4912,6 +4915,7 @@ static const struct global_parse_data gl
@@ -4914,6 +4917,7 @@ static const struct global_parse_data gl
{ INT(user_mpm), 0 },
{ INT_RANGE(max_peer_links, 0, 255), 0 },
{ INT(mesh_max_inactivity), 0 },
@ -164,7 +164,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -130,6 +130,7 @@ static struct mesh_conf * mesh_config_cr
@@ -137,6 +137,7 @@ static struct mesh_conf * mesh_config_cr
conf->mesh_cc_id = 0;
conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
@ -172,7 +172,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
@@ -335,6 +336,7 @@ static int wpa_supplicant_mesh_init(stru
@@ -434,6 +435,7 @@ static int wpa_supplicant_mesh_init(stru
bss->conf->start_disabled = 1;
bss->conf->mesh = MESH_ENABLED;
bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
@ -180,7 +180,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
@@ -556,6 +558,10 @@ int wpa_supplicant_join_mesh(struct wpa_
@@ -647,6 +649,10 @@ int wpa_supplicant_join_mesh(struct wpa_
}
params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;

View File

@ -253,7 +253,7 @@
struct wpa_supplicant *wpa_s;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -6597,7 +6597,6 @@ struct wpa_interface * wpa_supplicant_ma
@@ -6594,7 +6594,6 @@ struct wpa_interface * wpa_supplicant_ma
return NULL;
}
@ -261,7 +261,7 @@
/**
* wpa_supplicant_match_existing - Match existing interfaces
* @global: Pointer to global data from wpa_supplicant_init()
@@ -6634,6 +6633,11 @@ static int wpa_supplicant_match_existing
@@ -6631,6 +6630,11 @@ static int wpa_supplicant_match_existing
#endif /* CONFIG_MATCH_IFACE */
@ -273,7 +273,7 @@
/**
* wpa_supplicant_add_iface - Add a new network interface
@@ -6890,6 +6894,8 @@ struct wpa_global * wpa_supplicant_init(
@@ -6887,6 +6891,8 @@ struct wpa_global * wpa_supplicant_init(
#ifndef CONFIG_NO_WPA_MSG
wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
#endif /* CONFIG_NO_WPA_MSG */

View File

@ -20,18 +20,18 @@
INT(enable_edmg);
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -368,6 +368,8 @@ static int wpa_supplicant_mesh_init(stru
@@ -467,6 +467,8 @@ static int wpa_supplicant_mesh_init(stru
frequency);
goto out_free;
}
+ if (ssid->noscan)
+ conf->noscan = 1;
if (ssid->ht40)
conf->secondary_channel = ssid->ht40;
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
if (ssid->mesh_basic_rates == NULL) {
/*
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2338,12 +2338,12 @@ void ibss_mesh_setup_freq(struct wpa_sup
@@ -2334,12 +2334,12 @@ void ibss_mesh_setup_freq(struct wpa_sup
int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
enum hostapd_hw_mode hw_mode;
struct hostapd_hw_modes *mode = NULL;
@ -46,7 +46,7 @@
unsigned int j, k;
struct hostapd_freq_params vht_freq;
int chwidth, seg0, seg1;
@@ -2425,7 +2425,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
@@ -2421,7 +2421,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
#endif /* CONFIG_HE_OVERRIDES */
/* Setup higher BW only for 5 GHz */

View File

@ -1,6 +1,6 @@
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4952,7 +4952,7 @@ wpa_supplicant_alloc(struct wpa_supplica
@@ -4949,7 +4949,7 @@ wpa_supplicant_alloc(struct wpa_supplica
if (wpa_s == NULL)
return NULL;
wpa_s->scan_req = INITIAL_SCAN_REQ;

View File

@ -1,6 +1,6 @@
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1426,15 +1426,35 @@ int ap_switch_channel(struct wpa_supplic
@@ -1466,15 +1466,35 @@ int ap_switch_channel(struct wpa_supplic
#ifdef CONFIG_CTRL_IFACE

View File

@ -183,16 +183,16 @@
wpa_s->new_connection = 1;
wpa_drv_set_operstate(wpa_s, 0);
#ifndef IEEE8021X_EAPOL
@@ -2229,6 +2281,8 @@ void wpa_supplicant_associate(struct wpa
wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->id);
wpas_notify_mesh_group_started(wpa_s, ssid);
@@ -2225,6 +2277,8 @@ void wpa_supplicant_associate(struct wpa
return;
}
wpa_s->current_bss = bss;
+ if (wpa_s->hostapd)
+ hostapd_reload(wpa_s, wpa_s->current_bss);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
@@ -6210,6 +6264,16 @@ static int wpa_supplicant_init_iface(str
@@ -6207,6 +6261,16 @@ static int wpa_supplicant_init_iface(str
sizeof(wpa_s->bridge_ifname));
}
@ -209,7 +209,7 @@
/* RSNA Supplicant Key Management - INITIALIZE */
eapol_sm_notify_portEnabled(wpa_s->eapol, false);
eapol_sm_notify_portValid(wpa_s->eapol, false);
@@ -6543,6 +6607,11 @@ static void wpa_supplicant_deinit_iface(
@@ -6540,6 +6604,11 @@ static void wpa_supplicant_deinit_iface(
if (terminate)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);

View File

@ -182,7 +182,7 @@
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1284,7 +1284,7 @@ int wpas_ap_wps_nfc_report_handover(stru
@@ -1324,7 +1324,7 @@ int wpas_ap_wps_nfc_report_handover(stru
#endif /* CONFIG_WPS */

View File

@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
* macsec_policy - Determines the policy for MACsec secure session
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3641,6 +3641,12 @@ static void wpas_start_assoc_cb(struct w
@@ -3638,6 +3638,12 @@ static void wpas_start_assoc_cb(struct w
params.beacon_int = ssid->beacon_int;
else
params.beacon_int = wpa_s->conf->beacon_int;

View File

@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
struct wpa_driver_set_key_params {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -10039,6 +10039,18 @@ static int nl80211_put_mesh_id(struct nl
@@ -10043,6 +10043,18 @@ static int nl80211_put_mesh_id(struct nl
}
@ -48,7 +48,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
static int nl80211_put_mesh_config(struct nl_msg *msg,
struct wpa_driver_mesh_bss_params *params)
{
@@ -10100,6 +10112,7 @@ static int nl80211_join_mesh(struct i802
@@ -10104,6 +10116,7 @@ static int nl80211_join_mesh(struct i802
nl80211_put_basic_rates(msg, params->basic_rates) ||
nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
nl80211_put_beacon_int(msg, params->beacon_int) ||
@ -58,7 +58,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -501,6 +501,7 @@ int wpa_supplicant_join_mesh(struct wpa_
@@ -592,6 +592,7 @@ int wpa_supplicant_join_mesh(struct wpa_
params->meshid = ssid->ssid;
params->meshid_len = ssid->ssid_len;

View File

@ -1,6 +1,6 @@
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2411,11 +2411,13 @@ void ibss_mesh_setup_freq(struct wpa_sup
@@ -2407,11 +2407,13 @@ void ibss_mesh_setup_freq(struct wpa_sup
for (j = 0; j < wpa_s->last_scan_res_used; j++) {
struct wpa_bss *bss = wpa_s->last_scan_res[j];

View File

@ -39,7 +39,7 @@
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
@@ -603,6 +605,7 @@ hostapd_alloc_bss_data(struct hostapd_if
@@ -606,6 +608,7 @@ hostapd_alloc_bss_data(struct hostapd_if
struct hostapd_bss_config *bss);
int hostapd_setup_interface(struct hostapd_iface *iface);
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
@ -49,7 +49,7 @@
struct hostapd_iface * hostapd_alloc_iface(void);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -395,6 +395,7 @@ static void hostapd_free_hapd_data(struc
@@ -395,6 +395,7 @@ void hostapd_free_hapd_data(struct hosta
hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
@ -296,7 +296,7 @@
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -6797,6 +6797,8 @@ struct wpa_supplicant * wpa_supplicant_a
@@ -6794,6 +6794,8 @@ struct wpa_supplicant * wpa_supplicant_a
}
#endif /* CONFIG_P2P */
@ -305,7 +305,7 @@
return wpa_s;
}
@@ -6823,6 +6825,8 @@ int wpa_supplicant_remove_iface(struct w
@@ -6820,6 +6822,8 @@ int wpa_supplicant_remove_iface(struct w
struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
@ -314,7 +314,7 @@
/* Remove interface from the global list of interfaces */
prev = global->ifaces;
if (prev == wpa_s) {
@@ -7126,8 +7130,12 @@ int wpa_supplicant_run(struct wpa_global
@@ -7123,8 +7127,12 @@ int wpa_supplicant_run(struct wpa_global
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);

View File

@ -163,7 +163,7 @@
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
@@ -597,7 +598,7 @@ struct hostapd_iface {
@@ -600,7 +601,7 @@ struct hostapd_iface {
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);