Update to 5.6.1

This commit is contained in:
Rin Cat
2019-09-21 05:30:30 -04:00
parent 953142179e
commit 0644d0b316
413 changed files with 179115 additions and 110562 deletions

View File

@@ -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 */

View File

@@ -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

Binary file not shown.

View File

@@ -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

Binary file not shown.

View File

@@ -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

View File

@@ -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);

Binary file not shown.