qcacld-3.0: Add support for rssi based assoc rejection during connect
Add support to handle rssi based assoc rejection from a bssid and Try to connect to this bssid only after time interval indicated in Assoc reject or when rssi has improved by margin indicated in Assoc reject. Change-Id: I6363bf5346ff8804611afbac3058819dc820092d CRs-Fixed: 2070452
Cette révision appartient à :
@@ -116,6 +116,7 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN];
|
||||
(QOS_MAP_LEN_MIN + 2 * QOS_MAP_MAX_EX)
|
||||
#define NUM_CHAINS_MAX 2
|
||||
|
||||
#define MAX_RSSI_AVOID_BSSID_LIST 10
|
||||
/**
|
||||
* enum sir_conn_update_reason: Reason for conc connection update
|
||||
* @SIR_UPDATE_REASON_SET_OPER_CHAN: Set probable operating channel
|
||||
@@ -7426,4 +7427,21 @@ struct sir_peer_set_rx_blocksize {
|
||||
struct qdf_mac_addr peer_macaddr;
|
||||
uint32_t rx_block_ack_win_limit;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sir_rssi_disallow_lst - Structure holding Rssi based avoid candidate
|
||||
* list
|
||||
* @node: Node pointer
|
||||
* @bssid: BSSID of the AP
|
||||
* @retry_delay: Retry delay received during last rejection in ms
|
||||
* @ expected_rssi: RSSI at which STA can initate
|
||||
* @time_during_rejection: Timestamp during last rejection in millisec
|
||||
*/
|
||||
struct sir_rssi_disallow_lst {
|
||||
qdf_list_node_t node;
|
||||
struct qdf_mac_addr bssid;
|
||||
uint32_t retry_delay;
|
||||
int8_t expected_rssi;
|
||||
qdf_time_t time_during_rejection;
|
||||
};
|
||||
#endif /* __SIR_API_H */
|
||||
|
@@ -672,7 +672,11 @@ typedef enum eSirMacStatusCodes {
|
||||
eSIR_MAC_QOS_UNSPECIFIED_FAILURE_STATUS = 32, /* Unspecified, QoS-related failure */
|
||||
eSIR_MAC_QAP_NO_BANDWIDTH_STATUS = 33, /* Association denied because QoS AP has insufficient bandwidth to handle another */
|
||||
/* QoS STA */
|
||||
eSIR_MAC_XS_FRAME_LOSS_STATUS = 34, /* Association denied due to excessive frame loss rates and/or poor conditions on cur- */
|
||||
/*
|
||||
* Association denied due to excessive frame loss rates
|
||||
* and/or poor conditions/RSSI on cur channel
|
||||
*/
|
||||
eSIR_MAC_XS_FRAME_LOSS_POOR_CHANNEL_RSSI_STATUS = 34,
|
||||
/* rent operating channel */
|
||||
eSIR_MAC_STA_QOS_NOT_SUPPORTED_STATUS = 35, /* Association (with QoS BSS) denied because the requesting STA does not support the */
|
||||
/* QoS facility */
|
||||
|
@@ -323,6 +323,7 @@ typedef struct sSirAssocRsp {
|
||||
#endif
|
||||
tDot11fIEvendor_vht_ie vendor_vht_ie;
|
||||
tDot11fIEOBSSScanParameters obss_scanparams;
|
||||
tDot11fTLVrssi_assoc_rej rssi_assoc_rej;
|
||||
tSirQCNIE QCN_IE;
|
||||
tDot11fIEvendor_he_cap vendor_he_cap;
|
||||
tDot11fIEvendor_he_op vendor_he_op;
|
||||
|
@@ -713,6 +713,13 @@ lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx,
|
||||
else
|
||||
lim_stop_reassoc_retry_timer(mac_ctx);
|
||||
|
||||
if (eSIR_MAC_XS_FRAME_LOSS_POOR_CHANNEL_RSSI_STATUS ==
|
||||
assoc_rsp->statusCode &&
|
||||
assoc_rsp->rssi_assoc_rej.present)
|
||||
lim_assoc_rej_add_to_rssi_based_reject_list(mac_ctx,
|
||||
&assoc_rsp->rssi_assoc_rej, hdr->sa,
|
||||
WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info));
|
||||
|
||||
if (assoc_rsp->statusCode != eSIR_MAC_SUCCESS_STATUS
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
&& (!session_entry->limRmfEnabled ||
|
||||
|
@@ -7783,6 +7783,113 @@ error:
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lim_assoc_rej_get_remaining_delta() - Get remaining time delta for
|
||||
* the rssi based disallowed list entry
|
||||
* @node: rssi based disallowed list entry
|
||||
*
|
||||
* Return: remaining delta, can be -ve if time has already expired.
|
||||
*/
|
||||
static inline int
|
||||
lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node)
|
||||
{
|
||||
qdf_time_t cur_time;
|
||||
uint32_t time_diff;
|
||||
|
||||
cur_time = qdf_do_div(qdf_get_monotonic_boottime(),
|
||||
QDF_MC_TIMER_TO_MS_UNIT);
|
||||
time_diff = cur_time - node->time_during_rejection;
|
||||
|
||||
return node->retry_delay - time_diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* lim_assoc_rej_rem_entry_with_lowest_delta() - Remove the entry
|
||||
* with lowest time delta
|
||||
* @list: rssi based rejected BSSID list
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS
|
||||
lim_assoc_rej_rem_entry_with_lowest_delta(qdf_list_t *list)
|
||||
{
|
||||
struct sir_rssi_disallow_lst *oldest_node = NULL;
|
||||
struct sir_rssi_disallow_lst *cur_node;
|
||||
qdf_list_node_t *cur_list = NULL;
|
||||
qdf_list_node_t *next_list = NULL;
|
||||
|
||||
qdf_list_peek_front(list, &cur_list);
|
||||
while (cur_list) {
|
||||
cur_node = qdf_container_of(cur_list,
|
||||
struct sir_rssi_disallow_lst, node);
|
||||
if (!oldest_node ||
|
||||
(lim_assoc_rej_get_remaining_delta(oldest_node) >
|
||||
lim_assoc_rej_get_remaining_delta(cur_node)))
|
||||
oldest_node = cur_node;
|
||||
|
||||
qdf_list_peek_next(list, cur_list, &next_list);
|
||||
cur_list = next_list;
|
||||
next_list = NULL;
|
||||
}
|
||||
|
||||
if (oldest_node) {
|
||||
pe_debug("remove node %pM with lowest delta %d",
|
||||
oldest_node->bssid.bytes,
|
||||
lim_assoc_rej_get_remaining_delta(oldest_node));
|
||||
qdf_list_remove_node(list, &oldest_node->node);
|
||||
qdf_mem_free(oldest_node);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
void lim_assoc_rej_add_to_rssi_based_reject_list(tpAniSirGlobal mac_ctx,
|
||||
tDot11fTLVrssi_assoc_rej *rssi_assoc_rej,
|
||||
tSirMacAddr bssid, int8_t rssi)
|
||||
{
|
||||
struct sir_rssi_disallow_lst *entry;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
entry = qdf_mem_malloc(sizeof(*entry));
|
||||
if (!entry) {
|
||||
pe_err("malloc failed for bssid entry");
|
||||
return;
|
||||
}
|
||||
|
||||
pe_debug("%pM: assoc resp rssi %d, delta rssi %d retry delay %d sec and list size %d",
|
||||
bssid, rssi, rssi_assoc_rej->delta_rssi,
|
||||
rssi_assoc_rej->retry_delay,
|
||||
qdf_list_size(&mac_ctx->roam.rssi_disallow_bssid));
|
||||
|
||||
qdf_mem_copy(entry->bssid.bytes,
|
||||
bssid, QDF_MAC_ADDR_SIZE);
|
||||
entry->retry_delay = rssi_assoc_rej->retry_delay *
|
||||
QDF_MC_TIMER_TO_MS_UNIT;
|
||||
entry->expected_rssi = rssi + rssi_assoc_rej->delta_rssi;
|
||||
entry->time_during_rejection =
|
||||
qdf_do_div(qdf_get_monotonic_boottime(),
|
||||
QDF_MC_TIMER_TO_MS_UNIT);
|
||||
|
||||
if (qdf_list_size(&mac_ctx->roam.rssi_disallow_bssid) >=
|
||||
MAX_RSSI_AVOID_BSSID_LIST) {
|
||||
status = lim_assoc_rej_rem_entry_with_lowest_delta(
|
||||
&mac_ctx->roam.rssi_disallow_bssid);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
pe_err("Failed to remove entry with lowest delta");
|
||||
}
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
status = qdf_list_insert_back(
|
||||
&mac_ctx->roam.rssi_disallow_bssid,
|
||||
&entry->node);
|
||||
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
pe_err("Failed to enqueue bssid entry");
|
||||
qdf_mem_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void lim_decrement_pending_mgmt_count(tpAniSirGlobal mac_ctx)
|
||||
{
|
||||
qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock);
|
||||
|
@@ -1078,6 +1078,24 @@ static inline QDF_STATUS lim_populate_he_mcs_set(tpAniSirGlobal mac_ctx,
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lim_assoc_rej_add_to_rssi_based_reject_list() - Add BSSID to the rssi based
|
||||
* rejection list
|
||||
* @mac_ctx: mac ctx
|
||||
* @rssi_assoc_rej: rssi assoc reject attribute
|
||||
* @bssid : BSSID of the AP
|
||||
* @rssi : RSSI of the assoc resp
|
||||
*
|
||||
* Add BSSID to the rssi based rejection list. Also if number
|
||||
* of entries is greater than MAX_RSSI_AVOID_BSSID_LIST
|
||||
* remove the entry with lowest time delta
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void lim_assoc_rej_add_to_rssi_based_reject_list(tpAniSirGlobal mac_ctx,
|
||||
tDot11fTLVrssi_assoc_rej *rssi_assoc_rej,
|
||||
tSirMacAddr bssid, int8_t rssi);
|
||||
|
||||
/**
|
||||
* lim_decrement_pending_mgmt_count: Decrement mgmt frame count
|
||||
* @mac_ctx: Pointer to global MAC structure
|
||||
|
@@ -2972,6 +2972,13 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac,
|
||||
sizeof(tDot11fIEvendor_he_op));
|
||||
}
|
||||
|
||||
if (ar.MBO_IE.present && ar.MBO_IE.rssi_assoc_rej.present) {
|
||||
qdf_mem_copy(&pAssocRsp->rssi_assoc_rej,
|
||||
&ar.MBO_IE.rssi_assoc_rej,
|
||||
sizeof(tDot11fTLVrssi_assoc_rej));
|
||||
pe_debug("Received Assoc Response with rssi based assoc rej");
|
||||
}
|
||||
|
||||
return eSIR_SUCCESS;
|
||||
|
||||
} /* End sir_convert_assoc_resp_frame2_struct. */
|
||||
|
@@ -1009,6 +1009,7 @@ typedef struct tagCsrRoamStruct {
|
||||
uint8_t *pReassocResp; /* reassociation response from new AP */
|
||||
uint16_t reassocRespLen; /* length of reassociation response */
|
||||
qdf_mc_timer_t packetdump_timer;
|
||||
qdf_list_t rssi_disallow_bssid;
|
||||
} tCsrRoamStruct;
|
||||
|
||||
#define GET_NEXT_ROAM_ID(pRoamStruct) (((pRoamStruct)->nextRoamId + 1 == 0) ? \
|
||||
|
@@ -328,6 +328,8 @@ QDF_STATUS csr_open(tpAniSirGlobal pMac)
|
||||
(csr_ll_open(pMac->hHdd,
|
||||
&pMac->roam.peStatsReqList)))
|
||||
break;
|
||||
qdf_list_create(&pMac->roam.rssi_disallow_bssid,
|
||||
MAX_RSSI_AVOID_BSSID_LIST);
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
@@ -379,12 +381,41 @@ QDF_STATUS csr_set_channels(tHalHandle hHal, tCsrConfigParam *pParam)
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_assoc_rej_free_rssi_disallow_list() - Free the rssi diallowed
|
||||
* BSSID entries and destroy the list
|
||||
* @list: rssi based disallowed list entry
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void csr_assoc_rej_free_rssi_disallow_list(qdf_list_t *list)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct sir_rssi_disallow_lst *cur_node;
|
||||
qdf_list_node_t *cur_lst = NULL, *next_lst = NULL;
|
||||
|
||||
qdf_list_peek_front(list, &cur_lst);
|
||||
while (cur_lst) {
|
||||
qdf_list_peek_next(list, cur_lst, &next_lst);
|
||||
cur_node = qdf_container_of(cur_lst,
|
||||
struct sir_rssi_disallow_lst, node);
|
||||
status = qdf_list_remove_node(list, cur_lst);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
qdf_mem_free(cur_node);
|
||||
cur_lst = next_lst;
|
||||
next_lst = NULL;
|
||||
}
|
||||
qdf_list_destroy(list);
|
||||
}
|
||||
|
||||
QDF_STATUS csr_close(tpAniSirGlobal pMac)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
tSmeCmd *saved_scan_cmd;
|
||||
|
||||
csr_roam_close(pMac);
|
||||
csr_assoc_rej_free_rssi_disallow_list(
|
||||
&pMac->roam.rssi_disallow_bssid);
|
||||
csr_scan_close(pMac);
|
||||
csr_ll_close(&pMac->roam.statsClientReqList);
|
||||
csr_ll_close(&pMac->roam.peStatsReqList);
|
||||
|
@@ -5684,6 +5684,131 @@ static QDF_STATUS csr_parse_scan_list(tpAniSirGlobal mac_ctx,
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_remove_ap_due_to_rssi() - check if bss is present in
|
||||
* list of BSSID which rejected Assoc due to RSSI
|
||||
* @list: rssi based rejected BSS list
|
||||
* @bss_descr: pointer to bss description
|
||||
*
|
||||
* Check if the time interval indicated in last Assoc reject
|
||||
* has expired OR rssi has improved by margin indicated
|
||||
* in last Assoc reject. If any of the condition match remove
|
||||
* the AP from the avoid list, else do not try to conenct
|
||||
* to the AP
|
||||
*
|
||||
* Return: true if connection cannot be tried with AP else false
|
||||
*/
|
||||
static bool csr_remove_ap_due_to_rssi(qdf_list_t *list,
|
||||
tSirBssDescription *bss_descr)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct sir_rssi_disallow_lst *cur_node = NULL;
|
||||
qdf_list_node_t *cur_lst = NULL, *next_lst = NULL;
|
||||
qdf_time_t cur_time;
|
||||
uint32_t time_diff;
|
||||
|
||||
if (!qdf_list_size(list))
|
||||
return false;
|
||||
|
||||
cur_time = qdf_do_div(qdf_get_monotonic_boottime(),
|
||||
QDF_MC_TIMER_TO_MS_UNIT);
|
||||
|
||||
qdf_list_peek_front(list, &cur_lst);
|
||||
while (cur_lst) {
|
||||
cur_node = qdf_container_of(cur_lst,
|
||||
struct sir_rssi_disallow_lst, node);
|
||||
|
||||
qdf_list_peek_next(list, cur_lst, &next_lst);
|
||||
|
||||
time_diff = cur_time - cur_node->time_during_rejection;
|
||||
if ((time_diff > cur_node->retry_delay)) {
|
||||
sme_debug("Remove %pM as time diff %d is greater retry delay %d",
|
||||
cur_node->bssid.bytes, time_diff,
|
||||
cur_node->retry_delay);
|
||||
status = qdf_list_remove_node(list, cur_lst);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
qdf_mem_free(cur_node);
|
||||
cur_lst = next_lst;
|
||||
next_lst = NULL;
|
||||
cur_node = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!qdf_mem_cmp(cur_node->bssid.bytes,
|
||||
bss_descr->bssId, QDF_MAC_ADDR_SIZE))
|
||||
break;
|
||||
cur_lst = next_lst;
|
||||
next_lst = NULL;
|
||||
cur_node = NULL;
|
||||
}
|
||||
|
||||
if (cur_node) {
|
||||
time_diff = cur_time - cur_node->time_during_rejection;
|
||||
if (!(time_diff > cur_node->retry_delay ||
|
||||
bss_descr->rssi_raw >= cur_node->expected_rssi)) {
|
||||
sme_err("Don't Attempt to connect %pM (time diff %d retry delay %d rssi %d expected rssi %d)",
|
||||
cur_node->bssid.bytes, time_diff,
|
||||
cur_node->retry_delay, bss_descr->rssi_raw,
|
||||
cur_node->expected_rssi);
|
||||
return true;
|
||||
}
|
||||
sme_debug("Remove %pM as time diff %d is greater retry delay %d or RSSI %d is greater than expected %d",
|
||||
cur_node->bssid.bytes, time_diff,
|
||||
cur_node->retry_delay,
|
||||
bss_descr->rssi_raw,
|
||||
cur_node->expected_rssi);
|
||||
status = qdf_list_remove_node(list, cur_lst);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
qdf_mem_free(cur_node);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* csr_filter_ap_due_to_rssi_reject() - filter the AP who has sent
|
||||
* assoc reject due to RSSI if condition has not improved
|
||||
* @mac_ctx: mac context
|
||||
* @scan_list: candidate list for the connection
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void csr_filter_ap_due_to_rssi_reject(tpAniSirGlobal mac_ctx,
|
||||
tScanResultList *scan_list)
|
||||
{
|
||||
tListElem *cur_entry;
|
||||
tListElem *next_entry;
|
||||
tCsrScanResult *scan_res;
|
||||
bool remove;
|
||||
|
||||
if (!scan_list ||
|
||||
!qdf_list_size(&mac_ctx->roam.rssi_disallow_bssid))
|
||||
return;
|
||||
|
||||
csr_ll_lock(&scan_list->List);
|
||||
|
||||
cur_entry = csr_ll_peek_head(&scan_list->List, LL_ACCESS_NOLOCK);
|
||||
while (cur_entry) {
|
||||
scan_res = GET_BASE_ADDR(cur_entry, tCsrScanResult,
|
||||
Link);
|
||||
next_entry = csr_ll_next(&scan_list->List,
|
||||
cur_entry, LL_ACCESS_NOLOCK);
|
||||
remove = csr_remove_ap_due_to_rssi(
|
||||
&mac_ctx->roam.rssi_disallow_bssid,
|
||||
&scan_res->Result.BssDescriptor);
|
||||
if (remove) {
|
||||
csr_ll_remove_entry(&scan_list->List,
|
||||
cur_entry, LL_ACCESS_NOLOCK);
|
||||
csr_free_scan_result_entry(mac_ctx, scan_res);
|
||||
}
|
||||
cur_entry = next_entry;
|
||||
next_entry = NULL;
|
||||
}
|
||||
csr_ll_unlock(&scan_list->List);
|
||||
|
||||
}
|
||||
|
||||
QDF_STATUS csr_scan_get_result(tpAniSirGlobal mac_ctx,
|
||||
tCsrScanResultFilter *pFilter,
|
||||
tScanResultHandle *results)
|
||||
@@ -5740,6 +5865,8 @@ QDF_STATUS csr_scan_get_result(tpAniSirGlobal mac_ctx,
|
||||
/* Fail or No one wants the result. */
|
||||
csr_scan_result_purge(mac_ctx, (tScanResultHandle) ret_list);
|
||||
else {
|
||||
if (pFilter)
|
||||
csr_filter_ap_due_to_rssi_reject(mac_ctx, ret_list);
|
||||
if (!csr_ll_count(&ret_list->List)) {
|
||||
/* This mean that there is no match */
|
||||
csr_ll_close(&ret_list->List);
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur