blob: ccc8ec710419586241c6e1fa944c5a6ab17a5e14 [file] [log] [blame]
/*
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
*
* This file limProcessAssocRspFrame.cc contains the code
* for processing Re/Association Response Frame.
* Author: Chandra Modumudi
* Date: 03/18/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "wniApi.h"
#include "wniCfg.h"
#include "aniGlobal.h"
#include "cfgApi.h"
#include "utilsApi.h"
#include "pmmApi.h"
#include "limTypes.h"
#include "limUtils.h"
#include "limAssocUtils.h"
#include "limSecurityUtils.h"
#include "limSerDesUtils.h"
#include "limStaHashApi.h"
#include "limSendMessages.h"
#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
#include "eseApi.h"
#endif
#ifdef WLAN_FEATURE_LFR_MBB
#include "lim_mbb.h"
#endif
extern tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry);
/**
* @function : limUpdateAssocStaDatas
*
* @brief : This function is called to Update the Station Descriptor (dph) Details from
* Association / ReAssociation Response Frame
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pStaDs - Station Descriptor in DPH
* @param pAssocRsp - Pointer to Association Response Structure
*
* @return None
*/
void limUpdateAssocStaDatas(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpSirAssocRsp pAssocRsp,tpPESession psessionEntry)
{
tANI_U32 prop;
tANI_U32 phyMode;
tANI_U32 val;
//tpSirBoardCapabilities pBoardCaps;
tANI_BOOLEAN qosMode;
tANI_U16 rxHighestRate = 0;
uint32_t shortgi_20mhz_support;
uint32_t shortgi_40mhz_support;
limGetPhyMode(pMac, &phyMode, psessionEntry);
pStaDs->staType= STA_ENTRY_SELF;
limGetQosMode(psessionEntry, &qosMode);
// set the ani peer bit, if self mode is one of the proprietary modes
if(IS_DOT11_MODE_PROPRIETARY(psessionEntry->dot11mode))
{
wlan_cfgGetInt(pMac, WNI_CFG_PROPRIETARY_ANI_FEATURES_ENABLED, &prop);
if (prop)
{
pStaDs->aniPeer = eHAL_SET;
pStaDs->propCapability = pAssocRsp->propIEinfo.capability;
}
}
//pMac->lim.gLimMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
pStaDs->mlmStaContext.authType = psessionEntry->limCurrentAuthType;
// Add capabilities information, rates and AID
pStaDs->mlmStaContext.capabilityInfo = pAssocRsp->capabilityInfo;
pStaDs->shortPreambleEnabled= (tANI_U8)pAssocRsp->capabilityInfo.shortPreamble;
//Update HT Capabilites only when the self mode supports HT
if(IS_DOT11_MODE_HT(psessionEntry->dot11mode)) {
pStaDs->mlmStaContext.htCapability = pAssocRsp->HTCaps.present;
if ( pAssocRsp->HTCaps.present ) {
pStaDs->htGreenfield = ( tANI_U8 ) pAssocRsp->HTCaps.greenField;
if (psessionEntry->htSupportedChannelWidthSet)
{
pStaDs->htSupportedChannelWidthSet = ( tANI_U8 ) (pAssocRsp->HTCaps.supportedChannelWidthSet ?
pAssocRsp->HTInfo.recommendedTxWidthSet :
pAssocRsp->HTCaps.supportedChannelWidthSet );
}
else
{
pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ;
}
pStaDs->htLsigTXOPProtection = ( tANI_U8 ) pAssocRsp->HTCaps.lsigTXOPProtection;
pStaDs->htMIMOPSState = (tSirMacHTMIMOPowerSaveState)pAssocRsp->HTCaps.mimoPowerSave;
pStaDs->htMaxAmsduLength = ( tANI_U8 ) pAssocRsp->HTCaps.maximalAMSDUsize;
pStaDs->htAMpduDensity = pAssocRsp->HTCaps.mpduDensity;
pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocRsp->HTCaps.dsssCckMode40MHz;
pStaDs->htMaxRxAMpduFactor = pAssocRsp->HTCaps.maxRxAMPDUFactor;
limFillRxHighestSupportedRate(pMac, &rxHighestRate, pAssocRsp->HTCaps.supportedMCSSet);
pStaDs->supportedRates.rxHighestDataRate = rxHighestRate;
/* This is for AP as peer STA and we are INFRA STA. We will put APs offset in dph node which is peer STA */
pStaDs->htSecondaryChannelOffset = (tANI_U8)pAssocRsp->HTInfo.secondaryChannelOffset;
//FIXME_AMPDU
// In the future, may need to check for "assoc.HTCaps.delayedBA"
// For now, it is IMMEDIATE BA only on ALL TID's
pStaDs->baPolicyFlag = 0xFF;
/*
* Check if we have support for gShortGI20Mhz and
* gShortGI40Mhz from ini file.
*/
if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac,
WNI_CFG_SHORT_GI_20MHZ,
&shortgi_20mhz_support))) {
if (VOS_TRUE == shortgi_20mhz_support)
pStaDs->htShortGI20Mhz =
(tANI_U8)pAssocRsp->HTCaps.shortGI20MHz;
else
pStaDs->htShortGI20Mhz = VOS_FALSE;
} else {
limLog(pMac, LOGE,
FL("could not retrieve shortGI 20Mhz CFG,"
"setting value to default"));
pStaDs->htShortGI20Mhz = WNI_CFG_SHORT_GI_20MHZ_STADEF;
}
if (HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac,
WNI_CFG_SHORT_GI_40MHZ,
&shortgi_40mhz_support))) {
if (VOS_TRUE == shortgi_40mhz_support)
pStaDs->htShortGI40Mhz =
(tANI_U8)pAssocRsp->HTCaps.shortGI40MHz;
else
pStaDs->htShortGI40Mhz = VOS_FALSE;
} else {
limLog(pMac, LOGE,
FL("could not retrieve shortGI 40Mhz CFG,"
"setting value to default"));
pStaDs->htShortGI40Mhz = WNI_CFG_SHORT_GI_40MHZ_STADEF;
}
}
}
#ifdef WLAN_FEATURE_11AC
if(IS_DOT11_MODE_VHT(psessionEntry->dot11mode))
{
pStaDs->mlmStaContext.vhtCapability = pAssocRsp->VHTCaps.present;
if (pAssocRsp->VHTCaps.present && psessionEntry->htSupportedChannelWidthSet)
pStaDs->vhtSupportedChannelWidthSet = pAssocRsp->VHTOperation.chanWidth;
}
if (limPopulatePeerRateSet(pMac, &pStaDs->supportedRates,
pAssocRsp->HTCaps.supportedMCSSet,
false,psessionEntry , &pAssocRsp->VHTCaps) != eSIR_SUCCESS)
#else
if (limPopulatePeerRateSet(pMac, &pStaDs->supportedRates, pAssocRsp->HTCaps.supportedMCSSet, false,psessionEntry) != eSIR_SUCCESS)
#endif
{
limLog(pMac, LOGP, FL("could not get rateset and extended rate set"));
return;
}
//If one of the rates is 11g rates, set the ERP mode.
if ((phyMode == WNI_CFG_PHY_MODE_11G) && sirIsArate(pStaDs->supportedRates.llaRates[0] & 0x7f))
pStaDs->erpEnabled = eHAL_SET;
val = WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET_LEN;
if (wlan_cfgGetStr(pMac, WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET,
(tANI_U8 *) &pStaDs->mlmStaContext.propRateSet.propRate,
&val) != eSIR_SUCCESS) {
/// Could not get prop rateset from CFG. Log error.
limLog(pMac, LOGP, FL("could not retrieve prop rateset"));
return;
}
pStaDs->mlmStaContext.propRateSet.numPropRates = (tANI_U8) val;
pStaDs->qosMode = 0;
pStaDs->lleEnabled = 0;
// update TSID to UP mapping
//if (pMac->lim.gLimQosEnabled)
if (qosMode) {
if (pAssocRsp->edcaPresent) {
tSirRetStatus status;
status = schBeaconEdcaProcess(pMac,&pAssocRsp->edca, psessionEntry);
PELOG2(limLog(pMac, LOG2, "Edca set update based on AssocRsp: status %d",
status);)
if (status != eSIR_SUCCESS) {
PELOGE(limLog(pMac, LOGE, FL("Edca error in AssocResp "));)
} else { // update default tidmap based on ACM
pStaDs->qosMode = 1;
pStaDs->lleEnabled = 1;
}
}
}
pStaDs->wmeEnabled = 0;
pStaDs->wsmEnabled = 0;
if (psessionEntry->limWmeEnabled && pAssocRsp->wmeEdcaPresent)
{
tSirRetStatus status;
status = schBeaconEdcaProcess(pMac,&pAssocRsp->edca, psessionEntry);
PELOGW(limLog(pMac, LOGW, "WME Edca set update based on AssocRsp: status %d", status);)
if (status != eSIR_SUCCESS)
PELOGE(limLog(pMac, LOGE, FL("WME Edca error in AssocResp - ignoring"));)
else { // update default tidmap based on HashACM
pStaDs->qosMode = 1;
pStaDs->wmeEnabled = 1;
}
}
else {
/* We received assoc rsp from a legacy AP. So fill in the default
* local EDCA params. This is needed (refer to bug #14989) as we'll
* be passing the gLimEdcaParams to HAL in limProcessStaMlmAddBssRsp().
*/
schSetDefaultEdcaParams(pMac, psessionEntry);
}
if(qosMode && (!pStaDs->qosMode) && pStaDs->mlmStaContext.htCapability)
{
// Enable QOS for all HT AP's even though WMM or 802.11E IE is not present
pStaDs->qosMode = 1;
pStaDs->wmeEnabled = 1;
}
#ifdef WLAN_FEATURE_11W
if(psessionEntry->limRmfEnabled)
{
pStaDs->rmfEnabled = 1;
}
#endif
}
/**
* @function : limUpdateReAssocGlobals
*
* @brief : This function is called to Update the Globals (LIM) during ReAssoc.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pAssocRsp - Pointer to Association Response Structure
*
* @return None
*/
void limUpdateReAssocGlobals(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,tpPESession psessionEntry)
{
/**
* Update the status for PMM module
*/
pmmResetPmmState(pMac);
// Update the current Bss Information
vos_mem_copy(psessionEntry->bssId,
psessionEntry->limReAssocbssId, sizeof(tSirMacAddr));
psessionEntry->currentOperChannel = psessionEntry->limReassocChannelId;
psessionEntry->htSecondaryChannelOffset = psessionEntry->reAssocHtSupportedChannelWidthSet;
psessionEntry->htRecommendedTxWidthSet = psessionEntry->reAssocHtRecommendedTxWidthSet;
psessionEntry->htSecondaryChannelOffset = psessionEntry->reAssocHtSecondaryChannelOffset;
psessionEntry->limCurrentBssCaps = psessionEntry->limReassocBssCaps;
psessionEntry->limCurrentBssQosCaps = psessionEntry->limReassocBssQosCaps;
psessionEntry->limCurrentBssPropCap = psessionEntry->limReassocBssPropCap;
vos_mem_copy((tANI_U8 *) &psessionEntry->ssId,
(tANI_U8 *) &psessionEntry->limReassocSSID,
psessionEntry->limReassocSSID.length+1);
// Store assigned AID for TIM processing
psessionEntry->limAID = pAssocRsp->aid & 0x3FFF;
/** Set the State Back to ReAssoc Rsp*/
psessionEntry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState));
}
/**
* @function : limProcessAssocRspFrame
*
* @brief : This function is called by limProcessMessageQueue() upon
* Re/Association Response frame reception.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - A pointer to Rx packet info structure
* @param subType - Indicates whether it is Association Response (=0) or
* Reassociation Response (=1) frame
*
* @return None
*/
void
limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 subType,tpPESession psessionEntry)
{
tANI_U8 *pBody;
tANI_U16 caps;
tANI_U32 frameLen;
tSirMacAddr currentBssId;
tpSirMacMgmtHdr pHdr;
tSirMacCapabilityInfo localCapabilities;
tpDphHashNode pStaDs;
tpSirAssocRsp pAssocRsp;
tLimMlmAssocCnf mlmAssocCnf;
tSchBeaconStruct *pBeaconStruct;
//Initialize status code to success.
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
mlmAssocCnf.resultCode = eSIR_SME_SUCCESS;
/* Update PE session Id*/
mlmAssocCnf.sessionId = psessionEntry->peSessionId;
limLog(pMac, LOG1,
FL("received Re/Assoc(%d) resp on sessionid: %d with systemrole: %d "
"and mlmstate: %d RSSI %d from "MAC_ADDRESS_STR),subType,
psessionEntry->peSessionId,
psessionEntry->limSystemRole,psessionEntry->limMlmState,
(uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo)),
MAC_ADDR_ARRAY(pHdr->sa));
pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct));
if (NULL == pBeaconStruct)
{
limLog(pMac, LOGE, FL("Unable to allocate memory") );
return;
}
if (psessionEntry->limSystemRole == eLIM_AP_ROLE || psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE )
{
// Should not have received Re/Association Response
// frame on AP. Log error
limLog(pMac, LOGE,
FL("Should not recieved Re/Assoc Response in role %d "),
psessionEntry->limSystemRole);
vos_mem_free(pBeaconStruct);
return;
}
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
if (((subType == LIM_ASSOC) &&
(psessionEntry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) ||
((subType == LIM_REASSOC) &&
((psessionEntry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE)
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
&& (psessionEntry->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE)
#endif
)))
{
/// Received unexpected Re/Association Response frame
#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog(pMac, LOG1, FL("Recieved Re/Assoc rsp in unexpected "
"state %d on session=%d"),
psessionEntry->limMlmState, psessionEntry->peSessionId);
#endif
// Log error
if (!pHdr->fc.retry)
{
if ( !(pMac->lim.retryPacketCnt & 0xf))
{
limLog(pMac, LOGE,
FL("received Re/Assoc rsp frame is not a retry frame, "
"frame count %d"), ++pMac->lim.retryPacketCnt);
limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState);
}
else
{
pMac->lim.retryPacketCnt++;
}
}
vos_mem_free(pBeaconStruct);
return;
}
#if 0
if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, currentBssId, &cfg) !=
eSIR_SUCCESS)
{
/// Could not get BSSID from CFG. Log error.
limLog(pMac, LOGP, FL("could not retrieve BSSID"));
vos_mem_free(pBeaconStruct);
return;
}
#endif //TO SUPPORT BT-AMP
sirCopyMacAddr(currentBssId,psessionEntry->bssId);
if (subType == LIM_ASSOC)
{
if (!vos_mem_compare(pHdr->sa, currentBssId, sizeof(tSirMacAddr)))
{
/**
* Received Association Response frame from an entity
* other than one to which request was initiated.
* Ignore this and wait until Association Failure Timeout.
*/
// Log error
PELOGW(limLog(pMac, LOGW,
FL("received AssocRsp frame from unexpected peer "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));)
vos_mem_free(pBeaconStruct);
return;
}
}
else
{
if (!vos_mem_compare(pHdr->sa, psessionEntry->limReAssocbssId, sizeof(tSirMacAddr)))
{
/**
* Received Reassociation Response frame from an entity
* other than one to which request was initiated.
* Ignore this and wait until Reassociation Failure Timeout.
*/
// Log error
PELOGW(limLog(pMac, LOGW,
FL("received ReassocRsp frame from unexpected peer "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));)
vos_mem_free(pBeaconStruct);
return;
}
}
pAssocRsp = vos_mem_malloc(sizeof(*pAssocRsp));
if (NULL == pAssocRsp)
{
limLog(pMac, LOGP, FL("Allocate Memory failed in AssocRsp"));
vos_mem_free(pBeaconStruct);
return;
}
// Get pointer to Re/Association Response frame body
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
// parse Re/Association Response frame.
if (sirConvertAssocRespFrame2Struct(
pMac, pBody, frameLen, pAssocRsp) == eSIR_FAILURE)
{
vos_mem_free(pAssocRsp);
PELOGE(limLog(pMac, LOGE, FL("Parse error Assoc resp subtype %d,"
"length=%d"), frameLen,subType);)
vos_mem_free(pBeaconStruct);
return;
}
if(pAssocRsp->ExtCap.present)
{
struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
pAssocRsp->ExtCap.bytes;
limLog(pMac, LOG1,
FL("Filling tdls prohibited in session entry"));
psessionEntry->tdlsChanSwitProhibited =
p_ext_cap->TDLSChanSwitProhibited;
}
if(!pAssocRsp->suppRatesPresent)
{
PELOGE(limLog(pMac, LOGE, FL("assoc response does not have supported rate set"));)
vos_mem_copy(&pAssocRsp->supportedRates,
&psessionEntry->rateSet, sizeof(tSirMacRateSet));
}
mlmAssocCnf.protStatusCode = pAssocRsp->statusCode;
if( psessionEntry->assocRsp != NULL )
{
limLog(pMac, LOGW, FL("psessionEntry->assocRsp is not NULL freeing it "
"and setting NULL"));
vos_mem_free(psessionEntry->assocRsp);
psessionEntry->assocRsp = NULL;
}
if (frameLen) {
psessionEntry->assocRsp = vos_mem_malloc(frameLen);
if (NULL == psessionEntry->assocRsp)
{
PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response, len = %d"), frameLen);)
}
else
{
//Store the Assoc response. This is sent to csr/hdd in join cnf response.
vos_mem_copy(psessionEntry->assocRsp, pBody, frameLen);
psessionEntry->assocRspLen = frameLen;
}
}
#ifdef WLAN_FEATURE_VOWIFI_11R
if (psessionEntry->ricData != NULL)
{
vos_mem_free(psessionEntry->ricData);
psessionEntry->ricData = NULL;
}
if(pAssocRsp->ricPresent)
{
psessionEntry->RICDataLen = pAssocRsp->num_RICData * sizeof(tDot11fIERICDataDesc);
if (psessionEntry->RICDataLen)
{
psessionEntry->ricData = vos_mem_malloc(psessionEntry->RICDataLen);
if ( NULL == psessionEntry->ricData )
{
PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response"));)
psessionEntry->RICDataLen = 0;
}
else
{
vos_mem_copy(psessionEntry->ricData,
&pAssocRsp->RICData[0], psessionEntry->RICDataLen);
}
}
}
else
{
limLog(pMac, LOG1, FL("Ric is not present Setting RICDataLen 0 and ricData "
"as NULL"));
psessionEntry->RICDataLen = 0;
psessionEntry->ricData = NULL;
}
#endif
#ifdef FEATURE_WLAN_ESE
if (psessionEntry->tspecIes != NULL)
{
vos_mem_free(psessionEntry->tspecIes);
psessionEntry->tspecIes = NULL;
}
if(pAssocRsp->tspecPresent)
{
psessionEntry->tspecLen = pAssocRsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC);
psessionEntry->tspecIes = vos_mem_malloc(psessionEntry->tspecLen);
if ( NULL == psessionEntry->tspecIes )
{
PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response"));)
psessionEntry->tspecLen = 0;
}
else
{
vos_mem_copy(psessionEntry->tspecIes,
&pAssocRsp->TSPECInfo[0], psessionEntry->tspecLen);
}
limLog(pMac, LOG1, FL(" Tspec EID present in assoc rsp "));
}
else
{
psessionEntry->tspecLen = 0;
psessionEntry->tspecIes = NULL;
limLog(pMac, LOG1, FL(" Tspec EID *NOT* present in assoc rsp "));
}
#endif
if (pAssocRsp->capabilityInfo.ibss)
{
/**
* Received Re/Association Response from peer
* with IBSS capability set.
* Ignore the frame and wait until Re/assoc
* failure timeout.
*/
// Log error
limLog(pMac, LOGE,
FL("received Re/AssocRsp frame with IBSS capability"));
vos_mem_free(pAssocRsp);
vos_mem_free(pBeaconStruct);
return;
}
if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS)
{
/**
* Could not get Capabilities value
* from CFG. Log error.
*/
vos_mem_free(pAssocRsp);
vos_mem_free(pBeaconStruct);
limLog(pMac, LOGP, FL("could not retrieve Capabilities value"));
return;
}
limCopyU16((tANI_U8 *) &localCapabilities, caps);
if (subType == LIM_ASSOC) // Stop Association failure timer
limDeactivateAndChangeTimer(pMac, eLIM_ASSOC_FAIL_TIMER);
else // Stop Reassociation failure timer
{
#ifdef WLAN_FEATURE_LFR_MBB
if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb)
limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_MBB_RSP_TIMER);
#endif
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
pMac->lim.reAssocRetryAttempt = 0;
if ((NULL != pMac->lim.pSessionEntry) && (NULL != pMac->lim.pSessionEntry->pLimMlmReassocRetryReq))
{
vos_mem_free(pMac->lim.pSessionEntry->pLimMlmReassocRetryReq);
pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = NULL;
}
#endif
/* Dactivate timer when it is not LFR MBB */
if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb)
limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER);
}
if (pAssocRsp->statusCode != eSIR_MAC_SUCCESS_STATUS)
{
// Re/Association response was received
// either with failure code.
// Log error.
PELOGE(limLog(pMac, LOGE, FL("received Re/AssocRsp frame failure code %d"), pAssocRsp->statusCode);)
// Need to update 'association failure' error counter
// along with STATUS CODE
// Return Assoc confirm to SME with received failure code
if (pAssocRsp->propIEinfo.loadBalanceInfoPresent)
{
mlmAssocCnf.resultCode = eSIR_SME_TRANSFER_STA;
vos_mem_copy(pMac->lim.gLimAlternateRadio.bssId,
pAssocRsp->propIEinfo.alternateRadio.bssId, sizeof(tSirMacAddr));
pMac->lim.gLimAlternateRadio.channelId =
pAssocRsp->propIEinfo.alternateRadio.channelId;
}else
mlmAssocCnf.resultCode = eSIR_SME_ASSOC_REFUSED;
if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb)
goto assocReject;
// Delete Pre-auth context for the associated BSS
if (limSearchPreAuthList(pMac, pHdr->sa))
limDeletePreAuthNode(pMac, pHdr->sa);
goto assocReject;
}
else if ((pAssocRsp->aid & 0x3FFF) > 2007)
{
// Re/Association response was received
// with invalid AID value
// Log error
PELOGW(limLog(pMac, LOGE, FL("received Re/AssocRsp frame with"
"invalid aid %X"), pAssocRsp->aid);)
mlmAssocCnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
// Send advisory Disassociation frame to AP
limSendDisassocMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON,
pHdr->sa, psessionEntry, FALSE);
goto assocReject;
}
// Association Response received with success code
/*
* Set the link state to POSTASSOC now that we have received
* assoc/reassoc response
* NOTE: for BTAMP case, it is being handled in limProcessMlmAssocReq
*/
if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb) {
if (!((psessionEntry->bssType == eSIR_BTAMP_STA_MODE) ||
((psessionEntry->bssType == eSIR_BTAMP_AP_MODE) &&
(psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE))))
{
if (limSetLinkState(pMac, eSIR_LINK_POSTASSOC_STATE,
psessionEntry->bssId,
psessionEntry->selfMacAddr,
NULL, NULL) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("Set link state to POSTASSOC failed"));)
vos_mem_free(pBeaconStruct);
vos_mem_free(pAssocRsp);
return;
}
}
}
if (subType == LIM_REASSOC)
{
// Log success
limLog(pMac, LOG1, FL("Successfully Reassociated with BSS"));
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
psessionEntry, eSIR_SUCCESS, eSIR_SUCCESS);
#endif
#ifdef FEATURE_WLAN_ESE
{
tANI_U8 cnt = 0;
if (pAssocRsp->tsmPresent)
{
limLog(pMac, LOG1, "TSM IE Present in Reassoc Rsp");
// Start the TSM timer only if the TSPEC Ie is present in the reassoc rsp
if (pAssocRsp->tspecPresent) {
// Find the TSPEC IE with VO user priority
for (cnt=0; cnt<pAssocRsp->num_tspecs; cnt++) {
if ( upToAc(pAssocRsp->TSPECInfo[cnt].user_priority) == EDCA_AC_VO) {
psessionEntry->eseContext.tsm.tid = pAssocRsp->TSPECInfo[cnt].user_priority;
vos_mem_copy(&psessionEntry->eseContext.tsm.tsmInfo,
&pAssocRsp->tsmIE, sizeof(tSirMacESETSMIE));
#ifdef FEATURE_WLAN_ESE_UPLOAD
limSendSmeTsmIEInd(pMac,
psessionEntry,
pAssocRsp->tsmIE.tsid,
pAssocRsp->tsmIE.state,
pAssocRsp->tsmIE.msmt_interval);
#else
limActivateTSMStatsTimer(pMac, psessionEntry);
#endif /* FEATURE_WLAN_ESE_UPLOAD */
if(psessionEntry->eseContext.tsm.tsmInfo.state) {
psessionEntry->eseContext.tsm.tsmMetrics.RoamingCount++;
}
break;
}
}
} else {
limLog(pMac, LOGE, "TSM present but TSPEC IE not present in Reassoc Rsp");
}
}
}
#endif
if (psessionEntry->pLimMlmJoinReq)
{
vos_mem_free(psessionEntry->pLimMlmJoinReq);
psessionEntry->pLimMlmJoinReq = NULL;
}
psessionEntry->limAssocResponseData = (void *) pAssocRsp; /** Store the ReAssocRsp Frame in DphTable to be used
during processing DelSta nd DelBss to send AddBss again*/
pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable);
if(!pStaDs)
{
PELOGE(limLog(pMac, LOGE, FL("could not get hash entry at DPH for"));)
limPrintMacAddr(pMac, pHdr->sa, LOGE);
mlmAssocCnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
// Send advisory Disassociation frame to AP
limSendDisassocMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON,
pHdr->sa, psessionEntry, FALSE);
goto assocReject;
}
#ifdef WLAN_FEATURE_LFR_MBB
if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) {
limLog(pMac, LOG1, FL("Reassoc success for LFR MBB in state %d"),
psessionEntry->limMlmState);
if (psessionEntry->limMlmState ==
eLIM_MLM_WT_REASSOC_RSP_STATE) {
lim_handle_reassoc_mbb_success(pMac, psessionEntry,
pAssocRsp, pStaDs);
return;
}
goto assocReject;
}
#endif
#if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
if (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE)
{
#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOG1, FL("Sending self sta"));)
#endif
pmmResetPmmState(pMac);
limUpdateAssocStaDatas(pMac, pStaDs, pAssocRsp,psessionEntry);
// Store assigned AID for TIM processing
psessionEntry->limAID = pAssocRsp->aid & 0x3FFF;
// Downgrade the EDCA parameters if needed
limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry);
// Send the active EDCA parameters to HAL
if (pStaDs->aniPeer == eANI_BOOLEAN_TRUE)
{
limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, pStaDs->bssId, eANI_BOOLEAN_TRUE);
}
else
{
limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, pStaDs->bssId, eANI_BOOLEAN_FALSE);
}
limAddFTStaSelf(pMac, (pAssocRsp->aid & 0x3FFF), psessionEntry);
vos_mem_free(pBeaconStruct);
return;
}
#endif /* WLAN_FEATURE_VOWIFI_11R */
/* If we're re-associating to the same BSS, we don't want to invoke delete
* STA, delete BSS, as that would remove the already established TSPEC.
* Just go ahead and re-add the BSS, STA with new capability information.
* However, if we're re-associating to a different BSS, then follow thru
* with del STA, del BSS, add BSS, add STA.
*/
if (sirCompareMacAddr( psessionEntry->bssId, psessionEntry->limReAssocbssId))
limHandleAddBssInReAssocContext(pMac, pStaDs, psessionEntry);
else
{
// reset the uapsd mask settings since we're re-associating to new AP
pMac->lim.gUapsdPerAcDeliveryEnableMask = 0;
pMac->lim.gUapsdPerAcTriggerEnableMask = 0;
if (limCleanupRxPath(pMac, pStaDs,psessionEntry) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("Could not cleanup the rx path"));)
goto assocReject;
}
}
vos_mem_free(pBeaconStruct);
return;
}
// Log success
limLog(pMac, LOG1, FL("Successfully Associated with BSS "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
#ifdef FEATURE_WLAN_ESE
if(psessionEntry->eseContext.tsm.tsmInfo.state)
{
psessionEntry->eseContext.tsm.tsmMetrics.RoamingCount = 0;
}
#endif
/**
* Update the status for PMM module
*/
pmmResetPmmState(pMac);
// Store assigned AID for TIM processing
psessionEntry->limAID = pAssocRsp->aid & 0x3FFF;
//STA entry was created during pre-assoc state.
if ((pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL)
{
// Could not add hash table entry
PELOGE(limLog(pMac, LOGE, FL("could not get hash entry at DPH for "));)
limPrintMacAddr(pMac, pHdr->sa, LOGE);
mlmAssocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
mlmAssocCnf.protStatusCode = eSIR_SME_SUCCESS;
limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF,
(tANI_U32 *) &mlmAssocCnf);
vos_mem_free(pAssocRsp);
vos_mem_free(pBeaconStruct);
return;
}
// Delete Pre-auth context for the associated BSS
if (limSearchPreAuthList(pMac, pHdr->sa))
limDeletePreAuthNode(pMac, pHdr->sa);
limUpdateAssocStaDatas(pMac, pStaDs, pAssocRsp,psessionEntry);
// Extract the AP capabilities from the beacon that was received earlier
// TODO - Watch out for an error response!
limExtractApCapabilities(pMac,
(tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields,
GET_IE_LEN_IN_BSS(psessionEntry->pLimJoinReq->bssDescription.length),
pBeaconStruct);
if (pBeaconStruct->VHTCaps.present)
pStaDs->parsed_ies.vht_caps = pBeaconStruct->VHTCaps;
if (pBeaconStruct->HTCaps.present)
pStaDs->parsed_ies.ht_caps = pBeaconStruct->HTCaps;
if (pBeaconStruct->hs20vendor_ie.present)
pStaDs->parsed_ies.hs20vendor_ie =
pBeaconStruct->hs20vendor_ie;
if (pBeaconStruct->HTInfo.present)
pStaDs->parsed_ies.ht_operation = pBeaconStruct->HTInfo;
if (pBeaconStruct->VHTOperation.present)
pStaDs->parsed_ies.vht_operation = pBeaconStruct->VHTOperation;
if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry);
if(pBeaconStruct->erpPresent) {
if (pBeaconStruct->erpIEInfo.barkerPreambleMode)
psessionEntry->beaconParams.fShortPreamble = false;
else
psessionEntry->beaconParams.fShortPreamble = true;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_CONNECTED, psessionEntry,
eSIR_SUCCESS, eSIR_SUCCESS);
#endif
if(pAssocRsp->OBSSScanParameters.present)
{
limUpdateOBSSScanParams(psessionEntry , &pAssocRsp->OBSSScanParameters);
}
if( pAssocRsp->QosMapSet.present )
{
vos_mem_copy(&psessionEntry->QosMapSet,
&pAssocRsp->QosMapSet,
sizeof(tSirQosMapSet));
}
else
{
vos_mem_zero(&psessionEntry->QosMapSet, sizeof(tSirQosMapSet));
}
//Update the BSS Entry, this entry was added during preassoc.
if( eSIR_SUCCESS == limStaSendAddBss( pMac, pAssocRsp, pBeaconStruct,
&psessionEntry->pLimJoinReq->bssDescription, true, psessionEntry))
{
vos_mem_free(pAssocRsp);
vos_mem_free(pBeaconStruct);
return;
}
else
{
PELOGE(limLog(pMac, LOGE, FL("could not update the bss entry"));)
mlmAssocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
}
assocReject:
if ((subType == LIM_ASSOC)
#ifdef WLAN_FEATURE_VOWIFI_11R
|| ((subType == LIM_REASSOC) && (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))
#endif
) {
PELOGE(limLog(pMac, LOGE, FL("Assoc Rejected by the peer. "
"mlmestate: %d sessionid %d Reason: %d MACADDR:"
MAC_ADDRESS_STR), psessionEntry->limMlmState,
psessionEntry->peSessionId, mlmAssocCnf.resultCode,
MAC_ADDR_ARRAY(pHdr->sa));)
psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState));
if (psessionEntry->pLimMlmJoinReq)
{
vos_mem_free(psessionEntry->pLimMlmJoinReq);
psessionEntry->pLimMlmJoinReq = NULL;
}
if (subType == LIM_ASSOC)
{
limPostSmeMessage(pMac, LIM_MLM_ASSOC_CNF, (tANI_U32 *) &mlmAssocCnf);
}
#ifdef WLAN_FEATURE_VOWIFI_11R
else
{
mlmAssocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmAssocCnf);
}
#endif /* WLAN_FEATURE_VOWIFI_11R */
} else {
#ifdef WLAN_FEATURE_LFR_MBB
if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) {
lim_handle_reassoc_mbb_fail(pMac, psessionEntry);
vos_mem_free(pBeaconStruct);
vos_mem_free(pAssocRsp);
return;
}
#endif
limRestorePreReassocState( pMac,
eSIR_SME_REASSOC_REFUSED, mlmAssocCnf.protStatusCode,psessionEntry);
}
/* CR: vos packet memory is leaked when assoc rsp timeouted/failed. */
/* notify TL that association is failed so that TL can flush the cached frame */
limLog(pMac, LOG1, FL("notify TL that association is failed"));
WLANTL_AssocFailed (psessionEntry->staId);
vos_mem_free(pBeaconStruct);
vos_mem_free(pAssocRsp);
return;
} /*** end limProcessAssocRspFrame() ***/