From: Daniel Golle Date: Thu, 23 Jul 2020 17:34:00 +0000 (+0100) Subject: hostapd: update mesh DFS patches and add mesh HE support X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=34705946e2e98d96bd3562ea0bd8a34a0aeba456;p=openwrt%2Fstaging%2Fnbd.git 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 --- 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 +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 +Signed-off-by: Markus Theil +--- + 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 +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 +--- + 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 +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 +--- + 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-mesh-use-setup-completion-callback-to-complete-mesh-.patch b/package/network/services/hostapd/patches/004-mesh-use-setup-completion-callback-to-complete-mesh-.patch deleted file mode 100644 index 54dea274fa..0000000000 --- a/package/network/services/hostapd/patches/004-mesh-use-setup-completion-callback-to-complete-mesh-.patch +++ /dev/null @@ -1,124 +0,0 @@ -From c05ace7510ead96e72b97ce47b33f7b5865d6d36 Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:38 -0700 -Subject: [PATCH 1/7] 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 -it's supposed to be, so that some mesh parameter values -such as VHT capabilities not applied correct when mesh join -is in process. -Moreover current design of mesh join that is called directly -after mesh initialization isn't suitable for DFS channels to use, -since mesh join process should be paused until DFS CAC is -done and resumed after it's done. -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 -Signed-off-by: Peter Oh ---- - src/ap/hostapd.c | 11 ++++++++++- - wpa_supplicant/mesh.c | 13 +++++++------ - 2 files changed, 17 insertions(+), 7 deletions(-) - ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -434,6 +434,8 @@ static void hostapd_free_hapd_data(struc - #ifdef CONFIG_MESH - wpabuf_free(hapd->mesh_pending_auth); - hapd->mesh_pending_auth = NULL; -+ /* handling setup failure is already done */ -+ hapd->setup_complete_cb = NULL; - #endif /* CONFIG_MESH */ - - hostapd_clean_rrm(hapd); -@@ -2156,6 +2158,13 @@ dfs_offload: - if (hapd->setup_complete_cb) - hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); - -+#ifdef CONFIG_MESH -+ if (delay_apply_cfg && !iface->mconf) { -+ wpa_printf(MSG_ERROR, "Error while completing mesh init"); -+ goto fail; -+ } -+#endif /* CONFIG_MESH */ -+ - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); - if (iface->interfaces && iface->interfaces->terminate_on_error > 0) -@@ -2299,7 +2308,7 @@ int hostapd_setup_interface(struct hosta - ret = setup_interface(iface); - 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"); - return -1; - } - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -194,8 +194,9 @@ static int wpas_mesh_init_rsn(struct wpa - } - - --static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) -+static void wpas_mesh_complete_cb(void *ctx) - { -+ struct wpa_supplicant *wpa_s = ctx; - struct hostapd_iface *ifmsh = wpa_s->ifmsh; - struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params; - struct wpa_ssid *ssid = wpa_s->current_ssid; -@@ -204,7 +205,7 @@ static int wpas_mesh_complete(struct wpa - if (!params || !ssid || !ifmsh) { - wpa_printf(MSG_ERROR, "mesh: %s called without active mesh", - __func__); -- return -1; -+ return; - } - - if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && -@@ -213,7 +214,7 @@ static int wpas_mesh_complete(struct wpa - "mesh: RSN initialization failed - deinit mesh"); - wpa_supplicant_mesh_deinit(wpa_s); - wpa_drv_leave_mesh(wpa_s); -- return -1; -+ return; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { -@@ -239,8 +240,6 @@ static int wpas_mesh_complete(struct wpa - - if (!ret) - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); -- -- return ret; - } - - -@@ -267,6 +266,7 @@ static int wpa_supplicant_mesh_init(stru - if (!ifmsh) - return -ENOMEM; - -+ ifmsh->owner = wpa_s; - 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 - 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; - 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_ - goto out; - } - -- ret = wpas_mesh_complete(wpa_s); - out: - return ret; - } 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 +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 +--- + 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-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch b/package/network/services/hostapd/patches/005-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch deleted file mode 100644 index 1167982ba5..0000000000 --- a/package/network/services/hostapd/patches/005-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch +++ /dev/null @@ -1,26 +0,0 @@ -From c56f18380d1d404a2abc0ea5373d294508ef1e54 Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:41 -0700 -Subject: [PATCH 2/7] 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 -pri/sec channel switched will cause picking up wrong -channel number after applying secondary channel offset -for HT40 and leads failing interface bring-up. - -Signed-off-by: Peter Oh ---- - wpa_supplicant/mesh.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -292,6 +292,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; -+ ssid->frequency = frequency; - } - wpa_s->assoc_freq = frequency; - wpa_s->current_ssid = ssid; 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 +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 +--- + 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 +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 +--- + 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/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch b/package/network/services/hostapd/patches/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch deleted file mode 100644 index 2ca15e5d1e..0000000000 --- a/package/network/services/hostapd/patches/006-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 593602b7f14be5c2695979639764b1c50f01bbec Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:49 -0700 -Subject: [PATCH 7/7] 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 -resides in userspace. - -Signed-off-by: Peter Oh ---- - src/drivers/driver.h | 1 + - src/drivers/driver_nl80211.c | 3 +++ - wpa_supplicant/mesh.c | 1 + - 3 files changed, 5 insertions(+) - ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1542,6 +1542,7 @@ struct wpa_driver_mesh_join_params { - #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004 - #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 - unsigned int flags; -+ u8 handle_dfs; - }; - - 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 - - wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); - -+ if (params->handle_dfs) -+ if (nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS)) -+ goto fail; - container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP); - if (!container) - goto fail; ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -314,6 +314,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] = ' '; -+ wpa_s->mesh_params->handle_dfs = 1; - } - - bss->iconf = conf; 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 +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 +--- + 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 -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 ---- - 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/008-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 new file mode 100644 index 0000000000..28c283d035 --- /dev/null +++ b/package/network/services/hostapd/patches/008-mesh-use-setup-completion-callback-to-complete-mesh-.patch @@ -0,0 +1,108 @@ +From 11e5bbe58eebdb10793eec374b6c8ccc7daf7ec8 Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +it's supposed to be, so that some mesh parameter values +such as VHT capabilities not applied correct when mesh join +is in process. +Moreover current design of mesh join that is called directly +after mesh initialization isn't suitable for DFS channels to use, +since mesh join process should be paused until DFS CAC is +done and resumed after it's done. +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 +--- + src/ap/hostapd.c | 11 ++++++++++- + wpa_supplicant/mesh.c | 12 ++++++++++-- + 2 files changed, 20 insertions(+), 3 deletions(-) + +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -434,6 +434,8 @@ static void hostapd_free_hapd_data(struc + #ifdef CONFIG_MESH + wpabuf_free(hapd->mesh_pending_auth); + hapd->mesh_pending_auth = NULL; ++ /* handling setup failure is already done */ ++ hapd->setup_complete_cb = NULL; + #endif /* CONFIG_MESH */ + + hostapd_clean_rrm(hapd); +@@ -2156,6 +2158,13 @@ dfs_offload: + if (hapd->setup_complete_cb) + hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); + ++#ifdef CONFIG_MESH ++ if (delay_apply_cfg && iface->mconf == NULL) { ++ wpa_printf(MSG_ERROR, "Error while completing mesh init"); ++ goto fail; ++ } ++#endif /* CONFIG_MESH */ ++ + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", + iface->bss[0]->conf->iface); + if (iface->interfaces && iface->interfaces->terminate_on_error > 0) +@@ -2299,7 +2308,7 @@ int hostapd_setup_interface(struct hosta + ret = setup_interface(iface); + 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"); + return -1; + } + +--- a/wpa_supplicant/mesh.c ++++ b/wpa_supplicant/mesh.c +@@ -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) + { + struct hostapd_iface *ifmsh = wpa_s->ifmsh; +@@ -244,6 +243,13 @@ static int wpas_mesh_complete(struct wpa + } + + ++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; + ++ ifmsh->owner = wpa_s; + ifmsh->drv_flags = wpa_s->drv_flags; + ifmsh->drv_flags2 = wpa_s->drv_flags2; + ifmsh->num_bss = 1; +@@ -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; ++ bss->setup_complete_cb = wpas_mesh_complete_cb; ++ bss->setup_complete_cb_ctx = wpa_s; + frequency = ssid->frequency; + if (frequency != freq->freq && + frequency == freq->freq + freq->sec_channel_offset * 20) { +@@ -523,7 +532,6 @@ int wpa_supplicant_join_mesh(struct wpa_ + goto out; + } + +- ret = wpas_mesh_complete(wpa_s); + out: + return ret; + } diff --git a/package/network/services/hostapd/patches/009-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 new file mode 100644 index 0000000000..b48de67636 --- /dev/null +++ b/package/network/services/hostapd/patches/009-mesh-update-ssid-frequency-as-pri-sec-channel-switch.patch @@ -0,0 +1,26 @@ +From 87c5e8883898e7eb8e9637e212350c1925a22654 Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +pri/sec channel switched will cause picking up wrong +channel number after applying secondary channel offset +for HT40 and leads failing interface bring-up. + +Signed-off-by: Peter Oh +--- + wpa_supplicant/mesh.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/wpa_supplicant/mesh.c ++++ b/wpa_supplicant/mesh.c +@@ -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; ++ ssid->frequency = frequency; + } + wpa_s->assoc_freq = frequency; + wpa_s->current_ssid = ssid; diff --git a/package/network/services/hostapd/patches/010-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 new file mode 100644 index 0000000000..8afeba93ed --- /dev/null +++ b/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch @@ -0,0 +1,80 @@ +From 8de8cd8380af0c43d4fde67a668d79ef73b26b26 Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +Signed-off-by: Peter Oh +--- + 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 +@@ -2349,6 +2349,8 @@ void ibss_mesh_setup_freq(struct wpa_sup + int chwidth, seg0, seg1; + u32 vht_caps = 0; + int is_24ghz; ++ int dfs_enabled = wpa_s->conf->country[0] && ++ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR); + + freq->freq = ssid->frequency; + +@@ -2436,8 +2438,11 @@ void ibss_mesh_setup_freq(struct wpa_sup + return; + + /* Check primary channel flags */ +- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) ++ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED) + return; ++ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) ++ if (!dfs_enabled) ++ return; + + freq->channel = pri_chan->chan; + +@@ -2470,8 +2475,11 @@ void ibss_mesh_setup_freq(struct wpa_sup + return; + + /* Check secondary channel flags */ +- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) ++ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED) + return; ++ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) ++ if (!dfs_enabled) ++ return; + + if (ht40 == -1) { + if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS)) +@@ -2564,8 +2572,11 @@ skip_ht40: + return; + + /* Back to HT configuration if channel not usable */ +- if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) ++ if (chan->flag & HOSTAPD_CHAN_DISABLED) + return; ++ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) ++ if (!dfs_enabled) ++ return; + } + + chwidth = CHANWIDTH_80MHZ; +@@ -2585,10 +2596,12 @@ skip_ht40: + if (!chan) + continue; + +- if (chan->flag & (HOSTAPD_CHAN_DISABLED | +- HOSTAPD_CHAN_NO_IR | +- HOSTAPD_CHAN_RADAR)) ++ if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; ++ if (chan->flag & (HOSTAPD_CHAN_RADAR | ++ HOSTAPD_CHAN_NO_IR)) ++ if (!dfs_enabled) ++ continue; + + /* Found a suitable second segment for 80+80 */ + chwidth = CHANWIDTH_80P80MHZ; 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/011-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch deleted file mode 100644 index 3a9b847171..0000000000 --- a/package/network/services/hostapd/patches/011-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 89fa0d75fb1be82330258082ed3d7fd452eb6076 Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:45 -0700 -Subject: [PATCH 3/7] 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 -Signed-off-by: Peter Oh ---- - wpa_supplicant/wpa_supplicant.c | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - ---- a/wpa_supplicant/wpa_supplicant.c -+++ b/wpa_supplicant/wpa_supplicant.c -@@ -2349,6 +2349,8 @@ void ibss_mesh_setup_freq(struct wpa_sup - int chwidth, seg0, seg1; - u32 vht_caps = 0; - int is_24ghz; -+ int dfs_enabled = wpa_s->conf->country[0] && -+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR); - - freq->freq = ssid->frequency; - -@@ -2436,8 +2438,11 @@ void ibss_mesh_setup_freq(struct wpa_sup - return; - - /* Check primary channel flags */ -- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) -+ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED) - return; -+ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) -+ if (!dfs_enabled) -+ return; - - freq->channel = pri_chan->chan; - -@@ -2470,8 +2475,11 @@ void ibss_mesh_setup_freq(struct wpa_sup - return; - - /* Check secondary channel flags */ -- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) -+ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED) - return; -+ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) -+ if (!dfs_enabled) -+ return; - - if (ht40 == -1) { - if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS)) -@@ -2564,8 +2572,11 @@ skip_ht40: - return; - - /* Back to HT configuration if channel not usable */ -- if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) -+ if (chan->flag & HOSTAPD_CHAN_DISABLED) - return; -+ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) -+ if (!dfs_enabled) -+ return; - } - - chwidth = CHANWIDTH_80MHZ; -@@ -2585,10 +2596,11 @@ skip_ht40: - if (!chan) - continue; - -- if (chan->flag & (HOSTAPD_CHAN_DISABLED | -- HOSTAPD_CHAN_NO_IR | -- HOSTAPD_CHAN_RADAR)) -+ if (chan->flag & HOSTAPD_CHAN_DISABLED) - continue; -+ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR)) -+ if (!dfs_enabled) -+ continue; - - /* Found a suitable second segment for 80+80 */ - chwidth = CHANWIDTH_80P80MHZ; diff --git a/package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch b/package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch new file mode 100644 index 0000000000..d491f7c4bc --- /dev/null +++ b/package/network/services/hostapd/patches/011-mesh-do-not-set-offchanok-on-DFS-channels-in-non-ETS.patch @@ -0,0 +1,53 @@ +From af8dcbc87466ed6472850a4f1cfe252652cb3d26 Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +CAC result on current operating channel. +(mac80211 commit: 34373d12f3cbb74960a73431138ef619d857996f) +Hence don't set offchanok for mgmt tx in case of DFS channels +in non-ETSI. + +Signed-off-by: Peter Oh +--- + src/drivers/driver_nl80211.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -7788,7 +7788,11 @@ static int wpa_driver_nl80211_send_actio + int ret = -1; + u8 *buf; + struct ieee80211_hdr *hdr; ++ struct hostapd_hw_modes *modes; + 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) +@@ -7817,6 +7821,21 @@ static int wpa_driver_nl80211_send_actio + os_memset(bss->rand_addr, 0, ETH_ALEN); + } + ++ if (is_mesh_interface(drv->nlmode)) { ++ modes = nl80211_get_hw_feature_data(bss, &num_modes, ++ &flags, &dfs_domain); ++ if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && ++ ieee80211_is_dfs(bss->freq, modes, num_modes)) ++ offchanok = 0; ++ if (modes) { ++ for (i = 0; i < num_modes; i++) { ++ os_free(modes[i].channels); ++ os_free(modes[i].rates); ++ } ++ os_free(modes); ++ } ++ } ++ + if (is_ap_interface(drv->nlmode) && + (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || + (int) freq == bss->freq || drv->device_ap_sme || diff --git a/package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch b/package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch new file mode 100644 index 0000000000..f324d81ae3 --- /dev/null +++ b/package/network/services/hostapd/patches/012-mesh-fix-channel-switch-error-during-CAC.patch @@ -0,0 +1,66 @@ +From ab6995f15aae17af93507dd2344615f91672a31a Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +DFS radar detection during CAC which caused channel switch error. +This change fixes the error by updating its channel parameters +when channel's been changed from initial one. + +Signed-off-by: Peter Oh +--- + wpa_supplicant/mesh.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +--- a/wpa_supplicant/mesh.c ++++ b/wpa_supplicant/mesh.c +@@ -13,6 +13,7 @@ + #include "utils/uuid.h" + #include "common/ieee802_11_defs.h" + #include "common/wpa_ctrl.h" ++#include "common/hw_features_common.h" + #include "ap/sta_info.h" + #include "ap/hostapd.h" + #include "ap/ieee802_11.h" +@@ -206,6 +207,39 @@ static int wpas_mesh_complete(struct wpa + return -1; + } + ++ /* ++ * inspect if channel's been changed since initialized. ++ * i.e. DFS radar detection ++ */ ++ 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(¶ms->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); ++ return -1; ++ } ++ } ++ + if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && + wpas_mesh_init_rsn(wpa_s)) { + wpa_printf(MSG_ERROR, 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 -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 ---- - 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/013-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 new file mode 100644 index 0000000000..fb4e68636e --- /dev/null +++ b/package/network/services/hostapd/patches/013-mesh-inform-kernel-driver-DFS-handler-in-userspace.patch @@ -0,0 +1,48 @@ +From f1118eca5b1a63a4acb2a11ceea15dc4bc259c77 Mon Sep 17 00:00:00 2001 +From: Peter Oh +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 +resides in userspace. + +Signed-off-by: Peter Oh +--- + src/drivers/driver.h | 1 + + src/drivers/driver_nl80211.c | 3 +++ + wpa_supplicant/mesh.c | 1 + + 3 files changed, 5 insertions(+) + +--- a/src/drivers/driver.h ++++ b/src/drivers/driver.h +@@ -1542,6 +1542,7 @@ struct wpa_driver_mesh_join_params { + #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004 + #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 + unsigned int flags; ++ u8 handle_dfs; + }; + + struct wpa_driver_set_key_params { +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -10070,6 +10070,9 @@ static int nl80211_join_mesh(struct i802 + + wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); + ++ if (params->handle_dfs) ++ if (nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS)) ++ goto fail; + container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP); + if (!container) + goto fail; +--- a/wpa_supplicant/mesh.c ++++ b/wpa_supplicant/mesh.c +@@ -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] = ' '; ++ wpa_s->mesh_params->handle_dfs = 1; + } + + bss->iconf = conf; 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 +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 +--- + 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, ¶ms->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-do-not-use-offchan-mgmt-tx-on-DFS.patch b/package/network/services/hostapd/patches/015-mesh-do-not-use-offchan-mgmt-tx-on-DFS.patch deleted file mode 100644 index 7c6f249a0b..0000000000 --- a/package/network/services/hostapd/patches/015-mesh-do-not-use-offchan-mgmt-tx-on-DFS.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 71e9c65a7c8af90a5fd11072062b596421316452 Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:46 -0700 -Subject: [PATCH 4/7] 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 -CAC result on current operating channel. -(mac80211 commit: 34373d12f3cbb74960a73431138ef619d857996f) -Hence don't set offchanok for mgmt tx in case of DFS channels -in non-ETSI. - -Signed-off-by: Peter Oh ---- - src/drivers/driver_nl80211.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -7789,6 +7789,10 @@ static int wpa_driver_nl80211_send_actio - u8 *buf; - struct ieee80211_hdr *hdr; - int offchanok = 1; -+ struct hostapd_hw_modes *modes; -+ int i; -+ u16 num_modes, flags; -+ u8 dfs_domain; - - if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq && - bss->beacon_set) -@@ -7817,6 +7821,21 @@ static int wpa_driver_nl80211_send_actio - os_memset(bss->rand_addr, 0, ETH_ALEN); - } - -+ if (is_mesh_interface(drv->nlmode)) { -+ modes = nl80211_get_hw_feature_data(bss, &num_modes, -+ &flags, &dfs_domain); -+ if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && -+ ieee80211_is_dfs(bss->freq, modes, num_modes)) -+ offchanok = 0; -+ if (modes) { -+ for (i = 0; i < num_modes; i++) { -+ os_free(modes[i].channels); -+ os_free(modes[i].rates); -+ } -+ os_free(modes); -+ } -+ } -+ - if (is_ap_interface(drv->nlmode) && - (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || - (int) freq == bss->freq || drv->device_ap_sme || 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 +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 +--- + 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-mesh-fix-channel-switch-error-during-CAC.patch b/package/network/services/hostapd/patches/016-mesh-fix-channel-switch-error-during-CAC.patch deleted file mode 100644 index 6b52abf988..0000000000 --- a/package/network/services/hostapd/patches/016-mesh-fix-channel-switch-error-during-CAC.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 5913d6e2a741683e7c747c046f72ca790bbe1337 Mon Sep 17 00:00:00 2001 -From: Peter Oh -Date: Mon, 27 Aug 2018 14:28:47 -0700 -Subject: [PATCH 5/7] 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 -DFS radar detection during CAC which caused channel switch error. -This change fixes the error by updating its channel parameters -when channel's been changed from initial one. - -Signed-off-by: Peter Oh ---- - wpa_supplicant/mesh.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -13,6 +13,7 @@ - #include "utils/uuid.h" - #include "common/ieee802_11_defs.h" - #include "common/wpa_ctrl.h" -+#include "common/hw_features_common.h" - #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; - } - -+ /* -+ * inspect if channel's been changed since initialized. -+ * i.e. DFS radar detection -+ */ -+ if (ifmsh->freq != params->freq.freq) { -+ wpa_s->assoc_freq = ifmsh->freq; -+ ssid->frequency = ifmsh->freq; -+ if (hostapd_set_freq_params(¶ms->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->current_mode->vht_capab, -+ &ifmsh->current_mode->he_capab[IEEE80211_MODE_AP])) { -+ wpa_printf(MSG_ERROR, "Error updating mesh frequency params."); -+ wpa_supplicant_mesh_deinit(wpa_s); -+ return; -+ } -+ } -+ - if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && - wpas_mesh_init_rsn(wpa_s)) { - wpa_printf(MSG_ERROR, 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 +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 +--- + tests/hwsim/test_wpas_mesh.py | 56 +++++++++++++++++++++++++++++++++-- + 1 file changed, 54 insertions(+), 2 deletions(-) + +--- a/tests/hwsim/test_wpas_mesh.py ++++ b/tests/hwsim/test_wpas_mesh.py +@@ -80,8 +80,23 @@ def check_mesh_scan(dev, params, other_s + if '[MESH]' not in bss['flags']: + raise Exception("BSS output did not include MESH flag") + +-def check_mesh_group_added(dev): +- ev = dev.wait_event(["MESH-GROUP-STARTED"]) ++def check_dfs_started(dev, timeout=10): ++ ev = dev.wait_event(["DFS-CAC-START"], timeout=timeout) ++ if ev is None: ++ raise Exception("Test exception: CAC did not start") ++ ++def check_dfs_finished(dev, timeout=70): ++ ev = dev.wait_event(["DFS-CAC-COMPLETED"], timeout=timeout) ++ if ev is None: ++ raise Exception("Test exception: CAC did not finish") ++ ++def check_mesh_radar_handling_finished(dev, timeout=75): ++ ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH", "MESH-GROUP-STARTED"], timeout=timeout) ++ if ev is None: ++ raise Exception("Test exception: Couldn't join mesh") ++ ++def check_mesh_group_added(dev, timeout=10): ++ ev = dev.wait_event(["MESH-GROUP-STARTED"], timeout=timeout) + if ev is None: + raise Exception("Test exception: Couldn't join mesh") + +@@ -91,6 +106,10 @@ def check_mesh_group_removed(dev): + if ev is None: + raise Exception("Test exception: Couldn't leave mesh") + ++def check_regdom_change(dev, timeout=10): ++ ev = dev.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=timeout) ++ if ev is None: ++ raise Exception("Test exception: No regdom change happened.") + + def check_mesh_peer_connected(dev, timeout=10): + ev = dev.wait_event(["MESH-PEER-CONNECTED"], timeout=timeout) +@@ -167,6 +186,39 @@ def test_wpas_mesh_group_remove(dev): + check_mesh_group_removed(dev[0]) + dev[0].mesh_group_remove() + ++def dfs_simulate_radar(dev): ++ logger.info("Trigger a simulated radar event") ++ phyname = dev.get_driver_status_field("phyname") ++ radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar' ++ with open(radar_file, 'w') as f: ++ f.write('1') ++ ++@long_duration_test ++def test_wpas_mesh_peer_connected_dfs(dev): ++ """wpa_supplicant MESH peer connected""" ++ dev[0].set("country", "DE") ++ dev[1].set("country", "DE") ++ ++ check_regdom_change(dev[0]) ++ check_regdom_change(dev[1]) ++ ++ check_mesh_support(dev[0]) ++ add_open_mesh_network(dev[0], freq="5500", beacon_int=160) ++ add_open_mesh_network(dev[1], freq="5500", beacon_int=160) ++ check_dfs_started(dev[0]) ++ check_dfs_finished(dev[0]) ++ check_mesh_joined_connected(dev, timeout0=10) ++ ++ dfs_simulate_radar(dev[0]) ++ ++ check_mesh_radar_handling_finished(dev[0], timeout=75) ++ ++ dev[0].set("country", "00") ++ dev[1].set("country", "00") ++ ++ check_regdom_change(dev[0]) ++ check_regdom_change(dev[1]) ++ + def test_wpas_mesh_peer_connected(dev): + """wpa_supplicant MESH peer connected""" + check_mesh_support(dev[0]) 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 +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 +--- + 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-make-forwarding-configurable.patch b/package/network/services/hostapd/patches/018-mesh-make-forwarding-configurable.patch deleted file mode 100644 index 0bdc4cc154..0000000000 --- a/package/network/services/hostapd/patches/018-mesh-make-forwarding-configurable.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 90fe6429624fc48bc0e5d2d7eeecb7498708b5e3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 18 Apr 2018 19:24:31 +0200 -Subject: [PATCH 18/18] mesh: make forwarding configurable - -Allow mesh_fwding to be specified in a mesh bss config, pass that -to the driver (only nl80211 implemented for now) and announce -forwarding capability accordingly. - -Signed-off-by: Daniel Golle ---- - src/ap/ap_config.h | 2 ++ - src/drivers/driver.h | 2 ++ - src/drivers/driver_nl80211.c | 3 +++ - wpa_supplicant/config.c | 4 ++++ - wpa_supplicant/config.h | 9 +++++++++ - wpa_supplicant/config_file.c | 4 ++++ - wpa_supplicant/config_ssid.h | 5 +++++ - wpa_supplicant/mesh.c | 6 ++++++ - wpa_supplicant/mesh_mpm.c | 4 ++-- - wpa_supplicant/wpa_supplicant.conf | 3 +++ - 10 files changed, 40 insertions(+), 2 deletions(-) - ---- a/src/ap/ap_config.h -+++ b/src/ap/ap_config.h -@@ -51,6 +51,7 @@ struct mesh_conf { - int dot11MeshRetryTimeout; /* msec */ - int dot11MeshConfirmTimeout; /* msec */ - int dot11MeshHoldingTimeout; /* msec */ -+ int mesh_fwding; - }; - - #define MAX_STA_COUNT 2007 -@@ -701,6 +702,7 @@ struct hostapd_bss_config { - - #define MESH_ENABLED BIT(0) - int mesh; -+ int mesh_fwding; - - u8 radio_measurements[RRM_CAPABILITIES_IE_LEN]; - ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1515,6 +1515,7 @@ struct wpa_driver_mesh_bss_params { - #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004 - #define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008 - #define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010 -+#define WPA_DRIVER_MESH_CONF_FLAG_FORWARDING 0x00000020 - /* - * TODO: Other mesh configuration parameters would go here. - * See NL80211_MESHCONF_* for all the mesh config parameters. -@@ -1524,6 +1525,7 @@ struct wpa_driver_mesh_bss_params { - int peer_link_timeout; - int max_peer_links; - int rssi_threshold; -+ int forwarding; - u16 ht_opmode; - }; - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -10019,6 +10019,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)) || -+ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_FORWARDING) && -+ nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, -+ params->forwarding)) || - ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) && - nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, - params->max_peer_links)) || ---- a/wpa_supplicant/config.c -+++ b/wpa_supplicant/config.c -@@ -2473,6 +2473,7 @@ static const struct parse_data ssid_fiel - #ifdef CONFIG_MESH - { INT_RANGE(mode, 0, 5) }, - { INT_RANGE(no_auto_peer, 0, 1) }, -+ { INT_RANGE(mesh_fwding, 0, 1) }, - { 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 - ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; - ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; - ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; -+ ssid->mesh_fwding = DEFAULT_MESH_FWDING; - 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 - config->user_mpm = DEFAULT_USER_MPM; - config->max_peer_links = DEFAULT_MAX_PEER_LINKS; - config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; -+ config->mesh_fwding = DEFAULT_MESH_FWDING; - 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 - { INT(user_mpm), 0 }, - { INT_RANGE(max_peer_links, 0, 255), 0 }, - { INT(mesh_max_inactivity), 0 }, -+ { INT_RANGE(mesh_fwding, 0, 1), 0 }, - { INT(dot11RSNASAERetransPeriod), 0 }, - #endif /* CONFIG_MESH */ - { INT(disable_scan_offload), 0 }, ---- a/wpa_supplicant/config.h -+++ b/wpa_supplicant/config.h -@@ -18,6 +18,7 @@ - #define DEFAULT_USER_MPM 1 - #define DEFAULT_MAX_PEER_LINKS 99 - #define DEFAULT_MESH_MAX_INACTIVITY 300 -+#define DEFAULT_MESH_FWDING 1 - /* - * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard, - * but use 1000 ms in practice to avoid issues on low power CPUs. -@@ -1351,6 +1352,14 @@ struct wpa_config { - int mesh_max_inactivity; - - /** -+ * mesh_fwding - Mesh network layer-2 forwarding -+ * -+ * This controls whether to enable layer-2 forwarding. -+ * By default: 1: enabled -+ */ -+ int mesh_fwding; -+ -+ /** - * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame - * - * This timeout value is used in mesh STA to retransmit ---- a/wpa_supplicant/config_file.c -+++ b/wpa_supplicant/config_file.c -@@ -866,6 +866,7 @@ static void wpa_config_write_network(FIL - #endif /* IEEE8021X_EAPOL */ - INT(mode); - INT(no_auto_peer); -+ INT(mesh_fwding); - INT(frequency); - INT(enable_edmg); - INT(edmg_channel); -@@ -1527,6 +1528,9 @@ static void wpa_config_write_global(FILE - fprintf(f, "mesh_max_inactivity=%d\n", - config->mesh_max_inactivity); - -+ if (config->mesh_fwding != DEFAULT_MESH_FWDING) -+ fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding); -+ - if (config->dot11RSNASAERetransPeriod != - DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD) - fprintf(f, "dot11RSNASAERetransPeriod=%d\n", ---- a/wpa_supplicant/config_ssid.h -+++ b/wpa_supplicant/config_ssid.h -@@ -546,6 +546,11 @@ struct wpa_ssid { - int dot11MeshConfirmTimeout; /* msec */ - int dot11MeshHoldingTimeout; /* msec */ - -+ /** -+ * Mesh network layer-2 forwarding -+ */ -+ int mesh_fwding; -+ - int ht; - int ht40; - ---- a/wpa_supplicant/mesh.c -+++ b/wpa_supplicant/mesh.c -@@ -130,6 +130,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; -+ conf->mesh_fwding = ssid->mesh_fwding; - conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries; - conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout; - conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout; -@@ -335,6 +336,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; -+ bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding; - - 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_ - } - params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; - -+ /* always explicitely set forwarding to on or off for now */ -+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING; -+ params->conf.forwarding = ssid->mesh_fwding; -+ - os_free(wpa_s->mesh_params); - wpa_s->mesh_params = params; - if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { ---- a/wpa_supplicant/mesh_mpm.c -+++ b/wpa_supplicant/mesh_mpm.c -@@ -303,9 +303,9 @@ static void mesh_mpm_send_plink_action(s - info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1; - /* TODO: Add Connected to Mesh Gate/AS subfields */ - wpabuf_put_u8(buf, info); -- /* always forwarding & accepting plinks for now */ -+ /* set forwarding & always accepting plinks for now */ - wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER | -- MESH_CAP_FORWARDING); -+ (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0)); - } else { /* Peer closing frame */ - /* IE: Mesh ID */ - wpabuf_put_u8(buf, WLAN_EID_MESH_ID); ---- a/wpa_supplicant/wpa_supplicant.conf -+++ b/wpa_supplicant/wpa_supplicant.conf -@@ -150,6 +150,9 @@ ap_scan=1 - # This timeout value is used in mesh STA to clean up inactive stations. - #mesh_max_inactivity=300 - -+# Enable 802.11s layer-2 routing and forwarding -+#mesh_fwding=1 -+ - # cert_in_cb - Whether to include a peer certificate dump in events - # This controls whether peer certificates for authentication server and - # its certificate chain are included in EAP peer certificate events. This is 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 +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 +--- + 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(¶ms->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(¶ms->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 +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 +--- + 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/050-mesh-make-forwarding-configurable.patch b/package/network/services/hostapd/patches/050-mesh-make-forwarding-configurable.patch new file mode 100644 index 0000000000..0ecb9ba078 --- /dev/null +++ b/package/network/services/hostapd/patches/050-mesh-make-forwarding-configurable.patch @@ -0,0 +1,219 @@ +From 90fe6429624fc48bc0e5d2d7eeecb7498708b5e3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 18 Apr 2018 19:24:31 +0200 +Subject: [PATCH 18/18] mesh: make forwarding configurable + +Allow mesh_fwding to be specified in a mesh bss config, pass that +to the driver (only nl80211 implemented for now) and announce +forwarding capability accordingly. + +Signed-off-by: Daniel Golle +--- + src/ap/ap_config.h | 2 ++ + src/drivers/driver.h | 2 ++ + src/drivers/driver_nl80211.c | 3 +++ + wpa_supplicant/config.c | 4 ++++ + wpa_supplicant/config.h | 9 +++++++++ + wpa_supplicant/config_file.c | 4 ++++ + wpa_supplicant/config_ssid.h | 5 +++++ + wpa_supplicant/mesh.c | 6 ++++++ + wpa_supplicant/mesh_mpm.c | 4 ++-- + wpa_supplicant/wpa_supplicant.conf | 3 +++ + 10 files changed, 40 insertions(+), 2 deletions(-) + +--- a/src/ap/ap_config.h ++++ b/src/ap/ap_config.h +@@ -51,6 +51,7 @@ struct mesh_conf { + int dot11MeshRetryTimeout; /* msec */ + int dot11MeshConfirmTimeout; /* msec */ + int dot11MeshHoldingTimeout; /* msec */ ++ int mesh_fwding; + }; + + #define MAX_STA_COUNT 2007 +@@ -701,6 +702,7 @@ struct hostapd_bss_config { + + #define MESH_ENABLED BIT(0) + int mesh; ++ int mesh_fwding; + + u8 radio_measurements[RRM_CAPABILITIES_IE_LEN]; + +--- a/src/drivers/driver.h ++++ b/src/drivers/driver.h +@@ -1515,6 +1515,7 @@ struct wpa_driver_mesh_bss_params { + #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004 + #define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008 + #define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010 ++#define WPA_DRIVER_MESH_CONF_FLAG_FORWARDING 0x00000020 + /* + * TODO: Other mesh configuration parameters would go here. + * See NL80211_MESHCONF_* for all the mesh config parameters. +@@ -1524,6 +1525,7 @@ struct wpa_driver_mesh_bss_params { + int peer_link_timeout; + int max_peer_links; + int rssi_threshold; ++ int forwarding; + u16 ht_opmode; + }; + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -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)) || ++ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_FORWARDING) && ++ nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, ++ params->forwarding)) || + ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) && + nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, + params->max_peer_links)) || +--- a/wpa_supplicant/config.c ++++ b/wpa_supplicant/config.c +@@ -2473,6 +2473,7 @@ static const struct parse_data ssid_fiel + #ifdef CONFIG_MESH + { INT_RANGE(mode, 0, 5) }, + { INT_RANGE(no_auto_peer, 0, 1) }, ++ { INT_RANGE(mesh_fwding, 0, 1) }, + { INT_RANGE(mesh_rssi_threshold, -255, 1) }, + #else /* CONFIG_MESH */ + { INT_RANGE(mode, 0, 4) }, +@@ -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; ++ ssid->mesh_fwding = DEFAULT_MESH_FWDING; + ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD; + #endif /* CONFIG_MESH */ + #ifdef CONFIG_HT_OVERRIDES +@@ -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; ++ config->mesh_fwding = DEFAULT_MESH_FWDING; + config->dot11RSNASAERetransPeriod = + DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD; + config->fast_reauth = DEFAULT_FAST_REAUTH; +@@ -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 }, ++ { INT_RANGE(mesh_fwding, 0, 1), 0 }, + { INT(dot11RSNASAERetransPeriod), 0 }, + #endif /* CONFIG_MESH */ + { INT(disable_scan_offload), 0 }, +--- a/wpa_supplicant/config.h ++++ b/wpa_supplicant/config.h +@@ -18,6 +18,7 @@ + #define DEFAULT_USER_MPM 1 + #define DEFAULT_MAX_PEER_LINKS 99 + #define DEFAULT_MESH_MAX_INACTIVITY 300 ++#define DEFAULT_MESH_FWDING 1 + /* + * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard, + * but use 1000 ms in practice to avoid issues on low power CPUs. +@@ -1351,6 +1352,14 @@ struct wpa_config { + int mesh_max_inactivity; + + /** ++ * mesh_fwding - Mesh network layer-2 forwarding ++ * ++ * This controls whether to enable layer-2 forwarding. ++ * By default: 1: enabled ++ */ ++ int mesh_fwding; ++ ++ /** + * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame + * + * This timeout value is used in mesh STA to retransmit +--- a/wpa_supplicant/config_file.c ++++ b/wpa_supplicant/config_file.c +@@ -866,6 +866,7 @@ static void wpa_config_write_network(FIL + #endif /* IEEE8021X_EAPOL */ + INT(mode); + INT(no_auto_peer); ++ INT(mesh_fwding); + INT(frequency); + INT(enable_edmg); + INT(edmg_channel); +@@ -1527,6 +1528,9 @@ static void wpa_config_write_global(FILE + fprintf(f, "mesh_max_inactivity=%d\n", + config->mesh_max_inactivity); + ++ if (config->mesh_fwding != DEFAULT_MESH_FWDING) ++ fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding); ++ + if (config->dot11RSNASAERetransPeriod != + DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD) + fprintf(f, "dot11RSNASAERetransPeriod=%d\n", +--- a/wpa_supplicant/config_ssid.h ++++ b/wpa_supplicant/config_ssid.h +@@ -546,6 +546,11 @@ struct wpa_ssid { + int dot11MeshConfirmTimeout; /* msec */ + int dot11MeshHoldingTimeout; /* msec */ + ++ /** ++ * Mesh network layer-2 forwarding ++ */ ++ int mesh_fwding; ++ + int ht; + int ht40; + +--- a/wpa_supplicant/mesh.c ++++ b/wpa_supplicant/mesh.c +@@ -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; ++ conf->mesh_fwding = ssid->mesh_fwding; + conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries; + conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout; + conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout; +@@ -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; ++ bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding; + + if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes, + wpa_s->hw.num_modes) && wpa_s->conf->country[0]) { +@@ -647,6 +649,10 @@ int wpa_supplicant_join_mesh(struct wpa_ + } + params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; + ++ /* always explicitely set forwarding to on or off for now */ ++ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING; ++ params->conf.forwarding = ssid->mesh_fwding; ++ + os_free(wpa_s->mesh_params); + wpa_s->mesh_params = params; + if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { +--- a/wpa_supplicant/mesh_mpm.c ++++ b/wpa_supplicant/mesh_mpm.c +@@ -303,9 +303,9 @@ static void mesh_mpm_send_plink_action(s + info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1; + /* TODO: Add Connected to Mesh Gate/AS subfields */ + wpabuf_put_u8(buf, info); +- /* always forwarding & accepting plinks for now */ ++ /* set forwarding & always accepting plinks for now */ + wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER | +- MESH_CAP_FORWARDING); ++ (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0)); + } else { /* Peer closing frame */ + /* IE: Mesh ID */ + wpabuf_put_u8(buf, WLAN_EID_MESH_ID); +--- a/wpa_supplicant/wpa_supplicant.conf ++++ b/wpa_supplicant/wpa_supplicant.conf +@@ -150,6 +150,9 @@ ap_scan=1 + # This timeout value is used in mesh STA to clean up inactive stations. + #mesh_max_inactivity=300 + ++# Enable 802.11s layer-2 routing and forwarding ++#mesh_fwding=1 ++ + # cert_in_cb - Whether to include a peer certificate dump in events + # This controls whether peer certificates for authentication server and + # its certificate chain are included in EAP peer certificate events. This is 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 * 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 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 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 --- 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);