mac80211: set hostapd op_class for 6 GHz
[openwrt/staging/ynezz.git] / package / network / services / hostapd / patches / 015-mesh-fix-DFS-deinit-init.patch
1 From d017f5d98a143c46c3c3fcb0e6507ca0b2bebdb0 Mon Sep 17 00:00:00 2001
2 From: Markus Theil <markus.theil@tu-ilmenau.de>
3 Date: Tue, 30 Jun 2020 14:19:03 +0200
4 Subject: [PATCH 15/19] mesh: fix DFS deinit/init
5
6 The hostapd DFS code deinitializes and initializes the
7 AP interface, if a clean channel switch is not possible.
8 In this case the AP code paths would deinit the driver, for
9 example nl80211, without wpa_supplicant code paths getting
10 notice of this.
11
12 Therefore add callbacks for wpa_supplicant mesh methods,
13 which are called on init/deinit of the AP bss. These
14 callbacks are then used to handle the reset in the mesh
15 code.
16
17 Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
18 ---
19 src/ap/dfs.c | 2 +-
20 src/ap/hostapd.c | 17 ++++++--
21 src/ap/hostapd.h | 6 +++
22 wpa_supplicant/mesh.c | 90 +++++++++++++++++++++++++++++++++++++------
23 4 files changed, 100 insertions(+), 15 deletions(-)
24
25 --- a/src/ap/dfs.c
26 +++ b/src/ap/dfs.c
27 @@ -1112,7 +1112,7 @@ static int hostapd_dfs_start_channel_swi
28 oper_centr_freq_seg0_idx,
29 oper_centr_freq_seg1_idx,
30 cmode->vht_capab,
31 - &cmode->he_capab[IEEE80211_MODE_AP]);
32 + &cmode->he_capab[iface->conf->hw_mode]);
33
34 if (err) {
35 wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
36 --- a/src/ap/hostapd.c
37 +++ b/src/ap/hostapd.c
38 @@ -354,7 +354,7 @@ static int hostapd_broadcast_wep_set(str
39 #endif /* CONFIG_WEP */
40
41
42 -static void hostapd_free_hapd_data(struct hostapd_data *hapd)
43 +void hostapd_free_hapd_data(struct hostapd_data *hapd)
44 {
45 os_free(hapd->probereq_cb);
46 hapd->probereq_cb = NULL;
47 @@ -498,7 +498,7 @@ static void sta_track_deinit(struct host
48 }
49
50
51 -static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
52 +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
53 {
54 wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
55 #ifdef NEED_AP_MLME
56 @@ -626,7 +626,7 @@ static int hostapd_flush_old_stations(st
57 }
58
59
60 -static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
61 +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
62 {
63 hostapd_free_stas(hapd);
64 hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
65 @@ -2690,6 +2690,13 @@ int hostapd_enable_iface(struct hostapd_
66 {
67 size_t j;
68
69 + if (hapd_iface == NULL)
70 + return -1;
71 +
72 + if (hapd_iface->enable_iface_cb != NULL) {
73 + return hapd_iface->enable_iface_cb(hapd_iface);
74 + }
75 +
76 if (hapd_iface->bss[0]->drv_priv != NULL) {
77 wpa_printf(MSG_ERROR, "Interface %s already enabled",
78 hapd_iface->conf->bss[0]->iface);
79 @@ -2751,6 +2758,10 @@ int hostapd_disable_iface(struct hostapd
80 if (hapd_iface == NULL)
81 return -1;
82
83 + if (hapd_iface->disable_iface_cb != NULL) {
84 + return hapd_iface->disable_iface_cb(hapd_iface);
85 + }
86 +
87 if (hapd_iface->bss[0]->drv_priv == NULL) {
88 wpa_printf(MSG_INFO, "Interface %s already disabled",
89 hapd_iface->conf->bss[0]->iface);
90 --- a/src/ap/hostapd.h
91 +++ b/src/ap/hostapd.h
92 @@ -589,6 +589,9 @@ struct hostapd_iface {
93
94 /* Previous WMM element information */
95 struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
96 +
97 + int (*enable_iface_cb)(struct hostapd_iface *iface);
98 + int (*disable_iface_cb)(struct hostapd_iface *iface);
99 };
100
101 /* hostapd.c */
102 @@ -617,6 +620,9 @@ void hostapd_interface_deinit_free(struc
103 int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
104 int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
105 int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
106 +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd);
107 +void hostapd_free_hapd_data(struct hostapd_data *hapd);
108 +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface);
109 int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
110 int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
111 void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
112 --- a/wpa_supplicant/mesh.c
113 +++ b/wpa_supplicant/mesh.c
114 @@ -28,15 +28,20 @@
115 #include "mesh.h"
116
117
118 -static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
119 +static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, bool also_clear_hostapd)
120 {
121 - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true);
122 - wpa_s->ifmsh = NULL;
123 - wpa_s->current_ssid = NULL;
124 + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, also_clear_hostapd);
125 +
126 + if (also_clear_hostapd) {
127 + wpa_s->ifmsh = NULL;
128 + wpa_s->current_ssid = NULL;
129 + os_free(wpa_s->mesh_params);
130 + wpa_s->mesh_params = NULL;
131 + }
132 +
133 os_free(wpa_s->mesh_rsn);
134 wpa_s->mesh_rsn = NULL;
135 - os_free(wpa_s->mesh_params);
136 - wpa_s->mesh_params = NULL;
137 +
138 wpa_supplicant_leave_mesh(wpa_s, false);
139 }
140
141 @@ -237,7 +242,7 @@ static int wpas_mesh_complete(struct wpa
142 ifmsh->conf->vht_capab,
143 he_capab)) {
144 wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
145 - wpa_supplicant_mesh_deinit(wpa_s);
146 + wpa_supplicant_mesh_deinit(wpa_s, true);
147 return -1;
148 }
149 }
150 @@ -246,7 +251,7 @@ static int wpas_mesh_complete(struct wpa
151 wpas_mesh_init_rsn(wpa_s)) {
152 wpa_printf(MSG_ERROR,
153 "mesh: RSN initialization failed - deinit mesh");
154 - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false);
155 + wpa_supplicant_mesh_deinit(wpa_s, false);
156 return -1;
157 }
158
159 @@ -291,6 +296,67 @@ static void wpas_mesh_complete_cb(void *
160 }
161
162
163 +static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
164 +{
165 + struct wpa_supplicant *wpa_s = ifmsh->owner;
166 + struct hostapd_data *bss;
167 +
168 + ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
169 +
170 + bss = ifmsh->bss[0];
171 + bss->msg_ctx = wpa_s;
172 + os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
173 + bss->driver = wpa_s->driver;
174 + bss->drv_priv = wpa_s->drv_priv;
175 + bss->iface = ifmsh;
176 + bss->mesh_sta_free_cb = mesh_mpm_free_sta;
177 + bss->setup_complete_cb = wpas_mesh_complete_cb;
178 + bss->setup_complete_cb_ctx = wpa_s;
179 +
180 + bss->conf->start_disabled = 1;
181 + bss->conf->mesh = MESH_ENABLED;
182 + bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
183 +
184 + if (wpa_drv_init_mesh(wpa_s)) {
185 + wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
186 + return -1;
187 + }
188 +
189 + if (hostapd_setup_interface(ifmsh)) {
190 + wpa_printf(MSG_ERROR,
191 + "Failed to initialize hostapd interface for mesh");
192 + return -1;
193 + }
194 +
195 + return 0;
196 +}
197 +
198 +
199 +static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
200 +{
201 + struct wpa_supplicant *wpa_s = ifmsh->owner;
202 + int j;
203 +
204 + wpa_supplicant_mesh_deinit(wpa_s, false);
205 +
206 +#ifdef NEED_AP_MLME
207 + for (j = 0; j < ifmsh->num_bss; j++)
208 + hostapd_cleanup_cs_params(ifmsh->bss[j]);
209 +#endif /* NEED_AP_MLME */
210 +
211 + /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
212 + for (j = 0; j < ifmsh->num_bss; j++) {
213 + struct hostapd_data *hapd = ifmsh->bss[j];
214 + hostapd_bss_deinit_no_free(hapd);
215 + hostapd_free_hapd_data(hapd);
216 + }
217 +
218 + hostapd_cleanup_iface_partial(ifmsh);
219 +
220 + return 0;
221 +}
222 +
223 +
224 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
225 struct wpa_ssid *ssid,
226 struct hostapd_freq_params *freq)
227 @@ -318,6 +384,8 @@ static int wpa_supplicant_mesh_init(stru
228 ifmsh->drv_flags = wpa_s->drv_flags;
229 ifmsh->drv_flags2 = wpa_s->drv_flags2;
230 ifmsh->num_bss = 1;
231 + ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
232 + ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
233 ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
234 sizeof(struct hostapd_data *));
235 if (!ifmsh->bss)
236 @@ -451,7 +519,7 @@ static int wpa_supplicant_mesh_init(stru
237
238 return 0;
239 out_free:
240 - wpa_supplicant_mesh_deinit(wpa_s);
241 + wpa_supplicant_mesh_deinit(wpa_s, true);
242 return -ENOMEM;
243 }
244
245 @@ -499,7 +567,7 @@ int wpa_supplicant_join_mesh(struct wpa_
246 goto out;
247 }
248
249 - wpa_supplicant_mesh_deinit(wpa_s);
250 + wpa_supplicant_mesh_deinit(wpa_s, true);
251
252 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
253 wpa_s->group_cipher = WPA_CIPHER_NONE;
254 @@ -588,7 +656,7 @@ int wpa_supplicant_leave_mesh(struct wpa
255
256 /* Need to send peering close messages first */
257 if (need_deinit)
258 - wpa_supplicant_mesh_deinit(wpa_s);
259 + wpa_supplicant_mesh_deinit(wpa_s, true);
260
261 ret = wpa_drv_leave_mesh(wpa_s);
262 if (ret)