Skip to content

Commit

Permalink
hostapd: update mesh DFS patches and add mesh HE support
Browse files Browse the repository at this point in the history
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: 167028b ("hostapd: Update to version 2.9 (2019-08-08)")
Fixes: 0a3ec87 ("hostapd: update to latest Git hostap_2_9-1238-gdd2daf0848ed")
Fixes: 017320e ("hostapd: bring back mesh patches")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
  • Loading branch information
dangowrt committed Jul 30, 2020
1 parent 68ac3f2 commit 3470594
Show file tree
Hide file tree
Showing 34 changed files with 1,440 additions and 190 deletions.
2 changes: 1 addition & 1 deletion package/network/services/hostapd/Makefile
Expand Up @@ -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
Expand Down
@@ -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) {
/*
@@ -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);

0 comments on commit 3470594

Please sign in to comment.