mirror of
https://github.com/RinCat/RTL88x2BU-Linux-Driver.git
synced 2026-01-19 10:26:35 +00:00
Update to 5.6.1
This commit is contained in:
@@ -234,6 +234,259 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rtw_mesh_bss_peering_status(WLAN_BSSID_EX *bss, u8 *nop, u8 *accept)
|
||||
{
|
||||
u8 *ie;
|
||||
int ie_len;
|
||||
|
||||
if (nop)
|
||||
*nop = 0;
|
||||
if (accept)
|
||||
*accept = 0;
|
||||
|
||||
ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len,
|
||||
BSS_EX_TLV_IES_LEN(bss));
|
||||
if (!ie || ie_len != 7)
|
||||
goto exit;
|
||||
|
||||
if (nop)
|
||||
*nop = GET_MESH_CONF_ELE_NUM_OF_PEERINGS(ie + 2);
|
||||
if (accept)
|
||||
*accept = GET_MESH_CONF_ELE_ACCEPT_PEERINGS(ie + 2);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned)
|
||||
{
|
||||
bool acnode;
|
||||
u8 nop, accept;
|
||||
|
||||
rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
|
||||
|
||||
acnode = !nop && accept;
|
||||
|
||||
if (acnode && scanned->acnode_stime == 0) {
|
||||
scanned->acnode_stime = rtw_get_current_time();
|
||||
if (scanned->acnode_stime == 0)
|
||||
scanned->acnode_stime++;
|
||||
} else if (!acnode) {
|
||||
scanned->acnode_stime = 0;
|
||||
scanned->acnode_notify_etime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned)
|
||||
{
|
||||
return scanned->acnode_stime
|
||||
&& rtw_get_passing_time_ms(scanned->acnode_stime)
|
||||
> adapter->mesh_cfg.peer_sel_policy.acnode_conf_timeout_ms;
|
||||
}
|
||||
|
||||
static bool rtw_mesh_scanned_is_acnode_allow_notify(_adapter *adapter, struct wlan_network *scanned)
|
||||
{
|
||||
return scanned->acnode_notify_etime
|
||||
&& rtw_time_after(scanned->acnode_notify_etime, rtw_get_current_time());
|
||||
}
|
||||
|
||||
bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
|
||||
struct sta_priv *stapriv = &adapter->stapriv;
|
||||
bool allow = 0;
|
||||
|
||||
if (!mcfg->peer_sel_policy.acnode_prevent
|
||||
|| mcfg->max_peer_links <= 1
|
||||
|| stapriv->asoc_list_cnt < mcfg->max_peer_links)
|
||||
goto exit;
|
||||
|
||||
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
|
||||
if (rtw_mesh_cto_mgate_required(adapter))
|
||||
goto exit;
|
||||
#endif
|
||||
|
||||
allow = 1;
|
||||
|
||||
exit:
|
||||
return allow;
|
||||
}
|
||||
|
||||
static bool rtw_mesh_acnode_candidate_exist(_adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
|
||||
struct sta_priv *stapriv = &adapter->stapriv;
|
||||
struct mlme_priv *mlme = &adapter->mlmepriv;
|
||||
_queue *queue = &(mlme->scanned_queue);
|
||||
_list *head, *list;
|
||||
_irqL irqL;
|
||||
struct wlan_network *scanned = NULL;
|
||||
struct sta_info *sta = NULL;
|
||||
bool need = 0;
|
||||
|
||||
_enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
|
||||
|
||||
head = get_list_head(queue);
|
||||
list = get_next(head);
|
||||
while (!rtw_end_of_queue_search(head, list)) {
|
||||
scanned = LIST_CONTAINOR(list, struct wlan_network, list);
|
||||
list = get_next(list);
|
||||
|
||||
if (rtw_get_passing_time_ms(scanned->last_scanned) < mcfg->peer_sel_policy.scanr_exp_ms
|
||||
&& rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)
|
||||
&& (!mcfg->rssi_threshold || mcfg->rssi_threshold <= scanned->network.Rssi)
|
||||
#if CONFIG_RTW_MACADDR_ACL
|
||||
&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
|
||||
#endif
|
||||
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
|
||||
#endif
|
||||
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
|
||||
&& rtw_mesh_cto_mgate_network_filter(adapter, scanned)
|
||||
#endif
|
||||
) {
|
||||
need = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
|
||||
|
||||
exit:
|
||||
return need;
|
||||
}
|
||||
|
||||
static int rtw_mesh_acnode_prevent_sacrifice_chk(_adapter *adapter, struct sta_info **sac, struct sta_info *com)
|
||||
{
|
||||
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
|
||||
int updated = 0;
|
||||
|
||||
/*
|
||||
* TODO: compare next_hop reference cnt of forwarding info
|
||||
* don't sacrifice working next_hop or choose sta with least cnt
|
||||
*/
|
||||
|
||||
if (*sac == NULL) {
|
||||
updated = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
|
||||
if (mcfg->peer_sel_policy.cto_mgate_require
|
||||
&& !mcfg->dot11MeshGateAnnouncementProtocol
|
||||
) {
|
||||
if (IS_CTO_MGATE_CONF_TIMEOUT(com->plink)) {
|
||||
if (!IS_CTO_MGATE_CONF_TIMEOUT((*sac)->plink)) {
|
||||
/* blacklist > not blacklist */
|
||||
updated = 1;
|
||||
goto exit;
|
||||
}
|
||||
} else if (!IS_CTO_MGATE_CONF_DISABLED(com->plink)) {
|
||||
if (IS_CTO_MGATE_CONF_DISABLED((*sac)->plink)) {
|
||||
/* confirming > disabled */
|
||||
updated = 1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
if (updated)
|
||||
*sac = com;
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
struct sta_info *_rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
|
||||
{
|
||||
struct sta_priv *stapriv = &adapter->stapriv;
|
||||
_list *head, *list;
|
||||
struct sta_info *sta, *sacrifice = NULL;
|
||||
u8 nop;
|
||||
|
||||
head = &stapriv->asoc_list;
|
||||
list = get_next(head);
|
||||
while (rtw_end_of_queue_search(head, list) == _FALSE) {
|
||||
sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
|
||||
list = get_next(list);
|
||||
|
||||
if (!sta->plink || !sta->plink->scanned) {
|
||||
rtw_warn_on(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
rtw_mesh_bss_peering_status(&sta->plink->scanned->network, &nop, NULL);
|
||||
if (nop < 2)
|
||||
continue;
|
||||
|
||||
rtw_mesh_acnode_prevent_sacrifice_chk(adapter, &sacrifice, sta);
|
||||
}
|
||||
|
||||
return sacrifice;
|
||||
}
|
||||
|
||||
struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter)
|
||||
{
|
||||
struct sta_priv *stapriv = &adapter->stapriv;
|
||||
struct sta_info *sacrifice = NULL;
|
||||
|
||||
enter_critical_bh(&stapriv->asoc_list_lock);
|
||||
|
||||
sacrifice = _rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
|
||||
|
||||
exit_critical_bh(&stapriv->asoc_list_lock);
|
||||
|
||||
return sacrifice;
|
||||
}
|
||||
|
||||
static void rtw_mesh_acnode_rsvd_chk(_adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
|
||||
u8 acnode_rsvd = 0;
|
||||
|
||||
if (rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
|
||||
&& rtw_mesh_acnode_prevent_pick_sacrifice(adapter)
|
||||
&& rtw_mesh_acnode_candidate_exist(adapter))
|
||||
acnode_rsvd = 1;
|
||||
|
||||
if (plink_ctl->acnode_rsvd != acnode_rsvd) {
|
||||
plink_ctl->acnode_rsvd = acnode_rsvd;
|
||||
RTW_INFO(FUNC_ADPT_FMT" acnode_rsvd = %d\n", FUNC_ADPT_ARG(adapter), plink_ctl->acnode_rsvd);
|
||||
update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_mesh_acnode_set_notify_etime(_adapter *adapter, u8 *rframe_whdr)
|
||||
{
|
||||
if (adapter->mesh_info.plink_ctl.acnode_rsvd) {
|
||||
struct wlan_network *scanned = rtw_find_network(&adapter->mlmepriv.scanned_queue, get_addr2_ptr(rframe_whdr));
|
||||
|
||||
if (rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned)) {
|
||||
scanned->acnode_notify_etime = rtw_get_current_time()
|
||||
+ rtw_ms_to_systime(adapter->mesh_cfg.peer_sel_policy.acnode_notify_timeout_ms);
|
||||
if (scanned->acnode_notify_etime == 0)
|
||||
scanned->acnode_notify_etime++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
|
||||
|
||||
RTW_PRINT_SEL(sel, "%-6s %-12s %-14s\n"
|
||||
, "enable", "conf_timeout", "nofity_timeout");
|
||||
RTW_PRINT_SEL(sel, "%6u %12u %14u\n"
|
||||
, peer_sel_policy->acnode_prevent
|
||||
, peer_sel_policy->acnode_conf_timeout_ms
|
||||
, peer_sel_policy->acnode_notify_timeout_ms);
|
||||
}
|
||||
#endif /* CONFIG_RTW_MESH_ACNODE_PREVENT */
|
||||
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr)
|
||||
{
|
||||
@@ -355,10 +608,9 @@ void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
|
||||
|
||||
RTW_PRINT_SEL(sel, "%-7s %-12s %-17s\n"
|
||||
, "require", "conf_timeout", "blacklist_timeout");
|
||||
RTW_PRINT_SEL(sel, "%7u %12u %17u\n"
|
||||
, peer_sel_policy->cto_mgate_require
|
||||
RTW_PRINT_SEL(sel, "%-12s %-17s\n"
|
||||
, "conf_timeout", "blacklist_timeout");
|
||||
RTW_PRINT_SEL(sel, "%12u %17u\n"
|
||||
, peer_sel_policy->cto_mgate_conf_timeout_ms
|
||||
, peer_sel_policy->cto_mgate_blacklist_timeout_ms);
|
||||
}
|
||||
@@ -406,6 +658,7 @@ void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scann
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
|
||||
struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
|
||||
bool acnode = 0;
|
||||
|
||||
if (IS_CH_WAITING(rfctl) && !IS_UNDER_CAC(rfctl))
|
||||
goto exit;
|
||||
@@ -413,8 +666,16 @@ void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scann
|
||||
if (plink_ctl->num >= RTW_MESH_MAX_PEER_CANDIDATES)
|
||||
goto exit;
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
if (plink_ctl->acnode_rsvd) {
|
||||
acnode = rtw_mesh_scanned_is_acnode_confirmed(adapter, scanned);
|
||||
if (acnode && !rtw_mesh_scanned_is_acnode_allow_notify(adapter, scanned))
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */
|
||||
if (plink_ctl->num >= mcfg->max_peer_links)
|
||||
if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0)
|
||||
goto exit;
|
||||
|
||||
if (rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms
|
||||
@@ -433,6 +694,14 @@ void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scann
|
||||
)
|
||||
goto exit;
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
if (acnode) {
|
||||
scanned->acnode_notify_etime = 0;
|
||||
RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(scanned->network.MacAddress));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IOCTL_CFG80211
|
||||
rtw_cfg80211_notify_new_peer_candidate(adapter->rtw_wdev
|
||||
, scanned->network.MacAddress
|
||||
@@ -461,7 +730,7 @@ void rtw_mesh_peer_status_chk(_adapter *adapter)
|
||||
u8 cto_mgate, forwarding, mgate;
|
||||
#endif
|
||||
u8 flush;
|
||||
char flush_list[NUM_STA];
|
||||
s8 flush_list[NUM_STA];
|
||||
u8 flush_num = 0;
|
||||
int i;
|
||||
|
||||
@@ -579,14 +848,19 @@ flush_add:
|
||||
|
||||
exit_critical_bh(&(plink_ctl->lock));
|
||||
|
||||
for (i = 0; i < flush_num; i++) {
|
||||
if (flush_num) {
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 updated = _FALSE;
|
||||
|
||||
sta = rtw_get_stainfo_by_offset(stapriv, flush_list[i]);
|
||||
_rtw_memcpy(sta_addr, sta->cmn.mac_addr, ETH_ALEN);
|
||||
for (i = 0; i < flush_num; i++) {
|
||||
sta = rtw_get_stainfo_by_offset(stapriv, flush_list[i]);
|
||||
_rtw_memcpy(sta_addr, sta->cmn.mac_addr, ETH_ALEN);
|
||||
|
||||
ap_free_sta(adapter, sta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);
|
||||
rtw_mesh_expire_peer(adapter, sta_addr);
|
||||
updated |= ap_free_sta(adapter, sta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);
|
||||
rtw_mesh_expire_peer(adapter, sta_addr);
|
||||
}
|
||||
|
||||
associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
|
||||
}
|
||||
|
||||
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
|
||||
@@ -594,6 +868,10 @@ flush_add:
|
||||
rtw_mesh_cto_mgate_blacklist_chk(adapter);
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
rtw_mesh_acnode_rsvd_chk(adapter);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -651,10 +929,12 @@ u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
|
||||
u8 ret;
|
||||
u8 ret = 0;
|
||||
|
||||
ret = MLME_IS_MESH(adapter)
|
||||
&& check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE) == _TRUE
|
||||
if (!adapter->mesh_cfg.peer_sel_policy.offch_cand)
|
||||
goto exit;
|
||||
|
||||
ret = MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)
|
||||
&& (!plink_ctl->num || rtw_mesh_offch_cto_mgate_required(adapter))
|
||||
;
|
||||
|
||||
@@ -663,12 +943,12 @@ u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter)
|
||||
struct mi_state mstate_no_self;
|
||||
|
||||
rtw_mi_status_no_self(adapter, &mstate_no_self);
|
||||
if (MSTATE_STA_LD_NUM(&mstate_no_self) || MSTATE_AP_LD_NUM(&mstate_no_self)
|
||||
|| MSTATE_ADHOC_LD_NUM(&mstate_no_self) || MSTATE_MESH_LD_NUM(&mstate_no_self))
|
||||
if (MSTATE_STA_LD_NUM(&mstate_no_self))
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -686,12 +966,15 @@ u8 rtw_mesh_select_operating_ch(_adapter *adapter)
|
||||
_irqL irqL;
|
||||
struct wlan_network *scanned = NULL;
|
||||
int i;
|
||||
/* statistics for candidate accept peering */
|
||||
u8 cand_ap_cnt[MAX_CHANNEL_NUM] = {0};
|
||||
u8 max_cand_ap_ch = 0;
|
||||
u8 max_cand_ap_cnt = 0;
|
||||
/* statistics for candidate including not accept peering */
|
||||
u8 cand_cnt[MAX_CHANNEL_NUM] = {0};
|
||||
u8 max_cand_ch = 0;
|
||||
u8 max_cand_cnt = 0;
|
||||
|
||||
for (i = 0; i < rfctl->max_chan_nums; i++)
|
||||
rfctl->channel_set[i].mesh_candidate_cnt = 0;
|
||||
|
||||
_enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
|
||||
|
||||
head = get_list_head(queue);
|
||||
@@ -705,7 +988,7 @@ u8 rtw_mesh_select_operating_ch(_adapter *adapter)
|
||||
#if CONFIG_RTW_MACADDR_ACL
|
||||
&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
|
||||
#endif
|
||||
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 0, 1)
|
||||
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 0, 0)
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
|
||||
#endif
|
||||
@@ -718,18 +1001,38 @@ u8 rtw_mesh_select_operating_ch(_adapter *adapter)
|
||||
if (ch_set_idx >= 0
|
||||
&& !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx])
|
||||
) {
|
||||
rfctl->channel_set[ch_set_idx].mesh_candidate_cnt++;
|
||||
if (max_cand_cnt < rfctl->channel_set[ch_set_idx].mesh_candidate_cnt) {
|
||||
max_cand_cnt = rfctl->channel_set[ch_set_idx].mesh_candidate_cnt;
|
||||
u8 nop, accept;
|
||||
|
||||
rtw_mesh_bss_peering_status(&scanned->network, &nop, &accept);
|
||||
cand_cnt[ch_set_idx]++;
|
||||
if (max_cand_cnt < cand_cnt[ch_set_idx]) {
|
||||
max_cand_cnt = cand_cnt[ch_set_idx];
|
||||
max_cand_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
|
||||
}
|
||||
if (accept) {
|
||||
cand_ap_cnt[ch_set_idx]++;
|
||||
if (max_cand_ap_cnt < cand_ap_cnt[ch_set_idx]) {
|
||||
max_cand_ap_cnt = cand_ap_cnt[ch_set_idx];
|
||||
max_cand_ap_ch = rfctl->channel_set[ch_set_idx].ChannelNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
|
||||
|
||||
return max_cand_ch;
|
||||
return max_cand_ap_ch ? max_cand_ap_ch : max_cand_ch;
|
||||
}
|
||||
|
||||
void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
|
||||
|
||||
RTW_PRINT_SEL(sel, "%-6s %-11s\n"
|
||||
, "enable", "find_int_ms");
|
||||
RTW_PRINT_SEL(sel, "%6u %11u\n"
|
||||
, peer_sel_policy->offch_cand, peer_sel_policy->offch_find_int_ms);
|
||||
}
|
||||
#endif /* CONFIG_RTW_MESH_OFFCH_CAND */
|
||||
|
||||
@@ -737,36 +1040,24 @@ void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct mesh_peer_sel_policy *peer_sel_policy = &adapter->mesh_cfg.peer_sel_policy;
|
||||
|
||||
#if CONFIG_RTW_MESH_OFFCH_CAND
|
||||
#define OFFCH_CAND_TITLE_FMT " %-17s"
|
||||
#define OFFCH_CAND_VALUE_FMT " %17u"
|
||||
#define OFFCH_CAND_TITLE_ARG , "offch_find_int_ms"
|
||||
#define OFFCH_CAND_VALUE_ARG , peer_sel_policy->offch_find_int_ms
|
||||
#else
|
||||
#define OFFCH_CAND_TITLE_FMT ""
|
||||
#define OFFCH_CAND_VALUE_FMT ""
|
||||
#define OFFCH_CAND_TITLE_ARG
|
||||
#define OFFCH_CAND_VALUE_ARG
|
||||
#endif
|
||||
|
||||
RTW_PRINT_SEL(sel,
|
||||
"%-12s"
|
||||
OFFCH_CAND_TITLE_FMT
|
||||
"\n"
|
||||
, "scanr_exp_ms"
|
||||
OFFCH_CAND_TITLE_ARG
|
||||
);
|
||||
RTW_PRINT_SEL(sel,
|
||||
"%12u"
|
||||
OFFCH_CAND_VALUE_FMT
|
||||
"\n"
|
||||
, peer_sel_policy->scanr_exp_ms
|
||||
OFFCH_CAND_VALUE_ARG
|
||||
);
|
||||
RTW_PRINT_SEL(sel, "%-12s\n", "scanr_exp_ms");
|
||||
RTW_PRINT_SEL(sel, "%12u\n", peer_sel_policy->scanr_exp_ms);
|
||||
}
|
||||
|
||||
void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
{
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
#define NSTATE_TITLE_FMT_ACN " %-5s"
|
||||
#define NSTATE_VALUE_FMT_ACN " %5d"
|
||||
#define NSTATE_TITLE_ARG_ACN , "acn"
|
||||
#define NSTATE_VALUE_ARG_ACN , (acn_ms < 99999 ? acn_ms : 99999)
|
||||
#else
|
||||
#define NSTATE_TITLE_FMT_ACN ""
|
||||
#define NSTATE_VALUE_FMT_ACN ""
|
||||
#define NSTATE_TITLE_ARG_ACN
|
||||
#define NSTATE_VALUE_ARG_ACN
|
||||
#endif
|
||||
|
||||
struct mlme_priv *mlme = &(adapter->mlmepriv);
|
||||
_queue *queue = &(mlme->scanned_queue);
|
||||
struct wlan_network *network;
|
||||
@@ -777,13 +1068,16 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
u8 blocked;
|
||||
u8 established;
|
||||
s32 age_ms;
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
s32 acn_ms;
|
||||
#endif
|
||||
u8 *mesh_conf_ie;
|
||||
sint mesh_conf_ie_len;
|
||||
struct wlan_network **mesh_networks;
|
||||
u8 mesh_network_cnt = 0;
|
||||
int i;
|
||||
|
||||
mesh_networks = rtw_zvmalloc(MAX_BSS_CNT * sizeof(struct wlan_network *));
|
||||
mesh_networks = rtw_zvmalloc(mlme->max_bss_cnt * sizeof(struct wlan_network *));
|
||||
if (!mesh_networks)
|
||||
return;
|
||||
|
||||
@@ -808,9 +1102,12 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
|
||||
exit_critical_bh(&queue->lock);
|
||||
|
||||
RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-3s %-3s %-3s\n"
|
||||
, "bssid", "ch", "rssi", "age", "mesh_id", "nop", "fwd", "cto");
|
||||
|
||||
RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-3s %-3s %-3s"
|
||||
NSTATE_TITLE_FMT_ACN
|
||||
"\n"
|
||||
, "bssid", "ch", "rssi", "age", "mesh_id", "nop", "fwd", "cto"
|
||||
NSTATE_TITLE_ARG_ACN
|
||||
);
|
||||
|
||||
for (i = 0; i < mesh_network_cnt; i++) {
|
||||
network = mesh_networks[i];
|
||||
@@ -824,6 +1121,12 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
continue;
|
||||
|
||||
age_ms = rtw_get_passing_time_ms(network->last_scanned);
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
if (network->acnode_stime == 0)
|
||||
acn_ms = 0;
|
||||
else
|
||||
acn_ms = rtw_get_passing_time_ms(network->acnode_stime);
|
||||
#endif
|
||||
same_mbss = 0;
|
||||
candidate = 0;
|
||||
plink = NULL;
|
||||
@@ -844,7 +1147,9 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
same_mbss = 1;
|
||||
}
|
||||
|
||||
RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %c%2u %3u %c%c \n"
|
||||
RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %c%2u %3u %c%c "
|
||||
NSTATE_VALUE_FMT_ACN
|
||||
"\n"
|
||||
, established ? 'E' : (blocked ? 'B' : (plink ? 'N' : (candidate ? 'C' : (same_mbss ? 'S' : ' '))))
|
||||
, MAC_ARG(network->network.MacAddress)
|
||||
, network->network.Configuration.DSConfig
|
||||
@@ -856,10 +1161,22 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
|
||||
, GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
|
||||
, GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' '
|
||||
, GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' '
|
||||
NSTATE_VALUE_ARG_ACN
|
||||
);
|
||||
}
|
||||
|
||||
rtw_vmfree(mesh_networks, MAX_BSS_CNT * sizeof(struct wlan_network *));
|
||||
rtw_vmfree(mesh_networks, mlme->max_bss_cnt * sizeof(struct wlan_network *));
|
||||
}
|
||||
|
||||
void rtw_mesh_adjust_chbw(u8 req_ch, u8 *req_bw, u8 *req_offset)
|
||||
{
|
||||
if (req_ch >= 5 && req_ch <= 9) {
|
||||
/* prevent secondary channel offset mismatch */
|
||||
if (*req_bw > CHANNEL_WIDTH_20) {
|
||||
*req_bw = CHANNEL_WIDTH_20;
|
||||
*req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rtw_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx)
|
||||
@@ -1133,37 +1450,37 @@ struct mpm_frame_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* pid:0x0000 llid:0x0000 chosen_pmk:0x00000000000000000000000000000000
|
||||
* aid:0x0000 pid:0x0000 llid:0x0000 plid:0x0000 chosen_pmk:0x00000000000000000000000000000000
|
||||
* pid:0x0000 llid:0x0000 plid:0x0000 reason:0x0000 chosen_pmk:0x00000000000000000000000000000000
|
||||
* pid:00000 llid:00000 chosen_pmk:0x00000000000000000000000000000000
|
||||
* aid:00000 pid:00000 llid:00000 plid:00000 chosen_pmk:0x00000000000000000000000000000000
|
||||
* pid:00000 llid:00000 plid:00000 reason:00000 chosen_pmk:0x00000000000000000000000000000000
|
||||
*/
|
||||
#define MPM_LOG_BUF_LEN 96 /* this length is limited for legal combination */
|
||||
#define MPM_LOG_BUF_LEN 92 /* this length is limited for legal combination */
|
||||
static void rtw_mpm_info_msg(struct mpm_frame_info *mpm_info, u8 *mpm_log_buf)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
if (mpm_info->aid) {
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "aid:0x%04x ", mpm_info->aid_v);
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "aid:%u ", mpm_info->aid_v);
|
||||
if (cnt >= MPM_LOG_BUF_LEN - 1)
|
||||
goto exit;
|
||||
}
|
||||
if (mpm_info->pid) {
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "pid:0x%04x ", mpm_info->pid_v);
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "pid:%u ", mpm_info->pid_v);
|
||||
if (cnt >= MPM_LOG_BUF_LEN - 1)
|
||||
goto exit;
|
||||
}
|
||||
if (mpm_info->llid) {
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "llid:0x%04x ", mpm_info->llid_v);
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "llid:%u ", mpm_info->llid_v);
|
||||
if (cnt >= MPM_LOG_BUF_LEN - 1)
|
||||
goto exit;
|
||||
}
|
||||
if (mpm_info->plid) {
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "plid:0x%04x ", mpm_info->plid_v);
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "plid:%u ", mpm_info->plid_v);
|
||||
if (cnt >= MPM_LOG_BUF_LEN - 1)
|
||||
goto exit;
|
||||
}
|
||||
if (mpm_info->reason) {
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "reason:0x%04x ", mpm_info->reason_v);
|
||||
cnt += snprintf(mpm_log_buf + cnt, MPM_LOG_BUF_LEN - cnt - 1, "reason:%u ", mpm_info->reason_v);
|
||||
if (cnt >= MPM_LOG_BUF_LEN - 1)
|
||||
goto exit;
|
||||
}
|
||||
@@ -1345,6 +1662,40 @@ bypass_sync_bss:
|
||||
rtw_mesh_plink_set_peer_conf_timeout(adapter, peer_addr);
|
||||
|
||||
} else
|
||||
#endif
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
if (action == RTW_ACT_SELF_PROTECTED_MESH_CLOSE) {
|
||||
if (tx && mpm_info.reason && mpm_info.reason_v == WLAN_REASON_MESH_MAX_PEERS) {
|
||||
if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)
|
||||
&& rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
|
||||
) {
|
||||
struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
|
||||
|
||||
if (sac) {
|
||||
struct sta_priv *stapriv = &adapter->stapriv;
|
||||
_irqL irqL;
|
||||
u8 sta_addr[ETH_ALEN];
|
||||
u8 updated = _FALSE;
|
||||
|
||||
_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
|
||||
if (!rtw_is_list_empty(&sac->asoc_list)) {
|
||||
rtw_list_delete(&sac->asoc_list);
|
||||
stapriv->asoc_list_cnt--;
|
||||
STA_SET_MESH_PLINK(sac, NULL);
|
||||
}
|
||||
_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
|
||||
RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(sac->cmn.mac_addr));
|
||||
|
||||
_rtw_memcpy(sta_addr, sac->cmn.mac_addr, ETH_ALEN);
|
||||
updated = ap_free_sta(adapter, sac, 0, 0, 1);
|
||||
rtw_mesh_expire_peer(stapriv->padapter, sta_addr);
|
||||
|
||||
associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (action == RTW_ACT_SELF_PROTECTED_MESH_CONF) {
|
||||
_irqL irqL;
|
||||
@@ -1475,6 +1826,31 @@ int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len)
|
||||
return rtw_mesh_check_frames(adapter, &buf, &len, _FALSE);
|
||||
}
|
||||
|
||||
int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe)
|
||||
{
|
||||
u8 *whdr = rframe->u.hdr.rx_data;
|
||||
|
||||
#if CONFIG_RTW_MACADDR_ACL
|
||||
if (rtw_access_ctrl(adapter, get_addr2_ptr(whdr)) == _FALSE)
|
||||
return _SUCCESS;
|
||||
#endif
|
||||
|
||||
if (!rtw_mesh_plink_get(adapter, get_addr2_ptr(whdr))) {
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
rtw_mesh_acnode_set_notify_etime(adapter, whdr);
|
||||
#endif
|
||||
|
||||
if (adapter_to_rfctl(adapter)->offch_state == OFFCHS_NONE)
|
||||
issue_probereq(adapter, &adapter->mlmepriv.cur_network.network.mesh_id, get_addr2_ptr(whdr));
|
||||
|
||||
/* only peer being added (checked by notify conditions) is allowed */
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
rtw_cfg80211_rx_mframe(adapter, rframe, NULL);
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe)
|
||||
{
|
||||
unsigned int ret = _FAIL;
|
||||
@@ -1578,6 +1954,10 @@ bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss)
|
||||
int ie_len;
|
||||
bool updated = 0;
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
accept_peerings |= plink_ctl->acnode_rsvd;
|
||||
#endif
|
||||
|
||||
ie = rtw_get_ie(BSS_EX_TLV_IES(bss), WLAN_EID_MESH_CONFIG, &ie_len, BSS_EX_TLV_IES_LEN(bss));
|
||||
if (!ie || ie_len != 7) {
|
||||
rtw_warn_on(1);
|
||||
@@ -1945,6 +2325,9 @@ void dump_mesh_plink_ctl(void *sel, _adapter *adapter)
|
||||
int i;
|
||||
|
||||
RTW_PRINT_SEL(sel, "num:%u\n", plink_ctl->num);
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
RTW_PRINT_SEL(sel, "acnode_rsvd:%u\n", plink_ctl->acnode_rsvd);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < RTW_MESH_MAX_PEER_CANDIDATES; i++) {
|
||||
ent = &plink_ctl->ent[i];
|
||||
@@ -2076,6 +2459,10 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
|
||||
goto exit;
|
||||
|
||||
rtw_ap_parse_sta_wmm_ie(adapter, sta, tlv_ies, tlv_ieslen);
|
||||
#ifdef CONFIG_RTS_FULL_BW
|
||||
/*check vendor IE*/
|
||||
rtw_parse_sta_vendor_ie_8812(adapter, sta, tlv_ies, tlv_ieslen);
|
||||
#endif/*CONFIG_RTS_FULL_BW*/
|
||||
|
||||
rtw_ap_parse_sta_ht_ie(adapter, sta, &elems);
|
||||
rtw_ap_parse_sta_vht_ie(adapter, sta, &elems);
|
||||
@@ -2103,7 +2490,8 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
|
||||
_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
|
||||
if (rtw_is_list_empty(&sta->asoc_list)) {
|
||||
STA_SET_MESH_PLINK(sta, plink);
|
||||
sta->expire_to = mcfg->plink_timeout / 2;
|
||||
/* TBD: up layer timeout mechanism */
|
||||
/* sta->expire_to = mcfg->plink_timeout / 2; */
|
||||
rtw_list_insert_tail(&sta->asoc_list, &stapriv->asoc_list);
|
||||
stapriv->asoc_list_cnt++;
|
||||
}
|
||||
@@ -2587,13 +2975,58 @@ static int rtw_mesh_decache(_adapter *adapter, const u8 *msa, u32 seq)
|
||||
return rtw_mrc_check(adapter, msa, seq);
|
||||
}
|
||||
|
||||
#ifndef RTW_MESH_SCAN_RESULT_EXP_MS
|
||||
#define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000)
|
||||
#endif
|
||||
|
||||
#ifndef RTW_MESH_ACNODE_PREVENT
|
||||
#define RTW_MESH_ACNODE_PREVENT 0
|
||||
#endif
|
||||
#ifndef RTW_MESH_ACNODE_CONF_TIMEOUT_MS
|
||||
#define RTW_MESH_ACNODE_CONF_TIMEOUT_MS (20 * 1000)
|
||||
#endif
|
||||
#ifndef RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS
|
||||
#define RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS (2 * 1000)
|
||||
#endif
|
||||
|
||||
#ifndef RTW_MESH_OFFCH_CAND
|
||||
#define RTW_MESH_OFFCH_CAND 1
|
||||
#endif
|
||||
#ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS
|
||||
#define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000)
|
||||
#endif
|
||||
|
||||
#ifndef RTW_MESH_PEER_CONF_TIMEOUT_MS
|
||||
#define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000)
|
||||
#endif
|
||||
#ifndef RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS
|
||||
#define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000)
|
||||
#endif
|
||||
|
||||
#ifndef RTW_MESH_CTO_MGATE_REQUIRE
|
||||
#define RTW_MESH_CTO_MGATE_REQUIRE 0
|
||||
#endif
|
||||
#ifndef RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS
|
||||
#define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000)
|
||||
#endif
|
||||
#ifndef RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS
|
||||
#define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000)
|
||||
#endif
|
||||
|
||||
void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg)
|
||||
{
|
||||
struct mesh_peer_sel_policy *sel_policy = &mcfg->peer_sel_policy;
|
||||
|
||||
sel_policy->scanr_exp_ms = RTW_MESH_SCAN_RESULT_EXP_MS;
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
sel_policy->acnode_prevent = RTW_MESH_ACNODE_PREVENT;
|
||||
sel_policy->acnode_conf_timeout_ms = RTW_MESH_ACNODE_CONF_TIMEOUT_MS;
|
||||
sel_policy->acnode_notify_timeout_ms = RTW_MESH_ACNODE_NOTIFY_TIMEOUT_MS;
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_OFFCH_CAND
|
||||
sel_policy->offch_cand = RTW_MESH_OFFCH_CAND;
|
||||
sel_policy->offch_find_int_ms = RTW_MESH_OFFCH_CAND_FIND_INT_MS;
|
||||
#endif
|
||||
|
||||
@@ -2603,7 +3036,7 @@ void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg)
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
|
||||
sel_policy->cto_mgate_require = 0;
|
||||
sel_policy->cto_mgate_require = RTW_MESH_CTO_MGATE_REQUIRE;
|
||||
sel_policy->cto_mgate_conf_timeout_ms = RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS;
|
||||
sel_policy->cto_mgate_blacklist_timeout_ms = RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS;
|
||||
#endif
|
||||
@@ -2635,6 +3068,10 @@ void rtw_mesh_cfg_init(_adapter *adapter)
|
||||
mcfg->dot11MeshHWMPconfirmationInterval = RTW_MESH_ROOT_CONFIRMATION_INTERVAL;
|
||||
mcfg->path_gate_timeout_factor = 3;
|
||||
rtw_mesh_cfg_init_peer_sel_policy(mcfg);
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
mcfg->sane_metric_delta = RTW_MESH_SANE_METRIC_DELTA;
|
||||
mcfg->max_root_add_chk_cnt = RTW_MESH_MAX_ROOT_ADD_CHK_CNT;
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
|
||||
mcfg->b2u_flags_msrc = 0;
|
||||
@@ -3337,7 +3774,8 @@ endlookup:
|
||||
#define RTW_MESH_DECACHE_BMC 1
|
||||
#define RTW_MESH_DECACHE_UC 0
|
||||
|
||||
#define RTW_MESH_FORWARD_MDA_SELF_COND 1
|
||||
#define RTW_MESH_FORWARD_MDA_SELF_COND 0
|
||||
#define DBG_RTW_MESH_FORWARD_MDA_SELF_COND 0
|
||||
int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
|
||||
, const u8 *mda, const u8 *msa
|
||||
, const u8 *da, const u8 *sa
|
||||
@@ -3457,57 +3895,90 @@ int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
|
||||
} else {
|
||||
/* mDA is self */
|
||||
#if RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
u8 is_da_self = da == mda || _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN);
|
||||
|
||||
if (is_da_self) {
|
||||
if (da == mda
|
||||
|| _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN)
|
||||
) {
|
||||
/* DA is self, indicate */
|
||||
act |= RTW_RX_MSDU_ACT_INDICATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* DA is not self */
|
||||
if (rtw_mesh_nexthop_lookup(adapter, da, msa, fwd_ra) == _SUCCESS) {
|
||||
if (rtw_get_iface_by_macddr(adapter, da)) {
|
||||
/* DA is buddy, indicate */
|
||||
act |= RTW_RX_MSDU_ACT_INDICATE;
|
||||
#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is buddy("ADPT_FMT")\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), ADPT_ARG(rtw_get_iface_by_macddr(adapter, da)));
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* DA is not self or buddy */
|
||||
if (rtw_mesh_nexthop_lookup(adapter, da, msa, fwd_ra) == 0) {
|
||||
/* DA is known in fwd info */
|
||||
if (!mcfg->dot11MeshForwarding) {
|
||||
/* path error to? */
|
||||
#ifdef DBG_RX_DROP_FRAME
|
||||
#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") not self, !dot11MeshForwarding\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
mda = da;
|
||||
#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO(FUNC_ADPT_FMT" fwd to DA("MAC_FMT"), fwd_RA("MAC_FMT")\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(fwd_ra));
|
||||
#endif
|
||||
goto fwd_chk;
|
||||
}
|
||||
|
||||
rtw_rcu_read_lock();
|
||||
mppath = rtw_mpp_path_lookup(adapter, da);
|
||||
if (mppath && _rtw_memcmp(mppath->mpp, adapter_mac_addr(adapter), ETH_ALEN) == _FALSE) {
|
||||
/* DA is reached by the other gate */
|
||||
if (!mcfg->dot11MeshForwarding) {
|
||||
/* path error to? */
|
||||
#ifdef DBG_RX_DROP_FRAME
|
||||
RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is reached by proxy("MAC_FMT"), !dot11MeshForwarding\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
|
||||
#endif
|
||||
if (mppath) {
|
||||
if (_rtw_memcmp(mppath->mpp, adapter_mac_addr(adapter), ETH_ALEN) == _FALSE) {
|
||||
/* DA is proxied by others */
|
||||
if (!mcfg->dot11MeshForwarding) {
|
||||
/* path error to? */
|
||||
#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), !dot11MeshForwarding\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
|
||||
#endif
|
||||
rtw_rcu_read_unlock();
|
||||
goto exit;
|
||||
}
|
||||
_rtw_memcpy(fwd_mpp, mppath->mpp, ETH_ALEN);
|
||||
mda = fwd_mpp;
|
||||
msa = adapter_mac_addr(adapter);
|
||||
rtw_rcu_read_unlock();
|
||||
goto exit;
|
||||
}
|
||||
_rtw_memcpy(fwd_mpp, mppath->mpp, ETH_ALEN);
|
||||
mda = fwd_mpp;
|
||||
msa = adapter_mac_addr(adapter);
|
||||
rtw_rcu_read_unlock();
|
||||
|
||||
/* resolve RA */
|
||||
if (rtw_mesh_nexthop_lookup(adapter, mda, msa, fwd_ra) != _SUCCESS) {
|
||||
minfo->mshstats.dropped_frames_no_route++;
|
||||
goto exit;
|
||||
/* resolve RA */
|
||||
if (rtw_mesh_nexthop_lookup(adapter, mda, msa, fwd_ra) != 0) {
|
||||
minfo->mshstats.dropped_frames_no_route++;
|
||||
#if defined(DBG_RX_DROP_FRAME) || DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), RA resolve fail\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp));
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by ("MAC_FMT"), fwd_RA("MAC_FMT")\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da), MAC_ARG(mppath->mpp), MAC_ARG(fwd_ra));
|
||||
#endif
|
||||
goto fwd_chk; /* forward to other gate */
|
||||
} else {
|
||||
#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") is proxied by self\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
|
||||
#endif
|
||||
}
|
||||
goto fwd_chk; /* forward to other gate */
|
||||
}
|
||||
}
|
||||
rtw_rcu_read_unlock();
|
||||
|
||||
if (!mppath) {
|
||||
#if DBG_RTW_MESH_FORWARD_MDA_SELF_COND
|
||||
RTW_INFO(FUNC_ADPT_FMT" DA("MAC_FMT") unknown\n"
|
||||
, FUNC_ADPT_ARG(adapter), MAC_ARG(da));
|
||||
#endif
|
||||
/* DA is unknown */
|
||||
#if 0 /* TODO: flags with AE bit */
|
||||
rtw_mesh_path_error_tx(adapter
|
||||
@@ -3521,7 +3992,7 @@ int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
|
||||
|
||||
/*
|
||||
* indicate to DS for both cases:
|
||||
* 1.) DA is reached by self
|
||||
* 1.) DA is proxied by self
|
||||
* 2.) DA is unknown
|
||||
*/
|
||||
#endif /* RTW_MESH_FORWARD_MDA_SELF_COND */
|
||||
|
||||
@@ -19,25 +19,22 @@
|
||||
#error "CONFIG_RTW_MESH can't be enabled when CONFIG_AP_MODE is not defined\n"
|
||||
#endif
|
||||
|
||||
#ifndef RTW_MESH_SCAN_RESULT_EXP_MS
|
||||
#define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000)
|
||||
#endif
|
||||
#ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS
|
||||
#define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000)
|
||||
#endif
|
||||
#define RTW_MESH_TTL 31
|
||||
#define RTW_MESH_PERR_MIN_INT 100
|
||||
#define RTW_MESH_TTL 31
|
||||
#define RTW_MESH_PERR_MIN_INT 100
|
||||
#define RTW_MESH_DEFAULT_ELEMENT_TTL 31
|
||||
#define RTW_MESH_RANN_INTERVAL 5000
|
||||
#define RTW_MESH_RANN_INTERVAL 5000
|
||||
#define RTW_MESH_PATH_TO_ROOT_TIMEOUT 6000
|
||||
#define RTW_MESH_DIAM_TRAVERSAL_TIME 50
|
||||
#define RTW_MESH_PATH_TIMEOUT 5000
|
||||
#define RTW_MESH_PREQ_MIN_INT 10
|
||||
#define RTW_MESH_MAX_PREQ_RETRIES 4
|
||||
#define RTW_MESH_PATH_TIMEOUT 5000
|
||||
#define RTW_MESH_PREQ_MIN_INT 10
|
||||
#define RTW_MESH_MAX_PREQ_RETRIES 4
|
||||
#define RTW_MESH_MIN_DISCOVERY_TIMEOUT (2 * RTW_MESH_DIAM_TRAVERSAL_TIME)
|
||||
#define RTW_MESH_ROOT_CONFIRMATION_INTERVAL 2000
|
||||
#define RTW_MESH_PATH_REFRESH_TIME 1000
|
||||
#define RTW_MESH_ROOT_INTERVAL 5000
|
||||
#define RTW_MESH_ROOT_CONFIRMATION_INTERVAL 2000
|
||||
#define RTW_MESH_PATH_REFRESH_TIME 1000
|
||||
#define RTW_MESH_ROOT_INTERVAL 5000
|
||||
|
||||
#define RTW_MESH_SANE_METRIC_DELTA 100
|
||||
#define RTW_MESH_MAX_ROOT_ADD_CHK_CNT 2
|
||||
|
||||
#define RTW_MESH_PLINK_UNKNOWN 0
|
||||
#define RTW_MESH_PLINK_LISTEN 1
|
||||
@@ -105,8 +102,10 @@ extern const char *_rtw_mesh_ps_str[];
|
||||
/* Max number of paths */
|
||||
#define RTW_MESH_MAX_PATHS 1024
|
||||
|
||||
#define RTW_PREQ_Q_F_START 0x1
|
||||
#define RTW_PREQ_Q_F_START 0x1
|
||||
#define RTW_PREQ_Q_F_REFRESH 0x2
|
||||
#define RTW_PREQ_Q_F_CHK 0x4
|
||||
#define RTW_PREQ_Q_F_PEER_AKA 0x8
|
||||
struct rtw_mesh_preq_queue {
|
||||
_list list;
|
||||
u8 dst[ETH_ALEN];
|
||||
@@ -242,6 +241,10 @@ struct mesh_plink_pool {
|
||||
u8 num; /* current ent being used */
|
||||
struct mesh_plink_ent ent[RTW_MESH_MAX_PEER_CANDIDATES];
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
u8 acnode_rsvd;
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
_queue peer_blacklist;
|
||||
#endif
|
||||
@@ -250,16 +253,18 @@ struct mesh_plink_pool {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000)
|
||||
#define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000)
|
||||
#define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000)
|
||||
#define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000)
|
||||
|
||||
struct mesh_peer_sel_policy {
|
||||
u32 scanr_exp_ms;
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
u8 acnode_prevent;
|
||||
u32 acnode_conf_timeout_ms;
|
||||
u32 acnode_notify_timeout_ms;
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_OFFCH_CAND
|
||||
u32 offch_find_int_ms; /* 0 means no offch find by driver */
|
||||
u8 offch_cand;
|
||||
u32 offch_find_int_ms; /* 0 means no offch find triggerred by driver self*/
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
@@ -293,6 +298,11 @@ struct mesh_peer_sel_policy {
|
||||
|| ((flags & RTW_MESH_B2U_IP_MCAST) && (IP_MCAST_MAC(mda) || ICMPV6_MCAST_MAC(mda))) \
|
||||
)
|
||||
|
||||
/**
|
||||
* @sane_metric_delta: Controlling if trigger additional path check mechanism
|
||||
* @max_root_add_chk_cnt: The retry cnt to send additional root confirmation
|
||||
* PREQ through old(last) path
|
||||
*/
|
||||
struct rtw_mesh_cfg {
|
||||
u8 max_peer_links; /* peering limit */
|
||||
u32 plink_timeout; /* seconds */
|
||||
@@ -315,6 +325,10 @@ struct rtw_mesh_cfg {
|
||||
u32 dot11MeshHWMPactivePathToRootTimeout;
|
||||
u16 dot11MeshHWMProotInterval;
|
||||
u8 path_gate_timeout_factor;
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
u16 sane_metric_delta;
|
||||
u8 max_root_add_chk_cnt;
|
||||
#endif
|
||||
|
||||
struct mesh_peer_sel_policy peer_sel_policy;
|
||||
|
||||
@@ -370,6 +384,8 @@ struct rtw_mesh_info {
|
||||
int mpp_paths_generation;
|
||||
|
||||
int num_gates;
|
||||
struct rtw_mesh_path *max_addr_gate;
|
||||
bool max_addr_gate_is_larger_than_self;
|
||||
|
||||
struct rtw_mesh_stats mshstats;
|
||||
|
||||
@@ -401,9 +417,18 @@ void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scann
|
||||
|
||||
void rtw_mesh_peer_status_chk(_adapter *adapter);
|
||||
|
||||
#if CONFIG_RTW_MESH_ACNODE_PREVENT
|
||||
void rtw_mesh_update_scanned_acnode_status(_adapter *adapter, struct wlan_network *scanned);
|
||||
bool rtw_mesh_scanned_is_acnode_confirmed(_adapter *adapter, struct wlan_network *scanned);
|
||||
bool rtw_mesh_acnode_prevent_allow_sacrifice(_adapter *adapter);
|
||||
struct sta_info *rtw_mesh_acnode_prevent_pick_sacrifice(_adapter *adapter);
|
||||
void dump_mesh_acnode_prevent_settings(void *sel, _adapter *adapter);
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_OFFCH_CAND
|
||||
u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter);
|
||||
u8 rtw_mesh_select_operating_ch(_adapter *adapter);
|
||||
void dump_mesh_offch_cand_settings(void *sel, _adapter *adapter);
|
||||
#endif
|
||||
|
||||
#if CONFIG_RTW_MESH_PEER_BLACKLIST
|
||||
@@ -427,10 +452,13 @@ void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter);
|
||||
void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter);
|
||||
void dump_mesh_networks(void *sel, _adapter *adapter);
|
||||
|
||||
void rtw_mesh_adjust_chbw(u8 req_ch, u8 *req_bw, u8 *req_offset);
|
||||
|
||||
int rtw_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx);
|
||||
int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len);
|
||||
int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len);
|
||||
|
||||
int rtw_mesh_on_auth(_adapter *adapter, union recv_frame *rframe);
|
||||
unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe);
|
||||
|
||||
bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss);
|
||||
|
||||
BIN
core/mesh/rtw_mesh.o
Normal file
BIN
core/mesh/rtw_mesh.o
Normal file
Binary file not shown.
@@ -826,14 +826,16 @@ static void rtw_hwmp_prep_frame_process(_adapter *adapter,
|
||||
target_addr = RTW_PREP_IE_TARGET_ADDR(prep_elem);
|
||||
path = rtw_mesh_path_lookup(adapter, target_addr);
|
||||
if (path && path->gate_asked) {
|
||||
enter_critical_bh(&path->state_lock);
|
||||
path->gate_asked = false;
|
||||
exit_critical_bh(&path->state_lock);
|
||||
flags = RTW_PREP_IE_FLAGS(prep_elem);
|
||||
if ((flags & BIT(7)) && !(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG)) {
|
||||
if (flags & BIT(7)) {
|
||||
enter_critical_bh(&path->state_lock);
|
||||
rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
|
||||
path->gate_asked = false;
|
||||
exit_critical_bh(&path->state_lock);
|
||||
if (!(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG)) {
|
||||
enter_critical_bh(&path->state_lock);
|
||||
rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
|
||||
exit_critical_bh(&path->state_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,9 +1002,26 @@ static void rtw_hwmp_rann_frame_process(_adapter *adapter,
|
||||
rtw_root_path_confirmation_jiffies(adapter)) ||
|
||||
rtw_time_before(rtw_get_current_time(), path->last_preq_to_root))) &&
|
||||
!(path->flags & RTW_MESH_PATH_FIXED) && (ttl != 0)) {
|
||||
u8 preq_node_flag = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH;
|
||||
|
||||
RTW_HWMP_DBG("time to refresh root path "MAC_FMT"\n",
|
||||
MAC_ARG(originator_addr));
|
||||
rtw_mesh_queue_preq(path, RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH);
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
if (RTW_SN_LT(path->sn, originator_sn) &&
|
||||
(path->rann_metric + mshcfg->sane_metric_delta < metric) &&
|
||||
_rtw_memcmp(bcast_addr, path->rann_snd_addr, ETH_ALEN) == _FALSE) {
|
||||
RTW_HWMP_DBG("Trigger additional check for root "
|
||||
"confirm PREQ. rann_snd_addr = "MAC_FMT
|
||||
"add_chk_rann_snd_addr= "MAC_FMT"\n",
|
||||
MAC_ARG(mgmt->addr2),
|
||||
MAC_ARG(path->rann_snd_addr));
|
||||
_rtw_memcpy(path->add_chk_rann_snd_addr,
|
||||
path->rann_snd_addr, ETH_ALEN);
|
||||
preq_node_flag |= RTW_PREQ_Q_F_CHK;
|
||||
|
||||
}
|
||||
#endif
|
||||
rtw_mesh_queue_preq(path, preq_node_flag);
|
||||
path->last_preq_to_root = rtw_get_current_time();
|
||||
}
|
||||
|
||||
@@ -1138,6 +1157,13 @@ static u32 rtw_hwmp_route_info_get(_adapter *adapter,
|
||||
path->exp_time = rtw_time_after(path->exp_time, exp_time)
|
||||
? path->exp_time : exp_time;
|
||||
rtw_mesh_path_activate(path);
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
if (path->is_root && (action == RTW_MPATH_PREP)) {
|
||||
_rtw_memcpy(path->rann_snd_addr,
|
||||
mgmt->addr2, ETH_ALEN);
|
||||
path->rann_metric = new_metric;
|
||||
}
|
||||
#endif
|
||||
exit_critical_bh(&path->state_lock);
|
||||
rtw_mesh_path_tx_pending(path);
|
||||
} else
|
||||
@@ -1184,6 +1210,15 @@ static u32 rtw_hwmp_route_info_get(_adapter *adapter,
|
||||
return process ? new_metric : 0;
|
||||
}
|
||||
|
||||
static void rtw_mesh_rx_hwmp_frame_cnts(_adapter *adapter, u8 *addr)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
sta = rtw_get_stainfo(&adapter->stapriv, addr);
|
||||
if (sta)
|
||||
sta->sta_stats.rx_hwmp_pkts++;
|
||||
}
|
||||
|
||||
void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe)
|
||||
{
|
||||
struct mesh_plink_ent *plink = NULL;
|
||||
@@ -1200,6 +1235,8 @@ void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe)
|
||||
if (!plink || plink->plink_state != RTW_MESH_PLINK_ESTAB)
|
||||
return;
|
||||
|
||||
rtw_mesh_rx_hwmp_frame_cnts(adapter, get_addr2_ptr(pframe));
|
||||
|
||||
/* Mesh action frame IE offset = 2 */
|
||||
attrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
||||
left = frame_len - attrib->hdrlen - attrib->iv_len - attrib->icv_len - 2;
|
||||
@@ -1276,6 +1313,12 @@ void rtw_mesh_queue_preq(struct rtw_mesh_path *path, u8 flags)
|
||||
preq_node->flags = flags;
|
||||
|
||||
path->flags |= RTW_MESH_PATH_REQ_QUEUED;
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
if (flags & RTW_PREQ_Q_F_CHK)
|
||||
path->flags |= RTW_MESH_PATH_ROOT_ADD_CHK;
|
||||
#endif
|
||||
if (flags & RTW_PREQ_Q_F_PEER_AKA)
|
||||
path->flags |= RTW_MESH_PATH_PEER_AKA;
|
||||
_rtw_spinunlock(&path->state_lock);
|
||||
|
||||
rtw_list_insert_tail(&preq_node->list, &minfo->preq_queue.list);
|
||||
@@ -1291,7 +1334,27 @@ void rtw_mesh_queue_preq(struct rtw_mesh_path *path, u8 flags)
|
||||
rtw_mesh_work(&adapter->mesh_work);
|
||||
} else
|
||||
rtw_mod_timer(&adapter->mesh_path_timer, minfo->last_preq +
|
||||
rtw_min_preq_int_jiff(adapter));
|
||||
rtw_min_preq_int_jiff(adapter) + 1);
|
||||
}
|
||||
|
||||
static const u8 *rtw_hwmp_preq_da(struct rtw_mesh_path *path,
|
||||
BOOLEAN is_root_add_chk, BOOLEAN da_is_peer)
|
||||
{
|
||||
const u8 *da;
|
||||
|
||||
if (da_is_peer)
|
||||
da = path->dst;
|
||||
else if (path->is_root)
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
da = is_root_add_chk ? path->add_chk_rann_snd_addr:
|
||||
path->rann_snd_addr;
|
||||
#else
|
||||
da = path->rann_snd_addr;
|
||||
#endif
|
||||
else
|
||||
da = bcast_addr;
|
||||
|
||||
return da;
|
||||
}
|
||||
|
||||
void rtw_mesh_path_start_discovery(_adapter *adapter)
|
||||
@@ -1304,6 +1367,8 @@ void rtw_mesh_path_start_discovery(_adapter *adapter)
|
||||
const u8 *da;
|
||||
u32 lifetime;
|
||||
u8 flags = 0;
|
||||
BOOLEAN is_root_add_chk = _FALSE;
|
||||
BOOLEAN da_is_peer;
|
||||
|
||||
enter_critical_bh(&minfo->mesh_preq_queue_lock);
|
||||
if (!minfo->preq_queue_len ||
|
||||
@@ -1368,8 +1433,14 @@ void rtw_mesh_path_start_discovery(_adapter *adapter)
|
||||
else
|
||||
target_flags &= ~RTW_IEEE80211_PREQ_TO_FLAG;
|
||||
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
is_root_add_chk = !!(path->flags & RTW_MESH_PATH_ROOT_ADD_CHK);
|
||||
#endif
|
||||
da_is_peer = !!(path->flags & RTW_MESH_PATH_PEER_AKA);
|
||||
exit_critical_bh(&path->state_lock);
|
||||
da = (path->is_root) ? path->rann_snd_addr : bcast_addr;
|
||||
|
||||
da = rtw_hwmp_preq_da(path, is_root_add_chk, da_is_peer);
|
||||
|
||||
#ifdef CONFIG_RTW_MESH_ON_DMD_GANN
|
||||
flags = (mshcfg->dot11MeshGateAnnouncementProtocol)
|
||||
? RTW_IEEE80211_PREQ_IS_GATE_FLAG : 0;
|
||||
@@ -1389,7 +1460,10 @@ void rtw_mesh_path_timer(void *ctx)
|
||||
struct rtw_mesh_path *path = (void *) ctx;
|
||||
_adapter *adapter = path->adapter;
|
||||
int ret;
|
||||
|
||||
u8 retry = 0;
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
|
||||
#endif
|
||||
/* TBD: Proctect for suspend */
|
||||
#if 0
|
||||
if (suspending)
|
||||
@@ -1398,18 +1472,30 @@ void rtw_mesh_path_timer(void *ctx)
|
||||
enter_critical_bh(&path->state_lock);
|
||||
if (path->flags & RTW_MESH_PATH_RESOLVED ||
|
||||
(!(path->flags & RTW_MESH_PATH_RESOLVING))) {
|
||||
path->flags &= ~(RTW_MESH_PATH_RESOLVING | RTW_MESH_PATH_RESOLVED);
|
||||
path->flags &= ~(RTW_MESH_PATH_RESOLVING |
|
||||
RTW_MESH_PATH_RESOLVED |
|
||||
RTW_MESH_PATH_ROOT_ADD_CHK |
|
||||
RTW_MESH_PATH_PEER_AKA);
|
||||
exit_critical_bh(&path->state_lock);
|
||||
} else if (path->discovery_retries < rtw_max_preq_retries(adapter)) {
|
||||
++path->discovery_retries;
|
||||
path->discovery_timeout *= 2;
|
||||
path->flags &= ~RTW_MESH_PATH_REQ_QUEUED;
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
if (path->discovery_retries > mshcfg->max_root_add_chk_cnt)
|
||||
path->flags &= ~RTW_MESH_PATH_ROOT_ADD_CHK;
|
||||
#endif
|
||||
if (path->gate_asked)
|
||||
retry |= RTW_PREQ_Q_F_REFRESH;
|
||||
|
||||
exit_critical_bh(&path->state_lock);
|
||||
rtw_mesh_queue_preq(path, 0);
|
||||
rtw_mesh_queue_preq(path, retry);
|
||||
} else {
|
||||
path->flags &= ~(RTW_MESH_PATH_RESOLVING |
|
||||
RTW_MESH_PATH_RESOLVED |
|
||||
RTW_MESH_PATH_REQ_QUEUED);
|
||||
RTW_MESH_PATH_REQ_QUEUED |
|
||||
RTW_MESH_PATH_ROOT_ADD_CHK |
|
||||
RTW_MESH_PATH_PEER_AKA);
|
||||
path->exp_time = rtw_get_current_time();
|
||||
exit_critical_bh(&path->state_lock);
|
||||
if (!path->is_gate && rtw_mesh_gate_num(adapter) > 0) {
|
||||
@@ -1515,10 +1601,19 @@ void rtw_mesh_work_hdl(_workitem *work)
|
||||
{
|
||||
_adapter *adapter = container_of(work, _adapter, mesh_work);
|
||||
|
||||
if (adapter->mesh_info.preq_queue_len &&
|
||||
rtw_time_after(rtw_get_current_time(),
|
||||
adapter->mesh_info.last_preq + rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPpreqMinInterval)))
|
||||
rtw_mesh_path_start_discovery(adapter);
|
||||
while(adapter->mesh_info.preq_queue_len) {
|
||||
if (rtw_time_after(rtw_get_current_time(),
|
||||
adapter->mesh_info.last_preq + rtw_min_preq_int_jiff(adapter)))
|
||||
/* It will consume preq_queue_len */
|
||||
rtw_mesh_path_start_discovery(adapter);
|
||||
else {
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
|
||||
rtw_mod_timer(&adapter->mesh_path_timer,
|
||||
minfo->last_preq + rtw_min_preq_int_jiff(adapter) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rtw_test_and_clear_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags))
|
||||
rtw_ieee80211_mesh_rootpath(adapter);
|
||||
|
||||
BIN
core/mesh/rtw_mesh_hwmp.o
Normal file
BIN
core/mesh/rtw_mesh_hwmp.o
Normal file
Binary file not shown.
@@ -374,6 +374,15 @@ int rtw_mesh_path_add_gate(struct rtw_mesh_path *mpath)
|
||||
ori_num_gates = minfo->num_gates;
|
||||
minfo->num_gates++;
|
||||
rtw_hlist_add_head_rcu(&mpath->gate_list, &tbl->known_gates);
|
||||
|
||||
if (ori_num_gates == 0
|
||||
|| rtw_macaddr_is_larger(mpath->dst, minfo->max_addr_gate->dst)
|
||||
) {
|
||||
minfo->max_addr_gate = mpath;
|
||||
minfo->max_addr_gate_is_larger_than_self =
|
||||
rtw_macaddr_is_larger(mpath->dst, adapter_mac_addr(mpath->adapter));
|
||||
}
|
||||
|
||||
_rtw_spinunlock(&tbl->gates_lock);
|
||||
|
||||
exit_critical_bh(&mpath->state_lock);
|
||||
@@ -414,6 +423,23 @@ void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath)
|
||||
rtw_hlist_del_rcu(&mpath->gate_list);
|
||||
ori_num_gates = minfo->num_gates;
|
||||
minfo->num_gates--;
|
||||
|
||||
if (ori_num_gates == 1) {
|
||||
minfo->max_addr_gate = NULL;
|
||||
minfo->max_addr_gate_is_larger_than_self = 0;
|
||||
} else if (minfo->max_addr_gate == mpath) {
|
||||
struct rtw_mesh_path *gate, *max_addr_gate = NULL;
|
||||
rtw_hlist_node *node;
|
||||
|
||||
rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) {
|
||||
if (!max_addr_gate || rtw_macaddr_is_larger(gate->dst, max_addr_gate->dst))
|
||||
max_addr_gate = gate;
|
||||
}
|
||||
minfo->max_addr_gate = max_addr_gate;
|
||||
minfo->max_addr_gate_is_larger_than_self =
|
||||
rtw_macaddr_is_larger(max_addr_gate->dst, adapter_mac_addr(mpath->adapter));
|
||||
}
|
||||
|
||||
exit_critical_bh(&tbl->gates_lock);
|
||||
|
||||
if (ori_num_gates == 1)
|
||||
@@ -458,6 +484,45 @@ int rtw_mesh_gate_num(_adapter *adapter)
|
||||
return adapter->mesh_info.num_gates;
|
||||
}
|
||||
|
||||
bool rtw_mesh_is_primary_gate(_adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
|
||||
return mcfg->dot11MeshGateAnnouncementProtocol
|
||||
&& !minfo->max_addr_gate_is_larger_than_self;
|
||||
}
|
||||
|
||||
void dump_known_gates(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_info *minfo = &adapter->mesh_info;
|
||||
struct rtw_mesh_table *tbl;
|
||||
struct rtw_mesh_path *gate;
|
||||
rtw_hlist_node *node;
|
||||
|
||||
if (!rtw_mesh_gate_num(adapter))
|
||||
goto exit;
|
||||
|
||||
rtw_rcu_read_lock();
|
||||
|
||||
tbl = minfo->mesh_paths;
|
||||
if (!tbl)
|
||||
goto unlock;
|
||||
|
||||
RTW_PRINT_SEL(sel, "num:%d\n", rtw_mesh_gate_num(adapter));
|
||||
|
||||
rtw_hlist_for_each_entry_rcu(gate, node, &tbl->known_gates, gate_list) {
|
||||
RTW_PRINT_SEL(sel, "%c"MAC_FMT"\n"
|
||||
, gate == minfo->max_addr_gate ? '*' : ' '
|
||||
, MAC_ARG(gate->dst));
|
||||
}
|
||||
|
||||
unlock:
|
||||
rtw_rcu_read_unlock();
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
struct rtw_mesh_path *rtw_mesh_path_new(_adapter *adapter,
|
||||
const u8 *dst)
|
||||
@@ -574,6 +639,34 @@ int rtw_mpp_path_add(_adapter *adapter,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dump_mpp(void *sel, _adapter *adapter)
|
||||
{
|
||||
struct rtw_mesh_path *mpath;
|
||||
int idx = 0;
|
||||
char dst[ETH_ALEN];
|
||||
char mpp[ETH_ALEN];
|
||||
|
||||
RTW_PRINT_SEL(sel, "%-17s %-17s\n", "dst", "mpp");
|
||||
|
||||
do {
|
||||
rtw_rcu_read_lock();
|
||||
|
||||
mpath = rtw_mpp_path_lookup_by_idx(adapter, idx);
|
||||
if (mpath) {
|
||||
_rtw_memcpy(dst, mpath->dst, ETH_ALEN);
|
||||
_rtw_memcpy(mpp, mpath->mpp, ETH_ALEN);
|
||||
}
|
||||
|
||||
rtw_rcu_read_unlock();
|
||||
|
||||
if (mpath) {
|
||||
RTW_PRINT_SEL(sel, MAC_FMT" "MAC_FMT"\n"
|
||||
, MAC_ARG(dst), MAC_ARG(mpp));
|
||||
}
|
||||
|
||||
idx++;
|
||||
} while (mpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* rtw_mesh_plink_broken - deactivates paths and sends perr when a link breaks
|
||||
|
||||
@@ -38,7 +38,11 @@
|
||||
* already queued up, waiting for the discovery process to start.
|
||||
* @RTW_MESH_PATH_DELETED: the mesh path has been deleted and should no longer
|
||||
* be used
|
||||
*
|
||||
* @RTW_MESH_PATH_ROOT_ADD_CHK: root additional check in root mode.
|
||||
* With this flag, It will try the last used rann_snd_addr
|
||||
* @RTW_MESH_PATH_PEER_AKA: only used toward a peer, only used in active keep
|
||||
* alive mechanism. PREQ's da = path dst
|
||||
*
|
||||
* RTW_MESH_PATH_RESOLVED is used by the mesh path timer to
|
||||
* decide when to stop or cancel the mesh path discovery.
|
||||
*/
|
||||
@@ -50,6 +54,8 @@ enum rtw_mesh_path_flags {
|
||||
RTW_MESH_PATH_RESOLVED = BIT(4),
|
||||
RTW_MESH_PATH_REQ_QUEUED = BIT(5),
|
||||
RTW_MESH_PATH_DELETED = BIT(6),
|
||||
RTW_MESH_PATH_ROOT_ADD_CHK = BIT(7),
|
||||
RTW_MESH_PATH_PEER_AKA = BIT(8),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -111,6 +117,9 @@ struct rtw_mesh_path {
|
||||
enum rtw_mesh_path_flags flags;
|
||||
_lock state_lock;
|
||||
u8 rann_snd_addr[ETH_ALEN];
|
||||
#ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
|
||||
u8 add_chk_rann_snd_addr[ETH_ALEN];
|
||||
#endif
|
||||
u32 rann_metric;
|
||||
unsigned long last_preq_to_root;
|
||||
bool is_root;
|
||||
@@ -153,6 +162,8 @@ struct rtw_mesh_path *rtw_mpp_path_lookup(_adapter *adapter,
|
||||
const u8 *dst);
|
||||
int rtw_mpp_path_add(_adapter *adapter,
|
||||
const u8 *dst, const u8 *mpp);
|
||||
void dump_mpp(void *sel, _adapter *adapter);
|
||||
|
||||
struct rtw_mesh_path *
|
||||
rtw_mesh_path_lookup_by_idx(_adapter *adapter, int idx);
|
||||
struct rtw_mesh_path *
|
||||
@@ -168,6 +179,8 @@ void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath);
|
||||
bool rtw_mesh_gate_search(struct rtw_mesh_table *tbl, const u8 *addr);
|
||||
int rtw_mesh_path_send_to_gates(struct rtw_mesh_path *mpath);
|
||||
int rtw_mesh_gate_num(_adapter *adapter);
|
||||
bool rtw_mesh_is_primary_gate(_adapter *adapter);
|
||||
void dump_known_gates(void *sel, _adapter *adapter);
|
||||
|
||||
void rtw_mesh_plink_broken(struct sta_info *sta);
|
||||
|
||||
|
||||
BIN
core/mesh/rtw_mesh_pathtbl.o
Normal file
BIN
core/mesh/rtw_mesh_pathtbl.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user