• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _RTW_MESH_C_
16 
17 #ifdef CONFIG_RTW_MESH
18 #include <drv_types.h>
19 
20 const char *_rtw_mesh_plink_str[] = {
21 	"UNKNOWN",
22 	"LISTEN",
23 	"OPN_SNT",
24 	"OPN_RCVD",
25 	"CNF_RCVD",
26 	"ESTAB",
27 	"HOLDING",
28 	"BLOCKED",
29 };
30 
31 const char *_rtw_mesh_ps_str[] = {
32 	"UNKNOWN",
33 	"ACTIVE",
34 	"LSLEEP",
35 	"DSLEEP",
36 };
37 
38 const char *_action_self_protected_str[] = {
39 	"ACT_SELF_PROTECTED_RSVD",
40 	"MESH_OPEN",
41 	"MESH_CONF",
42 	"MESH_CLOSE",
43 	"MESH_GK_INFORM",
44 	"MESH_GK_ACK",
45 };
46 
rtw_set_ie_mesh_id(u8 * buf,u32 * buf_len,const char * mesh_id,u8 id_len)47 inline u8 *rtw_set_ie_mesh_id(u8 *buf, u32 *buf_len, const char *mesh_id, u8 id_len)
48 {
49 	return rtw_set_ie(buf, WLAN_EID_MESH_ID, id_len, mesh_id, buf_len);
50 }
51 
rtw_set_ie_mesh_config(u8 * buf,u32 * buf_len,u8 path_sel_proto,u8 path_sel_metric,u8 congest_ctl_mode,u8 sync_method,u8 auth_proto,u8 num_of_peerings,bool cto_mgate,bool cto_as,bool accept_peerings,bool mcca_sup,bool mcca_en,bool forwarding,bool mbca_en,bool tbtt_adj,bool ps_level)52 inline u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len
53 	, u8 path_sel_proto, u8 path_sel_metric, u8 congest_ctl_mode, u8 sync_method, u8 auth_proto
54 	, u8 num_of_peerings, bool cto_mgate, bool cto_as
55 	, bool accept_peerings, bool mcca_sup, bool mcca_en, bool forwarding
56 	, bool mbca_en, bool tbtt_adj, bool ps_level)
57 {
58 
59 	u8 conf[7] = {0};
60 
61 	SET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(conf, path_sel_proto);
62 	SET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(conf, path_sel_metric);
63 	SET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(conf, congest_ctl_mode);
64 	SET_MESH_CONF_ELE_SYNC_METHOD_ID(conf, sync_method);
65 	SET_MESH_CONF_ELE_AUTH_PROTO_ID(conf, auth_proto);
66 
67 	SET_MESH_CONF_ELE_CTO_MGATE(conf, cto_mgate);
68 	SET_MESH_CONF_ELE_NUM_OF_PEERINGS(conf, num_of_peerings);
69 	SET_MESH_CONF_ELE_CTO_AS(conf, cto_as);
70 
71 	SET_MESH_CONF_ELE_ACCEPT_PEERINGS(conf, accept_peerings);
72 	SET_MESH_CONF_ELE_MCCA_SUP(conf, mcca_sup);
73 	SET_MESH_CONF_ELE_MCCA_EN(conf, mcca_en);
74 	SET_MESH_CONF_ELE_FORWARDING(conf, forwarding);
75 	SET_MESH_CONF_ELE_MBCA_EN(conf, mbca_en);
76 	SET_MESH_CONF_ELE_TBTT_ADJ(conf, tbtt_adj);
77 	SET_MESH_CONF_ELE_PS_LEVEL(conf, ps_level);
78 
79 	return rtw_set_ie(buf, WLAN_EID_MESH_CONFIG, 7, conf, buf_len);
80 }
81 
rtw_set_ie_mpm(u8 * buf,u32 * buf_len,u8 proto_id,u16 llid,u16 * plid,u16 * reason,u8 * chosen_pmk)82 inline u8 *rtw_set_ie_mpm(u8 *buf, u32 *buf_len
83 	, u8 proto_id, u16 llid, u16 *plid, u16 *reason, u8 *chosen_pmk)
84 {
85 	u8 data[24] = {0};
86 	u8 *pos = data;
87 
88 	RTW_PUT_LE16(pos, proto_id);
89 	pos += 2;
90 
91 	RTW_PUT_LE16(pos, llid);
92 	pos += 2;
93 
94 	if (plid) {
95 		RTW_PUT_LE16(pos, *plid);
96 		pos += 2;
97 	}
98 
99 	if (reason) {
100 		RTW_PUT_LE16(pos, *reason);
101 		pos += 2;
102 	}
103 
104 	if (chosen_pmk) {
105 		_rtw_memcpy(pos, chosen_pmk, 16);
106 		pos += 16;
107 	}
108 
109 	return rtw_set_ie(buf, WLAN_EID_MPM, pos - data, data, buf_len);
110 }
111 
rtw_bss_is_forwarding(WLAN_BSSID_EX * bss)112 bool rtw_bss_is_forwarding(WLAN_BSSID_EX *bss)
113 {
114 	u8 *ie;
115 	int ie_len;
116 	bool ret = 0;
117 
118 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
119 			BSS_EX_TLV_IES_LEN(bss));
120 	if (!ie || ie_len != 7)
121 		goto exit;
122 
123 	ret = GET_MESH_CONF_ELE_FORWARDING(ie + 2);
124 
125 exit:
126 	return ret;
127 }
128 
rtw_bss_is_cto_mgate(WLAN_BSSID_EX * bss)129 bool rtw_bss_is_cto_mgate(WLAN_BSSID_EX *bss)
130 {
131 	u8 *ie;
132 	int ie_len;
133 	bool ret = 0;
134 
135 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
136 			BSS_EX_TLV_IES_LEN(bss));
137 	if (!ie || ie_len != 7)
138 		goto exit;
139 
140 	ret = GET_MESH_CONF_ELE_CTO_MGATE(ie + 2);
141 
142 exit:
143 	return ret;
144 }
145 
_rtw_bss_is_same_mbss(WLAN_BSSID_EX * a,WLAN_BSSID_EX * b,u8 ** a_mconf_ie_r,u8 ** b_mconf_ie_r)146 int _rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b, u8 **a_mconf_ie_r, u8 **b_mconf_ie_r)
147 {
148 	int ret = 0;
149 	u8 *a_mconf_ie, *b_mconf_ie;
150 	sint a_mconf_ie_len, b_mconf_ie_len;
151 
152 	if (a->InfrastructureMode != Ndis802_11_mesh)
153 		goto exit;
154 	a_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(a), WLAN_EID_MESH_CONFIG, &a_mconf_ie_len, BSS_EX_TLV_IES_LEN(a));
155 	if (!a_mconf_ie || a_mconf_ie_len != 7)
156 		goto exit;
157 	if (a_mconf_ie_r)
158 		*a_mconf_ie_r = a_mconf_ie;
159 
160 	if (b->InfrastructureMode != Ndis802_11_mesh)
161 		goto exit;
162 	b_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(b), WLAN_EID_MESH_CONFIG, &b_mconf_ie_len, BSS_EX_TLV_IES_LEN(b));
163 	if (!b_mconf_ie || b_mconf_ie_len != 7)
164 		goto exit;
165 	if (b_mconf_ie_r)
166 		*b_mconf_ie_r = b_mconf_ie;
167 
168 	if (a->mesh_id.SsidLength != b->mesh_id.SsidLength
169 		|| _rtw_memcmp(a->mesh_id.Ssid, b->mesh_id.Ssid, a->mesh_id.SsidLength) == _FALSE)
170 		goto exit;
171 
172 	if (_rtw_memcmp(a_mconf_ie + 2, b_mconf_ie + 2, 5) == _FALSE)
173 		goto exit;
174 
175 	ret = 1;
176 
177 exit:
178 	return ret;
179 }
180 
rtw_bss_is_same_mbss(WLAN_BSSID_EX * a,WLAN_BSSID_EX * b)181 int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
182 {
183 	return _rtw_bss_is_same_mbss(a, b, NULL, NULL);
184 }
185 
rtw_bss_is_candidate_mesh_peer(_adapter * adapter,WLAN_BSSID_EX * target,u8 ch,u8 add_peer)186 int rtw_bss_is_candidate_mesh_peer(_adapter *adapter, WLAN_BSSID_EX *target, u8 ch, u8 add_peer)
187 {
188 	int ret = 0;
189 	WLAN_BSSID_EX *self = &adapter->mlmepriv.cur_network.network;
190 	u8 *s_mconf_ie, *t_mconf_ie;
191 	u8 auth_pid;
192 	int i, j;
193 
194 	if (ch && self->Configuration.DSConfig != target->Configuration.DSConfig)
195 		goto exit;
196 
197 	if (!_rtw_bss_is_same_mbss(self, target, &s_mconf_ie, &t_mconf_ie))
198 		goto exit;
199 
200 	if (add_peer) {
201 		/* Accept additional mesh peerings */
202 		if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(t_mconf_ie + 2) == 0)
203 			goto exit;
204 	}
205 
206 	/* BSSBasicRateSet */
207 	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
208 		if (target->SupportedRates[i] == 0)
209 			break;
210 		if (target->SupportedRates[i] & 0x80) {
211 			u8 match = 0;
212 
213 			if (!ch) {
214 				/* off-channel, check target with our hardcode capability */
215 				if (target->Configuration.DSConfig > 14)
216 					match = rtw_is_basic_rate_ofdm(target->SupportedRates[i]);
217 				else
218 					match = rtw_is_basic_rate_mix(target->SupportedRates[i]);
219 			} else {
220 				for (j = 0; j < NDIS_802_11_LENGTH_RATES_EX; j++) {
221 					if (self->SupportedRates[j] == 0)
222 						break;
223 					if (self->SupportedRates[j] == target->SupportedRates[i]) {
224 						match = 1;
225 						break;
226 					}
227 				}
228 			}
229 			if (!match)
230 				goto exit;
231 		}
232 	}
233 
234 	/* BSSBasicMCSSet */
235 
236 
237 	auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(s_mconf_ie + 2);
238 	if (auth_pid && auth_pid <= 2) {
239 		struct security_priv *sec = &adapter->securitypriv;
240 		u8 *rsn_ie;
241 		int rsn_ie_len;
242 		int group_cipher = 0, pairwise_cipher = 0, gmcs = 0;
243 		u8 mfp_opt = MFP_NO;
244 
245 		/* 802.1X connected to AS ? */
246 
247 		/* RSN */
248 		rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(target), &rsn_ie_len, BSS_EX_TLV_IES_LEN(target));
249 		if (!rsn_ie || rsn_ie_len == 0)
250 			goto exit;
251 		if (rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, NULL, &mfp_opt, NULL) != _SUCCESS)
252 			goto exit;
253 		if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt < MFP_OPTIONAL)
254 			|| (mfp_opt == MFP_REQUIRED && sec->mfp_opt < MFP_OPTIONAL))
255 			goto exit;
256 		if (!(sec->wpa2_group_cipher & group_cipher))
257 			goto exit;
258 		if (!(sec->wpa2_pairwise_cipher & pairwise_cipher))
259 			goto exit;
260 		#ifdef CONFIG_IEEE80211W
261 		if ((sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)
262 			&& security_type_bip_to_gmcs(sec->dot11wCipher) != gmcs)
263 			goto exit;
264 		#endif
265 	}
266 
267 	ret = 1;
268 
269 exit:
270 	return ret;
271 }
272 
rtw_mesh_bss_peering_status(WLAN_BSSID_EX * bss,u8 * nop,u8 * accept)273 void rtw_mesh_bss_peering_status(WLAN_BSSID_EX *bss, u8 *nop, u8 *accept)
274 {
275 	u8 *ie;
276 	int ie_len;
277 
278 	if (nop)
279 		*nop = 0;
280 	if (accept)
281 		*accept = 0;
282 
283 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
284 			BSS_EX_TLV_IES_LEN(bss));
285 	if (!ie || ie_len != 7)
286 		goto exit;
287 
288 	if (nop)
289 		*nop = GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2);
290 	if (accept)
291 		*accept = GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2);
292 
293 exit:
294 	return;
295 }
296 
297 #if CONFIG_RTW_MESH_ACNODE_PREVENT
rtw_mesh_update_scanned_acnode_status(_adapter * adapter,struct wlan_network * scanned)298 void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned)
299 {
300 	bool acnode;
301 	u8 nop, accept;
302 
303 	rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
304 
305 	acnode = !nop && accept;
306 
307 	if (acnode && scanned->acnode_stime == 0) {
308 		scanned->acnode_stime = rtw_get_current_time();
309 		if (scanned->acnode_stime == 0)
310 			scanned->acnode_stime++;
311 	} else if (!acnode) {
312 		scanned->acnode_stime = 0;
313 		scanned->acnode_notify_etime = 0;
314 	}
315 }
316 
rtw_mesh_scanned_is_acnode_confirmed(_adapter * adapter,struct wlan_network * scanned)317 bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned)
318 {
319 	return scanned->acnode_stime
320 			&& rtw_get_passing_time_ms(scanned->acnode_stime)
321 				> adapter->mesh_cfg.peer_sel_policy.acnode_conf_timeout_ms;
322 }
323 
rtw_mesh_scanned_is_acnode_allow_notify(_adapter * adapter,struct wlan_network * scanned)324 static bool rtw_mesh_scanned_is_acnode_allow_notify(_adapter *adapter, struct wlan_network *scanned)
325 {
326 	return scanned->acnode_notify_etime
327 			&& rtw_time_after(scanned->acnode_notify_etime, rtw_get_current_time());
328 }
329 
rtw_mesh_acnode_prevent_allow_sacrifice(_adapter * adapter)330 bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter)
331 {
332 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
333 	struct sta_priv *stapriv = &adapter->stapriv;
334 	bool allow = 0;
335 
336 	if (!mcfg->peer_sel_policy.acnode_prevent
337 		|| mcfg->max_peer_links <= 1
338 		|| stapriv->asoc_list_cnt < mcfg->max_peer_links)
339 		goto exit;
340 
341 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
342 	if (rtw_mesh_cto_mgate_required(adapter))
343 		goto exit;
344 #endif
345 
346 	allow = 1;
347 
348 exit:
349 	return allow;
350 }
351 
rtw_mesh_acnode_candidate_exist(_adapter * adapter)352 static bool rtw_mesh_acnode_candidate_exist(_adapter *adapter)
353 {
354 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
355 	struct sta_priv *stapriv = &adapter->stapriv;
356 	struct mlme_priv *mlme = &adapter->mlmepriv;
357 	_queue *queue = &(mlme->scanned_queue);
358 	_list *head, *list;
359 	_irqL irqL;
360 	struct wlan_network *scanned = NULL;
361 	struct sta_info *sta = NULL;
362 	bool need = 0;
363 
364 	_enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
365 
366 	head = get_list_head(queue);
367 	list = get_next(head);
368 	while (!rtw_end_of_queue_search(head, list)) {
369 		scanned = LIST_CONTAINOR(list, struct wlan_network, list);
370 		list = get_next(list);
371 
372 		if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
373 			&& rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)
374 			&& (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
375 			#if CONFIG_RTW_MACADDR_ACL
376 			&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
377 			#endif
378 			&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
379 			#if CONFIG_RTW_MESH_PEER_BLACKLIST
380 			&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
381 			#endif
382 			#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
383 			&& rtw_mesh_cto_mgate_network_filter(adapter, scanned)
384 			#endif
385 		) {
386 			need = 1;
387 			break;
388 		}
389 	}
390 
391 	_exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
392 
393 	return need;
394 }
395 
rtw_mesh_acnode_prevent_sacrifice_chk(_adapter * adapter,struct sta_info ** sac,struct sta_info * com)396 static int rtw_mesh_acnode_prevent_sacrifice_chk(_adapter *adapter, struct sta_info **sac, struct sta_info *com)
397 {
398 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
399 	int updated = 0;
400 
401 	/*
402 	* TODO: compare next_hop reference cnt of forwarding info
403 	* don't sacrifice working next_hop or choose sta with least cnt
404 	*/
405 
406 	if (*sac == NULL) {
407 		updated = 1;
408 		goto exit;
409 	}
410 
411 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
412 	if (mcfg->peer_sel_policy.cto_mgate_require
413 		&& !mcfg->dot11MeshGateAnnouncementProtocol
414 	) {
415 		if (IS_CTO_MGATE_CONF_TIMEOUT(com->plink)) {
416 			if (!IS_CTO_MGATE_CONF_TIMEOUT((*sac)->plink)) {
417 				/* blacklist > not blacklist */
418 				updated = 1;
419 				goto exit;
420 			}
421 		} else if (!IS_CTO_MGATE_CONF_DISABLED(com->plink)) {
422 			if (IS_CTO_MGATE_CONF_DISABLED((*sac)->plink)) {
423 				/* confirming > disabled */
424 				updated = 1;
425 				goto exit;
426 			}
427 		}
428 	}
429 #endif
430 
431 exit:
432 	if (updated)
433 		*sac = com;
434 
435 	return updated;
436 }
437 
_rtw_mesh_acnode_prevent_pick_sacrifice(_adapter * adapter)438 struct sta_info *_rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
439 {
440 	struct sta_priv *stapriv = &adapter->stapriv;
441 	_list *head, *list;
442 	struct sta_info *sta, *sacrifice = NULL;
443 	u8 nop;
444 
445 	head = &stapriv->asoc_list;
446 	list = get_next(head);
447 	while (rtw_end_of_queue_search(head, list) == _FALSE) {
448 		sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
449 		list = get_next(list);
450 
451 		if (!sta->plink || !sta->plink->scanned) {
452 			rtw_warn_on(1);
453 			continue;
454 		}
455 
456 		rtw_mesh_bss_peering_status(&sta->plink->scanned->network, &nop, NULL);
457 		if (nop < 2)
458 			continue;
459 
460 		rtw_mesh_acnode_prevent_sacrifice_chk(adapter, &sacrifice, sta);
461 	}
462 
463 	return sacrifice;
464 }
465 
rtw_mesh_acnode_prevent_pick_sacrifice(_adapter * adapter)466 struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
467 {
468 	struct sta_priv *stapriv = &adapter->stapriv;
469 	struct sta_info *sacrifice = NULL;
470 
471 	enter_critical_bh(&stapriv->asoc_list_lock);
472 
473 	sacrifice = _rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
474 
475 	exit_critical_bh(&stapriv->asoc_list_lock);
476 
477 	return sacrifice;
478 }
479 
rtw_mesh_acnode_rsvd_chk(_adapter * adapter)480 static void rtw_mesh_acnode_rsvd_chk(_adapter *adapter)
481 {
482 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
483 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
484 	u8 acnode_rsvd = 0;
485 
486 	if (rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
487 		&& rtw_mesh_acnode_prevent_pick_sacrifice(adapter)
488 		&& rtw_mesh_acnode_candidate_exist(adapter))
489 		acnode_rsvd = 1;
490 
491 	if (plink_ctl->acnode_rsvd != acnode_rsvd) {
492 		plink_ctl->acnode_rsvd = acnode_rsvd;
493 		RTW_INFO(FUNC_ADPT_FMT" acnode_rsvd = %d\n", FUNC_ADPT_ARG(adapter), plink_ctl->acnode_rsvd);
494 		update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, 1, 0);
495 	}
496 }
497 
rtw_mesh_acnode_set_notify_etime(_adapter * adapter,u8 * rframe_whdr)498 static void rtw_mesh_acnode_set_notify_etime(_adapter *adapter, u8 *rframe_whdr)
499 {
500 	if (adapter->mesh_info.plink_ctl.acnode_rsvd) {
501 		struct wlan_network *scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, get_addr2_ptr(rframe_whdr));
502 
503 		if (rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)) {
504 			scanned->acnode_notify_etime = rtw_get_current_time()
505 				+ rtw_ms_to_systime(adapter->mesh_cfg.peer_sel_policy.acnode_notify_timeout_ms);
506 			if (scanned->acnode_notify_etime == 0)
507 				scanned->acnode_notify_etime++;
508 		}
509 	}
510 }
511 
dump_mesh_acnode_prevent_settings(void * sel,_adapter * adapter)512 void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter)
513 {
514 	struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
515 
516 	RTW_PRINT_SEL(sel, "%-6s %-12s %-14s\n"
517 		, "enable", "conf_timeout", "nofity_timeout");
518 	RTW_PRINT_SEL(sel, "%6u %12u %14u\n"
519 		, peer_sel_policy->acnode_prevent
520 		, peer_sel_policy->acnode_conf_timeout_ms
521 		, peer_sel_policy->acnode_notify_timeout_ms);
522 }
523 #endif /* CONFIG_RTW_MESH_ACNODE_PREVENT */
524 
525 #if CONFIG_RTW_MESH_PEER_BLACKLIST
rtw_mesh_peer_blacklist_add(_adapter * adapter,const u8 * addr)526 int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr)
527 {
528 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
529 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
530 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
531 
532 	return rtw_blacklist_add(&plink_ctl->peer_blacklist, addr
533 		, mcfg->peer_sel_policy.peer_blacklist_timeout_ms);
534 }
535 
rtw_mesh_peer_blacklist_del(_adapter * adapter,const u8 * addr)536 int rtw_mesh_peer_blacklist_del(_adapter *adapter, const u8 *addr)
537 {
538 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
539 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
540 
541 	return rtw_blacklist_del(&plink_ctl->peer_blacklist, addr);
542 }
543 
rtw_mesh_peer_blacklist_search(_adapter * adapter,const u8 * addr)544 int rtw_mesh_peer_blacklist_search(_adapter *adapter, const u8 *addr)
545 {
546 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
547 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
548 
549 	return rtw_blacklist_search(&plink_ctl->peer_blacklist, addr);
550 }
551 
rtw_mesh_peer_blacklist_flush(_adapter * adapter)552 void rtw_mesh_peer_blacklist_flush(_adapter *adapter)
553 {
554 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
555 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
556 
557 	rtw_blacklist_flush(&plink_ctl->peer_blacklist);
558 }
559 
dump_mesh_peer_blacklist(void * sel,_adapter * adapter)560 void dump_mesh_peer_blacklist(void *sel, _adapter *adapter)
561 {
562 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
563 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
564 
565 	dump_blacklist(sel, &plink_ctl->peer_blacklist, "blacklist");
566 }
567 
dump_mesh_peer_blacklist_settings(void * sel,_adapter * adapter)568 void dump_mesh_peer_blacklist_settings(void *sel, _adapter *adapter)
569 {
570 	struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
571 
572 	RTW_PRINT_SEL(sel, "%-12s %-17s\n"
573 		, "conf_timeout", "blacklist_timeout");
574 	RTW_PRINT_SEL(sel, "%12u %17u\n"
575 		, peer_sel_policy->peer_conf_timeout_ms
576 		, peer_sel_policy->peer_blacklist_timeout_ms);
577 }
578 #endif /* CONFIG_RTW_MESH_PEER_BLACKLIST */
579 
580 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
rtw_mesh_cto_mgate_required(_adapter * adapter)581 u8 rtw_mesh_cto_mgate_required(_adapter *adapter)
582 {
583 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
584 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
585 
586 	return mcfg->peer_sel_policy.cto_mgate_require
587 		&& !rtw_bss_is_cto_mgate(&(mlmeext->mlmext_info.network));
588 }
589 
rtw_mesh_cto_mgate_network_filter(_adapter * adapter,struct wlan_network * scanned)590 u8 rtw_mesh_cto_mgate_network_filter(_adapter *adapter, struct wlan_network *scanned)
591 {
592 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
593 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
594 
595 	return !rtw_mesh_cto_mgate_required(adapter)
596 			|| (rtw_bss_is_cto_mgate(&scanned->network)
597 				&& !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress));
598 }
599 
rtw_mesh_cto_mgate_blacklist_add(_adapter * adapter,const u8 * addr)600 int rtw_mesh_cto_mgate_blacklist_add(_adapter *adapter, const u8 *addr)
601 {
602 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
603 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
604 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
605 
606 	return rtw_blacklist_add(&plink_ctl->cto_mgate_blacklist, addr
607 		, mcfg->peer_sel_policy.cto_mgate_blacklist_timeout_ms);
608 }
609 
rtw_mesh_cto_mgate_blacklist_del(_adapter * adapter,const u8 * addr)610 int rtw_mesh_cto_mgate_blacklist_del(_adapter *adapter, const u8 *addr)
611 {
612 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
613 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
614 
615 	return rtw_blacklist_del(&plink_ctl->cto_mgate_blacklist, addr);
616 }
617 
rtw_mesh_cto_mgate_blacklist_search(_adapter * adapter,const u8 * addr)618 int rtw_mesh_cto_mgate_blacklist_search(_adapter *adapter, const u8 *addr)
619 {
620 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
621 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
622 
623 	return rtw_blacklist_search(&plink_ctl->cto_mgate_blacklist, addr);
624 }
625 
rtw_mesh_cto_mgate_blacklist_flush(_adapter * adapter)626 void rtw_mesh_cto_mgate_blacklist_flush(_adapter *adapter)
627 {
628 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
629 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
630 
631 	rtw_blacklist_flush(&plink_ctl->cto_mgate_blacklist);
632 }
633 
dump_mesh_cto_mgate_blacklist(void * sel,_adapter * adapter)634 void dump_mesh_cto_mgate_blacklist(void *sel, _adapter *adapter)
635 {
636 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
637 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
638 
639 	dump_blacklist(sel, &plink_ctl->cto_mgate_blacklist, "blacklist");
640 }
641 
dump_mesh_cto_mgate_blacklist_settings(void * sel,_adapter * adapter)642 void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter)
643 {
644 	struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
645 
646 	RTW_PRINT_SEL(sel, "%-12s %-17s\n"
647 		, "conf_timeout", "blacklist_timeout");
648 	RTW_PRINT_SEL(sel, "%12u %17u\n"
649 		, peer_sel_policy->cto_mgate_conf_timeout_ms
650 		, peer_sel_policy->cto_mgate_blacklist_timeout_ms);
651 }
652 
rtw_mesh_cto_mgate_blacklist_chk(_adapter * adapter)653 static void rtw_mesh_cto_mgate_blacklist_chk(_adapter *adapter)
654 {
655 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
656 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
657 	_queue *blist = &plink_ctl->cto_mgate_blacklist;
658 	_list *list, *head;
659 	struct blacklist_ent *ent = NULL;
660 	struct wlan_network *scanned = NULL;
661 
662 	enter_critical_bh(&blist->lock);
663 	head = &blist->queue;
664 	list = get_next(head);
665 	while (rtw_end_of_queue_search(head, list) == _FALSE) {
666 		ent = LIST_CONTAINOR(list, struct blacklist_ent, list);
667 		list = get_next(list);
668 
669 		if (rtw_time_after(rtw_get_current_time(), ent->exp_time)) {
670 			rtw_list_delete(&ent->list);
671 			rtw_mfree(ent, sizeof(struct blacklist_ent));
672 			continue;
673 		}
674 
675 		scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, ent->addr);
676 		if (!scanned)
677 			continue;
678 
679 		if (rtw_bss_is_forwarding(&scanned->network)) {
680 			rtw_list_delete(&ent->list);
681 			rtw_mfree(ent, sizeof(struct blacklist_ent));
682 		}
683 	}
684 
685 	exit_critical_bh(&blist->lock);
686 }
687 #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
688 
rtw_chk_candidate_peer_notify(_adapter * adapter,struct wlan_network * scanned)689 void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned)
690 {
691 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
692 	struct mlme_priv *mlme = &adapter->mlmepriv;
693 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
694 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
695 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
696 	bool acnode = 0;
697 
698 	if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl))
699 		goto exit;
700 
701 	if (plink_ctl->num >= RTW_MESH_MAX_PEER_CANDIDATES)
702 		goto exit;
703 
704 #if CONFIG_RTW_MESH_ACNODE_PREVENT
705 	if (plink_ctl->acnode_rsvd) {
706 		acnode = rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned);
707 		if (acnode && !rtw_mesh_scanned_is_acnode_allow_notify(adapter, scanned))
708 			goto exit;
709 	}
710 #endif
711 
712 	/* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */
713 	if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0)
714 		goto exit;
715 
716 	if (rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms
717 		|| (mcfg->rssi_threshold && mcfg->rssi_threshold > scanned->network.Rssi)
718 		|| !rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
719 		#if CONFIG_RTW_MACADDR_ACL
720 		|| rtw_access_ctrl(adapter, scanned->network.MacAddress) == _FALSE
721 		#endif
722 		|| rtw_mesh_plink_get(adapter, scanned->network.MacAddress)
723 		#if CONFIG_RTW_MESH_PEER_BLACKLIST
724 		|| rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
725 		#endif
726 		#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
727 		|| !rtw_mesh_cto_mgate_network_filter(adapter, scanned)
728 		#endif
729 	)
730 		goto exit;
731 
732 #if CONFIG_RTW_MESH_ACNODE_PREVENT
733 	if (acnode) {
734 		scanned->acnode_notify_etime = 0;
735 		RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n"
736 			, FUNC_ADPT_ARG(adapter), MAC_ARG(scanned->network.MacAddress));
737 	}
738 #endif
739 
740 #ifdef CONFIG_IOCTL_CFG80211
741 	rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev
742 		, scanned->network.MacAddress
743 		, BSS_EX_TLV_IES(&scanned->network)
744 		, BSS_EX_TLV_IES_LEN(&scanned->network)
745 		, scanned->network.Rssi
746 		, GFP_ATOMIC
747 	);
748 #endif
749 
750 exit:
751 	return;
752 }
753 
rtw_mesh_peer_status_chk(_adapter * adapter)754 void rtw_mesh_peer_status_chk(_adapter *adapter)
755 {
756 	struct mlme_priv *mlme = &adapter->mlmepriv;
757 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
758 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
759 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
760 	struct mesh_plink_ent *plink;
761 	_list *head, *list;
762 	struct sta_info *sta = NULL;
763 	struct sta_priv *stapriv = &adapter->stapriv;
764 	int stainfo_offset;
765 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
766 	u8 cto_mgate, forwarding, mgate;
767 #endif
768 	u8 flush;
769 	s8 flush_list[NUM_STA];
770 	u8 flush_num = 0;
771 	int i;
772 
773 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
774 	if (rtw_mesh_cto_mgate_required(adapter)) {
775 		/* active scan on operating channel */
776 		issue_probereq_ex(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, NULL, 0, 0, 0, 0);
777 	}
778 #endif
779 
780 	enter_critical_bh(&(plink_ctl->lock));
781 
782 	/* check established peers */
783 	enter_critical_bh(&stapriv->asoc_list_lock);
784 
785 	head = &stapriv->asoc_list;
786 	list = get_next(head);
787 	while (rtw_end_of_queue_search(head, list) == _FALSE) {
788 		sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
789 		list = get_next(list);
790 
791 		if (!sta->plink || !sta->plink->scanned) {
792 			rtw_warn_on(1);
793 			continue;
794 		}
795 		plink = sta->plink;
796 		flush = 0;
797 
798 		/* remove unsuitable peer */
799 		if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 0)
800 			#if CONFIG_RTW_MACADDR_ACL
801 			|| rtw_access_ctrl(adapter, plink->addr) == _FALSE
802 			#endif
803 		) {
804 			flush = 1;
805 			goto flush_add;
806 		}
807 
808 		#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
809 		cto_mgate = rtw_bss_is_cto_mgate(&(plink->scanned->network));
810 		forwarding = rtw_bss_is_forwarding(&(plink->scanned->network));
811 		mgate = rtw_mesh_gate_search(minfo->mesh_paths, sta->cmn.mac_addr);
812 
813 		/* CTO_MGATE required, remove peer without CTO_MGATE */
814 		if (rtw_mesh_cto_mgate_required(adapter) && !cto_mgate) {
815 			flush = 1;
816 			goto flush_add;
817 		}
818 
819 		/* cto_mgate_conf status update */
820 		if (IS_CTO_MGATE_CONF_DISABLED(plink)) {
821 			if (cto_mgate && !forwarding && !mgate)
822 				SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms);
823 			else
824 				rtw_mesh_cto_mgate_blacklist_del(adapter, sta->cmn.mac_addr);
825 		} else {
826 			/* cto_mgate_conf ongoing */
827 			if (cto_mgate && !forwarding && !mgate) {
828 				if (IS_CTO_MGATE_CONF_TIMEOUT(plink)) {
829 					rtw_mesh_cto_mgate_blacklist_add(adapter, sta->cmn.mac_addr);
830 
831 					/* CTO_MGATE required, remove peering can't achieve CTO_MGATE */
832 					if (rtw_mesh_cto_mgate_required(adapter)) {
833 						flush = 1;
834 						goto flush_add;
835 					}
836 				}
837 			} else {
838 				SET_CTO_MGATE_CONF_DISABLED(plink);
839 				rtw_mesh_cto_mgate_blacklist_del(adapter, sta->cmn.mac_addr);
840 			}
841 		}
842 		#endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
843 
844 flush_add:
845 		if (flush) {
846 			rtw_list_delete(&sta->asoc_list);
847 			stapriv->asoc_list_cnt--;
848 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
849 			if (sta->tbtx_enable)
850 				stapriv->tbtx_asoc_list_cnt--;
851 #endif
852 			STA_SET_MESH_PLINK(sta, NULL);
853 
854 			stainfo_offset = rtw_stainfo_offset(stapriv, sta);
855 			if (stainfo_offset_valid(stainfo_offset))
856 				flush_list[flush_num++] = stainfo_offset;
857 			else
858 				rtw_warn_on(1);
859 		}
860 	}
861 
862 	exit_critical_bh(&stapriv->asoc_list_lock);
863 
864 	/* check non-established peers */
865 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
866 		plink = &plink_ctl->ent[i];
867 		if (plink->valid != _TRUE || plink->plink_state == RTW_MESH_PLINK_ESTAB)
868 			continue;
869 
870 		/* remove unsuitable peer */
871 		if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 1)
872 			#if CONFIG_RTW_MACADDR_ACL
873 			|| rtw_access_ctrl(adapter, plink->addr) == _FALSE
874 			#endif
875 		) {
876 			_rtw_mesh_expire_peer_ent(adapter, plink);
877 			continue;
878 		}
879 
880 		#if CONFIG_RTW_MESH_PEER_BLACKLIST
881 		/* peer confirm check timeout, add to black list */
882 		if (IS_PEER_CONF_TIMEOUT(plink)) {
883 			rtw_mesh_peer_blacklist_add(adapter, plink->addr);
884 			_rtw_mesh_expire_peer_ent(adapter, plink);
885 		}
886 		#endif
887 	}
888 
889 	exit_critical_bh(&(plink_ctl->lock));
890 
891 	if (flush_num) {
892 		u8 sta_addr[ETH_ALEN];
893 		u8 updated = _FALSE;
894 
895 		for (i = 0; i < flush_num; i++) {
896 			sta = rtw_get_stainfo_by_offset(stapriv, flush_list[i]);
897 			_rtw_memcpy(sta_addr, sta->cmn.mac_addr, ETH_ALEN);
898 
899 			updated |= ap_free_sta(adapter, sta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);
900 			rtw_mesh_expire_peer(adapter, sta_addr);
901 		}
902 
903 		associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
904 	}
905 
906 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
907 	/* loop cto_mgate_blacklist to remove ent according to scan_r */
908 	rtw_mesh_cto_mgate_blacklist_chk(adapter);
909 #endif
910 
911 #if CONFIG_RTW_MESH_ACNODE_PREVENT
912 	rtw_mesh_acnode_rsvd_chk(adapter);
913 #endif
914 
915 	return;
916 }
917 
918 #if CONFIG_RTW_MESH_OFFCH_CAND
rtw_mesh_offch_cto_mgate_required(_adapter * adapter)919 static u8 rtw_mesh_offch_cto_mgate_required(_adapter *adapter)
920 {
921 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
922 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
923 	struct mlme_priv *mlme = &adapter->mlmepriv;
924 	_queue *queue = &(mlme->scanned_queue);
925 	_list *head, *pos;
926 	struct wlan_network *scanned = NULL;
927 	u8 ret = 0;
928 
929 	if (!rtw_mesh_cto_mgate_required(adapter))
930 		goto exit;
931 
932 	enter_critical_bh(&(mlme->scanned_queue.lock));
933 
934 	head = get_list_head(queue);
935 	pos = get_next(head);
936 	while (!rtw_end_of_queue_search(head, pos)) {
937 		scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
938 
939 		if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
940 			&& (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
941 			#if CONFIG_RTW_MACADDR_ACL
942 			&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
943 			#endif
944 			&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
945 			&& rtw_bss_is_cto_mgate(&scanned->network)
946 			#if CONFIG_RTW_MESH_PEER_BLACKLIST
947 			&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
948 			#endif
949 			&& !rtw_mesh_cto_mgate_blacklist_search(adapter, scanned->network.MacAddress)
950 		)
951 			break;
952 
953 		pos = get_next(pos);
954 	}
955 
956 	if (rtw_end_of_queue_search(head, pos))
957 		ret = 1;
958 
959 	exit_critical_bh(&(mlme->scanned_queue.lock));
960 
961 exit:
962 	return ret;
963 #else
964 	return 0;
965 #endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
966 }
967 
rtw_mesh_offch_candidate_accepted(_adapter * adapter)968 u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter)
969 {
970 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
971 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
972 	u8 ret = 0;
973 
974 	if (!adapter->mesh_cfg.peer_sel_policy.offch_cand)
975 		goto exit;
976 
977 	ret = MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)
978 		&& (!plink_ctl->num || rtw_mesh_offch_cto_mgate_required(adapter))
979 		;
980 
981 #ifdef CONFIG_CONCURRENT_MODE
982 	if (ret) {
983 		struct mi_state mstate_no_self;
984 
985 		rtw_mi_status_no_self(adapter, &mstate_no_self);
986 		if (MSTATE_STA_LD_NUM(&mstate_no_self))
987 			ret = 0;
988 	}
989 #endif
990 
991 exit:
992 	return ret;
993 }
994 
995 /*
996  * this function is called under off channel candidate is required
997  * the channel with maximum candidate count is selected
998 */
rtw_mesh_select_operating_ch(_adapter * adapter)999 u8 rtw_mesh_select_operating_ch(_adapter *adapter)
1000 {
1001 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
1002 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
1003 	struct mlme_priv *mlme = &adapter->mlmepriv;
1004 	_queue *queue = &(mlme->scanned_queue);
1005 	_list *head, *pos;
1006 	_irqL irqL;
1007 	struct wlan_network *scanned = NULL;
1008 	int i;
1009 	/* statistics for candidate accept peering */
1010 	u8 cand_ap_cnt[MAX_CHANNEL_NUM] = {0};
1011 	u8 max_cand_ap_ch = 0;
1012 	u8 max_cand_ap_cnt = 0;
1013 	/* statistics for candidate including not accept peering */
1014 	u8 cand_cnt[MAX_CHANNEL_NUM] = {0};
1015 	u8 max_cand_ch = 0;
1016 	u8 max_cand_cnt = 0;
1017 
1018 	_enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
1019 
1020 	head = get_list_head(queue);
1021 	pos = get_next(head);
1022 	while (!rtw_end_of_queue_search(head, pos)) {
1023 		scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
1024 		pos = get_next(pos);
1025 
1026 		if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
1027 			&& (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
1028 			#if CONFIG_RTW_MACADDR_ACL
1029 			&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
1030 			#endif
1031 			&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 0, 0)
1032 			#if CONFIG_RTW_MESH_PEER_BLACKLIST
1033 			&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
1034 			#endif
1035 			#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
1036 			&& rtw_mesh_cto_mgate_network_filter(adapter, scanned)
1037 			#endif
1038 		) {
1039 			int ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scanned->network.Configuration.DSConfig);
1040 
1041 			if (ch_set_idx >= 0
1042 				&& !(rfctl->channel_set[ch_set_idx].flags & RTW_CHF_NO_IR)
1043 				&& !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx])
1044 			) {
1045 				u8 nop, accept;
1046 
1047 				rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
1048 				cand_cnt[ch_set_idx]++;
1049 				if (max_cand_cnt < cand_cnt[ch_set_idx]) {
1050 					max_cand_cnt = cand_cnt[ch_set_idx];
1051 					max_cand_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
1052 				}
1053 				if (accept) {
1054 					cand_ap_cnt[ch_set_idx]++;
1055 					if (max_cand_ap_cnt < cand_ap_cnt[ch_set_idx]) {
1056 						max_cand_ap_cnt = cand_ap_cnt[ch_set_idx];
1057 						max_cand_ap_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
1058 					}
1059 				}
1060 			}
1061 		}
1062 	}
1063 
1064 	_exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
1065 
1066 	return max_cand_ap_ch ? max_cand_ap_ch : max_cand_ch;
1067 }
1068 
dump_mesh_offch_cand_settings(void * sel,_adapter * adapter)1069 void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter)
1070 {
1071 	struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
1072 
1073 	RTW_PRINT_SEL(sel, "%-6s %-11s\n"
1074 		, "enable", "find_int_ms");
1075 	RTW_PRINT_SEL(sel, "%6u %11u\n"
1076 		, peer_sel_policy->offch_cand, peer_sel_policy->offch_find_int_ms);
1077 }
1078 #endif /* CONFIG_RTW_MESH_OFFCH_CAND */
1079 
dump_mesh_peer_sel_policy(void * sel,_adapter * adapter)1080 void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter)
1081 {
1082 	struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
1083 
1084 	RTW_PRINT_SEL(sel, "%-12s\n", "scanr_exp_ms");
1085 	RTW_PRINT_SEL(sel, "%12u\n", peer_sel_policy->scanr_exp_ms);
1086 }
1087 
dump_mesh_networks(void * sel,_adapter * adapter)1088 void dump_mesh_networks(void *sel, _adapter *adapter)
1089 {
1090 #if CONFIG_RTW_MESH_ACNODE_PREVENT
1091 #define NSTATE_TITLE_FMT_ACN " %-5s"
1092 #define NSTATE_VALUE_FMT_ACN " %5d"
1093 #define NSTATE_TITLE_ARG_ACN , "acn"
1094 #define NSTATE_VALUE_ARG_ACN , (acn_ms < 99999 ? acn_ms : 99999)
1095 #else
1096 #define NSTATE_TITLE_FMT_ACN ""
1097 #define NSTATE_VALUE_FMT_ACN ""
1098 #define NSTATE_TITLE_ARG_ACN
1099 #define NSTATE_VALUE_ARG_ACN
1100 #endif
1101 
1102 	struct mlme_priv *mlme = &(adapter->mlmepriv);
1103 	_queue *queue = &(mlme->scanned_queue);
1104 	struct wlan_network	*network;
1105 	_list *list, *head;
1106 	u8 same_mbss;
1107 	u8 candidate;
1108 	struct mesh_plink_ent *plink;
1109 	u8 blocked;
1110 	u8 established;
1111 	s32 age_ms;
1112 #if CONFIG_RTW_MESH_ACNODE_PREVENT
1113 	s32 acn_ms;
1114 #endif
1115 	u8 *mesh_conf_ie;
1116 	sint mesh_conf_ie_len;
1117 	u8 auth_pid;
1118 	u8 *rsn_ie;
1119 	int rsn_ie_len;
1120 	int gcs, pcs, gmcs;
1121 	u8 mfp_opt;
1122 	struct wlan_network **mesh_networks;
1123 	u8 mesh_network_cnt = 0;
1124 	int i;
1125 
1126 	mesh_networks = rtw_zvmalloc(mlme->max_bss_cnt * sizeof(struct wlan_network *));
1127 	if (!mesh_networks)
1128 		return;
1129 
1130 	enter_critical_bh(&queue->lock);
1131 	head = get_list_head(queue);
1132 	list = get_next(head);
1133 
1134 	while (rtw_end_of_queue_search(head, list) == _FALSE) {
1135 		network = LIST_CONTAINOR(list, struct wlan_network, list);
1136 		list = get_next(list);
1137 
1138 		if (network->network.InfrastructureMode != Ndis802_11_mesh)
1139 			continue;
1140 
1141 		mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
1142 			, &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
1143 		if (!mesh_conf_ie || mesh_conf_ie_len != 7)
1144 			continue;
1145 
1146 		mesh_networks[mesh_network_cnt++] = network;
1147 	}
1148 
1149 	exit_critical_bh(&queue->lock);
1150 
1151 	RTW_PRINT_SEL(sel, "  %-17s %-3s %-4s %-5s %-32s %-10s"
1152 		" %-3s %-3s %-4s"
1153 		" %-3s %-3s %-3s"
1154 		NSTATE_TITLE_FMT_ACN
1155 		"\n"
1156 		, "bssid", "ch", "rssi", "age", "mesh_id", "P M C S A "
1157 		, "pcs", "gcs", "gmcs"
1158 		, "nop", "fwd", "cto"
1159 		NSTATE_TITLE_ARG_ACN
1160 	);
1161 
1162 	if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) {
1163 		network = &mlme->cur_network;
1164 		mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
1165 			, &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
1166 		if (mesh_conf_ie && mesh_conf_ie_len == 7) {
1167 			gcs = pcs = gmcs = 0;
1168 			mfp_opt = MFP_NO;
1169 			auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2);
1170 			if (auth_pid && auth_pid <= 2) {
1171 				rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network)
1172 							, &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
1173 				if (rsn_ie && rsn_ie_len)
1174 					rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL);
1175 			}
1176 			RTW_PRINT_SEL(sel, "* "MAC_FMT" %3d            %-32s %2x%2x%2x%2x%2x"
1177 				" %03x %03x %c%03x"
1178 				" %c%2u %3u %c%c "
1179 				"\n"
1180 				, MAC_ARG(network->network.MacAddress)
1181 				, network->network.Configuration.DSConfig
1182 				, network->network.mesh_id.Ssid
1183 				, GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2)
1184 				, GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2)
1185 				, GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2)
1186 				, GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2)
1187 				, auth_pid
1188 				, pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ')
1189 				, mfp_opt >= MFP_OPTIONAL ? gmcs : 0
1190 				, GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' '
1191 				, GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2)
1192 				, GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
1193 				, GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' '
1194 				, GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' '
1195 			);
1196 		}
1197 	}
1198 
1199 	for (i = 0; i < mesh_network_cnt; i++) {
1200 		network = mesh_networks[i];
1201 
1202 		if (network->network.InfrastructureMode != Ndis802_11_mesh)
1203 			continue;
1204 
1205 		mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
1206 			, &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
1207 		if (!mesh_conf_ie || mesh_conf_ie_len != 7)
1208 			continue;
1209 
1210 		gcs = pcs = gmcs = 0;
1211 		mfp_opt = MFP_NO;
1212 		auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2);
1213 		if (auth_pid && auth_pid <= 2) {
1214 			rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network), &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
1215 			if (rsn_ie && rsn_ie_len)
1216 				rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL);
1217 		}
1218 		age_ms = rtw_get_passing_time_ms(network->last_scanned);
1219 		#if CONFIG_RTW_MESH_ACNODE_PREVENT
1220 		if (network->acnode_stime == 0)
1221 			acn_ms = 0;
1222 		else
1223 			acn_ms = rtw_get_passing_time_ms(network->acnode_stime);
1224 		#endif
1225 		same_mbss = 0;
1226 		candidate = 0;
1227 		plink = NULL;
1228 		blocked = 0;
1229 		established = 0;
1230 
1231 		if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) {
1232 			plink = rtw_mesh_plink_get(adapter, network->network.MacAddress);
1233 			if (plink && plink->plink_state == RTW_MESH_PLINK_ESTAB)
1234 				established = 1;
1235 			else if (plink && plink->plink_state == RTW_MESH_PLINK_BLOCKED)
1236 				blocked = 1;
1237 			else if (plink)
1238 				;
1239 			else if (rtw_bss_is_candidate_mesh_peer(adapter, &network->network, 0, 1))
1240 				candidate = 1;
1241 			else if (rtw_bss_is_same_mbss(&mlme->cur_network.network, &network->network))
1242 				same_mbss = 1;
1243 		}
1244 
1245 		RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %2x%2x%2x%2x%2x"
1246 			" %03x %03x %c%03x"
1247 			" %c%2u %3u %c%c "
1248 			NSTATE_VALUE_FMT_ACN
1249 			"\n"
1250 			, established ? 'E' : (blocked ? 'B' : (plink ? 'N' : (candidate ? 'C' : (same_mbss ? 'S' : ' '))))
1251 			, MAC_ARG(network->network.MacAddress)
1252 			, network->network.Configuration.DSConfig
1253 			, network->network.Rssi
1254 			, age_ms < 99999 ? age_ms : 99999
1255 			, network->network.mesh_id.Ssid
1256 			, GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2)
1257 			, GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2)
1258 			, GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2)
1259 			, GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2)
1260 			, auth_pid
1261 			, pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ')
1262 			, mfp_opt >= MFP_OPTIONAL ? gmcs : 0
1263 			, GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' '
1264 			, GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2)
1265 			, GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
1266 			, GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' '
1267 			, GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' '
1268 			NSTATE_VALUE_ARG_ACN
1269 		);
1270 	}
1271 
1272 	rtw_vmfree(mesh_networks, mlme->max_bss_cnt * sizeof(struct wlan_network *));
1273 }
1274 
rtw_mesh_adjust_chbw(u8 req_ch,u8 * req_bw,u8 * req_offset)1275 void rtw_mesh_adjust_chbw(u8 req_ch, u8 *req_bw, u8 *req_offset)
1276 {
1277 	if (req_ch >= 5 && req_ch <= 9) {
1278 		/* prevent secondary channel offset mismatch */
1279 		if (*req_bw > CHANNEL_WIDTH_20) {
1280 			*req_bw = CHANNEL_WIDTH_20;
1281 			*req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1282 		}
1283 	}
1284 }
1285 
rtw_mesh_sae_check_frames(_adapter * adapter,const u8 * buf,u32 len,u8 tx,u16 alg,u16 seq,u16 status)1286 void rtw_mesh_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx, u16 alg, u16 seq, u16 status)
1287 {
1288 #if CONFIG_RTW_MESH_PEER_BLACKLIST
1289 	if (tx && seq == 1)
1290 		rtw_mesh_plink_set_peer_conf_timeout(adapter, GetAddr1Ptr(buf));
1291 #endif
1292 }
1293 
1294 #if CONFIG_RTW_MPM_TX_IES_SYNC_BSS
1295 #ifdef CONFIG_RTW_MESH_AEK
rtw_mpm_ampe_dec(_adapter * adapter,struct mesh_plink_ent * plink,u8 * fhead,size_t flen,u8 * fbody,u8 * mic_ie,u8 * ampe_buf)1296 static int rtw_mpm_ampe_dec(_adapter *adapter, struct mesh_plink_ent *plink
1297 	, u8 *fhead, size_t flen, u8* fbody, u8 *mic_ie, u8 *ampe_buf)
1298 {
1299 	int ret = _FAIL, verify_ret;
1300 	const u8 *aad[] = {adapter_mac_addr(adapter), plink->addr, fbody};
1301 	const size_t aad_len[] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody};
1302 	u8 *iv_crypt;
1303 	size_t iv_crypt_len = flen - (mic_ie + 2 - fhead);
1304 
1305 	iv_crypt = rtw_malloc(iv_crypt_len);
1306 	if (!iv_crypt)
1307 		goto exit;
1308 
1309 	_rtw_memcpy(iv_crypt, mic_ie + 2, iv_crypt_len);
1310 
1311 	verify_ret = rtw_aes_siv_decrypt(plink->aek, 32, iv_crypt, iv_crypt_len
1312 		, 3, aad, aad_len, ampe_buf);
1313 
1314 	rtw_mfree(iv_crypt, iv_crypt_len);
1315 
1316 	if (verify_ret) {
1317 		RTW_WARN("verify error, aek_valid=%u\n", plink->aek_valid);
1318 		goto exit;
1319 	} else if (*ampe_buf != WLAN_EID_AMPE) {
1320 		RTW_WARN("plaintext is not AMPE IE\n");
1321 		goto exit;
1322 	} else if ( 16 /* AES_BLOCK_SIZE*/ + 2 + *(ampe_buf + 1) > iv_crypt_len) {
1323 		RTW_WARN("plaintext AMPE IE length is not valid\n");
1324 		goto exit;
1325 	}
1326 
1327 	ret = _SUCCESS;
1328 
1329 exit:
1330 	return ret;
1331 }
1332 
rtw_mpm_ampe_enc(_adapter * adapter,struct mesh_plink_ent * plink,u8 * fbody,u8 * mic_ie,u8 * ampe_buf,bool inverse)1333 static int rtw_mpm_ampe_enc(_adapter *adapter, struct mesh_plink_ent *plink
1334 	, u8* fbody, u8 *mic_ie, u8 *ampe_buf, bool inverse)
1335 {
1336 	int ret = _FAIL, protect_ret;
1337 	const u8 *aad[3];
1338 	const size_t aad_len[3] = {ETH_ALEN, ETH_ALEN, mic_ie - fbody};
1339 	u8 *ampe_ie;
1340 	size_t ampe_ie_len = *(ampe_buf + 1) + 2; /* including id & len */
1341 
1342 	if (inverse) {
1343 		aad[0] = plink->addr;
1344 		aad[1] = adapter_mac_addr(adapter);
1345 	} else {
1346 		aad[0] = adapter_mac_addr(adapter);
1347 		aad[1] = plink->addr;
1348 	}
1349 	aad[2] = fbody;
1350 
1351 	ampe_ie = rtw_malloc(ampe_ie_len);
1352 	if (!ampe_ie)
1353 		goto exit;
1354 
1355 	_rtw_memcpy(ampe_ie, ampe_buf, ampe_ie_len);
1356 
1357 	protect_ret = rtw_aes_siv_encrypt(plink->aek, 32, ampe_ie, ampe_ie_len
1358 		, 3, aad, aad_len, mic_ie + 2);
1359 
1360 	rtw_mfree(ampe_ie, ampe_ie_len);
1361 
1362 	if (protect_ret) {
1363 		RTW_WARN("protect error, aek_valid=%u\n", plink->aek_valid);
1364 		goto exit;
1365 	}
1366 
1367 	ret = _SUCCESS;
1368 
1369 exit:
1370 	return ret;
1371 }
1372 #endif /* CONFIG_RTW_MESH_AEK */
1373 
rtw_mpm_tx_ies_sync_bss(_adapter * adapter,struct mesh_plink_ent * plink,u8 * fhead,size_t flen,u8 * fbody,u8 tlv_ies_offset,u8 * mpm_ie,u8 * mic_ie,u8 ** nbuf,size_t * nlen)1374 static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *plink
1375 	, u8 *fhead, size_t flen, u8* fbody, u8 tlv_ies_offset, u8 *mpm_ie, u8 *mic_ie
1376 	, u8 **nbuf, size_t *nlen)
1377 {
1378 	int ret = _FAIL;
1379 	struct mlme_priv *mlme = &(adapter->mlmepriv);
1380 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
1381 	struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
1382 	WLAN_BSSID_EX *network = &(mlmeinfo->network);
1383 	uint left;
1384 	u8 *pos;
1385 
1386 	uint mpm_ielen = *(mpm_ie + 1);
1387 	u8 *fpos;
1388 	u8 *new_buf = NULL;
1389 	size_t new_len = 0;
1390 
1391 	u8 *new_fhead;
1392 	size_t new_flen;
1393 	u8 *new_fbody;
1394 	u8 *new_mic_ie;
1395 
1396 #ifdef CONFIG_RTW_MESH_AEK
1397 	u8 *ampe_buf = NULL;
1398 	size_t ampe_buf_len = 0;
1399 
1400 	/* decode */
1401 	if (mic_ie) {
1402 		ampe_buf_len = flen - (mic_ie + 2 + 16 /* AES_BLOCK_SIZE */ - fhead);
1403 		ampe_buf = rtw_malloc(ampe_buf_len);
1404 		if (!ampe_buf)
1405 			goto exit;
1406 
1407 		if (rtw_mpm_ampe_dec(adapter, plink, fhead, flen, fbody, mic_ie, ampe_buf) != _SUCCESS)
1408 			goto exit;
1409 
1410 		if (*(ampe_buf + 1) >= 68) {
1411 			_rtw_memcpy(plink->sel_pcs, ampe_buf + 2, 4);
1412 			_rtw_memcpy(plink->l_nonce, ampe_buf + 6, 32);
1413 			_rtw_memcpy(plink->p_nonce, ampe_buf + 38, 32);
1414 		}
1415 	}
1416 #endif
1417 
1418 	/* count for new frame length  */
1419 	new_len = sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset;
1420 	left = BSS_EX_TLV_IES_LEN(network);
1421 	pos = BSS_EX_TLV_IES(network);
1422 	while (left >= 2) {
1423 		u8 id, elen;
1424 
1425 		id = *pos++;
1426 		elen = *pos++;
1427 		left -= 2;
1428 
1429 		if (elen > left)
1430 			break;
1431 
1432 		switch (id) {
1433 		case WLAN_EID_SSID:
1434 		case WLAN_EID_DS_PARAMS:
1435 		case WLAN_EID_TIM:
1436 			break;
1437 		default:
1438 			new_len += 2 + elen;
1439 		}
1440 
1441 		left -= elen;
1442 		pos += elen;
1443 	}
1444 	new_len += mpm_ielen + 2;
1445 	if (mic_ie)
1446 		new_len += 16 /* AES_BLOCK_SIZE*/ + 2 + ampe_buf_len;
1447 
1448 	/* alloc new frame */
1449 	new_buf = rtw_malloc(new_len);
1450 	if (!new_buf) {
1451 		rtw_warn_on(1);
1452 		goto exit;
1453 	}
1454 
1455 	/* build new frame  */
1456 	_rtw_memcpy(new_buf, fhead, sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset);
1457 	new_fhead = new_buf;
1458 	new_flen = new_len;
1459 	new_fbody = new_fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
1460 
1461 	fpos = new_fbody + tlv_ies_offset;
1462 	left = BSS_EX_TLV_IES_LEN(network);
1463 	pos = BSS_EX_TLV_IES(network);
1464 	while (left >= 2) {
1465 		u8 id, elen;
1466 
1467 		id = *pos++;
1468 		elen = *pos++;
1469 		left -= 2;
1470 
1471 		if (elen > left)
1472 			break;
1473 
1474 		switch (id) {
1475 		case WLAN_EID_SSID:
1476 		case WLAN_EID_DS_PARAMS:
1477 		case WLAN_EID_TIM:
1478 			break;
1479 		default:
1480 			fpos = rtw_set_ie(fpos, id, elen, pos, NULL);
1481 			if (id == WLAN_EID_MESH_CONFIG)
1482 				fpos = rtw_set_ie(fpos, WLAN_EID_MPM, mpm_ielen, mpm_ie + 2, NULL);
1483 		}
1484 
1485 		left -= elen;
1486 		pos += elen;
1487 	}
1488 	if (mic_ie) {
1489 		new_mic_ie = fpos;
1490 		*fpos++ = WLAN_EID_MIC;
1491 		*fpos++ = 16 /* AES_BLOCK_SIZE */;
1492 	}
1493 
1494 #ifdef CONFIG_RTW_MESH_AEK
1495 	/* encode */
1496 	if (mic_ie) {
1497 		int enc_ret = rtw_mpm_ampe_enc(adapter, plink, new_fbody, new_mic_ie, ampe_buf, 0);
1498 		if (enc_ret != _SUCCESS)
1499 			goto exit;
1500 	}
1501 #endif
1502 
1503 	*nlen = new_len;
1504 	*nbuf = new_buf;
1505 
1506 	ret = _SUCCESS;
1507 
1508 exit:
1509 	if (ret != _SUCCESS && new_buf)
1510 		rtw_mfree(new_buf, new_len);
1511 
1512 #ifdef CONFIG_RTW_MESH_AEK
1513 	if (ampe_buf)
1514 		rtw_mfree(ampe_buf, ampe_buf_len);
1515 #endif
1516 
1517 	return ret;
1518 }
1519 #endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */
1520 
1521 struct mpm_frame_info {
1522 	u8 *aid;
1523 	u16 aid_v;
1524 	u8 *pid;
1525 	u16 pid_v;
1526 	u8 *llid;
1527 	u16 llid_v;
1528 	u8 *plid;
1529 	u16 plid_v;
1530 	u8 *reason;
1531 	u16 reason_v;
1532 	u8 *chosen_pmk;
1533 };
1534 
1535 /*
1536 * pid:00000 llid:00000 chosen_pmk:0x00000000000000000000000000000000
1537 * aid:00000 pid:00000 llid:00000 plid:00000 chosen_pmk:0x00000000000000000000000000000000
1538 * pid:00000 llid:00000 plid:00000 reason:00000 chosen_pmk:0x00000000000000000000000000000000
1539 */
1540 #define MPM_LOG_BUF_LEN 92 /* this length is limited for legal combination */
rtw_mpm_info_msg(struct mpm_frame_info * mpm_info,u8 * mpm_log_buf)1541 static void rtw_mpm_info_msg(struct mpm_frame_info *mpm_info, u8 *mpm_log_buf)
1542 {
1543 	int cnt = 0;
1544 
1545 	if (mpm_info->aid) {
1546 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "aid:%u ", mpm_info->aid_v);
1547 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1548 			goto exit;
1549 	}
1550 	if (mpm_info->pid) {
1551 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "pid:%u ", mpm_info->pid_v);
1552 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1553 			goto exit;
1554 	}
1555 	if (mpm_info->llid) {
1556 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "llid:%u ", mpm_info->llid_v);
1557 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1558 			goto exit;
1559 	}
1560 	if (mpm_info->plid) {
1561 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "plid:%u ", mpm_info->plid_v);
1562 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1563 			goto exit;
1564 	}
1565 	if (mpm_info->reason) {
1566 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "reason:%u ", mpm_info->reason_v);
1567 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1568 			goto exit;
1569 	}
1570 	if (mpm_info->chosen_pmk) {
1571 		cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "chosen_pmk:0x"KEY_FMT, KEY_ARG(mpm_info->chosen_pmk));
1572 		if (cnt >= MPM_LOG_BUF_LEN - 1)
1573 			goto exit;
1574 	}
1575 
1576 exit:
1577 	return;
1578 }
1579 
rtw_mpm_check_frames(_adapter * adapter,u8 action,const u8 ** buf,size_t * len,u8 tx)1580 static int rtw_mpm_check_frames(_adapter *adapter, u8 action, const u8 **buf, size_t *len, u8 tx)
1581 {
1582 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
1583 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
1584 	struct mesh_plink_ent *plink = NULL;
1585 	u8 *nbuf = NULL;
1586 	size_t nlen = 0;
1587 	u8 *fhead = (u8 *)*buf;
1588 	size_t flen = *len;
1589 	u8 *peer_addr = tx ? GetAddr1Ptr(fhead) : get_addr2_ptr(fhead);
1590 	u8 *frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
1591 	struct mpm_frame_info mpm_info;
1592 	u8 tlv_ies_offset;
1593 	u8 *mpm_ie = NULL;
1594 	uint mpm_ielen = 0;
1595 	u8 *mic_ie = NULL;
1596 	uint mic_ielen = 0;
1597 	int ret = 0;
1598 	u8 mpm_log_buf[MPM_LOG_BUF_LEN] = {0};
1599 
1600 	if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN)
1601 		tlv_ies_offset = 4;
1602 	else if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF)
1603 		tlv_ies_offset = 6;
1604 	else if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE)
1605 		tlv_ies_offset = 2;
1606 	else {
1607 		rtw_warn_on(1);
1608 		goto exit;
1609 	}
1610 
1611 	plink = rtw_mesh_plink_get(adapter, peer_addr);
1612 	if (!plink && (tx == _TRUE || action == RTW_ACT_SELF_PROTECTED_MESH_CONF)) {
1613 		/* warning message if no plink when: 1.TX all MPM or 2.RX CONF */
1614 		RTW_WARN("RTW_%s:%s without plink of "MAC_FMT"\n"
1615 			, (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action), MAC_ARG(peer_addr));
1616 		goto exit;
1617 	}
1618 
1619 	_rtw_memset(&mpm_info, 0, sizeof(struct mpm_frame_info));
1620 
1621 	if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) {
1622 		mpm_info.aid = (u8 *)frame_body + 4;
1623 		mpm_info.aid_v = RTW_GET_LE16(mpm_info.aid);
1624 	}
1625 
1626 	mpm_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
1627 		, WLAN_EID_MPM, &mpm_ielen
1628 		, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
1629 	if (!mpm_ie || mpm_ielen < 2 + 2)
1630 		goto exit;
1631 
1632 	mpm_info.pid = mpm_ie + 2;
1633 	mpm_info.pid_v = RTW_GET_LE16(mpm_info.pid);
1634 	mpm_info.llid = mpm_info.pid + 2;
1635 	mpm_info.llid_v = RTW_GET_LE16(mpm_info.llid);
1636 
1637 	switch (action) {
1638 	case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
1639 		/* pid:2, llid:2, (chosen_pmk:16) */
1640 		if (mpm_info.pid_v == 0 && mpm_ielen == 4)
1641 			;
1642 		else if (mpm_info.pid_v == 1 && mpm_ielen == 20)
1643 			mpm_info.chosen_pmk = mpm_info.llid + 2;
1644 		else
1645 			goto exit;
1646 		break;
1647 	case RTW_ACT_SELF_PROTECTED_MESH_CONF:
1648 		/* pid:2, llid:2, plid:2, (chosen_pmk:16) */
1649 		mpm_info.plid = mpm_info.llid + 2;
1650 		mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
1651 		if (mpm_info.pid_v == 0 && mpm_ielen == 6)
1652 			;
1653 		else if (mpm_info.pid_v == 1 && mpm_ielen == 22)
1654 			mpm_info.chosen_pmk = mpm_info.plid + 2;
1655 		else
1656 			goto exit;
1657 		break;
1658 	case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
1659 		/* pid:2, llid:2, (plid:2), reason:2, (chosen_pmk:16) */
1660 		if (mpm_info.pid_v == 0 && mpm_ielen == 6) {
1661 			/* MPM, without plid */
1662 			mpm_info.reason = mpm_info.llid + 2;
1663 			mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
1664 		} else if (mpm_info.pid_v == 0 && mpm_ielen == 8) {
1665 			/* MPM, with plid */
1666 			mpm_info.plid = mpm_info.llid + 2;
1667 			mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
1668 			mpm_info.reason = mpm_info.plid + 2;
1669 			mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
1670 		} else if (mpm_info.pid_v == 1 && mpm_ielen == 22) {
1671 			/* AMPE, without plid */
1672 			mpm_info.reason = mpm_info.llid + 2;
1673 			mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
1674 			mpm_info.chosen_pmk = mpm_info.reason + 2;
1675 		} else if (mpm_info.pid_v == 1 && mpm_ielen == 24) {
1676 			/* AMPE, with plid */
1677 			mpm_info.plid = mpm_info.llid + 2;
1678 			mpm_info.plid_v = RTW_GET_LE16(mpm_info.plid);
1679 			mpm_info.reason = mpm_info.plid + 2;
1680 			mpm_info.reason_v = RTW_GET_LE16(mpm_info.reason);
1681 			mpm_info.chosen_pmk = mpm_info.reason + 2;
1682 		} else
1683 			goto exit;
1684 		break;
1685 	};
1686 
1687 	if (mpm_info.pid_v == 1) {
1688 		mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
1689 			, WLAN_EID_MIC, &mic_ielen
1690 			, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
1691 		if (!mic_ie || mic_ielen != 16 /* AES_BLOCK_SIZE */)
1692 			goto exit;
1693 	}
1694 
1695 #if CONFIG_RTW_MPM_TX_IES_SYNC_BSS
1696 	if ((action == RTW_ACT_SELF_PROTECTED_MESH_OPEN || action == RTW_ACT_SELF_PROTECTED_MESH_CONF)
1697 		&& tx == _TRUE
1698 	) {
1699 #define DBG_RTW_MPM_TX_IES_SYNC_BSS 0
1700 
1701 		if (mpm_info.pid_v == 1 && (!plink || !MESH_PLINK_AEK_VALID(plink))) {
1702 			RTW_WARN("AEK not ready, IEs can't sync with BSS\n");
1703 			goto bypass_sync_bss;
1704 		}
1705 
1706 		if (DBG_RTW_MPM_TX_IES_SYNC_BSS) {
1707 			RTW_INFO(FUNC_ADPT_FMT" before:\n", FUNC_ADPT_ARG(adapter));
1708 			dump_ies(RTW_DBGDUMP
1709 				, fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
1710 				, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
1711 		}
1712 
1713 		rtw_mpm_tx_ies_sync_bss(adapter, plink
1714 			, fhead, flen, frame_body, tlv_ies_offset, mpm_ie, mic_ie
1715 			, &nbuf, &nlen);
1716 		if (!nbuf)
1717 			goto exit;
1718 
1719 		/* update pointer & len for new frame */
1720 		fhead = nbuf;
1721 		flen = nlen;
1722 		frame_body = fhead + sizeof(struct rtw_ieee80211_hdr_3addr);
1723 		if (mpm_info.pid_v == 1) {
1724 			mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
1725 				, WLAN_EID_MIC, &mic_ielen
1726 				, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
1727 		}
1728 
1729 		if (DBG_RTW_MPM_TX_IES_SYNC_BSS) {
1730 			RTW_INFO(FUNC_ADPT_FMT" after:\n", FUNC_ADPT_ARG(adapter));
1731 			dump_ies(RTW_DBGDUMP
1732 				, fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
1733 				, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
1734 		}
1735 	}
1736 bypass_sync_bss:
1737 #endif /* CONFIG_RTW_MPM_TX_IES_SYNC_BSS */
1738 
1739 	if (!plink)
1740 		goto mpm_log;
1741 
1742 #if CONFIG_RTW_MESH_PEER_BLACKLIST
1743 	if (action == RTW_ACT_SELF_PROTECTED_MESH_OPEN) {
1744 		if (tx)
1745 			rtw_mesh_plink_set_peer_conf_timeout(adapter, peer_addr);
1746 
1747 	} else
1748 #endif
1749 #if CONFIG_RTW_MESH_ACNODE_PREVENT
1750 	if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE) {
1751 		if (tx && mpm_info.reason && mpm_info.reason_v == WLAN_REASON_MESH_MAX_PEERS) {
1752 			if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)
1753 				&& rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
1754 			) {
1755 				struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
1756 
1757 				if (sac) {
1758 					struct sta_priv *stapriv = &adapter->stapriv;
1759 					_irqL irqL;
1760 					u8 sta_addr[ETH_ALEN];
1761 					u8 updated = _FALSE;
1762 
1763 					_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
1764 					if (!rtw_is_list_empty(&sac->asoc_list)) {
1765 						rtw_list_delete(&sac->asoc_list);
1766 						stapriv->asoc_list_cnt--;
1767 						#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
1768 						if (sac->tbtx_enable)
1769 							stapriv->tbtx_asoc_list_cnt--;
1770 						#endif
1771 						STA_SET_MESH_PLINK(sac, NULL);
1772 					}
1773 					_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
1774 					RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"
1775 						, FUNC_ADPT_ARG(adapter), MAC_ARG(sac->cmn.mac_addr));
1776 
1777 					_rtw_memcpy(sta_addr, sac->cmn.mac_addr, ETH_ALEN);
1778 					updated = ap_free_sta(adapter, sac, 0, 0, 1);
1779 					rtw_mesh_expire_peer(stapriv->padapter, sta_addr);
1780 
1781 					associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
1782 				}
1783 			}
1784 		}
1785 	} else
1786 #endif
1787 	if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) {
1788 		_irqL irqL;
1789 		u8 *ies = NULL;
1790 		u16 ies_len = 0;
1791 
1792 		_enter_critical_bh(&(plink_ctl->lock), &irqL);
1793 
1794 		plink = _rtw_mesh_plink_get(adapter, peer_addr);
1795 		if (!plink)
1796 			goto release_plink_ctl;
1797 
1798 		if (tx == _FALSE) {
1799 			ies = plink->rx_conf_ies;
1800 			ies_len = plink->rx_conf_ies_len;
1801 			plink->rx_conf_ies = NULL;
1802 			plink->rx_conf_ies_len = 0;
1803 
1804 			plink->llid = mpm_info.plid_v;
1805 			plink->plid = mpm_info.llid_v;
1806 			plink->peer_aid = mpm_info.aid_v;
1807 			if (mpm_info.pid_v == 1)
1808 				_rtw_memcpy(plink->chosen_pmk, mpm_info.chosen_pmk, 16);
1809 		}
1810 		#ifdef CONFIG_RTW_MESH_DRIVER_AID
1811 		else {
1812 			ies = plink->tx_conf_ies;
1813 			ies_len = plink->tx_conf_ies_len;
1814 			plink->tx_conf_ies = NULL;
1815 			plink->tx_conf_ies_len = 0;
1816 		}
1817 		#endif
1818 
1819 		if (ies && ies_len)
1820 			rtw_mfree(ies, ies_len);
1821 
1822 		#ifndef CONFIG_RTW_MESH_DRIVER_AID
1823 		if (tx == _TRUE)
1824 			goto release_plink_ctl; /* no need to copy tx conf ies */
1825 		#endif
1826 
1827 		/* copy mesh confirm IEs */
1828 		if (mpm_info.pid_v == 1) /* not include MIC & encrypted AMPE */
1829 			ies_len = (mic_ie - fhead) - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
1830 		else
1831 			ies_len = flen - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
1832 
1833 		ies = rtw_zmalloc(ies_len);
1834 		if (ies) {
1835 			_rtw_memcpy(ies, fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + 2, ies_len);
1836 			if (tx == _FALSE) {
1837 				plink->rx_conf_ies = ies;
1838 				plink->rx_conf_ies_len = ies_len;
1839 			}
1840 			#ifdef CONFIG_RTW_MESH_DRIVER_AID
1841 			else {
1842 				plink->tx_conf_ies = ies;
1843 				plink->tx_conf_ies_len = ies_len;
1844 			}
1845 			#endif
1846 		}
1847 
1848 release_plink_ctl:
1849 		_exit_critical_bh(&(plink_ctl->lock), &irqL);
1850 	}
1851 
1852 mpm_log:
1853 	rtw_mpm_info_msg(&mpm_info, mpm_log_buf);
1854 	RTW_INFO("RTW_%s:%s %s\n"
1855 		, (tx == _TRUE) ? "Tx" : "Rx"
1856 		, action_self_protected_str(action)
1857 		, mpm_log_buf
1858 	);
1859 
1860 	ret = 1;
1861 
1862 exit:
1863 	if (nbuf) {
1864 		if (ret == 1) {
1865 			*buf = nbuf;
1866 			*len = nlen;
1867 		} else
1868 			rtw_mfree(nbuf, nlen);
1869 	}
1870 
1871 	return ret;
1872 }
1873 
rtw_mesh_check_frames(_adapter * adapter,const u8 ** buf,size_t * len,u8 tx)1874 static int rtw_mesh_check_frames(_adapter *adapter, const u8 **buf, size_t *len, u8 tx)
1875 {
1876 	int is_mesh_frame = -1;
1877 	const u8 *frame_body;
1878 	u8 category, action;
1879 
1880 	frame_body = *buf + sizeof(struct rtw_ieee80211_hdr_3addr);
1881 	category = frame_body[0];
1882 
1883 	if (category == RTW_WLAN_CATEGORY_SELF_PROTECTED) {
1884 		action = frame_body[1];
1885 		switch (action) {
1886 		case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
1887 		case RTW_ACT_SELF_PROTECTED_MESH_CONF:
1888 		case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
1889 			rtw_mpm_check_frames(adapter, action, buf, len, tx);
1890 			is_mesh_frame = action;
1891 			break;
1892 		case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM:
1893 		case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK:
1894 			RTW_INFO("RTW_%s:%s\n", (tx == _TRUE) ? "Tx" : "Rx", action_self_protected_str(action));
1895 			is_mesh_frame = action;
1896 			break;
1897 		default:
1898 			break;
1899 		};
1900 	}
1901 
1902 	return is_mesh_frame;
1903 }
1904 
rtw_mesh_check_frames_tx(_adapter * adapter,const u8 ** buf,size_t * len)1905 int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len)
1906 {
1907 	return rtw_mesh_check_frames(adapter, buf, len, _TRUE);
1908 }
1909 
rtw_mesh_check_frames_rx(_adapter * adapter,const u8 * buf,size_t len)1910 int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len)
1911 {
1912 	return rtw_mesh_check_frames(adapter, &buf, &len, _FALSE);
1913 }
1914 
rtw_mesh_on_auth(_adapter * adapter,union recv_frame * rframe)1915 int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe)
1916 {
1917 	u8 *whdr = rframe->u.hdr.rx_data;
1918 
1919 #if CONFIG_RTW_MACADDR_ACL
1920 	if (rtw_access_ctrl(adapter, get_addr2_ptr(whdr)) == _FALSE)
1921 		return _SUCCESS;
1922 #endif
1923 
1924 	if (!rtw_mesh_plink_get(adapter, get_addr2_ptr(whdr))) {
1925 		#if CONFIG_RTW_MESH_ACNODE_PREVENT
1926 		rtw_mesh_acnode_set_notify_etime(adapter, whdr);
1927 		#endif
1928 
1929 		if (adapter_to_rfctl(adapter)->offch_state == OFFCHS_NONE)
1930 			issue_probereq(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, get_addr2_ptr(whdr));
1931 
1932 		/* only peer being added (checked by notify conditions) is allowed */
1933 		return _SUCCESS;
1934 	}
1935 
1936 	rtw_cfg80211_rx_mframe(adapter, rframe, NULL);
1937 	return _SUCCESS;
1938 }
1939 
on_action_self_protected(_adapter * adapter,union recv_frame * rframe)1940 unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe)
1941 {
1942 	unsigned int ret = _FAIL;
1943 	struct sta_info *sta = NULL;
1944 	u8 *pframe = rframe->u.hdr.rx_data;
1945 	uint frame_len = rframe->u.hdr.len;
1946 	u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1947 	u8 category;
1948 	u8 action;
1949 
1950 	/* check RA matches or not */
1951 	if (!_rtw_memcmp(adapter_mac_addr(adapter), GetAddr1Ptr(pframe), ETH_ALEN))
1952 		goto exit;
1953 
1954 	category = frame_body[0];
1955 	if (category != RTW_WLAN_CATEGORY_SELF_PROTECTED)
1956 		goto exit;
1957 
1958 	action = frame_body[1];
1959 	switch (action) {
1960 	case RTW_ACT_SELF_PROTECTED_MESH_OPEN:
1961 	case RTW_ACT_SELF_PROTECTED_MESH_CONF:
1962 	case RTW_ACT_SELF_PROTECTED_MESH_CLOSE:
1963 	case RTW_ACT_SELF_PROTECTED_MESH_GK_INFORM:
1964 	case RTW_ACT_SELF_PROTECTED_MESH_GK_ACK:
1965 		if (!(MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)))
1966 			goto exit;
1967 #ifdef CONFIG_IOCTL_CFG80211
1968 		#if CONFIG_RTW_MACADDR_ACL
1969 		if (rtw_access_ctrl(adapter, get_addr2_ptr(pframe)) == _FALSE)
1970 			goto exit;
1971 		#endif
1972 		#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
1973 		if (rtw_mesh_cto_mgate_required(adapter)
1974 			/* only peer being added (checked by notify conditions) is allowed */
1975 			&& !rtw_mesh_plink_get(adapter, get_addr2_ptr(pframe)))
1976 			goto exit;
1977 		#endif
1978 		rtw_cfg80211_rx_action(adapter, rframe, NULL);
1979 		ret = _SUCCESS;
1980 #endif /* CONFIG_IOCTL_CFG80211 */
1981 		break;
1982 	default:
1983 		break;
1984 	}
1985 
1986 exit:
1987 	return ret;
1988 }
1989 
1990 const u8 ae_to_mesh_ctrl_len[] = {
1991 	6,
1992 	12, /* MESH_FLAGS_AE_A4 */
1993 	18, /* MESH_FLAGS_AE_A5_A6 */
1994 	0,
1995 };
1996 
on_action_mesh(_adapter * adapter,union recv_frame * rframe)1997 unsigned int on_action_mesh(_adapter *adapter, union recv_frame *rframe)
1998 {
1999 	unsigned int ret = _FAIL;
2000 	struct sta_info *sta = NULL;
2001 	struct sta_priv *stapriv = &adapter->stapriv;
2002 	u8 *pframe = rframe->u.hdr.rx_data;
2003 	uint frame_len = rframe->u.hdr.len;
2004 	u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
2005 	u8 category;
2006 	u8 action;
2007 
2008 	if (!MLME_IS_MESH(adapter))
2009 		goto exit;
2010 
2011 	/* check stainfo exist? */
2012 
2013 	category = frame_body[0];
2014 	if (category != RTW_WLAN_CATEGORY_MESH)
2015 		goto exit;
2016 
2017 	action = frame_body[1];
2018 	switch (action) {
2019 	case RTW_ACT_MESH_HWMP_PATH_SELECTION:
2020 		rtw_mesh_rx_path_sel_frame(adapter, rframe);
2021 		ret = _SUCCESS;
2022 		break;
2023 	default:
2024 		break;
2025 	}
2026 
2027 exit:
2028 	return ret;
2029 }
2030 
rtw_mesh_update_bss_peering_status(_adapter * adapter,WLAN_BSSID_EX * bss)2031 bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss)
2032 {
2033 	struct sta_priv *stapriv = &adapter->stapriv;
2034 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
2035 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2036 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2037 	u8 num_of_peerings = stapriv->asoc_list_cnt;
2038 	bool accept_peerings = stapriv->asoc_list_cnt < mcfg->max_peer_links;
2039 	u8 *ie;
2040 	int ie_len;
2041 	bool updated = 0;
2042 
2043 #if CONFIG_RTW_MESH_ACNODE_PREVENT
2044 	accept_peerings |= plink_ctl->acnode_rsvd;
2045 #endif
2046 
2047 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, BSS_EX_TLV_IES_LEN(bss));
2048 	if (!ie || ie_len != 7) {
2049 		rtw_warn_on(1);
2050 		goto exit;
2051 	}
2052 
2053 	if (GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2) != num_of_peerings) {
2054 		SET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2, num_of_peerings);
2055 		updated = 1;
2056 	}
2057 
2058 	if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2) != accept_peerings) {
2059 		SET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2, accept_peerings);
2060 		updated = 1;
2061 	}
2062 
2063 exit:
2064 	return updated;
2065 }
2066 
rtw_mesh_update_bss_formation_info(_adapter * adapter,WLAN_BSSID_EX * bss)2067 bool rtw_mesh_update_bss_formation_info(_adapter *adapter, WLAN_BSSID_EX *bss)
2068 {
2069 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
2070 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2071 	u8 cto_mgate = (minfo->num_gates || mcfg->dot11MeshGateAnnouncementProtocol);
2072 	u8 cto_as = 0;
2073 	u8 *ie;
2074 	int ie_len;
2075 	bool updated = 0;
2076 
2077 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
2078 			BSS_EX_TLV_IES_LEN(bss));
2079 	if (!ie || ie_len != 7) {
2080 		rtw_warn_on(1);
2081 		goto exit;
2082 	}
2083 
2084 	if (GET_MESH_CONF_ELE_CTO_MGATE(ie + 2) != cto_mgate) {
2085 		SET_MESH_CONF_ELE_CTO_MGATE(ie + 2, cto_mgate);
2086 		updated = 1;
2087 	}
2088 
2089 	if (GET_MESH_CONF_ELE_CTO_AS(ie + 2) != cto_as) {
2090 		SET_MESH_CONF_ELE_CTO_AS(ie + 2, cto_as);
2091 		updated = 1;
2092 	}
2093 
2094 exit:
2095 	return updated;
2096 }
2097 
rtw_mesh_update_bss_forwarding_state(_adapter * adapter,WLAN_BSSID_EX * bss)2098 bool rtw_mesh_update_bss_forwarding_state(_adapter *adapter, WLAN_BSSID_EX *bss)
2099 {
2100 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
2101 	u8 forward = mcfg->dot11MeshForwarding;
2102 	u8 *ie;
2103 	int ie_len;
2104 	bool updated = 0;
2105 
2106 	ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
2107 			BSS_EX_TLV_IES_LEN(bss));
2108 	if (!ie || ie_len != 7) {
2109 		rtw_warn_on(1);
2110 		goto exit;
2111 	}
2112 
2113 	if (GET_MESH_CONF_ELE_FORWARDING(ie + 2) != forward) {
2114 		SET_MESH_CONF_ELE_FORWARDING(ie + 2, forward);
2115 		updated = 1;
2116 	}
2117 
2118 exit:
2119 	return updated;
2120 }
2121 
_rtw_mesh_plink_get(_adapter * adapter,const u8 * hwaddr)2122 struct mesh_plink_ent *_rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr)
2123 {
2124 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2125 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2126 	struct mesh_plink_ent *ent = NULL;
2127 	int i;
2128 
2129 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
2130 		if (plink_ctl->ent[i].valid == _TRUE
2131 			&& _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
2132 		) {
2133 			ent = &plink_ctl->ent[i];
2134 			break;
2135 		}
2136 	}
2137 
2138 	return ent;
2139 }
2140 
rtw_mesh_plink_get(_adapter * adapter,const u8 * hwaddr)2141 struct mesh_plink_ent *rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr)
2142 {
2143 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2144 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2145 	struct mesh_plink_ent *ent = NULL;
2146 	_irqL irqL;
2147 
2148 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2149 	ent = _rtw_mesh_plink_get(adapter, hwaddr);
2150 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2151 
2152 	return ent;
2153 }
2154 
rtw_mesh_plink_get_no_estab_by_idx(_adapter * adapter,u8 idx)2155 struct mesh_plink_ent *rtw_mesh_plink_get_no_estab_by_idx(_adapter *adapter, u8 idx)
2156 {
2157 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2158 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2159 	struct mesh_plink_ent *ent = NULL;
2160 	int i, j = 0;
2161 	_irqL irqL;
2162 
2163 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2164 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
2165 		if (plink_ctl->ent[i].valid == _TRUE
2166 			&& plink_ctl->ent[i].plink_state != RTW_MESH_PLINK_ESTAB
2167 		) {
2168 			if (j == idx) {
2169 				ent = &plink_ctl->ent[i];
2170 				break;
2171 			}
2172 			j++;
2173 		}
2174 	}
2175 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2176 
2177 	return ent;
2178 }
2179 
_rtw_mesh_plink_add(_adapter * adapter,const u8 * hwaddr)2180 int _rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr)
2181 {
2182 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2183 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2184 	struct mesh_plink_ent *ent = NULL;
2185 	u8 exist = _FALSE;
2186 	int i;
2187 
2188 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
2189 		if (plink_ctl->ent[i].valid == _TRUE
2190 			&& _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
2191 		) {
2192 			ent = &plink_ctl->ent[i];
2193 			exist = _TRUE;
2194 			break;
2195 		}
2196 
2197 		if (ent == NULL && plink_ctl->ent[i].valid == _FALSE)
2198 			ent = &plink_ctl->ent[i];
2199 	}
2200 
2201 	if (exist == _FALSE && ent) {
2202 		_rtw_memcpy(ent->addr, hwaddr, ETH_ALEN);
2203 		ent->valid = _TRUE;
2204 		#ifdef CONFIG_RTW_MESH_AEK
2205 		ent->aek_valid = 0;
2206 		#endif
2207 		ent->llid = 0;
2208 		ent->plid = 0;
2209 		_rtw_memset(ent->chosen_pmk, 0, 16);
2210 		#ifdef CONFIG_RTW_MESH_AEK
2211 		_rtw_memset(ent->sel_pcs, 0, 4);
2212 		_rtw_memset(ent->l_nonce, 0, 32);
2213 		_rtw_memset(ent->p_nonce, 0, 32);
2214 		#endif
2215 		ent->plink_state = RTW_MESH_PLINK_LISTEN;
2216 		#ifndef CONFIG_RTW_MESH_DRIVER_AID
2217 		ent->aid = 0;
2218 		#endif
2219 		ent->peer_aid = 0;
2220 		SET_PEER_CONF_DISABLED(ent);
2221 		SET_CTO_MGATE_CONF_DISABLED(ent);
2222 		plink_ctl->num++;
2223 	}
2224 
2225 	return exist == _TRUE ? RTW_ALREADY : (ent ? _SUCCESS : _FAIL);
2226 }
2227 
rtw_mesh_plink_add(_adapter * adapter,const u8 * hwaddr)2228 int rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr)
2229 {
2230 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2231 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2232 	_irqL irqL;
2233 	int ret;
2234 
2235 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2236 	ret = _rtw_mesh_plink_add(adapter, hwaddr);
2237 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2238 
2239 	return ret;
2240 }
2241 
rtw_mesh_plink_set_state(_adapter * adapter,const u8 * hwaddr,u8 state)2242 int rtw_mesh_plink_set_state(_adapter *adapter, const u8 *hwaddr, u8 state)
2243 {
2244 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2245 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2246 	struct mesh_plink_ent *ent = NULL;
2247 	_irqL irqL;
2248 
2249 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2250 	ent = _rtw_mesh_plink_get(adapter, hwaddr);
2251 	if (ent)
2252 		ent->plink_state = state;
2253 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2254 
2255 	return ent ? _SUCCESS : _FAIL;
2256 }
2257 
2258 #ifdef CONFIG_RTW_MESH_AEK
rtw_mesh_plink_set_aek(_adapter * adapter,const u8 * hwaddr,const u8 * aek)2259 int rtw_mesh_plink_set_aek(_adapter *adapter, const u8 *hwaddr, const u8 *aek)
2260 {
2261 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2262 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2263 	struct mesh_plink_ent *ent = NULL;
2264 	_irqL irqL;
2265 
2266 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2267 	ent = _rtw_mesh_plink_get(adapter, hwaddr);
2268 	if (ent) {
2269 		_rtw_memcpy(ent->aek, aek, 32);
2270 		ent->aek_valid = 1;
2271 	}
2272 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2273 
2274 	return ent ? _SUCCESS : _FAIL;
2275 }
2276 #endif
2277 
2278 #if CONFIG_RTW_MESH_PEER_BLACKLIST
rtw_mesh_plink_set_peer_conf_timeout(_adapter * adapter,const u8 * hwaddr)2279 int rtw_mesh_plink_set_peer_conf_timeout(_adapter *adapter, const u8 *hwaddr)
2280 {
2281 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
2282 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2283 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2284 	struct mesh_plink_ent *ent = NULL;
2285 	_irqL irqL;
2286 
2287 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2288 	ent = _rtw_mesh_plink_get(adapter, hwaddr);
2289 	if (ent) {
2290 		if (IS_PEER_CONF_DISABLED(ent))
2291 			SET_PEER_CONF_END_TIME(ent, mcfg->peer_sel_policy.peer_conf_timeout_ms);
2292 	}
2293 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2294 
2295 	return ent ? _SUCCESS : _FAIL;
2296 }
2297 #endif
2298 
_rtw_mesh_plink_del_ent(_adapter * adapter,struct mesh_plink_ent * ent)2299 void _rtw_mesh_plink_del_ent(_adapter *adapter, struct mesh_plink_ent *ent)
2300 {
2301 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2302 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2303 
2304 	ent->valid = _FALSE;
2305 	#ifdef CONFIG_RTW_MESH_DRIVER_AID
2306 	if (ent->tx_conf_ies && ent->tx_conf_ies_len)
2307 		rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len);
2308 	ent->tx_conf_ies = NULL;
2309 	ent->tx_conf_ies_len = 0;
2310 	#endif
2311 	if (ent->rx_conf_ies && ent->rx_conf_ies_len)
2312 		rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len);
2313 	ent->rx_conf_ies = NULL;
2314 	ent->rx_conf_ies_len = 0;
2315 	if (ent->scanned)
2316 		ent->scanned = NULL;
2317 	plink_ctl->num--;
2318 }
2319 
rtw_mesh_plink_del(_adapter * adapter,const u8 * hwaddr)2320 int rtw_mesh_plink_del(_adapter *adapter, const u8 *hwaddr)
2321 {
2322 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2323 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2324 	struct mesh_plink_ent *ent = NULL;
2325 	u8 exist = _FALSE;
2326 	int i;
2327 	_irqL irqL;
2328 
2329 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2330 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
2331 		if (plink_ctl->ent[i].valid == _TRUE
2332 			&& _rtw_memcmp(plink_ctl->ent[i].addr, hwaddr, ETH_ALEN) == _TRUE
2333 		) {
2334 			ent = &plink_ctl->ent[i];
2335 			exist = _TRUE;
2336 			break;
2337 		}
2338 	}
2339 
2340 	if (exist == _TRUE)
2341 		_rtw_mesh_plink_del_ent(adapter, ent);
2342 
2343 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2344 
2345 	return exist == _TRUE ? _SUCCESS : RTW_ALREADY;
2346 }
2347 
rtw_mesh_plink_ctl_init(_adapter * adapter)2348 void rtw_mesh_plink_ctl_init(_adapter *adapter)
2349 {
2350 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2351 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2352 	int i;
2353 
2354 	_rtw_spinlock_init(&plink_ctl->lock);
2355 	plink_ctl->num = 0;
2356 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++)
2357 		plink_ctl->ent[i].valid = _FALSE;
2358 
2359 #if CONFIG_RTW_MESH_PEER_BLACKLIST
2360 	_rtw_init_queue(&plink_ctl->peer_blacklist);
2361 #endif
2362 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
2363 	_rtw_init_queue(&plink_ctl->cto_mgate_blacklist);
2364 #endif
2365 }
2366 
rtw_mesh_plink_ctl_deinit(_adapter * adapter)2367 void rtw_mesh_plink_ctl_deinit(_adapter *adapter)
2368 {
2369 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2370 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2371 	struct mesh_plink_ent *ent;
2372 	int i;
2373 	_irqL irqL;
2374 
2375 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2376 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
2377 		ent = &plink_ctl->ent[i];
2378 		#ifdef CONFIG_RTW_MESH_DRIVER_AID
2379 		if (ent->tx_conf_ies && ent->tx_conf_ies_len)
2380 			rtw_mfree(ent->tx_conf_ies, ent->tx_conf_ies_len);
2381 		#endif
2382 		if (ent->rx_conf_ies && ent->rx_conf_ies_len)
2383 			rtw_mfree(ent->rx_conf_ies, ent->rx_conf_ies_len);
2384 	}
2385 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2386 
2387 	_rtw_spinlock_free(&plink_ctl->lock);
2388 
2389 #if CONFIG_RTW_MESH_PEER_BLACKLIST
2390 	rtw_mesh_peer_blacklist_flush(adapter);
2391 	_rtw_deinit_queue(&plink_ctl->peer_blacklist);
2392 #endif
2393 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
2394 	rtw_mesh_cto_mgate_blacklist_flush(adapter);
2395 	_rtw_deinit_queue(&plink_ctl->cto_mgate_blacklist);
2396 #endif
2397 }
2398 
dump_mesh_plink_ctl(void * sel,_adapter * adapter)2399 void dump_mesh_plink_ctl(void *sel, _adapter *adapter)
2400 {
2401 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2402 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2403 	struct mesh_plink_ent *ent;
2404 	int i;
2405 
2406 	RTW_PRINT_SEL(sel, "num:%u\n", plink_ctl->num);
2407 	#if CONFIG_RTW_MESH_ACNODE_PREVENT
2408 	RTW_PRINT_SEL(sel, "acnode_rsvd:%u\n", plink_ctl->acnode_rsvd);
2409 	#endif
2410 
2411 	for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++)  {
2412 		ent = &plink_ctl->ent[i];
2413 		if (!ent->valid)
2414 			continue;
2415 
2416 		RTW_PRINT_SEL(sel, "\n");
2417 		RTW_PRINT_SEL(sel, "peer:"MAC_FMT"\n", MAC_ARG(ent->addr));
2418 		RTW_PRINT_SEL(sel, "plink_state:%s\n", rtw_mesh_plink_str(ent->plink_state));
2419 
2420 		#ifdef CONFIG_RTW_MESH_AEK
2421 		if (ent->aek_valid)
2422 			RTW_PRINT_SEL(sel, "aek:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->aek), KEY_ARG(ent->aek + 16));
2423 		#endif
2424 
2425 		RTW_PRINT_SEL(sel, "llid:%u, plid:%u\n", ent->llid, ent->plid);
2426 		#ifndef CONFIG_RTW_MESH_DRIVER_AID
2427 		RTW_PRINT_SEL(sel, "aid:%u\n", ent->aid);
2428 		#endif
2429 		RTW_PRINT_SEL(sel, "peer_aid:%u\n", ent->peer_aid);
2430 
2431 		RTW_PRINT_SEL(sel, "chosen_pmk:"KEY_FMT"\n", KEY_ARG(ent->chosen_pmk));
2432 
2433 		#ifdef CONFIG_RTW_MESH_AEK
2434 		RTW_PRINT_SEL(sel, "sel_pcs:%02x%02x%02x%02x\n"
2435 			, ent->sel_pcs[0], ent->sel_pcs[1], ent->sel_pcs[2], ent->sel_pcs[3]);
2436 		RTW_PRINT_SEL(sel, "l_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->l_nonce), KEY_ARG(ent->l_nonce + 16));
2437 		RTW_PRINT_SEL(sel, "p_nonce:"KEY_FMT KEY_FMT"\n", KEY_ARG(ent->p_nonce), KEY_ARG(ent->p_nonce + 16));
2438 		#endif
2439 
2440 		#ifdef CONFIG_RTW_MESH_DRIVER_AID
2441 		RTW_PRINT_SEL(sel, "tx_conf_ies:%p, len:%u\n", ent->tx_conf_ies, ent->tx_conf_ies_len);
2442 		#endif
2443 		RTW_PRINT_SEL(sel, "rx_conf_ies:%p, len:%u\n", ent->rx_conf_ies, ent->rx_conf_ies_len);
2444 		RTW_PRINT_SEL(sel, "scanned:%p\n", ent->scanned);
2445 
2446 		#if CONFIG_RTW_MESH_PEER_BLACKLIST
2447 		if (!IS_PEER_CONF_DISABLED(ent)) {
2448 			if (!IS_PEER_CONF_TIMEOUT(ent))
2449 				RTW_PRINT_SEL(sel, "peer_conf:%d\n", rtw_systime_to_ms(ent->peer_conf_end_time - rtw_get_current_time()));
2450 			else
2451 				RTW_PRINT_SEL(sel, "peer_conf:TIMEOUT\n");
2452 		}
2453 		#endif
2454 
2455 		#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
2456 		if (!IS_CTO_MGATE_CONF_DISABLED(ent)) {
2457 			if (!IS_CTO_MGATE_CONF_TIMEOUT(ent))
2458 				RTW_PRINT_SEL(sel, "cto_mgate_conf:%d\n", rtw_systime_to_ms(ent->cto_mgate_conf_end_time - rtw_get_current_time()));
2459 			else
2460 				RTW_PRINT_SEL(sel, "cto_mgate_conf:TIMEOUT\n");
2461 		}
2462 		#endif
2463 	}
2464 }
2465 
2466 /* this function is called with plink_ctl being locked */
rtw_mesh_peer_establish(_adapter * adapter,struct mesh_plink_ent * plink,struct sta_info * sta)2467 static int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta)
2468 {
2469 #ifndef DBG_RTW_MESH_PEER_ESTABLISH
2470 #define DBG_RTW_MESH_PEER_ESTABLISH 0
2471 #endif
2472 
2473 	struct sta_priv *stapriv = &adapter->stapriv;
2474 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
2475 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2476 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2477 	u8 *tlv_ies;
2478 	u16 tlv_ieslen;
2479 	struct rtw_ieee802_11_elems elems;
2480 	_irqL irqL;
2481 	int i;
2482 	u16 status = 0;
2483 	int ret = _FAIL;
2484 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
2485 	u8 sta_tbtx_enable = _FALSE;
2486 #endif
2487 
2488 	if (!plink->rx_conf_ies || !plink->rx_conf_ies_len) {
2489 		RTW_INFO(FUNC_ADPT_FMT" no rx confirm from sta "MAC_FMT"\n"
2490 			, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
2491 		goto exit;
2492 	}
2493 
2494 	if (plink->rx_conf_ies_len < 4) {
2495 		RTW_INFO(FUNC_ADPT_FMT" confirm from sta "MAC_FMT" too short\n"
2496 			, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
2497 		goto exit;
2498 	}
2499 
2500 #ifdef CONFIG_RTW_MESH_DRIVER_AID
2501 	if (!plink->tx_conf_ies || !plink->tx_conf_ies_len) {
2502 		RTW_INFO(FUNC_ADPT_FMT" no tx confirm to sta "MAC_FMT"\n"
2503 			, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
2504 		goto exit;
2505 	}
2506 
2507 	if (plink->tx_conf_ies_len < 4) {
2508 		RTW_INFO(FUNC_ADPT_FMT" confirm to sta "MAC_FMT" too short\n"
2509 			, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
2510 		goto exit;
2511 	}
2512 #endif
2513 
2514 	tlv_ies = plink->rx_conf_ies + 4;
2515 	tlv_ieslen = plink->rx_conf_ies_len - 4;
2516 
2517 	if (DBG_RTW_MESH_PEER_ESTABLISH)
2518 		dump_ies(RTW_DBGDUMP, tlv_ies, tlv_ieslen);
2519 
2520 	if (rtw_ieee802_11_parse_elems(tlv_ies, tlv_ieslen, &elems, 1) == ParseFailed) {
2521 		RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" sent invalid confirm\n"
2522 			, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
2523 		goto exit;
2524 	}
2525 
2526 	SET_PEER_CONF_DISABLED(plink);
2527 	if (rtw_bss_is_cto_mgate(&plink->scanned->network)
2528 		&& !rtw_bss_is_forwarding(&plink->scanned->network))
2529 		SET_CTO_MGATE_CONF_END_TIME(plink, mcfg->peer_sel_policy.cto_mgate_conf_timeout_ms);
2530 	else
2531 		SET_CTO_MGATE_CONF_DISABLED(plink);
2532 
2533 	sta->state &= (~WIFI_FW_AUTH_SUCCESS);
2534 	sta->state |= WIFI_FW_ASSOC_STATE;
2535 
2536 	rtw_ap_parse_sta_capability(adapter, sta, plink->rx_conf_ies);
2537 
2538 	status = rtw_ap_parse_sta_supported_rates(adapter, sta, tlv_ies, tlv_ieslen);
2539 	if (status != _STATS_SUCCESSFUL_)
2540 		goto exit;
2541 
2542 	status = rtw_ap_parse_sta_security_ie(adapter, sta, &elems);
2543 	if (status != _STATS_SUCCESSFUL_) {
2544 		RTW_INFO(FUNC_ADPT_FMT" security check fail, status=%u\n", FUNC_ADPT_ARG(adapter), status);
2545 		goto exit;
2546 	}
2547 
2548 	rtw_ap_parse_sta_wmm_ie(adapter, sta, tlv_ies, tlv_ieslen);
2549 #ifdef CONFIG_RTS_FULL_BW
2550 	/*check vendor IE*/
2551 	rtw_parse_sta_vendor_ie_8812(adapter, sta, tlv_ies, tlv_ieslen);
2552 #endif/*CONFIG_RTS_FULL_BW*/
2553 
2554 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
2555 	if (elems.tbtx_cap && elems.tbtx_cap_len != 0) {
2556 		if(rtw_is_tbtx_capabilty(elems.tbtx_cap, elems.tbtx_cap_len)) {
2557 			sta_tbtx_enable = _TRUE;
2558 		}
2559 	}
2560 #endif
2561 
2562 	rtw_ap_parse_sta_ht_ie(adapter, sta, &elems);
2563 	rtw_ap_parse_sta_vht_ie(adapter, sta, &elems);
2564 
2565 	/* AID */
2566 #ifdef CONFIG_RTW_MESH_DRIVER_AID
2567 	sta->cmn.aid = RTW_GET_LE16(plink->tx_conf_ies + 2);
2568 #else
2569 	sta->cmn.aid = plink->aid;
2570 #endif
2571 	stapriv->sta_aid[sta->cmn.aid - 1] = sta;
2572 	RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" aid:%u\n"
2573 		, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr), sta->cmn.aid);
2574 
2575 	sta->state &= (~WIFI_FW_ASSOC_STATE);
2576 	sta->state |= WIFI_FW_ASSOC_SUCCESS;
2577 
2578 	sta->local_mps = RTW_MESH_PS_ACTIVE;
2579 
2580 	rtw_ewma_err_rate_init(&sta->metrics.err_rate);
2581 	rtw_ewma_err_rate_add(&sta->metrics.err_rate, 1);
2582 	/* init data_rate to 1M */
2583 	sta->metrics.data_rate = 10;
2584 	sta->alive = _TRUE;
2585 
2586 	_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
2587 	if (rtw_is_list_empty(&sta->asoc_list)) {
2588 		STA_SET_MESH_PLINK(sta, plink);
2589 		/* TBD: up layer timeout mechanism */
2590 		/* sta->expire_to = mcfg->plink_timeout / 2; */
2591 		rtw_list_insert_tail(&sta->asoc_list, &stapriv->asoc_list);
2592 		stapriv->asoc_list_cnt++;
2593 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
2594 		if (sta_tbtx_enable) {
2595 			sta->tbtx_enable = _TRUE;
2596 			stapriv->tbtx_asoc_list_cnt++;
2597 		}
2598 #endif
2599 	}
2600 	_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
2601 
2602 	bss_cap_update_on_sta_join(adapter, sta);
2603 	sta_info_update(adapter, sta);
2604 	report_add_sta_event(adapter, sta->cmn.mac_addr);
2605 
2606 	ret = _SUCCESS;
2607 
2608 exit:
2609 	return ret;
2610 }
2611 
rtw_mesh_set_plink_state(_adapter * adapter,const u8 * mac,u8 plink_state)2612 int rtw_mesh_set_plink_state(_adapter *adapter, const u8 *mac, u8 plink_state)
2613 {
2614 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2615 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2616 	struct mesh_plink_ent *plink = NULL;
2617 	_irqL irqL2;
2618 	struct sta_priv *stapriv = &adapter->stapriv;
2619 	struct sta_info *sta = NULL;
2620 	_irqL irqL;
2621 	struct sta_info *del_sta = NULL;
2622 	int ret = _SUCCESS;
2623 
2624 	_enter_critical_bh(&(plink_ctl->lock), &irqL2);
2625 
2626 	plink = _rtw_mesh_plink_get(adapter, mac);
2627 	if (!plink) {
2628 		ret = _FAIL;
2629 		goto release_plink_ctl;
2630 	}
2631 
2632 	plink->plink_state = plink_state;
2633 
2634 	#if CONFIG_RTW_MESH_ACNODE_PREVENT
2635 	if (plink_state == RTW_MESH_PLINK_OPN_SNT) {
2636 		if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)
2637 			&& rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
2638 		) {
2639 			struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
2640 
2641 			if (sac) {
2642 				del_sta = sac;
2643 				_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
2644 				if (!rtw_is_list_empty(&del_sta->asoc_list)) {
2645 					rtw_list_delete(&del_sta->asoc_list);
2646 					stapriv->asoc_list_cnt--;
2647 					#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
2648 					if (del_sta->tbtx_enable)
2649 						stapriv->tbtx_asoc_list_cnt--;
2650 					#endif
2651 					STA_SET_MESH_PLINK(del_sta, NULL);
2652 				}
2653 				_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
2654 				RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"
2655 					, FUNC_ADPT_ARG(adapter), MAC_ARG(del_sta->cmn.mac_addr));
2656 			}
2657 		}
2658 	} else
2659 	#endif
2660 	if (plink_state == RTW_MESH_PLINK_OPN_RCVD
2661 		|| plink_state == RTW_MESH_PLINK_CNF_RCVD
2662 		|| plink_state == RTW_MESH_PLINK_ESTAB
2663 	) {
2664 		sta = rtw_get_stainfo(stapriv, mac);
2665 		if (!sta) {
2666 			sta = rtw_alloc_stainfo(stapriv, mac);
2667 			if (!sta)
2668 				goto release_plink_ctl;
2669 		}
2670 
2671 		if (plink_state == RTW_MESH_PLINK_ESTAB) {
2672 			if (rtw_mesh_peer_establish(adapter, plink, sta) != _SUCCESS) {
2673 				del_sta = sta;
2674 				ret = _FAIL;
2675 				goto release_plink_ctl;
2676 			}
2677 		}
2678 	}
2679 	else if (plink_state == RTW_MESH_PLINK_HOLDING) {
2680 		del_sta = rtw_get_stainfo(stapriv, mac);
2681 		if (!del_sta)
2682 			goto release_plink_ctl;
2683 
2684 		_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
2685 		if (!rtw_is_list_empty(&del_sta->asoc_list)) {
2686 			rtw_list_delete(&del_sta->asoc_list);
2687 			stapriv->asoc_list_cnt--;
2688 			#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
2689 			if (del_sta->tbtx_enable)
2690 				stapriv->tbtx_asoc_list_cnt--;
2691 			#endif
2692 			STA_SET_MESH_PLINK(del_sta, NULL);
2693 		}
2694 		_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
2695 	}
2696 
2697 release_plink_ctl:
2698 	_exit_critical_bh(&(plink_ctl->lock), &irqL2);
2699 
2700 	if (del_sta) {
2701 		u8 sta_addr[ETH_ALEN];
2702 		u8 updated = _FALSE;
2703 
2704 		_rtw_memcpy(sta_addr, del_sta->cmn.mac_addr, ETH_ALEN);
2705 		updated = ap_free_sta(adapter, del_sta, 0, 0, 1);
2706 		rtw_mesh_expire_peer(stapriv->padapter, sta_addr);
2707 
2708 		associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
2709 	}
2710 
2711 	return ret;
2712 }
2713 
2714 struct mesh_set_plink_cmd_parm {
2715 	const u8 *mac;
2716 	u8 plink_state;
2717 };
2718 
rtw_mesh_set_plink_state_cmd_hdl(_adapter * adapter,u8 * parmbuf)2719 u8 rtw_mesh_set_plink_state_cmd_hdl(_adapter *adapter, u8 *parmbuf)
2720 {
2721 	struct mesh_set_plink_cmd_parm *parm = (struct mesh_set_plink_cmd_parm *)parmbuf;
2722 
2723 	if (rtw_mesh_set_plink_state(adapter, parm->mac, parm->plink_state) == _SUCCESS)
2724 		return	H2C_SUCCESS;
2725 
2726 	return H2C_CMD_FAIL;
2727 }
2728 
rtw_mesh_set_plink_state_cmd(_adapter * adapter,const u8 * mac,u8 plink_state)2729 u8 rtw_mesh_set_plink_state_cmd(_adapter *adapter, const u8 *mac, u8 plink_state)
2730 {
2731 	struct cmd_obj *cmdobj;
2732 	struct mesh_set_plink_cmd_parm *parm;
2733 	struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2734 	struct submit_ctx sctx;
2735 	u8 res = _SUCCESS;
2736 
2737 	/* prepare cmd parameter */
2738 	parm = rtw_zmalloc(sizeof(*parm));
2739 	if (parm == NULL) {
2740 		res = _FAIL;
2741 		goto exit;
2742 	}
2743 	parm->mac = mac;
2744 	parm->plink_state = plink_state;
2745 
2746 	/* need enqueue, prepare cmd_obj and enqueue */
2747 	cmdobj = rtw_zmalloc(sizeof(*cmdobj));
2748 	if (cmdobj == NULL) {
2749 		res = _FAIL;
2750 		rtw_mfree(parm, sizeof(*parm));
2751 		goto exit;
2752 	}
2753 
2754 	init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_MESH_PLINK_STATE);
2755 	cmdobj->sctx = &sctx;
2756 	rtw_sctx_init(&sctx, 2000);
2757 
2758 	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
2759 	if (res == _SUCCESS) {
2760 		rtw_sctx_wait(&sctx, __func__);
2761 		_enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
2762 		if (sctx.status == RTW_SCTX_SUBMITTED)
2763 			cmdobj->sctx = NULL;
2764 		_exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
2765 		if (sctx.status != RTW_SCTX_DONE_SUCCESS)
2766 			res = _FAIL;
2767 	}
2768 
2769 exit:
2770 	return res;
2771 }
2772 
rtw_mesh_expire_peer_notify(_adapter * adapter,const u8 * peer_addr)2773 void rtw_mesh_expire_peer_notify(_adapter *adapter, const u8 *peer_addr)
2774 {
2775 	u8 null_ssid[2] = {0, 0};
2776 
2777 #ifdef CONFIG_IOCTL_CFG80211
2778 	rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev
2779 		, peer_addr
2780 		, null_ssid
2781 		, 2
2782 		, 0
2783 		, GFP_ATOMIC
2784 	);
2785 #endif
2786 
2787 	return;
2788 }
2789 
rtw_mesh_construct_peer_mesh_close(_adapter * adapter,struct mesh_plink_ent * plink,u16 reason,u32 * len)2790 static u8 *rtw_mesh_construct_peer_mesh_close(_adapter *adapter, struct mesh_plink_ent *plink, u16 reason, u32 *len)
2791 {
2792 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2793 	u8 *frame = NULL, *pos;
2794 	u32 flen;
2795 	struct rtw_ieee80211_hdr *whdr;
2796 
2797 	if (minfo->mesh_auth_id && !MESH_PLINK_AEK_VALID(plink))
2798 		goto exit;
2799 
2800 	flen = sizeof(struct rtw_ieee80211_hdr_3addr)
2801 		+ 2 /* category, action */
2802 		+ 2 + minfo->mesh_id_len /* mesh id */
2803 		+ 2 + 8 + (minfo->mesh_auth_id ? 16 : 0) /* mpm */
2804 		+ (minfo->mesh_auth_id ? 2 + 16 /* AES_BLOCK_SIZE */ : 0) /* mic */
2805 		+ (minfo->mesh_auth_id ? 70 : 0) /* ampe */
2806 		;
2807 
2808 	pos = frame = rtw_zmalloc(flen);
2809 	if (!frame)
2810 		goto exit;
2811 
2812 	whdr = (struct rtw_ieee80211_hdr *)frame;
2813 	_rtw_memcpy(whdr->addr1, adapter_mac_addr(adapter), ETH_ALEN);
2814 	_rtw_memcpy(whdr->addr2, plink->addr, ETH_ALEN);
2815 	_rtw_memcpy(whdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
2816 
2817 	set_frame_sub_type(frame, WIFI_ACTION);
2818 
2819 	pos += sizeof(struct rtw_ieee80211_hdr_3addr);
2820 	*(pos++) = RTW_WLAN_CATEGORY_SELF_PROTECTED;
2821 	*(pos++) = RTW_ACT_SELF_PROTECTED_MESH_CLOSE;
2822 
2823 	pos = rtw_set_ie_mesh_id(pos, NULL, minfo->mesh_id, minfo->mesh_id_len);
2824 
2825 	pos = rtw_set_ie_mpm(pos, NULL
2826 		, minfo->mesh_auth_id ? 1 : 0
2827 		, plink->plid
2828 		, &plink->llid
2829 		, &reason
2830 		, minfo->mesh_auth_id ? plink->chosen_pmk : NULL);
2831 
2832 #ifdef CONFIG_RTW_MESH_AEK
2833 	if (minfo->mesh_auth_id) {
2834 		u8 ampe_buf[70];
2835 		int enc_ret;
2836 
2837 		*pos = WLAN_EID_MIC;
2838 		*(pos + 1) = 16 /* AES_BLOCK_SIZE */;
2839 
2840 		ampe_buf[0] = WLAN_EID_AMPE;
2841 		ampe_buf[1] = 68;
2842 		_rtw_memcpy(ampe_buf + 2, plink->sel_pcs, 4);
2843 		_rtw_memcpy(ampe_buf + 6, plink->p_nonce, 32);
2844 		_rtw_memcpy(ampe_buf + 38, plink->l_nonce, 32);
2845 
2846 		enc_ret = rtw_mpm_ampe_enc(adapter, plink
2847 			, frame + sizeof(struct rtw_ieee80211_hdr_3addr)
2848 			, pos, ampe_buf, 1);
2849 		if (enc_ret != _SUCCESS) {
2850 			rtw_mfree(frame, flen);
2851 			frame = NULL;
2852 			goto exit;
2853 		}
2854 	}
2855 #endif
2856 
2857 	*len = flen;
2858 
2859 exit:
2860 	return frame;
2861 }
2862 
_rtw_mesh_expire_peer_ent(_adapter * adapter,struct mesh_plink_ent * plink)2863 void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink)
2864 {
2865 #if defined(CONFIG_RTW_MESH_STA_DEL_DISASOC)
2866 	_rtw_mesh_plink_del_ent(adapter, plink);
2867 	rtw_cfg80211_indicate_sta_disassoc(adapter, plink->addr, 0);
2868 #else
2869 	u8 *frame = NULL;
2870 	u32 flen;
2871 
2872 	if (plink->plink_state == RTW_MESH_PLINK_ESTAB)
2873 		frame = rtw_mesh_construct_peer_mesh_close(adapter, plink, WLAN_REASON_MESH_CLOSE, &flen);
2874 
2875 	if (frame) {
2876 		struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
2877 		struct wireless_dev *wdev = adapter->rtw_wdev;
2878 		s32 freq = rtw_ch2freq(mlmeext->cur_channel);
2879 
2880 		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2881 		rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, flen, GFP_ATOMIC);
2882 		#else
2883 		cfg80211_rx_action(adapter->pnetdev, freq, frame, flen, GFP_ATOMIC);
2884 		#endif
2885 
2886 		rtw_mfree(frame, flen);
2887 	} else {
2888 		rtw_mesh_expire_peer_notify(adapter, plink->addr);
2889 		RTW_INFO(FUNC_ADPT_FMT" set "MAC_FMT" plink unknown\n"
2890 			, FUNC_ADPT_ARG(adapter), MAC_ARG(plink->addr));
2891 		plink->plink_state = RTW_MESH_PLINK_UNKNOWN;
2892 	}
2893 #endif
2894 }
2895 
rtw_mesh_expire_peer(_adapter * adapter,const u8 * peer_addr)2896 void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr)
2897 {
2898 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2899 	struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
2900 	struct mesh_plink_ent *plink;
2901 	_irqL irqL;
2902 
2903 	_enter_critical_bh(&(plink_ctl->lock), &irqL);
2904 
2905 	plink = _rtw_mesh_plink_get(adapter, peer_addr);
2906 	if (!plink)
2907 		goto exit;
2908 
2909 	_rtw_mesh_expire_peer_ent(adapter, plink);
2910 
2911 exit:
2912 	_exit_critical_bh(&(plink_ctl->lock), &irqL);
2913 }
2914 
rtw_mesh_ps_annc(_adapter * adapter,u8 ps)2915 u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps)
2916 {
2917 	_irqL irqL;
2918 	_list *head, *list;
2919 	struct sta_info *sta;
2920 	struct sta_priv *stapriv = &adapter->stapriv;
2921 	u8 sta_alive_num = 0, i;
2922 	char sta_alive_list[NUM_STA];
2923 	u8 annc_cnt = 0;
2924 
2925 	if (rtw_linked_check(adapter) == _FALSE)
2926 		goto exit;
2927 
2928 	_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
2929 
2930 	head = &stapriv->asoc_list;
2931 	list = get_next(head);
2932 	while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
2933 		int stainfo_offset;
2934 
2935 		sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
2936 		list = get_next(list);
2937 
2938 		stainfo_offset = rtw_stainfo_offset(stapriv, sta);
2939 		if (stainfo_offset_valid(stainfo_offset))
2940 			sta_alive_list[sta_alive_num++] = stainfo_offset;
2941 	}
2942 	_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
2943 
2944 	for (i = 0; i < sta_alive_num; i++) {
2945 		sta = rtw_get_stainfo_by_offset(stapriv, sta_alive_list[i]);
2946 		if (!sta)
2947 			continue;
2948 
2949 		issue_qos_nulldata(adapter, sta->cmn.mac_addr, 7, ps, 3, 500);
2950 		annc_cnt++;
2951 	}
2952 
2953 exit:
2954 	return annc_cnt;
2955 }
2956 
mpath_tx_tasklet_hdl(unsigned long priv)2957 static void mpath_tx_tasklet_hdl(unsigned long priv)
2958 {
2959 	_adapter *adapter = (_adapter *)priv;
2960 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
2961 	struct xmit_frame *xframe;
2962 	_list *list, *head;
2963 	_list tmp;
2964 	u32 tmp_len;
2965 	s32 res;
2966 
2967 	_rtw_init_listhead(&tmp);
2968 
2969 	while (1) {
2970 		tmp_len = 0;
2971 		enter_critical_bh(&minfo->mpath_tx_queue.lock);
2972 		if (minfo->mpath_tx_queue_len) {
2973 			rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp);
2974 			tmp_len = minfo->mpath_tx_queue_len;
2975 			minfo->mpath_tx_queue_len = 0;
2976 		}
2977 		exit_critical_bh(&minfo->mpath_tx_queue.lock);
2978 
2979 		if (!tmp_len)
2980 			break;
2981 
2982 		head = &tmp;
2983 		list = get_next(head);
2984 		while (rtw_end_of_queue_search(head, list) == _FALSE) {
2985 			xframe = LIST_CONTAINOR(list, struct xmit_frame, list);
2986 			list = get_next(list);
2987 			rtw_list_delete(&xframe->list);
2988 			res = rtw_xmit_posthandle(adapter, xframe, xframe->pkt);
2989 			if (res < 0) {
2990 				#ifdef DBG_TX_DROP_FRAME
2991 				RTW_INFO("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__);
2992 				#endif
2993 				adapter->xmitpriv.tx_drop++;
2994 			}
2995 		}
2996 	}
2997 }
2998 
rtw_mpath_tx_queue_flush(_adapter * adapter)2999 static void rtw_mpath_tx_queue_flush(_adapter *adapter)
3000 {
3001 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3002 	struct xmit_frame *xframe;
3003 	_list *list, *head;
3004 	_list tmp;
3005 
3006 	_rtw_init_listhead(&tmp);
3007 
3008 	enter_critical_bh(&minfo->mpath_tx_queue.lock);
3009 	rtw_list_splice_init(&minfo->mpath_tx_queue.queue, &tmp);
3010 	minfo->mpath_tx_queue_len = 0;
3011 	exit_critical_bh(&minfo->mpath_tx_queue.lock);
3012 
3013 	head = &tmp;
3014 	list = get_next(head);
3015 	while (rtw_end_of_queue_search(head, list) == _FALSE) {
3016 		xframe = LIST_CONTAINOR(list, struct xmit_frame, list);
3017 		list = get_next(list);
3018 		rtw_list_delete(&xframe->list);
3019 		rtw_free_xmitframe(&adapter->xmitpriv, xframe);
3020 	}
3021 }
3022 
3023 #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
3024 #if defined(CONFIG_SLUB)
3025 #include <linux/slub_def.h>
3026 #elif defined(CONFIG_SLAB)
3027 #include <linux/slab_def.h>
3028 #endif
3029 typedef struct kmem_cache rtw_mcache;
3030 #endif
3031 
rtw_mcache_create(const char * name,size_t size)3032 rtw_mcache *rtw_mcache_create(const char *name, size_t size)
3033 {
3034 #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
3035 	return kmem_cache_create(name, size, 0, 0, NULL);
3036 #else
3037 	#error "TBD\n";
3038 #endif
3039 }
3040 
rtw_mcache_destroy(rtw_mcache * s)3041 void rtw_mcache_destroy(rtw_mcache *s)
3042 {
3043 #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
3044 	kmem_cache_destroy(s);
3045 #else
3046 	#error "TBD\n";
3047 #endif
3048 }
3049 
_rtw_mcache_alloc(rtw_mcache * cachep)3050 void *_rtw_mcache_alloc(rtw_mcache *cachep)
3051 {
3052 #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
3053 	return kmem_cache_alloc(cachep, GFP_ATOMIC);
3054 #else
3055 	#error "TBD\n";
3056 #endif
3057 }
3058 
_rtw_mcache_free(rtw_mcache * cachep,void * objp)3059 void _rtw_mcache_free(rtw_mcache *cachep, void *objp)
3060 {
3061 #ifdef PLATFORM_LINUX /* 3.10 ~ 4.13 checked */
3062 	kmem_cache_free(cachep, objp);
3063 #else
3064 	#error "TBD\n";
3065 #endif
3066 }
3067 
3068 #ifdef DBG_MEM_ALLOC
dbg_rtw_mcache_alloc(rtw_mcache * cachep,const enum mstat_f flags,const char * func,const int line)3069 inline void *dbg_rtw_mcache_alloc(rtw_mcache *cachep, const enum mstat_f flags, const char *func, const int line)
3070 {
3071 	void *p;
3072 	u32 sz = cachep->size;
3073 
3074 	if (match_mstat_sniff_rules(flags, sz))
3075 		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz);
3076 
3077 	p = _rtw_mcache_alloc(cachep);
3078 
3079 	rtw_mstat_update(
3080 		flags
3081 		, p ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
3082 		, sz
3083 	);
3084 
3085 	return p;
3086 }
3087 
dbg_rtw_mcache_free(rtw_mcache * cachep,void * pbuf,const enum mstat_f flags,const char * func,const int line)3088 inline void dbg_rtw_mcache_free(rtw_mcache *cachep, void *pbuf, const enum mstat_f flags, const char *func, const int line)
3089 {
3090 	u32 sz = cachep->size;
3091 
3092 	if (match_mstat_sniff_rules(flags, sz))
3093 		RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%u)\n", func, line, __func__, sz);
3094 
3095 	_rtw_mcache_free(cachep, pbuf);
3096 
3097 	rtw_mstat_update(
3098 		flags
3099 		, MSTAT_FREE
3100 		, sz
3101 	);
3102 }
3103 
3104 #define rtw_mcache_alloc(cachep) dbg_rtw_mcache_alloc(cachep, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__)
3105 #define rtw_mcache_free(cachep, objp) dbg_rtw_mcache_free(cachep, objp, MSTAT_TYPE_PHY, __FUNCTION__, __LINE__)
3106 #else
3107 #define rtw_mcache_alloc(cachep) _rtw_mcache_alloc(cachep)
3108 #define rtw_mcache_free(cachep, objp) _rtw_mcache_free(cachep, objp)
3109 #endif /* DBG_MEM_ALLOC */
3110 
3111 /* Mesh Received Cache */
3112 #define RTW_MRC_BUCKETS			256 /* must be a power of 2 */
3113 #define RTW_MRC_QUEUE_MAX_LEN	4
3114 #define RTW_MRC_TIMEOUT_MS		(3 * 1000)
3115 
3116 /**
3117  * struct rtw_mrc_entry - entry in the Mesh Received Cache
3118  *
3119  * @seqnum: mesh sequence number of the frame
3120  * @exp_time: expiration time of the entry
3121  * @msa: mesh source address of the frame
3122  * @list: hashtable list pointer
3123  *
3124  * The Mesh Received Cache keeps track of the latest received frames that
3125  * have been received by a mesh interface and discards received frames
3126  * that are found in the cache.
3127  */
3128 struct rtw_mrc_entry {
3129 	rtw_hlist_node list;
3130 	systime exp_time;
3131 	u32 seqnum;
3132 	u8 msa[ETH_ALEN];
3133 };
3134 
3135 struct rtw_mrc {
3136 	rtw_hlist_head bucket[RTW_MRC_BUCKETS];
3137 	u32 idx_mask;
3138 	rtw_mcache *cache;
3139 };
3140 
rtw_mrc_init(_adapter * adapter)3141 static int rtw_mrc_init(_adapter *adapter)
3142 {
3143 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3144 	char cache_name[IFNAMSIZ + 8 + 1];
3145 	int i;
3146 
3147 	minfo->mrc = rtw_malloc(sizeof(struct rtw_mrc));
3148 	if (!minfo->mrc)
3149 		return -ENOMEM;
3150 	minfo->mrc->idx_mask = RTW_MRC_BUCKETS - 1;
3151 	for (i = 0; i < RTW_MRC_BUCKETS; i++)
3152 		rtw_hlist_head_init(&minfo->mrc->bucket[i]);
3153 
3154 	sprintf(cache_name, "rtw_mrc_%s", ADPT_ARG(adapter));
3155 	minfo->mrc->cache = rtw_mcache_create(cache_name, sizeof(struct rtw_mrc_entry));
3156 
3157 	return 0;
3158 }
3159 
rtw_mrc_free(_adapter * adapter)3160 static void rtw_mrc_free(_adapter *adapter)
3161 {
3162 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3163 	struct rtw_mrc *mrc = minfo->mrc;
3164 	struct rtw_mrc_entry *p;
3165 	rtw_hlist_node *np, *n;
3166 	int i;
3167 
3168 	if (!mrc)
3169 		return;
3170 
3171 	for (i = 0; i < RTW_MRC_BUCKETS; i++) {
3172 		rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[i], list) {
3173 			rtw_hlist_del(&p->list);
3174 			rtw_mcache_free(mrc->cache, p);
3175 		}
3176 	}
3177 
3178 	rtw_mcache_destroy(mrc->cache);
3179 
3180 	rtw_mfree(mrc, sizeof(struct rtw_mrc));
3181 	minfo->mrc = NULL;
3182 }
3183 
3184 /**
3185  * rtw_mrc_check - Check frame in mesh received cache and add if absent.
3186  *
3187  * @adapter:	interface
3188  * @msa:		mesh source address
3189  * @seq:		mesh seq number
3190  *
3191  * Returns: 0 if the frame is not in the cache, nonzero otherwise.
3192  *
3193  * Checks using the mesh source address and the mesh sequence number if we have
3194  * received this frame lately. If the frame is not in the cache, it is added to
3195  * it.
3196  */
rtw_mrc_check(_adapter * adapter,const u8 * msa,u32 seq)3197 static int rtw_mrc_check(_adapter *adapter, const u8 *msa, u32 seq)
3198 {
3199 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3200 	struct rtw_mrc *mrc = minfo->mrc;
3201 	int entries = 0;
3202 	u8 idx;
3203 	struct rtw_mrc_entry *p;
3204 	rtw_hlist_node *np, *n;
3205 	u8 timeout;
3206 
3207 	if (!mrc)
3208 		return -1;
3209 
3210 	idx = seq & mrc->idx_mask;
3211 	rtw_hlist_for_each_entry_safe(p, np, n, &mrc->bucket[idx], list) {
3212 		++entries;
3213 		timeout = rtw_time_after(rtw_get_current_time(), p->exp_time);
3214 		if (timeout || entries == RTW_MRC_QUEUE_MAX_LEN) {
3215 			if (!timeout)
3216 				minfo->mshstats.mrc_del_qlen++;
3217 
3218 			rtw_hlist_del(&p->list);
3219 			rtw_mcache_free(mrc->cache, p);
3220 			--entries;
3221 		} else if ((seq == p->seqnum) && _rtw_memcmp(msa, p->msa, ETH_ALEN) == _TRUE)
3222 			return -1;
3223 	}
3224 
3225 	p = rtw_mcache_alloc(mrc->cache);
3226 	if (!p)
3227 		return 0;
3228 
3229 	p->seqnum = seq;
3230 	p->exp_time = rtw_get_current_time() + rtw_ms_to_systime(RTW_MRC_TIMEOUT_MS);
3231 	_rtw_memcpy(p->msa, msa, ETH_ALEN);
3232 	rtw_hlist_add_head(&p->list, &mrc->bucket[idx]);
3233 	return 0;
3234 }
3235 
rtw_mesh_decache(_adapter * adapter,const u8 * msa,u32 seq)3236 static int rtw_mesh_decache(_adapter *adapter, const u8 *msa, u32 seq)
3237 {
3238 	return rtw_mrc_check(adapter, msa, seq);
3239 }
3240 
3241 #ifndef RTW_MESH_SCAN_RESULT_EXP_MS
3242 #define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000)
3243 #endif
3244 
3245 #ifndef RTW_MESH_ACNODE_PREVENT
3246 #define RTW_MESH_ACNODE_PREVENT 0
3247 #endif
3248 #ifndef RTW_MESH_ACNODE_CONF_TIMEOUT_MS
3249 #define RTW_MESH_ACNODE_CONF_TIMEOUT_MS (20 * 1000)
3250 #endif
3251 #ifndef RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS
3252 #define RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS (2 * 1000)
3253 #endif
3254 
3255 #ifndef RTW_MESH_OFFCH_CAND
3256 #define RTW_MESH_OFFCH_CAND 1
3257 #endif
3258 #ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS
3259 #define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000)
3260 #endif
3261 
3262 #ifndef RTW_MESH_PEER_CONF_TIMEOUT_MS
3263 #define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000)
3264 #endif
3265 #ifndef RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS
3266 #define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000)
3267 #endif
3268 
3269 #ifndef RTW_MESH_CTO_MGATE_REQUIRE
3270 #define RTW_MESH_CTO_MGATE_REQUIRE 0
3271 #endif
3272 #ifndef RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS
3273 #define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000)
3274 #endif
3275 #ifndef RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS
3276 #define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000)
3277 #endif
3278 
rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg * mcfg)3279 void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg)
3280 {
3281 	struct mesh_peer_sel_policy *sel_policy = &mcfg->peer_sel_policy;
3282 
3283 	sel_policy->scanr_exp_ms = RTW_MESH_SCAN_RESULT_EXP_MS;
3284 
3285 #if CONFIG_RTW_MESH_ACNODE_PREVENT
3286 	sel_policy->acnode_prevent = RTW_MESH_ACNODE_PREVENT;
3287 	sel_policy->acnode_conf_timeout_ms = RTW_MESH_ACNODE_CONF_TIMEOUT_MS;
3288 	sel_policy->acnode_notify_timeout_ms = RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS;
3289 #endif
3290 
3291 #if CONFIG_RTW_MESH_OFFCH_CAND
3292 	sel_policy->offch_cand = RTW_MESH_OFFCH_CAND;
3293 	sel_policy->offch_find_int_ms = RTW_MESH_OFFCH_CAND_FIND_INT_MS;
3294 #endif
3295 
3296 #if CONFIG_RTW_MESH_PEER_BLACKLIST
3297 	sel_policy->peer_conf_timeout_ms = RTW_MESH_PEER_CONF_TIMEOUT_MS;
3298 	sel_policy->peer_blacklist_timeout_ms = RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS;
3299 #endif
3300 
3301 #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
3302 	sel_policy->cto_mgate_require = RTW_MESH_CTO_MGATE_REQUIRE;
3303 	sel_policy->cto_mgate_conf_timeout_ms = RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS;
3304 	sel_policy->cto_mgate_blacklist_timeout_ms = RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS;
3305 #endif
3306 }
3307 
rtw_mesh_cfg_init(_adapter * adapter)3308 void rtw_mesh_cfg_init(_adapter *adapter)
3309 {
3310 	struct registry_priv *regsty = adapter_to_regsty(adapter);
3311 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
3312 
3313 	mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS;
3314 	mcfg->plink_timeout = RTW_MESH_PEER_LINK_TIMEOUT;
3315 
3316 	mcfg->dot11MeshTTL = RTW_MESH_TTL;
3317 	mcfg->element_ttl = RTW_MESH_DEFAULT_ELEMENT_TTL;
3318 	mcfg->dot11MeshHWMPmaxPREQretries = RTW_MESH_MAX_PREQ_RETRIES;
3319 	mcfg->path_refresh_time = RTW_MESH_PATH_REFRESH_TIME;
3320 	mcfg->min_discovery_timeout = RTW_MESH_MIN_DISCOVERY_TIMEOUT;
3321 	mcfg->dot11MeshHWMPactivePathTimeout = RTW_MESH_PATH_TIMEOUT;
3322 	mcfg->dot11MeshHWMPpreqMinInterval = RTW_MESH_PREQ_MIN_INT;
3323 	mcfg->dot11MeshHWMPperrMinInterval = RTW_MESH_PERR_MIN_INT;
3324 	mcfg->dot11MeshHWMPnetDiameterTraversalTime = RTW_MESH_DIAM_TRAVERSAL_TIME;
3325 	mcfg->dot11MeshHWMPRootMode = RTW_IEEE80211_ROOTMODE_NO_ROOT;
3326 	mcfg->dot11MeshHWMPRannInterval = RTW_MESH_RANN_INTERVAL;
3327 	mcfg->dot11MeshGateAnnouncementProtocol = _FALSE;
3328 	mcfg->dot11MeshForwarding = _TRUE;
3329 	mcfg->rssi_threshold = 0;
3330 	mcfg->dot11MeshHWMPactivePathToRootTimeout = RTW_MESH_PATH_TO_ROOT_TIMEOUT;
3331 	mcfg->dot11MeshHWMProotInterval = RTW_MESH_ROOT_INTERVAL;
3332 	mcfg->dot11MeshHWMPconfirmationInterval = RTW_MESH_ROOT_CONFIRMATION_INTERVAL;
3333 	mcfg->path_gate_timeout_factor = 3;
3334 	rtw_mesh_cfg_init_peer_sel_policy(mcfg);
3335 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
3336 	mcfg->sane_metric_delta = RTW_MESH_SANE_METRIC_DELTA;
3337 	mcfg->max_root_add_chk_cnt = RTW_MESH_MAX_ROOT_ADD_CHK_CNT;
3338 #endif
3339 
3340 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3341 	mcfg->b2u_flags_msrc = regsty->msrc_b2u_flags;
3342 	mcfg->b2u_flags_mfwd = regsty->mfwd_b2u_flags;
3343 #endif
3344 }
3345 
rtw_mesh_cfg_init_max_peer_links(_adapter * adapter,u8 stack_conf)3346 void rtw_mesh_cfg_init_max_peer_links(_adapter *adapter, u8 stack_conf)
3347 {
3348 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
3349 
3350 	mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS;
3351 
3352 	if (mcfg->max_peer_links > stack_conf)
3353 		mcfg->max_peer_links = stack_conf;
3354 }
3355 
rtw_mesh_cfg_init_plink_timeout(_adapter * adapter,u32 stack_conf)3356 void rtw_mesh_cfg_init_plink_timeout(_adapter *adapter, u32 stack_conf)
3357 {
3358 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
3359 
3360 	mcfg->plink_timeout = stack_conf;
3361 }
3362 
rtw_mesh_init_mesh_info(_adapter * adapter)3363 void rtw_mesh_init_mesh_info(_adapter *adapter)
3364 {
3365 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3366 
3367 	_rtw_memset(minfo, 0, sizeof(struct rtw_mesh_info));
3368 
3369 	rtw_mesh_plink_ctl_init(adapter);
3370 
3371 	minfo->last_preq = rtw_get_current_time();
3372 	/* minfo->last_sn_update = rtw_get_current_time(); */
3373 	minfo->next_perr = rtw_get_current_time();
3374 
3375 	ATOMIC_SET(&minfo->mpaths, 0);
3376 	rtw_mesh_pathtbl_init(adapter);
3377 
3378 	_rtw_init_queue(&minfo->mpath_tx_queue);
3379 	tasklet_init(&minfo->mpath_tx_tasklet
3380 		, mpath_tx_tasklet_hdl
3381 		, (unsigned long)adapter);
3382 
3383 	rtw_mrc_init(adapter);
3384 
3385 	_rtw_init_listhead(&minfo->preq_queue.list);
3386 	_rtw_spinlock_init(&minfo->mesh_preq_queue_lock);
3387 
3388 	rtw_init_timer(&adapter->mesh_path_timer, adapter, rtw_ieee80211_mesh_path_timer, adapter);
3389 	rtw_init_timer(&adapter->mesh_path_root_timer, adapter, rtw_ieee80211_mesh_path_root_timer, adapter);
3390 	rtw_init_timer(&adapter->mesh_atlm_param_req_timer, adapter, rtw_mesh_atlm_param_req_timer, adapter);
3391 	_init_workitem(&adapter->mesh_work, rtw_mesh_work_hdl, NULL);
3392 }
3393 
rtw_mesh_deinit_mesh_info(_adapter * adapter)3394 void rtw_mesh_deinit_mesh_info(_adapter *adapter)
3395 {
3396 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
3397 
3398 	tasklet_kill(&minfo->mpath_tx_tasklet);
3399 	rtw_mpath_tx_queue_flush(adapter);
3400 	_rtw_deinit_queue(&adapter->mesh_info.mpath_tx_queue);
3401 
3402 	rtw_mrc_free(adapter);
3403 
3404 	rtw_mesh_pathtbl_unregister(adapter);
3405 
3406 	rtw_mesh_plink_ctl_deinit(adapter);
3407 
3408 	_cancel_workitem_sync(&adapter->mesh_work);
3409 	_cancel_timer_ex(&adapter->mesh_path_timer);
3410 	_cancel_timer_ex(&adapter->mesh_path_root_timer);
3411 	_cancel_timer_ex(&adapter->mesh_atlm_param_req_timer);
3412 }
3413 
3414 /**
3415  * rtw_mesh_nexthop_resolve - lookup next hop; conditionally start path discovery
3416  *
3417  * @skb: 802.11 frame to be sent
3418  * @sdata: network subif the frame will be sent through
3419  *
3420  * Lookup next hop for given skb and start path discovery if no
3421  * forwarding information is found.
3422  *
3423  * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
3424  * skb is freeed here if no mpath could be allocated.
3425  */
rtw_mesh_nexthop_resolve(_adapter * adapter,struct xmit_frame * xframe)3426 int rtw_mesh_nexthop_resolve(_adapter *adapter,
3427 			struct xmit_frame *xframe)
3428 {
3429 	struct pkt_attrib *attrib = &xframe->attrib;
3430 	struct rtw_mesh_path *mpath;
3431 	struct xmit_frame *xframe_to_free = NULL;
3432 	u8 *target_addr = attrib->mda;
3433 	int err = 0;
3434 	int ret = _SUCCESS;
3435 
3436 	rtw_rcu_read_lock();
3437 	err = rtw_mesh_nexthop_lookup(adapter, target_addr, attrib->msa, attrib->ra);
3438 	if (!err)
3439 		goto endlookup;
3440 
3441 	/* no nexthop found, start resolving */
3442 	mpath = rtw_mesh_path_lookup(adapter, target_addr);
3443 	if (!mpath) {
3444 		mpath = rtw_mesh_path_add(adapter, target_addr);
3445 		if (IS_ERR(mpath)) {
3446 			xframe->pkt = NULL; /* free pkt outside */
3447 			rtw_mesh_path_discard_frame(adapter, xframe);
3448 			err = PTR_ERR(mpath);
3449 			ret = _FAIL;
3450 			goto endlookup;
3451 		}
3452 	}
3453 
3454 	if (!(mpath->flags & RTW_MESH_PATH_RESOLVING))
3455 		rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START);
3456 
3457 	enter_critical_bh(&mpath->frame_queue.lock);
3458 
3459 	if (mpath->frame_queue_len >= RTW_MESH_FRAME_QUEUE_LEN) {
3460 		xframe_to_free = LIST_CONTAINOR(get_next(get_list_head(&mpath->frame_queue)), struct xmit_frame, list);
3461 		rtw_list_delete(&(xframe_to_free->list));
3462 		mpath->frame_queue_len--;
3463 	}
3464 
3465 	rtw_list_insert_tail(&xframe->list, get_list_head(&mpath->frame_queue));
3466 	mpath->frame_queue_len++;
3467 
3468 	exit_critical_bh(&mpath->frame_queue.lock);
3469 
3470 	ret = RTW_RA_RESOLVING;
3471 	if (xframe_to_free)
3472 		rtw_mesh_path_discard_frame(adapter, xframe_to_free);
3473 
3474 endlookup:
3475 	rtw_rcu_read_unlock();
3476 	return ret;
3477 }
3478 
3479 /**
3480  * rtw_mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
3481  * this function is considered "using" the associated mpath, so preempt a path
3482  * refresh if this mpath expires soon.
3483  *
3484  * @skb: 802.11 frame to be sent
3485  * @sdata: network subif the frame will be sent through
3486  *
3487  * Returns: 0 if the next hop was found. Nonzero otherwise.
3488  */
rtw_mesh_nexthop_lookup(_adapter * adapter,const u8 * mda,const u8 * msa,u8 * ra)3489 int rtw_mesh_nexthop_lookup(_adapter *adapter,
3490 	const u8 *mda, const u8 *msa, u8 *ra)
3491 {
3492 	struct rtw_mesh_path *mpath;
3493 	struct sta_info *next_hop;
3494 	const u8 *target_addr = mda;
3495 	int err = -ENOENT;
3496 	struct registry_priv  *registry_par = &adapter->registrypriv;
3497 	u8 peer_alive_based_preq = registry_par->peer_alive_based_preq;
3498 	BOOLEAN nexthop_alive = _TRUE;
3499 
3500 	rtw_rcu_read_lock();
3501 	mpath = rtw_mesh_path_lookup(adapter, target_addr);
3502 
3503 	if (!mpath || !(mpath->flags & RTW_MESH_PATH_ACTIVE))
3504 		goto endlookup;
3505 
3506 	next_hop = rtw_rcu_dereference(mpath->next_hop);
3507 	if (next_hop) {
3508 		_rtw_memcpy(ra, next_hop->cmn.mac_addr, ETH_ALEN);
3509 		err = 0;
3510 	}
3511 
3512 	if (peer_alive_based_preq && next_hop)
3513 		nexthop_alive = next_hop->alive;
3514 
3515 	if (_rtw_memcmp(adapter_mac_addr(adapter), msa, ETH_ALEN) == _TRUE &&
3516 	    !(mpath->flags & RTW_MESH_PATH_RESOLVING) &&
3517 	    !(mpath->flags & RTW_MESH_PATH_FIXED)) {
3518 		u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH;
3519 
3520 		if (peer_alive_based_preq && nexthop_alive == _FALSE) {
3521 			flags |= RTW_PREQ_Q_F_BCAST_PREQ;
3522 			rtw_mesh_queue_preq(mpath, flags);
3523 		} else if (rtw_time_after(rtw_get_current_time(),
3524 			mpath->exp_time -
3525 			rtw_ms_to_systime(adapter->mesh_cfg.path_refresh_time))) {
3526 			rtw_mesh_queue_preq(mpath, flags);
3527 		}
3528 	/* Avoid keeping trying unicast PREQ toward root,
3529 	   when next_hop leaves */
3530 	} else if (peer_alive_based_preq &&
3531 		   _rtw_memcmp(adapter_mac_addr(adapter), msa, ETH_ALEN) == _TRUE &&
3532 		   (mpath->flags & RTW_MESH_PATH_RESOLVING) &&
3533 		   !(mpath->flags & RTW_MESH_PATH_FIXED) &&
3534 		   !(mpath->flags & RTW_MESH_PATH_BCAST_PREQ) &&
3535 		   mpath->is_root && nexthop_alive == _FALSE) {
3536 		enter_critical_bh(&mpath->state_lock);
3537 		mpath->flags |= RTW_MESH_PATH_BCAST_PREQ;
3538 		exit_critical_bh(&mpath->state_lock);
3539 	}
3540 
3541 endlookup:
3542 	rtw_rcu_read_unlock();
3543 	return err;
3544 }
3545 
3546 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
rtw_mesh_data_bmc_to_uc(_adapter * adapter,const u8 * da,const u8 * sa,const u8 * mda,const u8 * msa,u8 ae_need,const u8 * ori_ta,u8 mfwd_ttl,u16 os_qid,_list * b2u_list,u8 * b2u_num,u32 * b2u_mseq)3547 static bool rtw_mesh_data_bmc_to_uc(_adapter *adapter
3548 	, const u8 *da, const u8 *sa, const u8 *mda, const u8 *msa
3549 	, u8 ae_need, const u8 *ori_ta, u8 mfwd_ttl
3550 	, u16 os_qid, _list *b2u_list, u8 *b2u_num, u32 *b2u_mseq)
3551 {
3552 	struct sta_priv *stapriv = &adapter->stapriv;
3553 	struct xmit_priv *xmitpriv = &adapter->xmitpriv;
3554 	_irqL irqL;
3555 	_list *head, *list;
3556 	struct sta_info *sta;
3557 	char b2u_sta_id[NUM_STA];
3558 	u8 b2u_sta_num = 0;
3559 	bool bmc_need = _FALSE;
3560 	int i;
3561 
3562 	_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
3563 	head = &stapriv->asoc_list;
3564 	list = get_next(head);
3565 
3566 	while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
3567 		int stainfo_offset;
3568 
3569 		sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
3570 		list = get_next(list);
3571 
3572 		stainfo_offset = rtw_stainfo_offset(stapriv, sta);
3573 		if (stainfo_offset_valid(stainfo_offset))
3574 			b2u_sta_id[b2u_sta_num++] = stainfo_offset;
3575 	}
3576 	_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
3577 
3578 	if (!b2u_sta_num)
3579 		goto exit;
3580 
3581 	for (i = 0; i < b2u_sta_num; i++) {
3582 		struct xmit_frame *b2uframe;
3583 		struct pkt_attrib *attrib;
3584 
3585 		sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]);
3586 		if (!(sta->state & WIFI_ASOC_STATE)
3587 			|| _rtw_memcmp(sta->cmn.mac_addr, msa, ETH_ALEN) == _TRUE
3588 			|| (ori_ta && _rtw_memcmp(sta->cmn.mac_addr, ori_ta, ETH_ALEN) == _TRUE)
3589 			|| is_broadcast_mac_addr(sta->cmn.mac_addr)
3590 			|| is_zero_mac_addr(sta->cmn.mac_addr))
3591 			continue;
3592 
3593 		b2uframe = rtw_alloc_xmitframe(xmitpriv, os_qid);
3594 		if (!b2uframe) {
3595 			bmc_need = _TRUE;
3596 			break;
3597 		}
3598 
3599 		if ((*b2u_num)++ == 0 && !ori_ta) {
3600 			*b2u_mseq = (cpu_to_le32(adapter->mesh_info.mesh_seqnum));
3601 			adapter->mesh_info.mesh_seqnum++;
3602 		}
3603 
3604 		attrib = &b2uframe->attrib;
3605 
3606 		attrib->mb2u = 1;
3607 		attrib->mseq = *b2u_mseq;
3608 		attrib->mfwd_ttl = ori_ta ? mfwd_ttl : 0;
3609 		_rtw_memcpy(attrib->ra, sta->cmn.mac_addr, ETH_ALEN);
3610 		_rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
3611 		_rtw_memcpy(attrib->mda, mda, ETH_ALEN);
3612 		_rtw_memcpy(attrib->msa, msa, ETH_ALEN);
3613 		_rtw_memcpy(attrib->dst, da, ETH_ALEN);
3614 		_rtw_memcpy(attrib->src, sa, ETH_ALEN);
3615 		attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
3616 
3617 		rtw_list_insert_tail(&b2uframe->list, b2u_list);
3618 	}
3619 
3620 exit:
3621 	return bmc_need;
3622 }
3623 
dump_mesh_b2u_flags(void * sel,_adapter * adapter)3624 void dump_mesh_b2u_flags(void *sel, _adapter *adapter)
3625 {
3626 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
3627 
3628 	RTW_PRINT_SEL(sel, "%4s %4s\n", "msrc", "mfwd");
3629 	RTW_PRINT_SEL(sel, "0x%02x 0x%02x\n", mcfg->b2u_flags_msrc, mcfg->b2u_flags_mfwd);
3630 }
3631 #endif /* CONFIG_RTW_MESH_DATA_BMC_TO_UC */
3632 
rtw_mesh_addr_resolve(_adapter * adapter,u16 os_qid,struct xmit_frame * xframe,_pkt * pkt,_list * b2u_list)3633 int rtw_mesh_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list)
3634 {
3635 	struct pkt_file pktfile;
3636 	struct ethhdr etherhdr;
3637 	struct pkt_attrib *attrib;
3638 	struct rtw_mesh_path *mpath = NULL, *mppath = NULL;
3639 	u8 is_da_mcast;
3640 	u8 ae_need;
3641 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3642 	bool bmc_need = _TRUE;
3643 	u8 b2u_num = 0;
3644 	u32 b2u_mseq = 0;
3645 #endif
3646 	int res = _SUCCESS;
3647 
3648 	_rtw_open_pktfile(pkt, &pktfile);
3649 	if (_rtw_pktfile_read(&pktfile, (u8 *)&etherhdr, ETH_HLEN) != ETH_HLEN) {
3650 		res = _FAIL;
3651 		goto exit;
3652 	}
3653 
3654 	xframe->pkt = pkt;
3655 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3656 	_rtw_init_listhead(b2u_list);
3657 #endif
3658 
3659 	is_da_mcast = IS_MCAST(etherhdr.h_dest);
3660 	if (!is_da_mcast) {
3661 		struct sta_info *next_hop;
3662 		bool mpp_lookup = 1;
3663 
3664 		mpath = rtw_mesh_path_lookup(adapter, etherhdr.h_dest);
3665 		if (mpath) {
3666 			mpp_lookup = 0;
3667 			next_hop = rtw_rcu_dereference(mpath->next_hop);
3668 			if (!next_hop
3669 				|| !(mpath->flags & (RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVING))
3670 			) {
3671 				/* mpath is not valid, search mppath */
3672 				mpp_lookup = 1;
3673 			}
3674 		}
3675 
3676 		if (mpp_lookup) {
3677 			mppath = rtw_mpp_path_lookup(adapter, etherhdr.h_dest);
3678 			if (mppath)
3679 				mppath->exp_time = rtw_get_current_time();
3680 		}
3681 
3682 		if (mppath && mpath)
3683 			rtw_mesh_path_del(adapter, mpath->dst);
3684 
3685 		ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE
3686 			|| (mppath && _rtw_memcmp(mppath->mpp, etherhdr.h_dest, ETH_ALEN) == _FALSE);
3687 	} else {
3688 		ae_need = _rtw_memcmp(adapter_mac_addr(adapter), etherhdr.h_source, ETH_ALEN) == _FALSE;
3689 
3690 		#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3691 		if (rtw_msrc_b2u_policy_chk(adapter->mesh_cfg.b2u_flags_msrc, etherhdr.h_dest)) {
3692 			bmc_need = rtw_mesh_data_bmc_to_uc(adapter
3693 				, etherhdr.h_dest, etherhdr.h_source
3694 				, etherhdr.h_dest, adapter_mac_addr(adapter), ae_need, NULL, 0
3695 				, os_qid, b2u_list, &b2u_num, &b2u_mseq);
3696 			if (bmc_need == _FALSE) {
3697 				res = RTW_ORI_NO_NEED;
3698 				goto exit;
3699 			}
3700 		}
3701 		#endif
3702 	}
3703 
3704 	attrib = &xframe->attrib;
3705 
3706 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3707 	if (b2u_num) {
3708 		attrib->mb2u = 1;
3709 		attrib->mseq = b2u_mseq;
3710 	} else
3711 		attrib->mb2u = 0;
3712 #endif
3713 
3714 	attrib->mfwd_ttl = 0;
3715 	_rtw_memcpy(attrib->dst, etherhdr.h_dest, ETH_ALEN);
3716 	_rtw_memcpy(attrib->src, etherhdr.h_source, ETH_ALEN);
3717 	_rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
3718 
3719 	if (is_da_mcast) {
3720 		attrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA;
3721 		_rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN);
3722 		_rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN);
3723 	} else {
3724 		attrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
3725 		_rtw_memcpy(attrib->mda, (mppath && ae_need) ? mppath->mpp : attrib->dst, ETH_ALEN);
3726 		_rtw_memcpy(attrib->msa, adapter_mac_addr(adapter), ETH_ALEN);
3727 		/* RA needs to be resolved */
3728 		res = rtw_mesh_nexthop_resolve(adapter, xframe);
3729 	}
3730 
3731 exit:
3732 	return res;
3733 }
3734 
rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode,struct pkt_attrib * attrib)3735 s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib)
3736 {
3737 	u8 ret = 0;
3738 	switch (mesh_frame_mode) {
3739 	case MESH_UCAST_DATA:
3740 		attrib->hdrlen = WLAN_HDR_A4_QOS_LEN;
3741 		/* mesh flag + mesh TTL + Mesh SN. no ext addr. */
3742 		attrib->meshctrl_len = 6;
3743 		break;
3744 	case MESH_BMCAST_DATA:
3745 		attrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
3746 		/* mesh flag + mesh TTL + Mesh SN. no ext addr. */
3747 		attrib->meshctrl_len = 6;
3748 		break;
3749 	case MESH_UCAST_PX_DATA:
3750 		attrib->hdrlen = WLAN_HDR_A4_QOS_LEN;
3751 		/* mesh flag + mesh TTL + Mesh SN + extaddr1 + extaddr2. */
3752 		attrib->meshctrl_len = 18;
3753 		break;
3754 	case MESH_BMCAST_PX_DATA:
3755 		attrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
3756 		/* mesh flag + mesh TTL + Mesh SN + extaddr1 */
3757 		attrib->meshctrl_len = 12;
3758 		break;
3759 	default:
3760 		RTW_WARN("Invalid mesh frame mode:%u\n", mesh_frame_mode);
3761 		ret = -1;
3762 		break;
3763 	}
3764 
3765 	return ret;
3766 }
3767 
rtw_mesh_tx_build_mctrl(_adapter * adapter,struct pkt_attrib * attrib,u8 * buf)3768 void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf)
3769 {
3770 	struct rtw_ieee80211s_hdr *mctrl = (struct rtw_ieee80211s_hdr *)buf;
3771 
3772 	_rtw_memset(mctrl, 0, XATTRIB_GET_MCTRL_LEN(attrib));
3773 
3774 	if (attrib->mfwd_ttl
3775 		#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3776 		|| attrib->mb2u
3777 		#endif
3778 	) {
3779 		#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
3780 		if (!attrib->mfwd_ttl)
3781 			mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL;
3782 		else
3783 		#endif
3784 			mctrl->ttl = attrib->mfwd_ttl;
3785 
3786 		mctrl->seqnum = (cpu_to_le32(attrib->mseq));
3787 	} else {
3788 		mctrl->ttl = adapter->mesh_cfg.dot11MeshTTL;
3789 		mctrl->seqnum = (cpu_to_le32(adapter->mesh_info.mesh_seqnum));
3790 		adapter->mesh_info.mesh_seqnum++;
3791 	}
3792 
3793 	switch (attrib->mesh_frame_mode){
3794 	case MESH_UCAST_DATA:
3795 	case MESH_BMCAST_DATA:
3796 		break;
3797 	case MESH_UCAST_PX_DATA:
3798 		mctrl->flags |= MESH_FLAGS_AE_A5_A6;
3799 		_rtw_memcpy(mctrl->eaddr1, attrib->dst, ETH_ALEN);
3800 		_rtw_memcpy(mctrl->eaddr2, attrib->src, ETH_ALEN);
3801 		break;
3802 	case MESH_BMCAST_PX_DATA:
3803 		mctrl->flags |= MESH_FLAGS_AE_A4;
3804 		_rtw_memcpy(mctrl->eaddr1, attrib->src, ETH_ALEN);
3805 		break;
3806 	case MESH_MHOP_UCAST_ACT:
3807 		/* TBD */
3808 		break;
3809 	case MESH_MHOP_BMCAST_ACT:
3810 		/* TBD */
3811 		break;
3812 	default:
3813 		break;
3814 	}
3815 }
3816 
rtw_mesh_tx_build_whdr(_adapter * adapter,struct pkt_attrib * attrib,u16 * fctrl,struct rtw_ieee80211_hdr * whdr)3817 u8 rtw_mesh_tx_build_whdr(_adapter *adapter, struct pkt_attrib *attrib
3818 	, u16 *fctrl, struct rtw_ieee80211_hdr *whdr)
3819 {
3820 	switch (attrib->mesh_frame_mode) {
3821 	case MESH_UCAST_DATA:		/* 1, 1, RA, TA, mDA(=DA),	mSA(=SA) */
3822 	case MESH_UCAST_PX_DATA:	/* 1, 1, RA, TA, mDA,		mSA,		[DA, SA] */
3823 		SetToDs(fctrl);
3824 		SetFrDs(fctrl);
3825 		_rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN);
3826 		_rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN);
3827 		_rtw_memcpy(whdr->addr3, attrib->mda, ETH_ALEN);
3828 		_rtw_memcpy(whdr->addr4, attrib->msa, ETH_ALEN);
3829 		break;
3830 	case MESH_BMCAST_DATA:		/* 0, 1, RA(DA), TA, mSA(SA) */
3831 	case MESH_BMCAST_PX_DATA:	/* 0, 1, RA(DA), TA, mSA,		[SA] */
3832 		SetFrDs(fctrl);
3833 		_rtw_memcpy(whdr->addr1, attrib->ra, ETH_ALEN);
3834 		_rtw_memcpy(whdr->addr2, attrib->ta, ETH_ALEN);
3835 		_rtw_memcpy(whdr->addr3, attrib->msa, ETH_ALEN);
3836 		break;
3837 	case MESH_MHOP_UCAST_ACT:
3838 		/* TBD */
3839 		RTW_INFO("MESH_MHOP_UCAST_ACT\n");
3840 		break;
3841 	case MESH_MHOP_BMCAST_ACT:
3842 		/* TBD */
3843 		RTW_INFO("MESH_MHOP_BMCAST_ACT\n");
3844 		break;
3845 	default:
3846 		RTW_WARN("Invalid mesh frame mode\n");
3847 		break;
3848 	}
3849 
3850 	return 0;
3851 }
3852 
rtw_mesh_rx_data_validate_hdr(_adapter * adapter,union recv_frame * rframe,struct sta_info ** sta)3853 int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta)
3854 {
3855 	struct sta_priv *stapriv = &adapter->stapriv;
3856 	struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
3857 	u8 *whdr = get_recvframe_data(rframe);
3858 	u8 is_ra_bmc = 0;
3859 	u8 a4_shift = 0;
3860 	u8 ps;
3861 	u8 *qc;
3862 	u8 mps_mode = RTW_MESH_PS_UNKNOWN;
3863 	sint ret = _FAIL;
3864 
3865 	if (!(MLME_STATE(adapter) & WIFI_ASOC_STATE))
3866 		goto exit;
3867 
3868 	if (!rattrib->qos)
3869 		goto exit;
3870 
3871 	switch (rattrib->to_fr_ds) {
3872 	case 2:
3873 		if (!IS_MCAST(GetAddr1Ptr(whdr)))
3874 			goto exit;
3875 		*sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr));
3876 		if (*sta == NULL) {
3877 			ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */
3878 			goto exit;
3879 		}
3880 		_rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
3881 		_rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
3882 		_rtw_memcpy(rattrib->mda, GetAddr1Ptr(whdr), ETH_ALEN);
3883 		_rtw_memcpy(rattrib->msa, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
3884 		_rtw_memcpy(rattrib->dst, GetAddr1Ptr(whdr), ETH_ALEN);
3885 		_rtw_memcpy(rattrib->src, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
3886 		_rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN);
3887 		is_ra_bmc = 1;
3888 		break;
3889 	case 3:
3890 		if (IS_MCAST(GetAddr1Ptr(whdr)))
3891 			goto exit;
3892 		*sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr));
3893 		if (*sta == NULL) {
3894 			ret = _SUCCESS; /* return _SUCCESS to drop at sta checking */
3895 			goto exit;
3896 		}
3897 		_rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
3898 		_rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
3899 		_rtw_memcpy(rattrib->mda, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
3900 		_rtw_memcpy(rattrib->msa, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
3901 		_rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
3902 		_rtw_memcpy(rattrib->src, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking mesh ctrl field */
3903 		_rtw_memcpy(rattrib->bssid, get_addr2_ptr(whdr), ETH_ALEN);
3904 		a4_shift = ETH_ALEN;
3905 		break;
3906 	default:
3907 		goto exit;
3908 	}
3909 
3910 	qc = whdr + WLAN_HDR_A3_LEN + a4_shift;
3911 	ps = GetPwrMgt(whdr);
3912 	mps_mode = ps ? (is_ra_bmc || (get_mps_lv(qc)) ? RTW_MESH_PS_DSLEEP : RTW_MESH_PS_LSLEEP) : RTW_MESH_PS_ACTIVE;
3913 
3914 	if (ps) {
3915 		if (!((*sta)->state & WIFI_SLEEP_STATE))
3916 			stop_sta_xmit(adapter, *sta);
3917 	} else {
3918 		if ((*sta)->state & WIFI_SLEEP_STATE)
3919 			wakeup_sta_to_xmit(adapter, *sta, ALL_FRAME);
3920 	}
3921 
3922 	if (is_ra_bmc)
3923 		(*sta)->nonpeer_mps = mps_mode;
3924 	else {
3925 		(*sta)->peer_mps = mps_mode;
3926 		if (mps_mode != RTW_MESH_PS_ACTIVE && (*sta)->nonpeer_mps == RTW_MESH_PS_ACTIVE)
3927 			(*sta)->nonpeer_mps = RTW_MESH_PS_DSLEEP;
3928 	}
3929 
3930 	if (get_frame_sub_type(whdr) & BIT(6)) {
3931 		/* No data, will not indicate to upper layer, temporily count it here */
3932 		count_rx_stats(adapter, rframe, *sta);
3933 		ret = RTW_RX_HANDLED;
3934 		goto exit;
3935 	}
3936 
3937 	rattrib->mesh_ctrl_present = get_mctrl_present(qc) ? 1 : 0;
3938 	if (!rattrib->mesh_ctrl_present)
3939 		goto exit;
3940 
3941 	ret = _SUCCESS;
3942 
3943 exit:
3944 	return ret;
3945 }
3946 
rtw_mesh_rx_data_validate_mctrl(_adapter * adapter,union recv_frame * rframe,const struct rtw_ieee80211s_hdr * mctrl,const u8 * mda,const u8 * msa,u8 * mctrl_len,const u8 ** da,const u8 ** sa)3947 int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe
3948 	, const struct rtw_ieee80211s_hdr *mctrl, const u8 *mda, const u8 *msa
3949 	, u8 *mctrl_len
3950 	, const u8 **da, const u8 **sa)
3951 {
3952 	struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
3953 	u8 mlen;
3954 	u8 ae;
3955 	int ret = _SUCCESS;
3956 
3957 	ae = mctrl->flags & MESH_FLAGS_AE;
3958 	mlen = ae_to_mesh_ctrl_len[ae];
3959 	switch (rattrib->to_fr_ds) {
3960 	case 2:
3961 		*da = mda;
3962 		if (ae == MESH_FLAGS_AE_A4)
3963 			*sa = mctrl->eaddr1;
3964 		else if (ae == 0)
3965 			*sa = msa;
3966 		else
3967 			ret = _FAIL;
3968 		break;
3969 	case 3:
3970 		if (ae == MESH_FLAGS_AE_A5_A6) {
3971 			*da = mctrl->eaddr1;
3972 			*sa = mctrl->eaddr2;
3973 		} else if (ae == 0) {
3974 			*da = mda;
3975 			*sa = msa;
3976 		} else
3977 			ret = _FAIL;
3978 		break;
3979 	default:
3980 		ret = _FAIL;
3981 	}
3982 
3983 	if (ret == _FAIL) {
3984 		#ifdef DBG_RX_DROP_FRAME
3985 		RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" invalid tfDS:%u AE:%u combination ra="MAC_FMT" ta="MAC_FMT"\n"
3986 			, FUNC_ADPT_ARG(adapter), rattrib->to_fr_ds, ae, MAC_ARG(rattrib->ra), MAC_ARG(rattrib->ta));
3987 		#endif
3988 		*mctrl_len = 0;
3989 	} else
3990 		*mctrl_len = mlen;
3991 
3992 	return ret;
3993 }
3994 
rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter * adapter,union recv_frame * rframe)3995 inline int rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter *adapter, union recv_frame *rframe)
3996 {
3997 	struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
3998 	const u8 *da, *sa;
3999 	int ret;
4000 
4001 	ret = rtw_mesh_rx_data_validate_mctrl(adapter, rframe
4002 			, (struct rtw_ieee80211s_hdr *)(get_recvframe_data(rframe) + rattrib->hdrlen + rattrib->iv_len)
4003 			, rattrib->mda, rattrib->msa
4004 			, &rattrib->mesh_ctrl_len
4005 			, &da, &sa);
4006 
4007 	if (ret == _SUCCESS) {
4008 		_rtw_memcpy(rattrib->dst, da, ETH_ALEN);
4009 		_rtw_memcpy(rattrib->src, sa, ETH_ALEN);
4010 	}
4011 
4012 	return ret;
4013 }
4014 
4015 /**
4016  * rtw_mesh_rx_nexthop_resolve - lookup next hop; conditionally start path discovery
4017  *
4018  * @skb: 802.11 frame to be sent
4019  * @sdata: network subif the frame will be sent through
4020  *
4021  * Lookup next hop for given skb and start path discovery if no
4022  * forwarding information is found.
4023  *
4024  * Returns: 0 if the next hop was found and -ENOENT if the frame was queued.
4025  * skb is freeed here if no mpath could be allocated.
4026  */
rtw_mesh_rx_nexthop_resolve(_adapter * adapter,const u8 * mda,const u8 * msa,u8 * ra)4027 static int rtw_mesh_rx_nexthop_resolve(_adapter *adapter,
4028 	const u8 *mda, const u8 *msa, u8 *ra)
4029 {
4030 	struct rtw_mesh_path *mpath;
4031 	struct xmit_frame *xframe_to_free = NULL;
4032 	int err = 0;
4033 	int ret = _SUCCESS;
4034 
4035 	rtw_rcu_read_lock();
4036 	err = rtw_mesh_nexthop_lookup(adapter, mda, msa, ra);
4037 	if (!err)
4038 		goto endlookup;
4039 
4040 	/* no nexthop found, start resolving */
4041 	mpath = rtw_mesh_path_lookup(adapter, mda);
4042 	if (!mpath) {
4043 		mpath = rtw_mesh_path_add(adapter, mda);
4044 		if (IS_ERR(mpath)) {
4045 			err = PTR_ERR(mpath);
4046 			ret = _FAIL;
4047 			goto endlookup;
4048 		}
4049 	}
4050 
4051 	if (!(mpath->flags & RTW_MESH_PATH_RESOLVING))
4052 		rtw_mesh_queue_preq(mpath, RTW_PREQ_Q_F_START);
4053 
4054 	ret = _FAIL;
4055 
4056 endlookup:
4057 	rtw_rcu_read_unlock();
4058 	return ret;
4059 }
4060 
4061 #define RTW_MESH_DECACHE_BMC 1
4062 #define RTW_MESH_DECACHE_UC 0
4063 
4064 #define RTW_MESH_FORWARD_MDA_SELF_COND 0
4065 #define DBG_RTW_MESH_FORWARD_MDA_SELF_COND 0
rtw_mesh_rx_msdu_act_check(union recv_frame * rframe,const u8 * mda,const u8 * msa,const u8 * da,const u8 * sa,struct rtw_ieee80211s_hdr * mctrl,u8 * msdu,enum rtw_rx_llc_hdl llc_hdl,struct xmit_frame ** fwd_frame,_list * b2u_list)4066 int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
4067 	, const u8 *mda, const u8 *msa
4068 	, const u8 *da, const u8 *sa
4069 	, struct rtw_ieee80211s_hdr *mctrl
4070 	, u8 *msdu, enum rtw_rx_llc_hdl llc_hdl
4071 	, struct xmit_frame **fwd_frame, _list *b2u_list)
4072 {
4073 	_adapter *adapter = rframe->u.hdr.adapter;
4074 	struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
4075 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
4076 	struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
4077 	struct rtw_mesh_path *mppath;
4078 	u8 is_mda_bmc = IS_MCAST(mda);
4079 	u8 is_mda_self = !is_mda_bmc && _rtw_memcmp(mda, adapter_mac_addr(adapter), ETH_ALEN);
4080 	u16 os_qid;
4081 	struct xmit_frame *xframe;
4082 	struct pkt_attrib *xattrib;
4083 	u8 fwd_ra[ETH_ALEN] = {0};
4084 	u8 fwd_mpp[ETH_ALEN] = {0}; /* forward to other gate */
4085 	u32 fwd_mseq;
4086 	int act = 0;
4087 	u8 ae_need;
4088 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
4089 	bool ori_need = _TRUE;
4090 	u8 b2u_num = 0;
4091 #endif
4092 
4093 	/* fwd info lifetime update */
4094 	#if 0
4095 	if (!is_mda_self)
4096 		mDA(A3) fwinfo.lifetime
4097 	mSA(A4) fwinfo.lifetime
4098 	Precursor-to-mDA(A2) fwinfo.lifetime
4099 	#endif
4100 
4101 	/* update/create pxoxy info for SA, mSA */
4102 	if ((mctrl->flags & MESH_FLAGS_AE)
4103 		&& sa != msa && _rtw_memcmp(sa, msa, ETH_ALEN) == _FALSE
4104 	) {
4105 		const u8 *proxied_addr = sa;
4106 		const u8 *mpp_addr = msa;
4107 
4108 		rtw_rcu_read_lock();
4109 		mppath = rtw_mpp_path_lookup(adapter, proxied_addr);
4110 		if (!mppath)
4111 			rtw_mpp_path_add(adapter, proxied_addr, mpp_addr);
4112 		else {
4113 			enter_critical_bh(&mppath->state_lock);
4114 			if (_rtw_memcmp(mppath->mpp, mpp_addr, ETH_ALEN) == _FALSE)
4115 				_rtw_memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
4116 			mppath->exp_time = rtw_get_current_time();
4117 			exit_critical_bh(&mppath->state_lock);
4118 		}
4119 		rtw_rcu_read_unlock();
4120 	}
4121 
4122 	/* mSA is self, need no further process */
4123 	if (_rtw_memcmp(msa, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE)
4124 		goto exit;
4125 
4126 	fwd_mseq = le32_to_cpu(mctrl->seqnum);
4127 
4128 	/* check duplicate MSDU from mSA */
4129 	if (((RTW_MESH_DECACHE_BMC && is_mda_bmc)
4130 			|| (RTW_MESH_DECACHE_UC && !is_mda_bmc))
4131 		&& rtw_mesh_decache(adapter, msa, fwd_mseq)
4132 	) {
4133 		minfo->mshstats.dropped_frames_duplicate++;
4134 		goto exit;
4135 	}
4136 
4137 	if (is_mda_bmc) {
4138 		/* mDA is bmc addr */
4139 		act |= RTW_RX_MSDU_ACT_INDICATE;
4140 		if (!mcfg->dot11MeshForwarding)
4141 			goto exit;
4142 		goto fwd_chk;
4143 
4144 	} else if (!is_mda_self) {
4145 		/* mDA is unicast but not self */
4146 		if (!mcfg->dot11MeshForwarding) {
4147 			rtw_mesh_path_error_tx(adapter
4148 				, adapter->mesh_cfg.element_ttl
4149 				, mda, 0
4150 				, WLAN_REASON_MESH_PATH_NOFORWARD
4151 				, rattrib->ta
4152 			);
4153 			#ifdef DBG_RX_DROP_FRAME
4154 			RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") not self, !dot11MeshForwarding\n"
4155 				, FUNC_ADPT_ARG(adapter), MAC_ARG(mda));
4156 			#endif
4157 			goto exit;
4158 		}
4159 
4160 		if (rtw_mesh_rx_nexthop_resolve(adapter, mda, msa, fwd_ra) != _SUCCESS) {
4161 			/* mDA is unknown */
4162 			rtw_mesh_path_error_tx(adapter
4163 				, adapter->mesh_cfg.element_ttl
4164 				, mda, 0
4165 				, WLAN_REASON_MESH_PATH_NOFORWARD
4166 				, rattrib->ta
4167 			);
4168 			#ifdef DBG_RX_DROP_FRAME
4169 			RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" mDA("MAC_FMT") unknown\n"
4170 				, FUNC_ADPT_ARG(adapter), MAC_ARG(mda));
4171 			#endif
4172 			minfo->mshstats.dropped_frames_no_route++;
4173 			goto exit;
4174 
4175 		} else {
4176 			/* mDA is known in fwd info */
4177 			#if 0
4178 			if	(TA is not in precursors)
4179 				goto exit;
4180 			#endif
4181 			goto fwd_chk;
4182 		}
4183 
4184 	} else {
4185 		/* mDA is self */
4186 		#if RTW_MESH_FORWARD_MDA_SELF_COND
4187 		if (da == mda
4188 			|| _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN)
4189 		) {
4190 			/* DA is self, indicate */
4191 			act |= RTW_RX_MSDU_ACT_INDICATE;
4192 			goto exit;
4193 		}
4194 
4195 		if (rtw_get_iface_by_macddr(adapter, da)) {
4196 			/* DA is buddy, indicate */
4197 			act |= RTW_RX_MSDU_ACT_INDICATE;
4198 			#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4199 			RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is buddy("ADPT_FMT")\n"
4200 				, FUNC_ADPT_ARG(adapter), MAC_ARG(da), ADPT_ARG(rtw_get_iface_by_macddr(adapter, da)));
4201 			#endif
4202 			goto exit;
4203 		}
4204 
4205 		/* DA is not self or buddy */
4206 		if (rtw_mesh_nexthop_lookup(adapter, da, msa, fwd_ra) == 0) {
4207 			/* DA is known in fwd info */
4208 			if (!mcfg->dot11MeshForwarding) {
4209 				/* path error to? */
4210 				#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4211 				RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") not self, !dot11MeshForwarding\n"
4212 					, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
4213 				#endif
4214 				goto exit;
4215 			}
4216 			mda = da;
4217 			#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4218 			RTW_INFO(FUNC_ADPT_FMT" fwd to DA("MAC_FMT"), fwd_RA("MAC_FMT")\n"
4219 				, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(fwd_ra));
4220 			#endif
4221 			goto fwd_chk;
4222 		}
4223 
4224 		rtw_rcu_read_lock();
4225 		mppath = rtw_mpp_path_lookup(adapter, da);
4226 		if (mppath) {
4227 			if (_rtw_memcmp(mppath->mpp, adapter_mac_addr(adapter), ETH_ALEN) == _FALSE) {
4228 				/* DA is proxied by others */
4229 				if (!mcfg->dot11MeshForwarding) {
4230 					/* path error to? */
4231 					#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4232 					RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), !dot11MeshForwarding\n"
4233 						, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
4234 					#endif
4235 					rtw_rcu_read_unlock();
4236 					goto exit;
4237 				}
4238 				_rtw_memcpy(fwd_mpp, mppath->mpp, ETH_ALEN);
4239 				mda = fwd_mpp;
4240 				msa = adapter_mac_addr(adapter);
4241 				rtw_rcu_read_unlock();
4242 
4243 				/* resolve RA */
4244 				if (rtw_mesh_nexthop_lookup(adapter, mda, msa, fwd_ra) != 0) {
4245 					minfo->mshstats.dropped_frames_no_route++;
4246 					#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4247 					RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), RA resolve fail\n"
4248 						, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
4249 					#endif
4250 					goto exit;
4251 				}
4252 				#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4253 				RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), fwd_RA("MAC_FMT")\n"
4254 					, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp), MAC_ARG(fwd_ra));
4255 				#endif
4256 				goto fwd_chk; /*  forward to other gate */
4257 			} else {
4258 				#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4259 				RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by self\n"
4260 					, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
4261 				#endif
4262 			}
4263 		}
4264 		rtw_rcu_read_unlock();
4265 
4266 		if (!mppath) {
4267 			#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
4268 			RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") unknown\n"
4269 				, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
4270 			#endif
4271 			/* DA is unknown */
4272 			#if 0 /* TODO: flags with AE bit */
4273 			rtw_mesh_path_error_tx(adapter
4274 				, adapter->mesh_cfg.element_ttl
4275 				, mda, adapter->mesh_info.last_sn_update
4276 				, WLAN_REASON_MESH_PATH_NOPROXY
4277 				, msa
4278 			);
4279 			#endif
4280 		}
4281 
4282 		/*
4283 		* indicate to DS for both cases:
4284 		* 1.) DA is proxied by self
4285 		* 2.) DA is unknown
4286 		*/
4287 		#endif /* RTW_MESH_FORWARD_MDA_SELF_COND */
4288 		act |= RTW_RX_MSDU_ACT_INDICATE;
4289 		goto exit;
4290 	}
4291 
4292 fwd_chk:
4293 
4294 	if (adapter->stapriv.asoc_list_cnt <= 1)
4295 		goto exit;
4296 
4297 	if (mctrl->ttl == 1) {
4298 		minfo->mshstats.dropped_frames_ttl++;
4299 		if (!act) {
4300 			#ifdef DBG_RX_DROP_FRAME
4301 			RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" ttl reaches 0, not forwarding\n"
4302 				, FUNC_ADPT_ARG(adapter));
4303 			#endif
4304 		}
4305 		goto exit;
4306 	}
4307 
4308 	os_qid = rtw_os_recv_select_queue(msdu, llc_hdl);
4309 
4310 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
4311 	_rtw_init_listhead(b2u_list);
4312 #endif
4313 
4314 	ae_need = _rtw_memcmp(da , mda, ETH_ALEN) == _FALSE
4315 		|| _rtw_memcmp(sa , msa, ETH_ALEN) == _FALSE;
4316 
4317 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
4318 	if (is_mda_bmc
4319 		&& rtw_mfwd_b2u_policy_chk(mcfg->b2u_flags_mfwd, mda, rattrib->to_fr_ds == 3)
4320 	) {
4321 		ori_need = rtw_mesh_data_bmc_to_uc(adapter
4322 			, da, sa, mda, msa, ae_need, rframe->u.hdr.psta->cmn.mac_addr, mctrl->ttl - 1
4323 			, os_qid, b2u_list, &b2u_num, &fwd_mseq);
4324 	}
4325 
4326 	if (ori_need == _TRUE)
4327 #endif
4328 	{
4329 		xframe = rtw_alloc_xmitframe(&adapter->xmitpriv, os_qid);
4330 		if (!xframe) {
4331 			#ifdef DBG_TX_DROP_FRAME
4332 			RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" rtw_alloc_xmitframe fail\n"
4333 				, FUNC_ADPT_ARG(adapter));
4334 			#endif
4335 			goto exit;
4336 		}
4337 
4338 		xattrib = &xframe->attrib;
4339 
4340 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
4341 		if (b2u_num)
4342 			xattrib->mb2u = 1;
4343 		else
4344 			xattrib->mb2u = 0;
4345 #endif
4346 		xattrib->mfwd_ttl = mctrl->ttl - 1;
4347 		xattrib->mseq = fwd_mseq;
4348 		_rtw_memcpy(xattrib->dst, da, ETH_ALEN);
4349 		_rtw_memcpy(xattrib->src, sa, ETH_ALEN);
4350 		_rtw_memcpy(xattrib->mda, mda, ETH_ALEN);
4351 		_rtw_memcpy(xattrib->msa, msa, ETH_ALEN);
4352 		_rtw_memcpy(xattrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
4353 
4354 		if (is_mda_bmc) {
4355 			xattrib->mesh_frame_mode = ae_need ? MESH_BMCAST_PX_DATA : MESH_BMCAST_DATA;
4356 			_rtw_memcpy(xattrib->ra, mda, ETH_ALEN);
4357 		} else {
4358 			xattrib->mesh_frame_mode = ae_need ? MESH_UCAST_PX_DATA : MESH_UCAST_DATA;
4359 			_rtw_memcpy(xattrib->ra, fwd_ra, ETH_ALEN);
4360 		}
4361 
4362 		*fwd_frame = xframe;
4363 	}
4364 
4365 #if CONFIG_RTW_MESH_DATA_BMC_TO_UC
4366 	if (ori_need || b2u_num)
4367 #endif
4368 	{
4369 		act |= RTW_RX_MSDU_ACT_FORWARD;
4370 		if (is_mda_bmc)
4371 			minfo->mshstats.fwded_mcast++;
4372 		else
4373 			minfo->mshstats.fwded_unicast++;
4374 		minfo->mshstats.fwded_frames++;
4375 	}
4376 
4377 exit:
4378 	return act;
4379 }
4380 
dump_mesh_stats(void * sel,_adapter * adapter)4381 void dump_mesh_stats(void *sel, _adapter *adapter)
4382 {
4383 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
4384 	struct rtw_mesh_stats *stats = &minfo->mshstats;
4385 
4386 	RTW_PRINT_SEL(sel, "fwd_bmc:%u\n", stats->fwded_mcast);
4387 	RTW_PRINT_SEL(sel, "fwd_uc:%u\n", stats->fwded_unicast);
4388 
4389 	RTW_PRINT_SEL(sel, "drop_ttl:%u\n", stats->dropped_frames_ttl);
4390 	RTW_PRINT_SEL(sel, "drop_no_route:%u\n", stats->dropped_frames_no_route);
4391 	RTW_PRINT_SEL(sel, "drop_congestion:%u\n", stats->dropped_frames_congestion);
4392 	RTW_PRINT_SEL(sel, "drop_dup:%u\n", stats->dropped_frames_duplicate);
4393 
4394 	RTW_PRINT_SEL(sel, "mrc_del_qlen:%u\n", stats->mrc_del_qlen);
4395 }
4396 #endif /* CONFIG_RTW_MESH */
4397 
4398