[openwrt/openwrt] hostapd: update mesh DFS patches and add mesh HE support

LEDE Commits lede-commits at lists.infradead.org
Thu Jul 30 12:17:55 EDT 2020


dangole pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/34705946e2e98d96bd3562ea0bd8a34a0aeba456

commit 34705946e2e98d96bd3562ea0bd8a34a0aeba456
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Thu Jul 23 18:34:00 2020 +0100

    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 at makrotopia.org>
---
 package/network/services/hostapd/Makefile          |   2 +-
 ...E-VHT-fix-frequency-setup-with-HE-enabled.patch | 196 +++++++++++++++
 ...annel-init-order-disable-pri-sec-channel-.patch | 126 ++++++++++
 ...ant-handle-HT40-and-mode-downgrade-in-AP-.patch | 102 ++++++++
 ...ant-fix-frequency-config-for-non-p2p-vht-.patch |  63 +++++
 ...ant-enable-vht-and-he-in-default-config-p.patch |  25 ++
 ...-better-debug-messages-for-some-error-cas.patch |  83 +++++++
 ...se-helper-functions-for-vht-he-parameters.patch |  27 +++
 ...ly-channel-attributes-before-running-Mesh.patch |  47 ----
 ...up-completion-callback-to-complete-mesh-.patch} |  68 ++----
 ...ssid-frequency-as-pri-sec-channel-switch.patch} |   8 +-
 ...FS-channels-to-be-selected-if-dfs-is-ena.patch} |  18 +-
 ...set-offchanok-on-DFS-channels-in-non-ETS.patch} |  17 +-
 ...mesh-fix-channel-switch-error-during-CAC.patch} |  25 +-
 ...-mesh-do-not-allow-pri-sec-channel-switch.patch |  29 ---
 ...m-kernel-driver-DFS-handler-in-userspace.patch} |  10 +-
 .../014-mesh-fixes-for-mesh-init-deinit.patch      | 158 +++++++++++++
 .../patches/015-mesh-fix-DFS-deinit-init.patch     | 262 +++++++++++++++++++++
 ...16-tests-DFS-test-for-wpa_supplicant-mesh.patch |  94 ++++++++
 .../patches/017-mesh-fix-mesh_oom-test.patch       |  24 ++
 ...sh-move-mesh-freq-setting-to-own-function.patch |  93 ++++++++
 ...e-deterministic-channel-on-channel-switch.patch |  81 +++++++
 ...=> 050-mesh-make-forwarding-configurable.patch} |  14 +-
 .../services/hostapd/patches/200-multicall.patch   |   6 +-
 .../services/hostapd/patches/301-mesh-noscan.patch |  12 +-
 .../hostapd/patches/310-rescan_immediately.patch   |   2 +-
 .../341-mesh-ctrl-iface-channel-switch.patch       |   2 +-
 .../hostapd/patches/370-ap_sta_support.patch       |  12 +-
 .../patches/380-disable_ctrl_iface_mib.patch       |   2 +-
 ...ant-add-new-config-params-to-be-used-with.patch |   2 +-
 .../patches/463-add-mcast_rate-to-11s.patch        |   6 +-
 .../hostapd/patches/464-fix-mesh-obss-check.patch  |   2 +-
 .../hostapd/patches/600-ubus_support.patch         |  10 +-
 .../services/hostapd/patches/700-wifi-reload.patch |   2 +-
 34 files changed, 1440 insertions(+), 190 deletions(-)

diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile
index d754f19857..91c3876378 100644
--- a/package/network/services/hostapd/Makefile
+++ b/package/network/services/hostapd/Makefile
@@ -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
diff --git a/package/network/services/hostapd/patches/001-HE-VHT-fix-frequency-setup-with-HE-enabled.patch b/package/network/services/hostapd/patches/001-HE-VHT-fix-frequency-setup-with-HE-enabled.patch
new file mode 100644
index 0000000000..37c17c50af
--- /dev/null
+++ b/package/network/services/hostapd/patches/001-HE-VHT-fix-frequency-setup-with-HE-enabled.patch
@@ -0,0 +1,196 @@
+From 91976250359b263a44861aebe553b20627fe487e Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at phrozen.org>
+Signed-off-by: Markus Theil <markus.theil at 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) {
+ 		/*
diff --git a/package/network/services/hostapd/patches/002-mesh-fix-channel-init-order-disable-pri-sec-channel-.patch b/package/network/services/hostapd/patches/002-mesh-fix-channel-init-order-disable-pri-sec-channel-.patch
new file mode 100644
index 0000000000..c7101b1dbc
--- /dev/null
+++ b/package/network/services/hostapd/patches/002-mesh-fix-channel-init-order-disable-pri-sec-channel-.patch
@@ -0,0 +1,126 @@
+From d869c753b79a1423c2bd9b0afdfa0d89d55a930c Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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);
diff --git a/package/network/services/hostapd/patches/003-wpa_supplicant-handle-HT40-and-mode-downgrade-in-AP-.patch b/package/network/services/hostapd/patches/003-wpa_supplicant-handle-HT40-and-mode-downgrade-in-AP-.patch
new file mode 100644
index 0000000000..f42620042d
--- /dev/null
+++ b/package/network/services/hostapd/patches/003-wpa_supplicant-handle-HT40-and-mode-downgrade-in-AP-.patch
@@ -0,0 +1,102 @@
+From 978a59514ccde994b5c06e1cbb49cc8cebe6381c Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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 &&
diff --git a/package/network/services/hostapd/patches/004-wpa_supplicant-fix-frequency-config-for-non-p2p-vht-.patch b/package/network/services/hostapd/patches/004-wpa_supplicant-fix-frequency-config-for-non-p2p-vht-.patch
new file mode 100644
index 0000000000..e8682af644
--- /dev/null
+++ b/package/network/services/hostapd/patches/004-wpa_supplicant-fix-frequency-config-for-non-p2p-vht-.patch
@@ -0,0 +1,63 @@
+From 7f7325dae1d03a3964d4e91940d8369f3fed7b43 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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);
diff --git a/package/network/services/hostapd/patches/005-wpa_supplicant-enable-vht-and-he-in-default-config-p.patch b/package/network/services/hostapd/patches/005-wpa_supplicant-enable-vht-and-he-in-default-config-p.patch
new file mode 100644
index 0000000000..25d74252cd
--- /dev/null
+++ b/package/network/services/hostapd/patches/005-wpa_supplicant-enable-vht-and-he-in-default-config-p.patch
@@ -0,0 +1,25 @@
+From ff7fb3fa0831c8521327d777c5607a3b7d8736b8 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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;
diff --git a/package/network/services/hostapd/patches/006-hw_features-better-debug-messages-for-some-error-cas.patch b/package/network/services/hostapd/patches/006-hw_features-better-debug-messages-for-some-error-cas.patch
new file mode 100644
index 0000000000..31b1ac0d38
--- /dev/null
+++ b/package/network/services/hostapd/patches/006-hw_features-better-debug-messages-for-some-error-cas.patch
@@ -0,0 +1,83 @@
+From 6522dcbbcf71abcb80cce84b93b4a9a5cfcd4fca Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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;
+ 	}
+ 
diff --git a/package/network/services/hostapd/patches/007-dfs-use-helper-functions-for-vht-he-parameters.patch b/package/network/services/hostapd/patches/007-dfs-use-helper-functions-for-vht-he-parameters.patch
new file mode 100644
index 0000000000..3481c52eef
--- /dev/null
+++ b/package/network/services/hostapd/patches/007-dfs-use-helper-functions-for-vht-he-parameters.patch
@@ -0,0 +1,27 @@
+From 6eacc14904b6f09a1490e697c01adf5dc56c4905 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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);
+ 		}
+ 	}
+ 
diff --git a/package/network/services/hostapd/patches/007-mesh-apply-channel-attributes-before-running-Mesh.patch b/package/network/services/hostapd/patches/007-mesh-apply-channel-attributes-before-running-Mesh.patch
deleted file mode 100644
index a0d20023be..0000000000
--- a/package/network/services/hostapd/patches/007-mesh-apply-channel-attributes-before-running-Mesh.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 2564184440d9d6041d11a8c7d50b31368634c3bd Mon Sep 17 00:00:00 2001
-From: Peter Oh <peter.oh at 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 at 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);
diff --git a/package/network/services/hostapd/patches/004-mesh-use-setup-completion-callback-to-complete-mesh-.patch b/package/network/services/hostapd/patches/008-mesh-use-setup-completion-callback-to-complete-mesh-.patch
similarity index 60%
rename from package/network/services/hostapd/patches/004-mesh-use-setup-completion-callback-to-complete-mesh-.patch
rename to package/network/services/hostapd/patches/008-mesh-use-setup-completion-callback-to-complete-mesh-.patch
index 54dea274fa..28c283d035 100644
--- a/package/network/services/hostapd/patches/004-mesh-use-setup-completion-callback-to-complete-mesh-.patch
+++ b/package/network/services/hostapd/patches/008-mesh-use-setup-completion-callback-to-complete-mesh-.patch
@@ -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 at 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 at bowerswilkins.com>
 Signed-off-by: Peter Oh <peter.oh at 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 at 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 at 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)
+-
+ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
  {
-+	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;
+@@ -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 at 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 at 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;
  	}
  
diff --git a/package/network/services/hostapd/patches/005-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch b/package/network/services/hostapd/patches/009-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch
similarity index 75%
rename from package/network/services/hostapd/patches/005-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch
rename to package/network/services/hostapd/patches/009-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch
index 1167982ba5..b48de67636 100644
--- a/package/network/services/hostapd/patches/005-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch
+++ b/package/network/services/hostapd/patches/009-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch
@@ -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 at 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 at 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;
diff --git a/package/network/services/hostapd/patches/011-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch b/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
similarity index 81%
rename from package/network/services/hostapd/patches/011-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
rename to package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
index 3a9b847171..8afeba93ed 100644
--- a/package/network/services/hostapd/patches/011-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
+++ b/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
@@ -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 at 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 at sipsolutions.net>
 Signed-off-by: Peter Oh <peter.oh at 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 at 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 at 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 at 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;
  
diff --git a/package/network/services/hostapd/patches/015-mesh-do-not-use-offchan-mgmt-tx-on-DFS.patch b/package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch
similarity index 79%
rename from package/network/services/hostapd/patches/015-mesh-do-not-use-offchan-mgmt-tx-on-DFS.patch
rename to package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch
index 7c6f249a0b..d491f7c4bc 100644
--- a/package/network/services/hostapd/patches/015-mesh-do-not-use-offchan-mgmt-tx-on-DFS.patch
+++ b/package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch
@@ -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 at 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 at 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)
diff --git a/package/network/services/hostapd/patches/016-mesh-fix-channel-switch-error-during-CAC.patch b/package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch
similarity index 74%
rename from package/network/services/hostapd/patches/016-mesh-fix-channel-switch-error-during-CAC.patch
rename to package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch
index 6b52abf988..f324d81ae3 100644
--- a/package/network/services/hostapd/patches/016-mesh-fix-channel-switch-error-during-CAC.patch
+++ b/package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch
@@ -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 at 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 at 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 at 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 at 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 at 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;
 +		}
 +	}
 +
diff --git a/package/network/services/hostapd/patches/013-mesh-do-not-allow-pri-sec-channel-switch.patch b/package/network/services/hostapd/patches/013-mesh-do-not-allow-pri-sec-channel-switch.patch
deleted file mode 100644
index 45c18fb3b6..0000000000
--- a/package/network/services/hostapd/patches/013-mesh-do-not-allow-pri-sec-channel-switch.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 4f4a9b9e2e61fba334a21dadea749e4b440f42e6 Mon Sep 17 00:00:00 2001
-From: Peter Oh <peter.oh at 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 at 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;
diff --git a/package/network/services/hostapd/patches/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch b/package/network/services/hostapd/patches/013-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch
similarity index 80%
rename from package/network/services/hostapd/patches/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch
rename to package/network/services/hostapd/patches/013-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch
index 2ca15e5d1e..fb4e68636e 100644
--- a/package/network/services/hostapd/patches/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch
+++ b/package/network/services/hostapd/patches/013-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch
@@ -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 at 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 at 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 at 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] = ' ';
diff --git a/package/network/services/hostapd/patches/014-mesh-fixes-for-mesh-init-deinit.patch b/package/network/services/hostapd/patches/014-mesh-fixes-for-mesh-init-deinit.patch
new file mode 100644
index 0000000000..fe12d401e4
--- /dev/null
+++ b/package/network/services/hostapd/patches/014-mesh-fixes-for-mesh-init-deinit.patch
@@ -0,0 +1,158 @@
+From 30bdefd7559d57eae8c3c7e6f721ecf7be929bf2 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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 */
diff --git a/package/network/services/hostapd/patches/015-mesh-fix-DFS-deinit-init.patch b/package/network/services/hostapd/patches/015-mesh-fix-DFS-deinit-init.patch
new file mode 100644
index 0000000000..c540dd6786
--- /dev/null
+++ b/package/network/services/hostapd/patches/015-mesh-fix-DFS-deinit-init.patch
@@ -0,0 +1,262 @@
+From d017f5d98a143c46c3c3fcb0e6507ca0b2bebdb0 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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)
diff --git a/package/network/services/hostapd/patches/016-tests-DFS-test-for-wpa_supplicant-mesh.patch b/package/network/services/hostapd/patches/016-tests-DFS-test-for-wpa_supplicant-mesh.patch
new file mode 100644
index 0000000000..b6a51b2f35
--- /dev/null
+++ b/package/network/services/hostapd/patches/016-tests-DFS-test-for-wpa_supplicant-mesh.patch
@@ -0,0 +1,94 @@
+From 6ee4e70d469b8ce05013ed524eea32ea303e6563 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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')
++
++ at 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])
diff --git a/package/network/services/hostapd/patches/017-mesh-fix-mesh_oom-test.patch b/package/network/services/hostapd/patches/017-mesh-fix-mesh_oom-test.patch
new file mode 100644
index 0000000000..cc566c7de2
--- /dev/null
+++ b/package/network/services/hostapd/patches/017-mesh-fix-mesh_oom-test.patch
@@ -0,0 +1,24 @@
+From 928da9a270deaf4409aee4d87a33a6f61b56c136 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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;
diff --git a/package/network/services/hostapd/patches/018-mesh-move-mesh-freq-setting-to-own-function.patch b/package/network/services/hostapd/patches/018-mesh-move-mesh-freq-setting-to-own-function.patch
new file mode 100644
index 0000000000..1dd7d37411
--- /dev/null
+++ b/package/network/services/hostapd/patches/018-mesh-move-mesh-freq-setting-to-own-function.patch
@@ -0,0 +1,93 @@
+From 1eab0e62920f443f8814bad846f6439843223b69 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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;
diff --git a/package/network/services/hostapd/patches/019-mesh-use-deterministic-channel-on-channel-switch.patch b/package/network/services/hostapd/patches/019-mesh-use-deterministic-channel-on-channel-switch.patch
new file mode 100644
index 0000000000..8e38a8e53c
--- /dev/null
+++ b/package/network/services/hostapd/patches/019-mesh-use-deterministic-channel-on-channel-switch.patch
@@ -0,0 +1,81 @@
+From fc8ea40f6130ac18d9c66797de2cf1d5af55d496 Mon Sep 17 00:00:00 2001
+From: Markus Theil <markus.theil at 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 at 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)
diff --git a/package/network/services/hostapd/patches/018-mesh-make-forwarding-configurable.patch b/package/network/services/hostapd/patches/050-mesh-make-forwarding-configurable.patch
similarity index 94%
rename from package/network/services/hostapd/patches/018-mesh-make-forwarding-configurable.patch
rename to package/network/services/hostapd/patches/050-mesh-make-forwarding-configurable.patch
index 0bdc4cc154..0ecb9ba078 100644
--- a/package/network/services/hostapd/patches/018-mesh-make-forwarding-configurable.patch
+++ b/package/network/services/hostapd/patches/050-mesh-make-forwarding-configurable.patch
@@ -59,7 +59,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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 at 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 at 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 at 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 at 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 at 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;
  
diff --git a/package/network/services/hostapd/patches/200-multicall.patch b/package/network/services/hostapd/patches/200-multicall.patch
index 0b371afe3e..9119a24c55 100644
--- a/package/network/services/hostapd/patches/200-multicall.patch
+++ b/package/network/services/hostapd/patches/200-multicall.patch
@@ -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 */
diff --git a/package/network/services/hostapd/patches/301-mesh-noscan.patch b/package/network/services/hostapd/patches/301-mesh-noscan.patch
index fac9bffabd..f85b72453e 100644
--- a/package/network/services/hostapd/patches/301-mesh-noscan.patch
+++ b/package/network/services/hostapd/patches/301-mesh-noscan.patch
@@ -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 */
diff --git a/package/network/services/hostapd/patches/310-rescan_immediately.patch b/package/network/services/hostapd/patches/310-rescan_immediately.patch
index be2be615e3..0040b61c6b 100644
--- a/package/network/services/hostapd/patches/310-rescan_immediately.patch
+++ b/package/network/services/hostapd/patches/310-rescan_immediately.patch
@@ -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;
diff --git a/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch b/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
index a1e59cc95d..90fa5eff5d 100644
--- a/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
+++ b/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
@@ -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
diff --git a/package/network/services/hostapd/patches/370-ap_sta_support.patch b/package/network/services/hostapd/patches/370-ap_sta_support.patch
index f96017de2e..1c5f72ddc0 100644
--- a/package/network/services/hostapd/patches/370-ap_sta_support.patch
+++ b/package/network/services/hostapd/patches/370-ap_sta_support.patch
@@ -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);
  
diff --git a/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch b/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
index cd4a2c9f14..b98b2d0cba 100644
--- a/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
+++ b/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
@@ -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 */
  
  
diff --git a/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch b/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
index 0a16af3099..99c552821b 100644
--- a/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
+++ b/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
@@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli <ordex at 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;
diff --git a/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
index 5bb0142341..33ef097e75 100644
--- a/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
+++ b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
@@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich at 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 at 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 at 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;
diff --git a/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch b/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
index 5f1f8e3d82..6d48175163 100644
--- a/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
+++ b/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
@@ -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];
  
diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch
index f0a637e4b6..938840755a 100644
--- a/package/network/services/hostapd/patches/600-ubus_support.patch
+++ b/package/network/services/hostapd/patches/600-ubus_support.patch
@@ -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);
  
diff --git a/package/network/services/hostapd/patches/700-wifi-reload.patch b/package/network/services/hostapd/patches/700-wifi-reload.patch
index 8949789204..4acf4aaa06 100644
--- a/package/network/services/hostapd/patches/700-wifi-reload.patch
+++ b/package/network/services/hostapd/patches/700-wifi-reload.patch
@@ -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);



More information about the lede-commits mailing list