mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 18:47:06 +00:00
34705946e2
Drop outdated and by now broken patchset originally supplied by Peter Oh in August 2018 but never merged upstream. Instead add the more promissing rework recently submitted by Markus Theil who picked up Peter's patchset, fixed and completed it and added support for HE (802.11ax) in mesh mode. This is only compile tested and needs some real-life testing. Fixes: FS#3214 Fixes:167028b750
("hostapd: Update to version 2.9 (2019-08-08)") Fixes:0a3ec87a66
("hostapd: update to latest Git hostap_2_9-1238-gdd2daf0848ed") Fixes:017320ead3
("hostapd: bring back mesh patches") Signed-off-by: Daniel Golle <daniel@makrotopia.org>
263 lines
8.0 KiB
Diff
263 lines
8.0 KiB
Diff
From d017f5d98a143c46c3c3fcb0e6507ca0b2bebdb0 Mon Sep 17 00:00:00 2001
|
|
From: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
Date: Tue, 30 Jun 2020 14:19:03 +0200
|
|
Subject: [PATCH 15/19] mesh: fix DFS deinit/init
|
|
|
|
The hostapd DFS code deinitializes and initializes the
|
|
AP interface, if a clean channel switch is not possible.
|
|
In this case the AP code paths would deinit the driver, for
|
|
example nl80211, without wpa_supplicant code paths getting
|
|
notice of this.
|
|
|
|
Therefore add callbacks for wpa_supplicant mesh methods,
|
|
which are called on init/deinit of the AP bss. These
|
|
callbacks are then used to handle the reset in the mesh
|
|
code.
|
|
|
|
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
---
|
|
src/ap/dfs.c | 2 +-
|
|
src/ap/hostapd.c | 17 ++++++--
|
|
src/ap/hostapd.h | 6 +++
|
|
wpa_supplicant/mesh.c | 90 +++++++++++++++++++++++++++++++++++++------
|
|
4 files changed, 100 insertions(+), 15 deletions(-)
|
|
|
|
--- a/src/ap/dfs.c
|
|
+++ b/src/ap/dfs.c
|
|
@@ -1112,7 +1112,7 @@ static int hostapd_dfs_start_channel_swi
|
|
oper_centr_freq_seg0_idx,
|
|
oper_centr_freq_seg1_idx,
|
|
cmode->vht_capab,
|
|
- &cmode->he_capab[IEEE80211_MODE_AP]);
|
|
+ &cmode->he_capab[iface->conf->hw_mode]);
|
|
|
|
if (err) {
|
|
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -354,7 +354,7 @@ static int hostapd_broadcast_wep_set(str
|
|
#endif /* CONFIG_WEP */
|
|
|
|
|
|
-static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|
+void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|
{
|
|
os_free(hapd->probereq_cb);
|
|
hapd->probereq_cb = NULL;
|
|
@@ -498,7 +498,7 @@ static void sta_track_deinit(struct host
|
|
}
|
|
|
|
|
|
-static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
|
+void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
|
|
{
|
|
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
|
|
#ifdef NEED_AP_MLME
|
|
@@ -626,7 +626,7 @@ static int hostapd_flush_old_stations(st
|
|
}
|
|
|
|
|
|
-static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
|
|
+void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
|
|
{
|
|
hostapd_free_stas(hapd);
|
|
hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
|
|
@@ -2690,6 +2690,13 @@ int hostapd_enable_iface(struct hostapd_
|
|
{
|
|
size_t j;
|
|
|
|
+ if (hapd_iface == NULL)
|
|
+ return -1;
|
|
+
|
|
+ if (hapd_iface->enable_iface_cb != NULL) {
|
|
+ return hapd_iface->enable_iface_cb(hapd_iface);
|
|
+ }
|
|
+
|
|
if (hapd_iface->bss[0]->drv_priv != NULL) {
|
|
wpa_printf(MSG_ERROR, "Interface %s already enabled",
|
|
hapd_iface->conf->bss[0]->iface);
|
|
@@ -2751,6 +2758,10 @@ int hostapd_disable_iface(struct hostapd
|
|
if (hapd_iface == NULL)
|
|
return -1;
|
|
|
|
+ if (hapd_iface->disable_iface_cb != NULL) {
|
|
+ return hapd_iface->disable_iface_cb(hapd_iface);
|
|
+ }
|
|
+
|
|
if (hapd_iface->bss[0]->drv_priv == NULL) {
|
|
wpa_printf(MSG_INFO, "Interface %s already disabled",
|
|
hapd_iface->conf->bss[0]->iface);
|
|
--- a/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
@@ -589,6 +589,9 @@ struct hostapd_iface {
|
|
|
|
/* Previous WMM element information */
|
|
struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
|
|
+
|
|
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
|
|
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
|
|
};
|
|
|
|
/* hostapd.c */
|
|
@@ -617,6 +620,9 @@ void hostapd_interface_deinit_free(struc
|
|
int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
|
|
int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
|
|
int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
|
|
+void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
|
|
+void hostapd_free_hapd_data(struct hostapd_data *hapd);
|
|
+void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
|
|
int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
|
|
int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
|
|
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
|
|
--- a/wpa_supplicant/mesh.c
|
|
+++ b/wpa_supplicant/mesh.c
|
|
@@ -28,15 +28,20 @@
|
|
#include "mesh.h"
|
|
|
|
|
|
-static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
|
|
+static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, bool also_clear_hostapd)
|
|
{
|
|
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
|
|
- wpa_s->ifmsh = NULL;
|
|
- wpa_s->current_ssid = NULL;
|
|
+ wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, also_clear_hostapd);
|
|
+
|
|
+ if (also_clear_hostapd) {
|
|
+ wpa_s->ifmsh = NULL;
|
|
+ wpa_s->current_ssid = NULL;
|
|
+ os_free(wpa_s->mesh_params);
|
|
+ wpa_s->mesh_params = NULL;
|
|
+ }
|
|
+
|
|
os_free(wpa_s->mesh_rsn);
|
|
wpa_s->mesh_rsn = NULL;
|
|
- os_free(wpa_s->mesh_params);
|
|
- wpa_s->mesh_params = NULL;
|
|
+
|
|
wpa_supplicant_leave_mesh(wpa_s, false);
|
|
}
|
|
|
|
@@ -237,7 +242,7 @@ static int wpas_mesh_complete(struct wpa
|
|
ifmsh->conf->vht_capab,
|
|
he_capab)) {
|
|
wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
|
|
- wpa_supplicant_mesh_deinit(wpa_s);
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, true);
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -246,7 +251,7 @@ static int wpas_mesh_complete(struct wpa
|
|
wpas_mesh_init_rsn(wpa_s)) {
|
|
wpa_printf(MSG_ERROR,
|
|
"mesh: RSN initialization failed - deinit mesh");
|
|
- wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false);
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, false);
|
|
return -1;
|
|
}
|
|
|
|
@@ -291,6 +296,67 @@ static void wpas_mesh_complete_cb(void *
|
|
}
|
|
|
|
|
|
+static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = ifmsh->owner;
|
|
+ struct hostapd_data *bss;
|
|
+
|
|
+ ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
|
|
+
|
|
+ bss = ifmsh->bss[0];
|
|
+ bss->msg_ctx = wpa_s;
|
|
+ os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
|
|
+ bss->driver = wpa_s->driver;
|
|
+ bss->drv_priv = wpa_s->drv_priv;
|
|
+ bss->iface = ifmsh;
|
|
+ bss->mesh_sta_free_cb = mesh_mpm_free_sta;
|
|
+ bss->setup_complete_cb = wpas_mesh_complete_cb;
|
|
+ bss->setup_complete_cb_ctx = wpa_s;
|
|
+
|
|
+ bss->conf->start_disabled = 1;
|
|
+ bss->conf->mesh = MESH_ENABLED;
|
|
+ bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
|
|
+
|
|
+ if (wpa_drv_init_mesh(wpa_s)) {
|
|
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (hostapd_setup_interface(ifmsh)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Failed to initialize hostapd interface for mesh");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = ifmsh->owner;
|
|
+ int j;
|
|
+
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, false);
|
|
+
|
|
+#ifdef NEED_AP_MLME
|
|
+ for (j = 0; j < ifmsh->num_bss; j++)
|
|
+ hostapd_cleanup_cs_params(ifmsh->bss[j]);
|
|
+#endif /* NEED_AP_MLME */
|
|
+
|
|
+ /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
|
|
+ for (j = 0; j < ifmsh->num_bss; j++) {
|
|
+ struct hostapd_data *hapd = ifmsh->bss[j];
|
|
+ hostapd_bss_deinit_no_free(hapd);
|
|
+ hostapd_free_hapd_data(hapd);
|
|
+ }
|
|
+
|
|
+ hostapd_cleanup_iface_partial(ifmsh);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
|
|
struct wpa_ssid *ssid,
|
|
struct hostapd_freq_params *freq)
|
|
@@ -318,6 +384,8 @@ static int wpa_supplicant_mesh_init(stru
|
|
ifmsh->drv_flags = wpa_s->drv_flags;
|
|
ifmsh->drv_flags2 = wpa_s->drv_flags2;
|
|
ifmsh->num_bss = 1;
|
|
+ ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
|
|
+ ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
|
|
ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
|
|
sizeof(struct hostapd_data *));
|
|
if (!ifmsh->bss)
|
|
@@ -451,7 +519,7 @@ static int wpa_supplicant_mesh_init(stru
|
|
|
|
return 0;
|
|
out_free:
|
|
- wpa_supplicant_mesh_deinit(wpa_s);
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, true);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -499,7 +567,7 @@ int wpa_supplicant_join_mesh(struct wpa_
|
|
goto out;
|
|
}
|
|
|
|
- wpa_supplicant_mesh_deinit(wpa_s);
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, true);
|
|
|
|
wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
|
|
wpa_s->group_cipher = WPA_CIPHER_NONE;
|
|
@@ -588,7 +656,7 @@ int wpa_supplicant_leave_mesh(struct wpa
|
|
|
|
/* Need to send peering close messages first */
|
|
if (need_deinit)
|
|
- wpa_supplicant_mesh_deinit(wpa_s);
|
|
+ wpa_supplicant_mesh_deinit(wpa_s, true);
|
|
|
|
ret = wpa_drv_leave_mesh(wpa_s);
|
|
if (ret)
|