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 à :
Abhishek Singh
2017-06-28 16:04:06 +05:30
révisé par snandini
Parent b08e721916
révision f3756fcb5c
10 fichiers modifiés avec 322 ajouts et 1 suppressions

Voir le fichier

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

Voir le fichier

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

Voir le fichier

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

Voir le fichier

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

Voir le fichier

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

Voir le fichier

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

Voir le fichier

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

Voir le fichier

@@ -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) ? \

Voir le fichier

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

Voir le fichier

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