blob: 7636056b8bfe3a5e6a965041142e3a080cebb7ef [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.
*/
#ifdef WLAN_FEATURE_VOWIFI_11R
/**=========================================================================
\brief implementation for PE 11r VoWiFi FT Protocol
========================================================================*/
/* $Header$ */
/*--------------------------------------------------------------------------
Include Files
------------------------------------------------------------------------*/
#include <limSendMessages.h>
#include <limTypes.h>
#include <limFT.h>
#include <limFTDefs.h>
#include <limUtils.h>
#include <limPropExtsUtils.h>
#include <limAssocUtils.h>
#include <limSession.h>
#include <limSessionUtils.h>
#include <limAdmitControl.h>
#include "wmmApsd.h"
extern void limSendSetStaKeyReq( tpAniSirGlobal pMac,
tLimMlmSetKeysReq *pMlmSetKeysReq,
tANI_U16 staIdx,
tANI_U8 defWEPIdx,
tpPESession sessionEntry,
tANI_BOOLEAN sendRsp);
/*--------------------------------------------------------------------------
Initialize the FT variables.
------------------------------------------------------------------------*/
void limFTOpen(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
if (psessionEntry)
vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0);
}
/*--------------------------------------------------------------------------
Clean up FT variables.
------------------------------------------------------------------------*/
void limFTCleanupPreAuthInfo(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
tpPESession pReAssocSessionEntry = NULL;
tANI_U8 sessionId = 0;
if (!psessionEntry) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, "%s: psessionEntry is NULL", __func__);)
#endif
return;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
if (psessionEntry->ftPEContext.pFTPreAuthReq) {
pReAssocSessionEntry =
peFindSessionByBssid(pMac,
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId,
&sessionId);
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOG1(limLog( pMac, LOG1, FL("Freeing pFTPreAuthReq= %pK"),
psessionEntry->ftPEContext.pFTPreAuthReq);)
#endif
if (psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
vos_mem_free(
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription);
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL;
}
vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq);
psessionEntry->ftPEContext.pFTPreAuthReq = NULL;
}
if (psessionEntry->ftPEContext.pAddBssReq) {
vos_mem_free(psessionEntry->ftPEContext.pAddBssReq);
psessionEntry->ftPEContext.pAddBssReq = NULL;
}
if (psessionEntry->ftPEContext.pAddStaReq) {
vos_mem_free(psessionEntry->ftPEContext.pAddStaReq);
psessionEntry->ftPEContext.pAddStaReq = NULL;
}
/* The session is being deleted, cleanup the contents */
vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0);
/* Delete the session created while handling pre-auth response */
if (pReAssocSessionEntry) {
/* If we have successful pre-auth response, then we would have
* created a session on which reassoc request will be sent
*/
if (pReAssocSessionEntry->valid &&
pReAssocSessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) {
limLog( pMac, LOG1, FL("Deleting Preauth Session %d"),
pReAssocSessionEntry->peSessionId);
peDeleteSession(pMac, pReAssocSessionEntry);
}
}
}
void limFTCleanupAllFTSessions(tpAniSirGlobal pMac)
{
/* Wrapper function to cleanup all FT sessions */
int i;
for (i = 0; i < pMac->lim.maxBssId; i++) {
if (VOS_TRUE == pMac->lim.gpSession[i].valid) {
/* The session is valid, may have FT data */
limFTCleanup(pMac, &pMac->lim.gpSession[i]);
}
}
}
void limFTCleanup(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
if (NULL == psessionEntry) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is NULL"));)
#endif
return;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOG1(limLog( pMac, LOG1, FL("Freeing pFTPreAuthReq= %pK"),
psessionEntry->ftPEContext.pFTPreAuthReq);)
#endif
if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
vos_mem_free(
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription);
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL;
}
vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq);
psessionEntry->ftPEContext.pFTPreAuthReq = NULL;
}
if (psessionEntry->ftPEContext.pAddBssReq) {
vos_mem_free(psessionEntry->ftPEContext.pAddBssReq);
psessionEntry->ftPEContext.pAddBssReq = NULL;
}
if (psessionEntry->ftPEContext.pAddStaReq) {
vos_mem_free(psessionEntry->ftPEContext.pAddStaReq);
psessionEntry->ftPEContext.pAddStaReq = NULL;
}
/* The session is being deleted, cleanup the contents */
vos_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0);
}
/*------------------------------------------------------------------
*
* This is the handler after suspending the link.
* We suspend the link and then now proceed to switch channel.
*
*------------------------------------------------------------------*/
void static
limFTPreAuthSuspendLinkHandler(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data)
{
tpPESession psessionEntry = (tpPESession)data;
/* The link is suspended of not */
if (NULL == psessionEntry ||
NULL == psessionEntry->ftPEContext.pFTPreAuthReq ||
status != eHAL_STATUS_SUCCESS) {
PELOGE(limLog( pMac, LOGE,
FL("preAuth error, status = %d"), status);)
limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
return;
}
/* Suspended, now move to a different channel.
* Perform some sanity check before proceeding
*/
if (psessionEntry->ftPEContext.pFTPreAuthReq) {
limChangeChannelWithCallback(pMac,
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum,
limPerformFTPreAuth, NULL, psessionEntry);
return;
}
}
/*--------------------------------------------------------------------------
In this function, we process the FT Pre Auth Req.
We receive Pre-Auth
Suspend link
Register a call back
In the call back, we will need to accept frames from the new bssid
Send out the auth req to new AP.
Start timer and when the timer is done or if we receive the Auth response
We change channel
Resume link
------------------------------------------------------------------------*/
int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
{
int bufConsumed = FALSE;
tpPESession psessionEntry;
tANI_U8 sessionId;
tpSirFTPreAuthReq ftPreAuthReq =
(tSirFTPreAuthReq *)pMsg->bodyptr;
if (NULL == ftPreAuthReq) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("tSirFTPreAuthReq is NULL"));)
#endif
return bufConsumed;
}
/* Get the current session entry */
psessionEntry =
peFindSessionByBssid(pMac, ftPreAuthReq->currbssId, &sessionId);
if (psessionEntry == NULL) {
PELOGE(limLog( pMac, LOGE,
FL("Unable to find session for the following bssid"));)
limPrintMacAddr( pMac, ftPreAuthReq->currbssId, LOGE );
/* Post the FT Pre Auth Response to SME */
limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
/* return FALSE, since the Pre-Auth Req will be freed in
* limPostFTPreAuthRsp on failure
*/
return bufConsumed;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
bufConsumed = TRUE;
return bufConsumed;
}
/* Can set it only after sending auth */
psessionEntry->ftPEContext.ftPreAuthStatus = eSIR_FAILURE;
psessionEntry->ftPEContext.ftPreAuthSession = VOS_TRUE;
/* Indicate that this is the session on which preauth is being done */
if (psessionEntry->ftPEContext.pFTPreAuthReq) {
if (psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription)
{
vos_mem_free(
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription);
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription = NULL;
}
vos_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq);
psessionEntry->ftPEContext.pFTPreAuthReq = NULL;
}
/* We need information from the Pre-Auth Req. Lets save that */
psessionEntry->ftPEContext.pFTPreAuthReq = ftPreAuthReq;
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog( pMac, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"),
psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[0],
psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[1],
psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies[2]);)
#endif
#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT,
psessionEntry, 0, 0);
#endif
/* Dont need to suspend if APs are in same channel and DUT is not in MCC state*/
if ((psessionEntry->currentOperChannel !=
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum)
|| limIsInMCC(pMac)) {
/* Need to suspend link only if the channels are different */
PELOG2(limLog(pMac, LOG2, FL("Performing pre-auth on different"
" channel (session %pK)"), psessionEntry);)
limSuspendLink(pMac, eSIR_CHECK_ROAMING_SCAN,
limFTPreAuthSuspendLinkHandler,
(tANI_U32 *)psessionEntry);
} else {
PELOG2(limLog(pMac, LOG2, FL("Performing pre-auth on same"
" channel (session %pK)"), psessionEntry);)
/* We are in the same channel. Perform pre-auth */
limPerformFTPreAuth(pMac, eHAL_STATUS_SUCCESS, NULL, psessionEntry);
}
return bufConsumed;
}
/*------------------------------------------------------------------
* Send the Auth1
* Receive back Auth2
*------------------------------------------------------------------*/
void limPerformFTPreAuth(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry)
{
tSirMacAuthFrameBody authFrame;
tANI_U32 session_id;
eCsrAuthType auth_type;
if (NULL == psessionEntry) {
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is NULL"));)
return;
}
session_id = psessionEntry->smeSessionId;
auth_type = pMac->roam.roamSession[session_id].connectedProfile.AuthType;
if (psessionEntry->is11Rconnection &&
psessionEntry->ftPEContext.pFTPreAuthReq) {
/* Only 11r assoc has FT IEs */
if ((auth_type != eCSR_AUTH_TYPE_OPEN_SYSTEM) &&
(psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies_length == 0)) {
PELOGE(limLog( pMac, LOGE,
"%s: FTIEs for Auth Req Seq 1 is absent",
__func__);)
goto preauth_fail;
}
}
if (status != eHAL_STATUS_SUCCESS) {
PELOGE(limLog( pMac, LOGE,
"%s: Change channel not successful for FT pre-auth",
__func__);)
goto preauth_fail;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOG2(limLog(pMac,LOG2,"Entered wait auth2 state for FT"
" (old session %pK)", psessionEntry);)
#endif
if (psessionEntry->is11Rconnection) {
/* Now we are on the right channel and need to send out Auth1 and
* receive Auth2
*/
authFrame.authAlgoNumber = eSIR_FT_AUTH;
}
#if defined FEATURE_WLAN_ESE || defined FEATURE_WLAN_LFR
else {
/* Will need to make isESEconnection a enum may be for further
* improvements to this to match this algorithm number
*/
authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM;
}
#endif
authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
authFrame.authStatusCode = 0;
pMac->lim.limTimers.g_lim_periodic_auth_retry_timer.sessionId =
psessionEntry->peSessionId;
/* Start timer here to come back to operating channel */
pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId =
psessionEntry->peSessionId;
if(TX_SUCCESS !=
tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog( pMac, LOGE, FL("FT Auth Rsp Timer Start Failed"));)
#endif
goto preauth_fail;
}
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId,
eLIM_FT_PREAUTH_RSP_TIMER));
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOG1(limLog( pMac, LOG1, FL("FT Auth Rsp Timer Started"));)
#endif
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT,
pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS);
#endif
limSendAuthMgmtFrame(pMac, &authFrame,
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId,
LIM_NO_WEP_IN_FC, psessionEntry, eSIR_TRUE);
return;
preauth_fail:
limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
return;
}
/*------------------------------------------------------------------
*
* Create the new Add Bss Req to the new AP.
* This will be used when we are ready to FT to the new AP.
* The newly created ft Session entry is passed to this function
*
*------------------------------------------------------------------*/
tSirRetStatus limFTPrepareAddBssReq( tpAniSirGlobal pMac,
tANI_U8 updateEntry, tpPESession pftSessionEntry,
tpSirBssDescription bssDescription )
{
tpAddBssParams pAddBssParams = NULL;
tANI_U8 chanWidthSupp = 0;
tSchBeaconStruct *pBeaconStruct;
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(pftSessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return eSIR_FAILURE;
}
pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct));
if (NULL == pBeaconStruct) {
limLog(pMac, LOGE,
FL("Unable to allocate memory for creating ADD_BSS") );
return eSIR_MEM_ALLOC_FAILED;
}
// Package SIR_HAL_ADD_BSS_REQ message parameters
pAddBssParams = vos_mem_malloc(sizeof( tAddBssParams ));
if (NULL == pAddBssParams) {
vos_mem_free(pBeaconStruct);
limLog( pMac, LOGP,
FL( "Unable to allocate memory for creating ADD_BSS" ));
return (eSIR_MEM_ALLOC_FAILED);
}
vos_mem_set((tANI_U8 *) pAddBssParams, sizeof( tAddBssParams ), 0);
limExtractApCapabilities(pMac,
(tANI_U8 *) bssDescription->ieFields,
GET_IE_LEN_IN_BSS(bssDescription->length), pBeaconStruct);
if (pMac->lim.gLimProtectionControl !=
WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, pftSessionEntry);
vos_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
sizeof(tSirMacAddr));
// Fill in tAddBssParams selfMacAddr
vos_mem_copy(pAddBssParams->selfMacAddr, pftSessionEntry->selfMacAddr,
sizeof(tSirMacAddr));
pAddBssParams->bssType = pftSessionEntry->bssType;
pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA;
pAddBssParams->beaconInterval = bssDescription->beaconInterval;
pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
pAddBssParams->updateBss = updateEntry;
pAddBssParams->reassocReq = true;
pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount;
pAddBssParams->cfParamSet.cfpPeriod = pBeaconStruct->cfParamSet.cfpPeriod;
pAddBssParams->cfParamSet.cfpMaxDuration =
pBeaconStruct->cfParamSet.cfpMaxDuration;
pAddBssParams->cfParamSet.cfpDurRemaining =
pBeaconStruct->cfParamSet.cfpDurRemaining;
pAddBssParams->rateSet.numRates = pBeaconStruct->supportedRates.numRates;
vos_mem_copy(pAddBssParams->rateSet.rate,
pBeaconStruct->supportedRates.rate,
pBeaconStruct->supportedRates.numRates);
pAddBssParams->nwType = bssDescription->nwType;
pAddBssParams->shortSlotTimeSupported =
(tANI_U8)pBeaconStruct->capabilityInfo.shortSlotTime;
pAddBssParams->llaCoexist =
(tANI_U8) pftSessionEntry->beaconParams.llaCoexist;
pAddBssParams->llbCoexist =
(tANI_U8) pftSessionEntry->beaconParams.llbCoexist;
pAddBssParams->llgCoexist =
(tANI_U8) pftSessionEntry->beaconParams.llgCoexist;
pAddBssParams->ht20Coexist =
(tANI_U8) pftSessionEntry->beaconParams.ht20Coexist;
#ifdef WLAN_FEATURE_11W
pAddBssParams->rmfEnabled = pftSessionEntry->limRmfEnabled;
#endif
// Use the advertised capabilities from the received beacon/PR
if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) &&
( pBeaconStruct->HTCaps.present ))
{
pAddBssParams->htCapable = pBeaconStruct->HTCaps.present;
vos_mem_copy(&pAddBssParams->staContext.capab_info,
&pBeaconStruct->capabilityInfo,
sizeof(pAddBssParams->staContext.capab_info));
vos_mem_copy(&pAddBssParams->staContext.ht_caps,
(tANI_U8 *)&pBeaconStruct->HTCaps + sizeof(tANI_U8),
sizeof(pAddBssParams->staContext.ht_caps));
if ( pBeaconStruct->HTInfo.present )
{
pAddBssParams->htOperMode =
(tSirMacHTOperatingMode)pBeaconStruct->HTInfo.opMode;
pAddBssParams->dualCTSProtection =
( tANI_U8 ) pBeaconStruct->HTInfo.dualCTSProtection;
chanWidthSupp = limGetHTCapability( pMac,
eHT_SUPPORTED_CHANNEL_WIDTH_SET,
pftSessionEntry);
if( (pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
(chanWidthSupp) )
{
pAddBssParams->txChannelWidthSet =
( tANI_U8 ) pBeaconStruct->HTInfo.recommendedTxWidthSet;
pAddBssParams->currentExtChannel =
pBeaconStruct->HTInfo.secondaryChannelOffset;
}
else
{
pAddBssParams->txChannelWidthSet =
WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
pAddBssParams->currentExtChannel = PHY_SINGLE_CHANNEL_CENTERED;
}
pAddBssParams->llnNonGFCoexist =
(tANI_U8)pBeaconStruct->HTInfo.nonGFDevicesPresent;
pAddBssParams->fLsigTXOPProtectionFullSupport =
(tANI_U8)pBeaconStruct->HTInfo.lsigTXOPProtectionFullSupport;
pAddBssParams->fRIFSMode = pBeaconStruct->HTInfo.rifsMode;
}
}
pAddBssParams->currentOperChannel = bssDescription->channelId;
pftSessionEntry->htSecondaryChannelOffset =
pAddBssParams->currentExtChannel;
#ifdef WLAN_FEATURE_11AC
if (pftSessionEntry->vhtCapability &&
pftSessionEntry->vhtCapabilityPresentInBeacon)
{
pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present;
pAddBssParams->vhtTxChannelWidthSet =
pBeaconStruct->VHTOperation.chanWidth;
pAddBssParams->currentExtChannel =
limGet11ACPhyCBState(pMac,
pAddBssParams->currentOperChannel,
pAddBssParams->currentExtChannel,
pftSessionEntry->apCenterChan,
pftSessionEntry);
pAddBssParams->staContext.vht_caps =
((pBeaconStruct->VHTCaps.maxMPDULen <<
SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
(pBeaconStruct->VHTCaps.supportedChannelWidthSet <<
SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
(pBeaconStruct->VHTCaps.ldpcCodingCap <<
SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
(pBeaconStruct->VHTCaps.shortGI80MHz <<
SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
(pBeaconStruct->VHTCaps.shortGI160and80plus80MHz <<
SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
(pBeaconStruct->VHTCaps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) |
(pBeaconStruct->VHTCaps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) |
(pBeaconStruct->VHTCaps.suBeamFormerCap <<
SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
(pBeaconStruct->VHTCaps.suBeamformeeCap <<
SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
(pBeaconStruct->VHTCaps.csnofBeamformerAntSup <<
SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
(pBeaconStruct->VHTCaps.numSoundingDim <<
SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
(pBeaconStruct->VHTCaps.muBeamformerCap <<
SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP)|
(pBeaconStruct->VHTCaps.muBeamformeeCap <<
SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
(pBeaconStruct->VHTCaps.vhtTXOPPS << SIR_MAC_VHT_CAP_TXOPPS) |
(pBeaconStruct->VHTCaps.htcVHTCap << SIR_MAC_VHT_CAP_HTC_CAP) |
(pBeaconStruct->VHTCaps.maxAMPDULenExp <<
SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
(pBeaconStruct->VHTCaps.vhtLinkAdaptCap <<
SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
(pBeaconStruct->VHTCaps.rxAntPattern <<
SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
(pBeaconStruct->VHTCaps.txAntPattern <<
SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
(pBeaconStruct->VHTCaps.reserved1 << SIR_MAC_VHT_CAP_RESERVED2));
}
else
{
pAddBssParams->vhtCapable = 0;
}
#endif
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog( pMac, LOG1, FL( "SIR_HAL_ADD_BSS_REQ with channel = %d..." ),
pAddBssParams->currentOperChannel);
#endif
// Populate the STA-related parameters here
// Note that the STA here refers to the AP
{
pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
vos_mem_copy(pAddBssParams->staContext.bssId,
bssDescription->bssId,
sizeof(tSirMacAddr));
pAddBssParams->staContext.listenInterval =
bssDescription->beaconInterval;
pAddBssParams->staContext.assocId = 0;
pAddBssParams->staContext.uAPSD = 0;
pAddBssParams->staContext.maxSPLen = 0;
pAddBssParams->staContext.shortPreambleSupported =
(tANI_U8)pBeaconStruct->capabilityInfo.shortPreamble;
pAddBssParams->staContext.updateSta = updateEntry;
pAddBssParams->staContext.encryptType = pftSessionEntry->encryptType;
#ifdef WLAN_FEATURE_11W
pAddBssParams->staContext.rmfEnabled = pftSessionEntry->limRmfEnabled;
#endif
if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) &&
( pBeaconStruct->HTCaps.present )) {
pAddBssParams->staContext.us32MaxAmpduDuration = 0;
pAddBssParams->staContext.htCapable = 1;
pAddBssParams->staContext.greenFieldCapable =
( tANI_U8 ) pBeaconStruct->HTCaps.greenField;
pAddBssParams->staContext.lsigTxopProtection =
( tANI_U8 ) pBeaconStruct->HTCaps.lsigTXOPProtection;
if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
(chanWidthSupp)) {
pAddBssParams->staContext.txChannelWidthSet =
( tANI_U8 )pBeaconStruct->HTInfo.recommendedTxWidthSet;
}
else {
pAddBssParams->staContext.txChannelWidthSet =
WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
}
#ifdef WLAN_FEATURE_11AC
if (pftSessionEntry->vhtCapability &&
IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps))
{
pAddBssParams->staContext.vhtCapable = 1;
if ((pBeaconStruct->VHTCaps.suBeamFormerCap ||
pBeaconStruct->VHTCaps.muBeamformerCap) &&
pftSessionEntry->txBFIniFeatureEnabled)
{
pAddBssParams->staContext.vhtTxBFCapable = 1;
}
}
#endif
if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
(chanWidthSupp))
{
pAddBssParams->staContext.txChannelWidthSet =
(tANI_U8)pBeaconStruct->HTInfo.recommendedTxWidthSet;
#ifdef WLAN_FEATURE_11AC
if (pAddBssParams->staContext.vhtCapable)
{
pAddBssParams->staContext.vhtTxChannelWidthSet =
pBeaconStruct->VHTOperation.chanWidth;
}
#endif
}
else
{
pAddBssParams->staContext.txChannelWidthSet =
WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
}
pAddBssParams->staContext.mimoPS =
(tSirMacHTMIMOPowerSaveState)pBeaconStruct->HTCaps.mimoPowerSave;
pAddBssParams->staContext.delBASupport =
( tANI_U8 ) pBeaconStruct->HTCaps.delayedBA;
pAddBssParams->staContext.maxAmsduSize =
( tANI_U8 ) pBeaconStruct->HTCaps.maximalAMSDUsize;
pAddBssParams->staContext.maxAmpduDensity =
pBeaconStruct->HTCaps.mpduDensity;
pAddBssParams->staContext.fDsssCckMode40Mhz =
(tANI_U8)pBeaconStruct->HTCaps.dsssCckMode40MHz;
pAddBssParams->staContext.fShortGI20Mhz =
(tANI_U8)pBeaconStruct->HTCaps.shortGI20MHz;
pAddBssParams->staContext.fShortGI40Mhz =
(tANI_U8)pBeaconStruct->HTCaps.shortGI40MHz;
pAddBssParams->staContext.maxAmpduSize =
pBeaconStruct->HTCaps.maxRxAMPDUFactor;
if( pBeaconStruct->HTInfo.present )
pAddBssParams->staContext.rifsMode =
pBeaconStruct->HTInfo.rifsMode;
}
if ((pftSessionEntry->limWmeEnabled && pBeaconStruct->wmeEdcaPresent) ||
(pftSessionEntry->limQosEnabled && pBeaconStruct->edcaPresent))
pAddBssParams->staContext.wmmEnabled = 1;
else
pAddBssParams->staContext.wmmEnabled = 0;
pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent;
/* For OSEN Connection AP does not advertise RSN or WPA IE
* so from the IEs we get from supplicant we get this info
* so for FW to transmit EAPOL message 4 we shall set
* wpa_rsn
*/
pAddBssParams->staContext.wpa_rsn |= (pBeaconStruct->wpaPresent << 1);
if ((!pAddBssParams->staContext.wpa_rsn) &&
(pftSessionEntry->isOSENConnection))
pAddBssParams->staContext.wpa_rsn = 1;
//Update the rates
#ifdef WLAN_FEATURE_11AC
limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates,
pBeaconStruct->HTCaps.supportedMCSSet,
false,pftSessionEntry,&pBeaconStruct->VHTCaps);
#else
limPopulatePeerRateSet(pMac, &pAddBssParams->staContext.supportedRates,
beaconStruct.HTCaps.supportedMCSSet, false,pftSessionEntry);
#endif
if (pftSessionEntry->htCapability)
{
pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11n;
if (pftSessionEntry->vhtCapability)
pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11ac;
}
else
{
if (pftSessionEntry->limRFBand == SIR_BAND_5_GHZ)
{
pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11a;
}
else
{
pAddBssParams->staContext.supportedRates.opRateMode = eSTA_11bg;
}
}
}
#if defined WLAN_FEATURE_VOWIFI
pAddBssParams->maxTxPower = pftSessionEntry->maxTxPower;
#endif
#ifdef WLAN_FEATURE_11W
if (pftSessionEntry->limRmfEnabled)
{
pAddBssParams->rmfEnabled = 1;
pAddBssParams->staContext.rmfEnabled = 1;
}
#endif
pAddBssParams->status = eHAL_STATUS_SUCCESS;
pAddBssParams->respReqd = true;
pAddBssParams->staContext.sessionId = pftSessionEntry->peSessionId;
pAddBssParams->staContext.smesessionId = pftSessionEntry->smeSessionId;
pAddBssParams->sessionId = pftSessionEntry->peSessionId;
// Set a new state for MLME
pftSessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, pftSessionEntry->peSessionId,
eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE));
pAddBssParams->halPersona=(tANI_U8)pftSessionEntry->pePersona;
pftSessionEntry->ftPEContext.pAddBssReq = pAddBssParams;
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog( pMac, LOG1, FL( "Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap..." ));
#endif
vos_mem_free(pBeaconStruct);
return 0;
}
/*------------------------------------------------------------------
*
* Setup the new session for the pre-auth AP.
* Return the newly created session entry.
*
*------------------------------------------------------------------*/
void limFillFTSession(tpAniSirGlobal pMac,
tpSirBssDescription pbssDescription,
tpPESession pftSessionEntry,
tpPESession psessionEntry)
{
tANI_U8 currentBssUapsd;
tPowerdBm localPowerConstraint;
tPowerdBm regMax;
tSchBeaconStruct *pBeaconStruct;
ePhyChanBondState cbEnabledMode;
#ifdef WLAN_FEATURE_11W
VOS_STATUS vosStatus;
#endif
pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct));
if (NULL == pBeaconStruct) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog(pMac, LOGE,
FL("Unable to allocate memory for creating limFillFTSession") );
#endif
return;
}
/* Retrieve the session that has already been created and update the entry */
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
limPrintMacAddr(pMac, pbssDescription->bssId, LOG1);
#endif
pftSessionEntry->limWmeEnabled = psessionEntry->limWmeEnabled;
pftSessionEntry->limQosEnabled = psessionEntry->limQosEnabled;
pftSessionEntry->limWsmEnabled = psessionEntry->limWsmEnabled;
pftSessionEntry->lim11hEnable = psessionEntry->lim11hEnable;
pftSessionEntry->isOSENConnection = psessionEntry->isOSENConnection;
// Fields to be filled later
pftSessionEntry->pLimJoinReq = NULL;
pftSessionEntry->smeSessionId = psessionEntry->smeSessionId;
pftSessionEntry->transactionId = 0;
limExtractApCapabilities(pMac,
(tANI_U8 *)pbssDescription->ieFields,
GET_IE_LEN_IN_BSS(pbssDescription->length),
pBeaconStruct);
pftSessionEntry->rateSet.numRates = pBeaconStruct->supportedRates.numRates;
vos_mem_copy(pftSessionEntry->rateSet.rate,
pBeaconStruct->supportedRates.rate, pBeaconStruct->supportedRates.numRates);
pftSessionEntry->extRateSet.numRates = pBeaconStruct->extendedRates.numRates;
vos_mem_copy(pftSessionEntry->extRateSet.rate,
pBeaconStruct->extendedRates.rate, pftSessionEntry->extRateSet.numRates);
pftSessionEntry->ssId.length = pBeaconStruct->ssId.length;
vos_mem_copy(pftSessionEntry->ssId.ssId, pBeaconStruct->ssId.ssId,
pftSessionEntry->ssId.length);
pftSessionEntry->dot11mode =
psessionEntry->ftPEContext.pFTPreAuthReq->dot11mode;
limLog(pMac, LOG1, FL("dot11mode %d"), pftSessionEntry->dot11mode);
pftSessionEntry->vhtCapability =
(IS_DOT11_MODE_VHT(pftSessionEntry->dot11mode)
&& IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps));
pftSessionEntry->htCapability = (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode)
&& pBeaconStruct->HTCaps.present);
#ifdef WLAN_FEATURE_11AC
if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && pBeaconStruct->VHTOperation.present)
{
pftSessionEntry->vhtCapabilityPresentInBeacon = 1;
pftSessionEntry->apCenterChan =
pBeaconStruct->VHTOperation.chanCenterFreqSeg1;
pftSessionEntry->apChanWidth = pBeaconStruct->VHTOperation.chanWidth;
}
else
{
pftSessionEntry->vhtCapabilityPresentInBeacon = 0;
}
#endif
sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr);
sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId);
sirCopyMacAddr(pftSessionEntry->prev_ap_bssid, psessionEntry->bssId);
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
limPrintMacAddr(pMac, pftSessionEntry->limReAssocbssId, LOG1);
#endif
/* Store beaconInterval */
pftSessionEntry->beaconParams.beaconInterval =
pbssDescription->beaconInterval;
pftSessionEntry->bssType = psessionEntry->bssType;
pftSessionEntry->statypeForBss = STA_ENTRY_PEER;
pftSessionEntry->nwType = pbssDescription->nwType;
/* Copy The channel Id to the session Table */
pftSessionEntry->limReassocChannelId = pbssDescription->channelId;
pftSessionEntry->currentOperChannel = pbssDescription->channelId;
if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE)
{
pftSessionEntry->limSystemRole = eLIM_STA_ROLE;
}
else if(pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE)
{
pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE;
}
else
{
/* Throw an error and return and make sure to delete the session.*/
limLog(pMac, LOGE, FL("Invalid bss type"));
}
pftSessionEntry->limCurrentBssCaps = pbssDescription->capabilityInfo;
pftSessionEntry->limReassocBssCaps = pbssDescription->capabilityInfo;
if( pMac->roam.configParam.shortSlotTime &&
SIR_MAC_GET_SHORT_SLOT_TIME(pftSessionEntry->limReassocBssCaps))
{
pftSessionEntry->shortSlotTimeSupported = TRUE;
}
regMax = cfgGetRegulatoryMaxTransmitPower(pMac,
pftSessionEntry->currentOperChannel );
localPowerConstraint = regMax;
limExtractApCapability( pMac, (tANI_U8 *) pbssDescription->ieFields,
GET_IE_LEN_IN_BSS(pbssDescription->length),
&pftSessionEntry->limCurrentBssQosCaps,
&pftSessionEntry->limCurrentBssPropCap,
&currentBssUapsd , &localPowerConstraint, pftSessionEntry);
pftSessionEntry->limReassocBssQosCaps =
pftSessionEntry->limCurrentBssQosCaps;
pftSessionEntry->limReassocBssPropCap =
pftSessionEntry->limCurrentBssPropCap;
#ifdef WLAN_FEATURE_VOWIFI_11R
pftSessionEntry->is11Rconnection = psessionEntry->is11Rconnection;
#endif
#ifdef FEATURE_WLAN_ESE
pftSessionEntry->isESEconnection = psessionEntry->isESEconnection;
pftSessionEntry->is_ese_version_ie_present =
pBeaconStruct->is_ese_ver_ie_present;
#endif
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
pftSessionEntry->isFastTransitionEnabled =
psessionEntry->isFastTransitionEnabled;
#endif
#ifdef FEATURE_WLAN_LFR
pftSessionEntry->isFastRoamIniFeatureEnabled =
psessionEntry->isFastRoamIniFeatureEnabled;
#endif
#ifdef FEATURE_WLAN_ESE
pftSessionEntry->maxTxPower =
limGetMaxTxPower(regMax, localPowerConstraint,
pMac->roam.configParam.nTxPowerCap);
#else
pftSessionEntry->maxTxPower = VOS_MIN( regMax , (localPowerConstraint) );
#endif
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog(pMac, LOG1,
FL("Reg max = %d, local power = %d, ini tx power = %d, max tx = %d"),
regMax, localPowerConstraint, pMac->roam.configParam.nTxPowerCap,
pftSessionEntry->maxTxPower);
#endif
pftSessionEntry->limRFBand =
limGetRFBand(pftSessionEntry->currentOperChannel);
pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState;
pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, pftSessionEntry->peSessionId,
pftSessionEntry->limSmeState));
pftSessionEntry->encryptType = psessionEntry->encryptType;
#ifdef WLAN_FEATURE_11W
pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled;
if (pftSessionEntry->limRmfEnabled) {
pftSessionEntry->pmfComebackTimerInfo.pMac = pMac;
pftSessionEntry->pmfComebackTimerInfo.sessionID =
psessionEntry->smeSessionId;
vosStatus = vos_timer_init(&pftSessionEntry->pmfComebackTimer,
VOS_TIMER_TYPE_SW,
limPmfComebackTimerCallback,
(void *)&pftSessionEntry->pmfComebackTimerInfo);
if (VOS_STATUS_SUCCESS != vosStatus) {
limLog(pMac, LOGP,
FL("cannot init pmf comeback timer."));
}
}
#endif
if (pftSessionEntry->limRFBand == SIR_BAND_2_4_GHZ)
{
cbEnabledMode = pMac->roam.configParam.channelBondingMode24GHz;
}
else
{
cbEnabledMode = pMac->roam.configParam.channelBondingMode5GHz;
}
pftSessionEntry->htSupportedChannelWidthSet =
(pBeaconStruct->HTInfo.present)?
(cbEnabledMode && pBeaconStruct->HTInfo.recommendedTxWidthSet):0;
pftSessionEntry->htRecommendedTxWidthSet =
pftSessionEntry->htSupportedChannelWidthSet;
pftSessionEntry->enableHtSmps = psessionEntry->enableHtSmps;
pftSessionEntry->htSmpsvalue = psessionEntry->htSmpsvalue;
/*
* By default supported NSS 1x1 is set to true
* and later on updated while determining session
* supported rates which is the intersection of
* self and peer rates
*/
pftSessionEntry->supported_nss_1x1 = true;
limLog(pMac, LOG1,
FL("FT enable smps: %d mode: %d supported nss 1x1: %d"),
pftSessionEntry->enableHtSmps,
pftSessionEntry->htSmpsvalue,
pftSessionEntry->supported_nss_1x1);
vos_mem_free(pBeaconStruct);
}
/*------------------------------------------------------------------
*
* Setup the session and the add bss req for the pre-auth AP.
*
*------------------------------------------------------------------*/
tSirRetStatus limFTSetupAuthSession(tpAniSirGlobal pMac,
tpPESession psessionEntry)
{
tpPESession pftSessionEntry = NULL;
tANI_U8 sessionId = 0;
pftSessionEntry =
peFindSessionByBssid(pMac, psessionEntry->limReAssocbssId, &sessionId);
if (pftSessionEntry == NULL) {
PELOGE(limLog(pMac, LOGE,
FL("Unable to find session for the following bssid"));)
limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE);
return eSIR_FAILURE;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return eSIR_FAILURE;
}
if (psessionEntry->ftPEContext.pFTPreAuthReq &&
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
limFillFTSession(pMac,
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription,
pftSessionEntry,
psessionEntry);
limFTPrepareAddBssReq( pMac, FALSE, pftSessionEntry,
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription );
}
return eSIR_SUCCESS;
}
/*------------------------------------------------------------------
* Resume Link Call Back
*------------------------------------------------------------------*/
void limFTProcessPreAuthResult(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data)
{
tpPESession psessionEntry = (tpPESession)data;
if (NULL == psessionEntry ||
NULL == psessionEntry->ftPEContext.pFTPreAuthReq)
return;
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) {
psessionEntry->ftPEContext.ftPreAuthStatus =
limFTSetupAuthSession(pMac, psessionEntry);
}
// Post the FT Pre Auth Response to SME
limPostFTPreAuthRsp(pMac, psessionEntry->ftPEContext.ftPreAuthStatus,
psessionEntry->ftPEContext.saved_auth_rsp,
psessionEntry->ftPEContext.saved_auth_rsp_length, psessionEntry);
}
/*------------------------------------------------------------------
* Resume Link Call Back
*------------------------------------------------------------------*/
void limPerformPostFTPreAuthAndChannelChange(tpAniSirGlobal pMac,
eHalStatus status,
tANI_U32 *data,
tpPESession psessionEntry)
{
/* Set the resume channel to Any valid channel (invalid)
* This will instruct HAL to set it to any previous valid channel.
*/
peSetResumeChannel(pMac, 0, 0);
limResumeLink(pMac, limFTProcessPreAuthResult, (tANI_U32 *)psessionEntry);
}
/*------------------------------------------------------------------
*
* Will post pre auth response to SME.
*
*------------------------------------------------------------------*/
void limPostFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status,
tANI_U8 *auth_rsp, tANI_U16 auth_rsp_length,
tpPESession psessionEntry)
{
tpSirFTPreAuthRsp pFTPreAuthRsp;
tSirMsgQ mmhMsg;
tANI_U16 rspLen = sizeof(tSirFTPreAuthRsp);
pFTPreAuthRsp = (tpSirFTPreAuthRsp)vos_mem_malloc(rspLen);
if (NULL == pFTPreAuthRsp) {
PELOGE(limLog( pMac, LOGE, "Failed to allocate memory");)
VOS_ASSERT(pFTPreAuthRsp != NULL);
return;
}
vos_mem_zero( pFTPreAuthRsp, rspLen);
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog( pMac, LOG1, FL("Auth Rsp = %pK"), pFTPreAuthRsp);)
#endif
if (psessionEntry) {
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
vos_mem_free(pFTPreAuthRsp);
return;
}
pFTPreAuthRsp->smeSessionId = psessionEntry->smeSessionId;
/* The bssid of the AP we are sending Auth1 to. */
if (psessionEntry->ftPEContext.pFTPreAuthReq)
sirCopyMacAddr(pFTPreAuthRsp->preAuthbssId,
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId);
}
pFTPreAuthRsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP;
pFTPreAuthRsp->length = (tANI_U16) rspLen;
pFTPreAuthRsp->status = status;
/* Attach the auth response now back to SME */
pFTPreAuthRsp->ft_ies_length = 0;
if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) {
/* Only 11r assoc has FT IEs */
vos_mem_copy(pFTPreAuthRsp->ft_ies, auth_rsp, auth_rsp_length);
pFTPreAuthRsp->ft_ies_length = auth_rsp_length;
}
if (status != eSIR_SUCCESS) {
/* Ensure that on Pre-Auth failure the cached Pre-Auth Req and
* other allocated memory is freed up before returning.
*/
limLog(pMac, LOG1, "Pre-Auth Failed, Cleanup!");
limFTCleanup(pMac, psessionEntry);
}
mmhMsg.type = pFTPreAuthRsp->messageType;
mmhMsg.bodyptr = pFTPreAuthRsp;
mmhMsg.bodyval = 0;
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog( pMac, LOG1,
"Posted Auth Rsp to SME with status of 0x%x", status);)
#endif
#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT
if (status == eSIR_SUCCESS)
limDiagEventReport(pMac, WLAN_PE_DIAG_PREAUTH_DONE, psessionEntry,
status, 0);
#endif
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
}
/*------------------------------------------------------------------
*
* Send the FT Pre Auth Response to SME whenever we have a status
* ready to be sent to SME
*
* SME will be the one to send it up to the supplicant to receive
* FTIEs which will be required for Reassoc Req.
*
*------------------------------------------------------------------*/
void limHandleFTPreAuthRsp(tpAniSirGlobal pMac, tSirRetStatus status,
tANI_U8 *auth_rsp, tANI_U16 auth_rsp_length,
tpPESession psessionEntry)
{
tpPESession pftSessionEntry = NULL;
tANI_U8 sessionId = 0;
tpSirBssDescription pbssDescription = NULL;
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT,
psessionEntry, (tANI_U16)status, 0);
#endif
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
/* Save the status of pre-auth */
psessionEntry->ftPEContext.ftPreAuthStatus = status;
/* Save the auth rsp, so we can send it to
* SME once we resume link
*/
psessionEntry->ftPEContext.saved_auth_rsp_length = 0;
if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) {
vos_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp,
auth_rsp, auth_rsp_length);
psessionEntry->ftPEContext.saved_auth_rsp_length =
auth_rsp_length;
}
if (!psessionEntry->ftPEContext.pFTPreAuthReq ||
!psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
limLog(pMac, LOGE,
FL("pFTPreAuthReq or pbssDescription is NULL"));
return;
}
/* Create FT session for the re-association at this point */
if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) {
pbssDescription =
psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription;
limPrintMacAddr(pMac, pbssDescription->bssId, LOG1);
if((pftSessionEntry =
peCreateSession(pMac, pbssDescription->bssId,
&sessionId, pMac->lim.maxStation,
psessionEntry->bssType)) == NULL) {
limLog(pMac, LOGE,
FL("Session Can not be created for pre-auth 11R AP"));
status = eSIR_FAILURE;
psessionEntry->ftPEContext.ftPreAuthStatus = status;
goto send_rsp;
}
pftSessionEntry->peSessionId = sessionId;
pftSessionEntry->smeSessionId = psessionEntry->smeSessionId;
sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr);
sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId);
pftSessionEntry->bssType = psessionEntry->bssType;
if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) {
pftSessionEntry->limSystemRole = eLIM_STA_ROLE;
}
else if(pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE;
}
else {
limLog(pMac, LOGE, FL("Invalid bss type"));
}
pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState;
vos_mem_copy(&(pftSessionEntry->htConfig), &(psessionEntry->htConfig),
sizeof(psessionEntry->htConfig));
pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
pftSessionEntry->smpsMode = psessionEntry->smpsMode;
if (IS_5G_CH(psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum))
pftSessionEntry->vdev_nss = pMac->vdev_type_nss_5g.sta;
else
pftSessionEntry->vdev_nss = pMac->vdev_type_nss_2g.sta;
PELOGE(limLog(pMac, LOG1, "%s:created session (%pK) with id = %d",
__func__, pftSessionEntry, pftSessionEntry->peSessionId);)
/* Update the ReAssoc BSSID of the current session */
sirCopyMacAddr(psessionEntry->limReAssocbssId, pbssDescription->bssId);
limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOG1);
}
send_rsp:
if ((psessionEntry->currentOperChannel !=
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum)
|| limIsInMCC(pMac)) {
/* Need to move to the original AP channel */
limChangeChannelWithCallback(pMac, psessionEntry->currentOperChannel,
limPerformPostFTPreAuthAndChannelChange,
NULL, psessionEntry);
}
else {
#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog( pMac, LOG1,
"Pre auth on same channel as connected AP channel %d",
psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum);)
#endif
limFTProcessPreAuthResult(pMac, status, (tANI_U32 *)psessionEntry);
}
}
/**
* lim_ft_reassoc_set_link_state_callback()- registered callback to perform post
* peer creation operations
*
* @mac: pointer to global mac structure
* @callback_arg: registered callback argument
* @status: peer creation status
*
* this is registered callback function during ft reassoc scenario to perform
* post peer creation operation based on the peer creation status
*
* Return: none
*/
void lim_ft_reassoc_set_link_state_callback(tpAniSirGlobal mac,
void *callback_arg, bool status)
{
tpPESession session_entry;
tSirMsgQ msg_q;
tLimMlmReassocReq *mlm_reassoc_req = (tLimMlmReassocReq *) callback_arg;
tSirRetStatus ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
tLimMlmReassocCnf mlm_reassoc_cnf = {0};
session_entry = peFindSessionBySessionId(mac,
mlm_reassoc_req->sessionId);
if (!status || !session_entry) {
limLog(mac, LOGE, FL("Failed: session:%pK for session id:%d status:%d"),
session_entry, mlm_reassoc_req->sessionId, status);
goto failure;
}
/*
* we need to defer the message until we get the
* response back from HAL
*/
SET_LIM_PROCESS_DEFD_MESGS(mac, false);
msg_q.type = SIR_HAL_ADD_BSS_REQ;
msg_q.reserved = 0;
msg_q.bodyptr = session_entry->ftPEContext.pAddBssReq;
msg_q.bodyval = 0;
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
limLog(mac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ..."));
#endif
MTRACE(macTraceMsgTx(mac, session_entry->peSessionId, msg_q.type));
ret_code = wdaPostCtrlMsg(mac, &msg_q);
if(eSIR_SUCCESS != ret_code) {
vos_mem_free(session_entry->ftPEContext.pAddBssReq);
limLog(mac, LOGE, FL("Post ADD_BSS_REQ failed reason=%X"),
ret_code);
session_entry->ftPEContext.pAddBssReq = NULL;
goto failure;
}
session_entry->pLimMlmReassocReq = mlm_reassoc_req;
session_entry->ftPEContext.pAddBssReq = NULL;
return;
failure:
vos_mem_free(mlm_reassoc_req);
mlm_reassoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
mlm_reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
/* Update PE session Id*/
if (session_entry)
mlm_reassoc_cnf.sessionId = session_entry->peSessionId;
limPostSmeMessage(mac, LIM_MLM_REASSOC_CNF,
(tANI_U32 *) &mlm_reassoc_cnf);
}
/*------------------------------------------------------------------
*
* This function handles the 11R Reassoc Req from SME
*
*------------------------------------------------------------------*/
void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf,
tpPESession psessionEntry)
{
tANI_U8 smeSessionId = 0;
tANI_U16 transactionId = 0;
tANI_U8 chanNum = 0;
tLimMlmReassocReq *pMlmReassocReq;
tANI_U16 caps;
tANI_U32 val;
tANI_U32 teleBcnEn = 0;
tLimMlmReassocCnf mlm_reassoc_cnf = {0};
chanNum = psessionEntry->currentOperChannel;
limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId);
psessionEntry->smeSessionId = smeSessionId;
psessionEntry->transactionId = transactionId;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOCIATING, psessionEntry, 0, 0);
#endif
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
if (NULL == psessionEntry->ftPEContext.pAddBssReq) {
limLog(pMac, LOGE, FL("pAddBssReq is NULL"));
goto end;
}
pMlmReassocReq = vos_mem_malloc(sizeof(tLimMlmReassocReq));
if (NULL == pMlmReassocReq) {
limLog(pMac, LOGE,
FL("call to AllocateMemory failed for mlmReassocReq"));
goto end;
}
vos_mem_copy(pMlmReassocReq->peerMacAddr,
psessionEntry->bssId,
sizeof(tSirMacAddr));
if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT,
(tANI_U32 *) &pMlmReassocReq->reassocFailureTimeout)
!= eSIR_SUCCESS) {
/**
* Could not get ReassocFailureTimeout value
* from CFG. Log error.
*/
limLog(pMac, LOGE,
FL("could not retrieve ReassocFailureTimeout value"));
vos_mem_free(pMlmReassocReq);
goto end;
}
if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) {
/**
* Could not get Capabilities value
* from CFG. Log error.
*/
limLog(pMac, LOGE, FL("could not retrieve Capabilities value"));
vos_mem_free(pMlmReassocReq);
goto end;
}
lim_update_caps_info_for_bss(pMac, &caps,
psessionEntry->pLimReAssocReq->bssDescription.capabilityInfo);
limLog(pMac, LOG1, FL("Capabilities info FT Reassoc: 0x%X"), caps);
pMlmReassocReq->capabilityInfo = caps;
/* Update PE sessionId*/
pMlmReassocReq->sessionId = psessionEntry->peSessionId;
/* If telescopic beaconing is enabled, set listen interval
to WNI_CFG_TELE_BCN_MAX_LI
*/
if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) !=
eSIR_SUCCESS) {
limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN"));
vos_mem_free(pMlmReassocReq);
goto end;
}
if (teleBcnEn) {
if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS)
{
/**
* Could not get ListenInterval value
* from CFG. Log error.
*/
limLog(pMac, LOGE, FL("could not retrieve ListenInterval"));
vos_mem_free(pMlmReassocReq);
goto end;
}
}
else {
if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) {
/**
* Could not get ListenInterval value
* from CFG. Log error.
*/
limLog(pMac, LOGE, FL("could not retrieve ListenInterval"));
vos_mem_free(pMlmReassocReq);
goto end;
}
}
pMlmReassocReq->listenInterval = (tANI_U16) val;
if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId,
psessionEntry->selfMacAddr,
lim_ft_reassoc_set_link_state_callback,
pMlmReassocReq) != eSIR_SUCCESS) {
vos_mem_free(pMlmReassocReq);
goto end;
}
return;
end:
mlm_reassoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
mlm_reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
/* Update PE session Id*/
mlm_reassoc_cnf.sessionId = psessionEntry->peSessionId;
limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF,
(tANI_U32 *) &mlm_reassoc_cnf);
}
/*------------------------------------------------------------------
*
* This function is called if preauth response is not received from the AP
* within this timeout while FT in progress
*
*------------------------------------------------------------------*/
void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac)
{
tpPESession psessionEntry;
/* We have failed pre auth. We need to resume link and get back on
* home channel
*/
limLog(pMac, LOGE, FL("FT Pre-Auth Time Out!!!!"));
if ((psessionEntry =
peFindSessionBySessionId(pMac,
pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId)) == NULL) {
limLog(pMac, LOGE, FL("Session Does not exist for given sessionID"));
return;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
/* Reset the flag to indicate preauth request session */
psessionEntry->ftPEContext.ftPreAuthSession = VOS_FALSE;
if (NULL ==
psessionEntry->ftPEContext.pFTPreAuthReq) {
limLog(pMac,LOGE,FL("pFTPreAuthReq is NULL"));
return;
}
if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) {
limLog(pMac, LOGE, FL("Auth Rsp might already be posted to SME and "
"ftcleanup done! sessionId:%d"),
pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId);
return;
}
/* To handle the race condition where we recieve preauth rsp after
* timer has expired.
*/
if (eANI_BOOLEAN_TRUE ==
psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) {
limLog(pMac,LOGE,FL("Auth rsp already posted to SME"
" (session %pK)"), psessionEntry);
return;
}
else {
/* Here we are sending preauth rsp with failure state
* and which is forwarded to SME. Now, if we receive an preauth
* resp from AP with success it would create a FT pesession, but
* will be dropped in SME leaving behind the pesession.
* Mark Preauth rsp processed so that any rsp from AP is dropped in
* limProcessAuthFrameNoSession.
*/
limLog(pMac,LOG1,FL("Auth rsp not yet posted to SME"
" (session %pK)"), psessionEntry);
psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed =
eANI_BOOLEAN_TRUE;
}
/* Attempted at Pre-Auth and failed. If we are off channel. We need
* to get back to home channel
*/
limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
}
/*------------------------------------------------------------------
*
* This function is called to process the update key request from SME
*
*------------------------------------------------------------------*/
tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf )
{
tAddBssParams *pAddBssParams;
tSirFTUpdateKeyInfo *pKeyInfo;
tANI_U32 val = 0;
tpPESession psessionEntry;
tANI_U8 sessionId;
/* Sanity Check */
if( pMac == NULL || pMsgBuf == NULL )
{
return VOS_FALSE;
}
pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf;
psessionEntry =
peFindSessionByBssid(pMac, pKeyInfo->bssId, &sessionId);
if (NULL == psessionEntry)
{
PELOGE(limLog( pMac, LOGE,
"%s: Unable to find session for the following bssid",
__func__);)
limPrintMacAddr( pMac, pKeyInfo->bssId, LOGE );
return VOS_FALSE;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return VOS_FALSE;
}
if (NULL == psessionEntry->ftPEContext.pAddBssReq)
{
// AddBss Req is NULL, save the keys to configure them later.
tpLimMlmSetKeysReq pMlmSetKeysReq =
&psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParam;
vos_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq));
vos_mem_copy(pMlmSetKeysReq->peerMacAddr, pKeyInfo->bssId,
sizeof(tSirMacAddr));
pMlmSetKeysReq->sessionId = psessionEntry->peSessionId;
pMlmSetKeysReq->smesessionId = psessionEntry->smeSessionId;
pMlmSetKeysReq->edType = pKeyInfo->keyMaterial.edType;
pMlmSetKeysReq->numKeys = pKeyInfo->keyMaterial.numKeys;
vos_mem_copy((tANI_U8 *) &pMlmSetKeysReq->key,
(tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof(tSirKeys));
psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParamValid = TRUE;
limLog( pMac, LOGE, FL( "pAddBssReq is NULL" ));
if (psessionEntry->ftPEContext.pAddStaReq == NULL)
{
limLog( pMac, LOGE, FL( "pAddStaReq is NULL" ));
limSendSetStaKeyReq(pMac, pMlmSetKeysReq, 0, 0, psessionEntry,
FALSE);
psessionEntry->ftPEContext.PreAuthKeyInfo.extSetStaKeyParamValid =
FALSE;
}
}
else
{
pAddBssParams = psessionEntry->ftPEContext.pAddBssReq;
/* Store the key information in the ADD BSS parameters */
pAddBssParams->extSetStaKeyParamValid = 1;
pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType;
vos_mem_copy((tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key,
(tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof(tSirKeys));
if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val))
{
limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" ));
}
pAddBssParams->extSetStaKeyParam.singleTidRc = val;
PELOG1(limLog(pMac, LOG1, FL("Key valid %d, keyLength=%d"),
pAddBssParams->extSetStaKeyParamValid,
pAddBssParams->extSetStaKeyParam.key[0].keyLength);)
pAddBssParams->extSetStaKeyParam.staIdx = 0;
PELOG1(limLog(pMac, LOG1,
FL("BSSID = "MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pKeyInfo->bssId));)
sirCopyMacAddr(pAddBssParams->extSetStaKeyParam.peerMacAddr,
pKeyInfo->bssId);
pAddBssParams->extSetStaKeyParam.sendRsp = FALSE;
}
return TRUE;
}
void
limFTSendAggrQosRsp(tpAniSirGlobal pMac, tANI_U8 rspReqd,
tpAggrAddTsParams aggrQosRsp, tANI_U8 smesessionId)
{
tpSirAggrQosRsp rsp;
int i = 0;
if (! rspReqd)
{
return;
}
rsp = vos_mem_malloc(sizeof(tSirAggrQosRsp));
if (NULL == rsp)
{
limLog(pMac, LOGP, FL("AllocateMemory failed for tSirAggrQosRsp"));
return;
}
vos_mem_set((tANI_U8 *) rsp, sizeof(*rsp), 0);
rsp->messageType = eWNI_SME_FT_AGGR_QOS_RSP;
rsp->sessionId = smesessionId;
rsp->length = sizeof(*rsp);
rsp->aggrInfo.tspecIdx = aggrQosRsp->tspecIdx;
for( i = 0; i < SIR_QOS_NUM_AC_MAX; i++ )
{
if( (1 << i) & aggrQosRsp->tspecIdx )
{
rsp->aggrInfo.aggrRsp[i].status = aggrQosRsp->status[i];
rsp->aggrInfo.aggrRsp[i].tspec = aggrQosRsp->tspec[i];
}
}
limSendSmeAggrQosRsp(pMac, rsp, smesessionId);
return;
}
void limProcessFTAggrQoSRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
{
tpAggrAddTsParams pAggrQosRspMsg = NULL;
tAddTsParams addTsParam = {0};
tpDphHashNode pSta = NULL;
tANI_U16 assocId =0;
tSirMacAddr peerMacAddr;
tANI_U8 rspReqd = 1;
tpPESession psessionEntry = NULL;
int i = 0;
PELOG1(limLog(pMac, LOG1, FL(" Received AGGR_QOS_RSP from HAL"));)
/* Need to process all the deferred messages enqueued since sending the
SIR_HAL_AGGR_ADD_TS_REQ */
SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
pAggrQosRspMsg = (tpAggrAddTsParams) (limMsg->bodyptr);
if (NULL == pAggrQosRspMsg)
{
PELOGE(limLog(pMac, LOGE, FL("NULL pAggrQosRspMsg"));)
return;
}
psessionEntry = peFindSessionBySessionId(pMac, pAggrQosRspMsg->sessionId);
if (NULL == psessionEntry)
{
PELOGE(limLog(pMac, LOGE,
FL("Cant find session entry for %s"), __func__);)
if( pAggrQosRspMsg != NULL )
{
vos_mem_free(pAggrQosRspMsg);
}
return;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
return;
}
for( i = 0; i < HAL_QOS_NUM_AC_MAX; i++ )
{
if((((1 << i) & pAggrQosRspMsg->tspecIdx)) &&
(pAggrQosRspMsg->status[i] != eHAL_STATUS_SUCCESS))
{
/* send DELTS to the station */
sirCopyMacAddr(peerMacAddr,psessionEntry->bssId);
addTsParam.staIdx = pAggrQosRspMsg->staIdx;
addTsParam.sessionId = pAggrQosRspMsg->sessionId;
addTsParam.tspec = pAggrQosRspMsg->tspec[i];
addTsParam.tspecIdx = pAggrQosRspMsg->tspecIdx;
limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd,
&addTsParam.tspec.tsinfo,
&addTsParam.tspec, psessionEntry);
pSta = dphLookupAssocId(pMac, addTsParam.staIdx, &assocId,
&psessionEntry->dph.dphHashTable);
if (pSta != NULL)
{
limAdmitControlDeleteTS(pMac, assocId, &addTsParam.tspec.tsinfo,
NULL, (tANI_U8 *)&addTsParam.tspecIdx);
}
}
}
/* Send the Aggr QoS response to SME */
limFTSendAggrQosRsp(pMac, rspReqd, pAggrQosRspMsg,
psessionEntry->smeSessionId);
if( pAggrQosRspMsg != NULL )
{
vos_mem_free(pAggrQosRspMsg);
}
return;
}
tSirRetStatus
limProcessFTAggrQosReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf )
{
tSirMsgQ msg;
tSirAggrQosReq * aggrQosReq = (tSirAggrQosReq *)pMsgBuf;
tpAggrAddTsParams pAggrAddTsParam;
tpPESession psessionEntry = NULL;
tpLimTspecInfo tspecInfo;
tANI_U8 ac;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U8 sessionId;
int i;
pAggrAddTsParam = vos_mem_malloc(sizeof(tAggrAddTsParams));
if (NULL == pAggrAddTsParam)
{
PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));)
return eSIR_MEM_ALLOC_FAILED;
}
psessionEntry = peFindSessionByBssid(pMac, aggrQosReq->bssId, &sessionId);
if (psessionEntry == NULL) {
PELOGE(limLog(pMac, LOGE, FL("psession Entry Null for sessionId = %d"),
aggrQosReq->sessionId);)
vos_mem_free(pAggrAddTsParam);
return eSIR_FAILURE;
}
/* Nothing to be done if the session is not in STA mode */
if (!LIM_IS_STA_ROLE(psessionEntry)) {
#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));)
#endif
vos_mem_free(pAggrAddTsParam);
return eSIR_FAILURE;
}
pSta = dphLookupHashEntry(pMac, aggrQosReq->bssId, &aid,
&psessionEntry->dph.dphHashTable);
if (pSta == NULL)
{
PELOGE(limLog(pMac, LOGE,
FL("Station context not found - ignoring AddTsRsp"));)
vos_mem_free(pAggrAddTsParam);
return eSIR_FAILURE;
}
vos_mem_set((tANI_U8 *)pAggrAddTsParam,
sizeof(tAggrAddTsParams), 0);
pAggrAddTsParam->staIdx = psessionEntry->staId;
// Fill in the sessionId specific to PE
pAggrAddTsParam->sessionId = sessionId;
pAggrAddTsParam->tspecIdx = aggrQosReq->aggrInfo.tspecIdx;
for( i = 0; i < HAL_QOS_NUM_AC_MAX; i++ )
{
if (aggrQosReq->aggrInfo.tspecIdx & (1<<i))
{
tSirMacTspecIE *pTspec =
&aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
/* Since AddTS response was successful, check for the PSB flag
* and directional flag inside the TS Info field.
* An AC is trigger enabled AC if the PSB subfield is set to 1
* in the uplink direction.
* An AC is delivery enabled AC if the PSB subfield is set to 1
* in the downlink direction.
* An AC is trigger and delivery enabled AC if the PSB subfield
* is set to 1 in the bi-direction field.
*/
if(!pMac->psOffloadEnabled)
{
if (pTspec->tsinfo.traffic.psb == 1)
{
limSetTspecUapsdMask(pMac, &pTspec->tsinfo, SET_UAPSD_MASK);
}
else
{
limSetTspecUapsdMask(pMac, &pTspec->tsinfo,
CLEAR_UAPSD_MASK);
}
/*
* ADDTS success, so AC is now admitted.
* We shall now use the default
* EDCA parameters as advertised by AP and
* send the updated EDCA params
* to HAL.
*/
ac = upToAc(pTspec->tsinfo.traffic.userPrio);
if(pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
}
else if(pTspec->tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_DNLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
}
else if(pTspec->tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_BIDIR)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
}
}
else
{
if (pTspec->tsinfo.traffic.psb == 1)
{
limSetTspecUapsdMaskPerSession(pMac, psessionEntry,
&pTspec->tsinfo,
SET_UAPSD_MASK);
}
else
{
limSetTspecUapsdMaskPerSession(pMac, psessionEntry,
&pTspec->tsinfo,
CLEAR_UAPSD_MASK);
}
/*
* ADDTS success, so AC is now admitted.
* We shall now use the default
* EDCA parameters as advertised by AP and
* send the updated EDCA params
* to HAL.
*/
ac = upToAc(pTspec->tsinfo.traffic.userPrio);
if(pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK)
{
psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
}
else if(pTspec->tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_DNLINK)
{
psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
}
else if(pTspec->tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_BIDIR)
{
psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
}
}
limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams,
psessionEntry);
limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive,
pSta->bssId);
if(eSIR_SUCCESS != limTspecAdd(pMac, pSta->staAddr, pSta->assocId,
pTspec, 0, &tspecInfo))
{
PELOGE(limLog(pMac, LOGE,
FL("Adding entry in lim Tspec Table failed "));)
pMac->lim.gLimAddtsSent = false;
vos_mem_free(pAggrAddTsParam);
return eSIR_FAILURE;
}
pAggrAddTsParam->tspec[i] =
aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
}
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
if (!pMac->roam.configParam.isRoamOffloadEnabled ||
(pMac->roam.configParam.isRoamOffloadEnabled &&
!psessionEntry->is11Rconnection))
#endif
{
msg.type = WDA_AGGR_QOS_REQ;
msg.bodyptr = pAggrAddTsParam;
msg.bodyval = 0;
/* We need to defer any incoming messages until we get a
* WDA_AGGR_QOS_RSP from HAL.
*/
SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msg.type));
if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
{
PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));)
SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
vos_mem_free(pAggrAddTsParam);
return eSIR_FAILURE;
}
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
else
{
/* Implies it is a LFR3.0 based 11r connection
* so donot send add ts request to fimware since it
* already has the RIC IEs */
/* Send the Aggr QoS response to SME */
limFTSendAggrQosRsp(pMac, true, pAggrAddTsParam,
psessionEntry->smeSessionId);
if( pAggrAddTsParam != NULL )
{
vos_mem_free(pAggrAddTsParam);
}
}
#endif
return eSIR_SUCCESS;
}
#endif /* WLAN_FEATURE_VOWIFI_11R */