blob: 0329b1a2c2cc9c0564799b7e02e4c295a5b8f44b [file] [log] [blame]
/*
* Copyright (c) 2012-2017, 2019-2020 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 limProcessActionFrame.cc contains the code
* for processing Action Frame.
* Author: Michael Lui
* Date: 05/23/03
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "palTypes.h"
#include "wniApi.h"
#include "sirApi.h"
#include "aniGlobal.h"
#include "wniCfg.h"
#include "schApi.h"
#include "utilsApi.h"
#include "limTypes.h"
#include "limUtils.h"
#include "limAssocUtils.h"
#include "limSecurityUtils.h"
#include "limSerDesUtils.h"
#include "limSendSmeRspMessages.h"
#include "parserApi.h"
#include "limAdmitControl.h"
#include "wmmApsd.h"
#include "limSendMessages.h"
#if defined WLAN_FEATURE_VOWIFI
#include "rrmApi.h"
#endif
#include "limSessionUtils.h"
#ifdef WLAN_FEATURE_RMC
#include "limRMC.h"
#endif
#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
#include "eseApi.h"
#endif
#include "wlan_qct_wda.h"
#ifdef WLAN_FEATURE_LFR_MBB
#include "lim_mbb.h"
#endif
#include "dot11f.h"
#define BA_DEFAULT_TX_BUFFER_SIZE 64
typedef enum
{
LIM_ADDBA_RSP = 0,
LIM_ADDBA_REQ = 1
}tLimAddBaValidationReqType;
/* Note: The test passes if the STAUT stops sending any frames, and no further
frames are transmitted on this channel by the station when the AP has sent
the last 6 beacons, with the channel switch information elements as seen
with the sniffer.*/
#define SIR_CHANSW_TX_STOP_MAX_COUNT 6
/**-----------------------------------------------------------------
\fn limStopTxAndSwitchChannel
\brief Stops the transmission if channel switch mode is silent and
starts the channel switch timer.
\param pMac
\return NONE
-----------------------------------------------------------------*/
void limStopTxAndSwitchChannel(tpAniSirGlobal pMac, tANI_U8 sessionId)
{
tANI_U8 isFullPowerRequested = 0;
tpPESession psessionEntry;
psessionEntry = peFindSessionBySessionId( pMac , sessionId );
if( NULL == psessionEntry )
{
limLog(pMac, LOGE, FL("Session %d not active\n "), sessionId);
return;
}
if(pMac->ft.ftPEContext.pFTPreAuthReq)
{
limLog(pMac, LOGE,
FL("Avoid Switch Channel req during pre auth"));
return;
}
limLog(pMac, LOG1, FL("Channel switch Mode == %d"),
psessionEntry->gLimChannelSwitch.switchMode);
if (psessionEntry->gLimChannelSwitch.switchMode == eSIR_CHANSW_MODE_SILENT ||
psessionEntry->gLimChannelSwitch.switchCount <= SIR_CHANSW_TX_STOP_MAX_COUNT)
{
/* Freeze the transmission */
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX);
/*Request for Full power only if the device is in powersave*/
if(!limIsSystemInActiveState(pMac))
{
/* Request Full Power */
limSendSmePreChannelSwitchInd(pMac);
isFullPowerRequested = 1;
}
}
else
{
/* Resume the transmission */
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
}
pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId = sessionId;
/* change the channel immediatly only if the channel switch count is 0 and the
* device is not in powersave
* If the device is in powersave channel switch should happen only after the
* device comes out of the powersave */
if (psessionEntry->gLimChannelSwitch.switchCount == 0)
{
if(limIsSystemInActiveState(pMac))
{
limProcessChannelSwitchTimeout(pMac);
}
else if(!isFullPowerRequested)
{
/* If the Full power is already not requested
* Request Full Power so the channel switch happens
* after device comes to full power */
limSendSmePreChannelSwitchInd(pMac);
}
return;
}
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_CHANNEL_SWITCH_TIMER));
if (tx_timer_activate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("tx_timer_activate failed"));
}
return;
}
/**------------------------------------------------------------
\fn limStartChannelSwitch
\brief Switches the channel if switch count == 0, otherwise
starts the timer for channel switch and stops BG scan
and heartbeat timer tempororily.
\param pMac
\param psessionEntry
\return NONE
------------------------------------------------------------*/
tSirRetStatus limStartChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
limLog(pMac, LOG1, FL(" ENTER"));
#ifdef WLAN_FEATURE_LFR_MBB
if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry))
{
limLog(pMac, LOGE,
FL("Ignore channel switch as LFR MBB in progress"));
return eSIR_SUCCESS;
}
#endif
/*If channel switch is already running and it is on a different session, just return*/
/*This need to be removed for MCC */
if( limIsChanSwitchRunning (pMac) &&
psessionEntry->gLimSpecMgmt.dot11hChanSwState != eLIM_11H_CHANSW_RUNNING )
{
limLog(pMac, LOGW, FL("Ignoring channel switch on session %d"), psessionEntry->peSessionId);
return eSIR_SUCCESS;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_CHANNEL_SWITCH_ANOUNCEMENT,
psessionEntry, eSIR_SUCCESS, LIM_SWITCH_CHANNEL_CSA);
#endif
psessionEntry->channelChangeCSA = LIM_SWITCH_CHANNEL_CSA;
/* Deactivate and change reconfigure the timeout value */
//limDeactivateAndChangeTimer(pMac, eLIM_CHANNEL_SWITCH_TIMER);
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("tx_timer_deactivate failed!"));
return eSIR_FAILURE;
}
if (tx_timer_change(&pMac->lim.limTimers.gLimChannelSwitchTimer,
psessionEntry->gLimChannelSwitch.switchTimeoutValue,
0) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("tx_timer_change failed "));
return eSIR_FAILURE;
}
/* Follow the channel switch, forget about the previous quiet. */
//If quiet is running, chance is there to resume tx on its timeout.
//so stop timer for a safer side.
if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN)
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("tx_timer_deactivate failed"));
return eSIR_FAILURE;
}
}
else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING)
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("tx_timer_deactivate failed"));
return eSIR_FAILURE;
}
}
psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
/* Prepare for 11h channel switch */
limPrepareFor11hChannelSwitch(pMac, psessionEntry);
/** Dont add any more statements here as we posted finish scan request
* to HAL, wait till we get the response
*/
return eSIR_SUCCESS;
}
/**
* __limProcessChannelSwitchActionFrame
*
*FUNCTION:
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - A pointer to packet info structure
* @return None
*/
static void
__limProcessChannelSwitchActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tDot11fChannelSwitch *pChannelSwitchFrame;
tANI_U16 beaconPeriod;
tANI_U32 val;
tANI_U32 frameLen;
tANI_U32 nStatus;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
limLog(pMac, LOG1, FL("Received Channel switch action frame"));
if (!psessionEntry->lim11hEnable)
return;
pChannelSwitchFrame = vos_mem_malloc(sizeof(*pChannelSwitchFrame));
if (NULL == pChannelSwitchFrame)
{
limLog(pMac, LOGE,
FL("AllocateMemory failed"));
return;
}
/* Unpack channel switch frame */
nStatus = dot11fUnpackChannelSwitch(pMac, pBody, frameLen, pChannelSwitchFrame);
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE,
FL( "Failed to unpack and parse an 11h-CHANSW Request (0x%08x, %d bytes):"),
nStatus,
frameLen);
vos_mem_free(pChannelSwitchFrame);
return;
}
else if(DOT11F_WARNED( nStatus ))
{
limLog( pMac, LOGW,
FL( "There were warnings while unpacking an 11h-CHANSW Request (0x%08x, %d bytes):"),
nStatus,
frameLen);
}
if (vos_mem_compare((tANI_U8 *) &psessionEntry->bssId,
(tANI_U8 *) &pHdr->sa,
sizeof(tSirMacAddr)))
{
#if 0
if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &val) != eSIR_SUCCESS)
{
vos_mem_free(pChannelSwitchFrame);
limLog(pMac, LOGP, FL("could not retrieve Beacon interval"));
return;
}
#endif// TO SUPPORT BT-AMP
/* copy the beacon interval from psessionEntry*/
val = psessionEntry->beaconParams.beaconInterval;
beaconPeriod = (tANI_U16) val;
psessionEntry->gLimChannelSwitch.primaryChannel = pChannelSwitchFrame->ChanSwitchAnn.newChannel;
psessionEntry->gLimChannelSwitch.switchCount = pChannelSwitchFrame->ChanSwitchAnn.switchCount;
psessionEntry->gLimChannelSwitch.switchTimeoutValue = SYS_MS_TO_TICKS(beaconPeriod) *
psessionEntry->gLimChannelSwitch.switchCount;
psessionEntry->gLimChannelSwitch.switchMode = pChannelSwitchFrame->ChanSwitchAnn.switchMode;
#ifdef WLAN_FEATURE_11AC
if ( pChannelSwitchFrame->WiderBWChanSwitchAnn.present && psessionEntry->vhtCapability)
{
psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = pChannelSwitchFrame->WiderBWChanSwitchAnn.newChanWidth;
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = pChannelSwitchFrame->WiderBWChanSwitchAnn.newCenterChanFreq0;
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = pChannelSwitchFrame->WiderBWChanSwitchAnn.newCenterChanFreq1;
}
#endif
limLog(pMac, LOG1, FL("Rcv Chnl Swtch Frame: Timeout in %d ticks"),
psessionEntry->gLimChannelSwitch.switchTimeoutValue);
/* Only primary channel switch element is present */
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
psessionEntry->gLimChannelSwitch.secondarySubBand = PHY_SINGLE_CHANNEL_CENTERED;
if (psessionEntry->htSupportedChannelWidthSet)
{
if ((pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) ||
(pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY))
{
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
psessionEntry->gLimChannelSwitch.secondarySubBand = pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset;
}
#ifdef WLAN_FEATURE_11AC
if(psessionEntry->vhtCapability && pChannelSwitchFrame->WiderBWChanSwitchAnn.present)
{
if (pChannelSwitchFrame->WiderBWChanSwitchAnn.newChanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
{
if (pChannelSwitchFrame->sec_chan_offset.present && ((pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) ||
(pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)))
{
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
psessionEntry->gLimChannelSwitch.secondarySubBand =
limGet11ACPhyCBState(pMac,
psessionEntry->gLimChannelSwitch.primaryChannel,
pChannelSwitchFrame->sec_chan_offset.secondaryChannelOffset,
pChannelSwitchFrame->WiderBWChanSwitchAnn.newCenterChanFreq0,
psessionEntry);
}
}
}
#endif
}
}
else
{
limLog(pMac, LOG1, FL("LIM: Received action frame not from our BSS, dropping..."));
}
if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry))
{
limLog(pMac, LOG1, FL("Could not start channel switch"));
}
vos_mem_free(pChannelSwitchFrame);
return;
} /*** end limProcessChannelSwitchActionFrame() ***/
/**
* lim_process_ecsa_action_frame()- Process ECSA Action
* Frames.
* @mac_ctx: pointer to global mac structure
* @rx_packet_info: rx packet meta information
* @session_entry: Session entry.
*
* This function is called when ECSA action frame is received on STA interface.
*
* Return: void
*/
static void
lim_process_ecsa_action_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_packet_info, tpPESession session_entry)
{
tpSirMacMgmtHdr hdr;
uint8_t *body;
tDot11fext_channel_switch_action_frame *ecsa_frame;
struct ecsa_frame_params ecsa_req;
uint32_t frame_len;
uint32_t status;
hdr = WDA_GET_RX_MAC_HEADER(rx_packet_info);
body = WDA_GET_RX_MPDU_DATA(rx_packet_info);
frame_len = WDA_GET_RX_PAYLOAD_LEN(rx_packet_info);
limLog(mac_ctx, LOG1, FL("Received ECSA action frame"));
ecsa_frame = vos_mem_malloc(sizeof(*ecsa_frame));
if (!ecsa_frame) {
limLog(mac_ctx, LOGE, FL("AllocateMemory failed"));
return;
}
/* Unpack channel switch frame */
status = dot11fUnpackext_channel_switch_action_frame(mac_ctx,
body, frame_len, ecsa_frame);
if (DOT11F_FAILED(status)) {
limLog(mac_ctx, LOGE, FL("Failed to parse CHANSW action frame (0x%08x, len %d):"),
status, frame_len);
goto free_ecsa;
} else if (DOT11F_WARNED(status)) {
limLog(mac_ctx, LOGW, FL("There were warnings while unpacking CHANSW Request (0x%08x, %d bytes):"),
status, frame_len);
}
if (session_entry->currentOperChannel ==
ecsa_frame->ext_chan_switch_ann_action.new_channel) {
limLog(mac_ctx, LOGE, FL("New channel %d is same as old channel ignore req"),
ecsa_frame->ext_chan_switch_ann_action.new_channel);
goto free_ecsa;
}
ecsa_req.new_channel = ecsa_frame->ext_chan_switch_ann_action.new_channel;
ecsa_req.op_class = ecsa_frame->ext_chan_switch_ann_action.op_class;
ecsa_req.switch_mode = ecsa_frame->ext_chan_switch_ann_action.switch_mode;
ecsa_req.switch_count = ecsa_frame->ext_chan_switch_ann_action.switch_count;
limLog(mac_ctx, LOG1, FL("New channel %d op class %d switch mode %d switch count %d"),
ecsa_req.new_channel, ecsa_req.op_class,
ecsa_req.switch_mode, ecsa_req.switch_count);
lim_handle_ecsa_req(mac_ctx, &ecsa_req, session_entry);
free_ecsa:
vos_mem_free(ecsa_frame);
}
#ifdef WLAN_FEATURE_11AC
static void
__limProcessOperatingModeActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tDot11fOperatingMode *pOperatingModeframe;
tANI_U32 frameLen;
tANI_U32 nStatus;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U8 operMode;
tANI_U32 channelBondingMode;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
limLog(pMac, LOG1, FL("Received Operating Mode action frame"));
if( RF_CHAN_14 >= psessionEntry->currentOperChannel )
{
channelBondingMode = pMac->roam.configParam.channelBondingMode24GHz;
}
else
{
channelBondingMode = pMac->roam.configParam.channelBondingMode5GHz;
}
/* Do not update the channel bonding mode if channel bonding
* mode is disabled in INI.
*/
if(WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == channelBondingMode)
{
limLog(pMac, LOGW,
FL("channel bonding disabled"));
return;
}
if (( RF_CHAN_14 >= psessionEntry->currentOperChannel )&&
!IS_HT40_OBSS_SCAN_FEATURE_ENABLE)
{
limLog(pMac, LOGW,
FL("channel bonding disabled as FW doesn't supoort CB in 2.4gz"));
return;
}
pOperatingModeframe = vos_mem_malloc(sizeof(*pOperatingModeframe));
if (NULL == pOperatingModeframe)
{
limLog(pMac, LOGE,
FL("AllocateMemory failed"));
return;
}
/* Unpack channel switch frame */
nStatus = dot11fUnpackOperatingMode(pMac, pBody, frameLen, pOperatingModeframe);
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE,
FL( "Failed to unpack and parse an 11h-CHANSW Request (0x%08x, %d bytes):"),
nStatus,
frameLen);
vos_mem_free(pOperatingModeframe);
return;
}
else if(DOT11F_WARNED( nStatus ))
{
limLog( pMac, LOGW,
FL( "There were warnings while unpacking an 11h-CHANSW Request (0x%08x, %d bytes):"),
nStatus,
frameLen);
}
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
if (pSta == NULL)
{
PELOGE(limLog(pMac, LOGE, FL("Station context not found"));)
return;
}
operMode = pSta->vhtSupportedChannelWidthSet ? eHT_CHANNEL_WIDTH_80MHZ : pSta->htSupportedChannelWidthSet ? eHT_CHANNEL_WIDTH_40MHZ: eHT_CHANNEL_WIDTH_20MHZ;
if( operMode != pOperatingModeframe->OperatingMode.chanWidth)
{
limLog(pMac, LOGE,
FL(" received Chanwidth %d, staIdx = %d"),
(pOperatingModeframe->OperatingMode.chanWidth ),
pSta->staIndex);
limLog(pMac, LOGE,
FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
pHdr->sa[0],
pHdr->sa[1],
pHdr->sa[2],
pHdr->sa[3],
pHdr->sa[4],
pHdr->sa[5]);
if(pOperatingModeframe->OperatingMode.chanWidth == eHT_CHANNEL_WIDTH_80MHZ)
{
pSta->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
}
else if(pOperatingModeframe->OperatingMode.chanWidth == eHT_CHANNEL_WIDTH_40MHZ)
{
pSta->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
}
else if(pOperatingModeframe->OperatingMode.chanWidth == eHT_CHANNEL_WIDTH_20MHZ)
{
pSta->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
pSta->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ;
}
limCheckVHTOpModeChange( pMac, psessionEntry,
(pOperatingModeframe->OperatingMode.chanWidth), pSta->staIndex);\
}
vos_mem_free(pOperatingModeframe);
return;
}
#endif
static void
__limProcessAddTsReq(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
}
static void
__limProcessAddTsRsp(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tSirAddtsRspInfo addts;
tSirRetStatus retval;
tpSirMacMgmtHdr pHdr;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U32 frameLen;
tANI_U8 *pBody;
tpLimTspecInfo tspecInfo;
tANI_U8 ac;
tpDphHashNode pStaDs = NULL;
tANI_U8 rspReqd = 1;
tANI_U32 cfgLen;
tSirMacAddr peerMacAddr;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
PELOGW(limLog(pMac, LOGW, "Recv AddTs Response");)
if ((psessionEntry->limSystemRole == eLIM_AP_ROLE)||(psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE))
{
PELOGW(limLog(pMac, LOGW, FL("AddTsRsp recvd at AP: ignoring"));)
return;
}
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
if (pSta == NULL)
{
PELOGE(limLog(pMac, LOGE, FL("Station context not found - ignoring AddTsRsp"));)
return;
}
retval = sirConvertAddtsRsp2Struct(pMac, pBody, frameLen, &addts);
if (retval != eSIR_SUCCESS)
{
PELOGW(limLog(pMac, LOGW, FL("AddTsRsp parsing failed (error %d)"), retval);)
return;
}
// don't have to check for qos/wme capabilities since we wouldn't have this
// flag set otherwise
if (! pMac->lim.gLimAddtsSent)
{
// we never sent an addts request!
PELOGW(limLog(pMac, LOGW, "Recvd AddTsRsp but no request was ever sent - ignoring");)
return;
}
if (pMac->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken)
{
limLog(pMac, LOGW, "AddTsRsp: token mismatch (got %d, exp %d) - ignoring",
addts.dialogToken, pMac->lim.gLimAddtsReq.req.dialogToken);
return;
}
/*
* for successful addts reponse, try to add the classifier.
* if this fails for any reason, we should send a delts request to the ap
* for now, its ok not to send a delts since we are going to add support for
* multiple tclas soon and until then we won't send any addts requests with
* multiple tclas elements anyway.
* In case of addClassifier failure, we just let the addts timer run out
*/
if (((addts.tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) ||
(addts.tspec.tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH)) &&
(addts.status == eSIR_MAC_SUCCESS_STATUS))
{
// add the classifier - this should always succeed
if (addts.numTclas > 1) // currently no support for multiple tclas elements
{
limLog(pMac, LOGE, FL("Sta %d: Too many Tclas (%d), only 1 supported"),
aid, addts.numTclas);
return;
}
else if (addts.numTclas == 1)
{
limLog(pMac, LOGW, "AddTs Response from STA %d: tsid %d, UP %d, OK!", aid,
addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio);
}
}
limLog(pMac, LOGW, "Recv AddTsRsp: tsid %d, UP %d, status %d ",
addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio,
addts.status);
// deactivate the response timer
limDeactivateAndChangeTimer(pMac, eLIM_ADDTS_RSP_TIMER);
if (addts.status != eSIR_MAC_SUCCESS_STATUS)
{
limLog(pMac, LOGW, "Recv AddTsRsp: tsid %d, UP %d, status %d ",
addts.tspec.tsinfo.traffic.tsid, addts.tspec.tsinfo.traffic.userPrio,
addts.status);
limSendSmeAddtsRsp(pMac, true, addts.status, psessionEntry, addts.tspec,
psessionEntry->smeSessionId, psessionEntry->transactionId);
// clear the addts flag
pMac->lim.gLimAddtsSent = false;
return;
}
#ifdef FEATURE_WLAN_ESE
if (addts.tsmPresent)
{
limLog(pMac, LOGW, "TSM IE Present");
psessionEntry->eseContext.tsm.tid = addts.tspec.tsinfo.traffic.userPrio;
vos_mem_copy(&psessionEntry->eseContext.tsm.tsmInfo,
&addts.tsmIE,sizeof(tSirMacESETSMIE));
#ifdef FEATURE_WLAN_ESE_UPLOAD
limSendSmeTsmIEInd(pMac, psessionEntry, addts.tsmIE.tsid,
addts.tsmIE.state, addts.tsmIE.msmt_interval);
#else
limActivateTSMStatsTimer(pMac, psessionEntry);
#endif /* FEATURE_WLAN_ESE_UPLOAD */
}
#endif
/* 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 (addts.tspec.tsinfo.traffic.psb == 1)
limSetTspecUapsdMask(pMac, &addts.tspec.tsinfo, SET_UAPSD_MASK);
else
limSetTspecUapsdMask(pMac, &addts.tspec.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(addts.tspec.tsinfo.traffic.userPrio);
if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |= (1 << ac);
}
else if(addts.tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_DNLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |= (1 << ac);
}
else if(addts.tspec.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);
}
limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry);
pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable);
if (pStaDs != NULL)
{
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);
}
else
limLog(pMac, LOGE, FL("Self entry missing in Hash Table "));
sirCopyMacAddr(peerMacAddr,psessionEntry->bssId);
//if schedule is not present then add TSPEC with svcInterval as 0.
if(!addts.schedulePresent)
addts.schedule.svcInterval = 0;
if(eSIR_SUCCESS != limTspecAdd(pMac, pSta->staAddr, pSta->assocId, &addts.tspec, addts.schedule.svcInterval, &tspecInfo))
{
PELOGE(limLog(pMac, LOGE, FL("Adding entry in lim Tspec Table failed "));)
limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &addts.tspec.tsinfo, &addts.tspec,
psessionEntry);
pMac->lim.gLimAddtsSent = false;
return; //Error handling. send the response with error status. need to send DelTS to tear down the TSPEC status.
}
if((addts.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA) ||
((upToAc(addts.tspec.tsinfo.traffic.userPrio) < MAX_NUM_AC)))
{
retval = limSendHalMsgAddTs(pMac, pSta->staIndex, tspecInfo->idx, addts.tspec, psessionEntry->peSessionId);
if(eSIR_SUCCESS != retval)
{
limAdmitControlDeleteTS(pMac, pSta->assocId, &addts.tspec.tsinfo, NULL, &tspecInfo->idx);
// Send DELTS action frame to AP
cfgLen = sizeof(tSirMacAddr);
limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &addts.tspec.tsinfo, &addts.tspec,
psessionEntry);
limSendSmeAddtsRsp(pMac, true, retval, psessionEntry, addts.tspec,
psessionEntry->smeSessionId, psessionEntry->transactionId);
pMac->lim.gLimAddtsSent = false;
return;
}
PELOGW(limLog(pMac, LOGW, FL("AddTsRsp received successfully(UP %d, TSID %d)"),
addts.tspec.tsinfo.traffic.userPrio, addts.tspec.tsinfo.traffic.tsid);)
}
else
{
PELOGW(limLog(pMac, LOGW, FL("AddTsRsp received successfully(UP %d, TSID %d)"),
addts.tspec.tsinfo.traffic.userPrio, addts.tspec.tsinfo.traffic.tsid);)
PELOGW(limLog(pMac, LOGW, FL("no ACM: Bypass sending WDA_ADD_TS_REQ to HAL "));)
// Use the smesessionId and smetransactionId from the PE session context
limSendSmeAddtsRsp(pMac, true, eSIR_SME_SUCCESS, psessionEntry, addts.tspec,
psessionEntry->smeSessionId, psessionEntry->transactionId);
}
// clear the addts flag
pMac->lim.gLimAddtsSent = false;
return;
}
static void
__limProcessDelTsReq(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tSirRetStatus retval;
tSirDeltsReqInfo delts;
tpSirMacMgmtHdr pHdr;
tpDphHashNode pSta;
tANI_U32 frameLen;
tANI_U16 aid;
tANI_U8 *pBody;
tANI_U8 tsStatus;
tSirMacTSInfo *tsinfo;
tANI_U8 tspecIdx;
tANI_U8 ac;
tpDphHashNode pStaDs = NULL;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
if (pSta == NULL)
{
PELOGE(limLog(pMac, LOGE, FL("Station context not found - ignoring DelTs"));)
return;
}
// parse the delts request
retval = sirConvertDeltsReq2Struct(pMac, pBody, frameLen, &delts);
if (retval != eSIR_SUCCESS)
{
PELOGW(limLog(pMac, LOGW, FL("DelTs parsing failed (error %d)"), retval);)
return;
}
if (delts.wmeTspecPresent)
{
if ((!psessionEntry->limWmeEnabled) || (! pSta->wmeEnabled))
{
PELOGW(limLog(pMac, LOGW, FL("Ignoring delts request: wme not enabled/capable"));)
return;
}
limLog(pMac, LOG1, FL("WME Delts received"));
}
else if ((psessionEntry->limQosEnabled) && pSta->lleEnabled)
{
limLog(pMac, LOG1, FL("11e QoS Delts received"));
}
else if ((psessionEntry->limWsmEnabled) && pSta->wsmEnabled)
{
limLog(pMac, LOG1, FL("WSM Delts received"));
}
else
{
PELOGW(limLog(pMac, LOGW, FL("Ignoring delts request: qos not enabled/capable"));)
return;
}
tsinfo = delts.wmeTspecPresent ? &delts.tspec.tsinfo : &delts.tsinfo;
// if no Admit Control, ignore the request
if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA))
{
if (upToAc(tsinfo->traffic.userPrio) >= MAX_NUM_AC)
{
limLog(pMac, LOGW, FL("DelTs with UP %d has no AC - ignoring request"),
tsinfo->traffic.userPrio);
return;
}
}
if ((psessionEntry->limSystemRole != eLIM_AP_ROLE) &&
(psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE))
limSendSmeDeltsInd(pMac, &delts, aid,psessionEntry);
// try to delete the TS
if (eSIR_SUCCESS != limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx))
{
PELOGW(limLog(pMac, LOGW, FL("Unable to Delete TS"));)
return;
}
else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) ||
(tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_BOTH))
{
//Edca only for now.
}
else
{
//send message to HAL to delete TS
if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac,
pSta->staIndex,
tspecIdx,
delts,
psessionEntry->peSessionId,
psessionEntry->bssId))
{
limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"),
tsinfo->traffic.userPrio);
return;
}
}
/* We successfully deleted the TSPEC. Update the dynamic UAPSD Mask.
* The AC for this TSPEC is no longer trigger enabled if this Tspec
* was set-up in uplink direction only.
* The AC for this TSPEC is no longer delivery enabled if this Tspec
* was set-up in downlink direction only.
* The AC for this TSPEC is no longer triiger enabled and delivery
* enabled if this Tspec was a bidirectional TSPEC.
*/
limSetTspecUapsdMask(pMac, tsinfo, CLEAR_UAPSD_MASK);
/* We're deleting the TSPEC.
* The AC for this TSPEC is no longer admitted in uplink/downlink direction
* if this TSPEC was set-up in uplink/downlink direction only.
* The AC for this TSPEC is no longer admitted in both uplink and downlink
* directions if this TSPEC was a bi-directional TSPEC.
* If ACM is set for this AC and this AC is admitted only in downlink
* direction, PE needs to downgrade the EDCA parameter
* (for the AC for which TS is being deleted) to the
* next best AC for which ACM is not enabled, and send the
* updated values to HAL.
*/
ac = upToAc(tsinfo->traffic.userPrio);
if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac);
}
else if(tsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK)
{
pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac);
}
else if(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);
}
limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry);
pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable);
if (pStaDs != NULL)
{
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);
}
else
limLog(pMac, LOGE, FL("Self entry missing in Hash Table "));
limLog(pMac, LOG1, FL("DeleteTS succeeded"));
#ifdef FEATURE_WLAN_ESE
#ifdef FEATURE_WLAN_ESE_UPLOAD
limSendSmeTsmIEInd(pMac, psessionEntry, 0, 0, 0);
#else
limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER);
#endif /* FEATURE_WLAN_ESE_UPLOAD */
#endif
}
static void
__limProcessQosMapConfigureFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U32 frameLen;
tANI_U8 *pBody;
tSirRetStatus retval;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
retval = sirConvertQosMapConfigureFrame2Struct(pMac, pBody, frameLen,
&psessionEntry->QosMapSet);
if (retval != eSIR_SUCCESS)
{
PELOGW(limLog(pMac, LOGE,
FL("QosMapConfigure frame parsing failed (error %d)"), retval);)
return;
}
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo, psessionEntry,
WDA_GET_RX_RSSI_DB(pRxPacketInfo));
}
#ifdef ANI_SUPPORT_11H
/**
* limProcessBasicMeasReq
*
*FUNCTION:
* This function is called by limProcessMeasurementRequestFrame()
* when it received a Basic measurement Request action frame.
* Station/BP receiving this should perform basic measurements
* and then send Basic Measurement Report. AP should not perform
* any measurements, and send report indicating refusal.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pMeasReqFrame - A pointer to Basic Meas. Req structure
* @return None
*/
static void
__limProcessBasicMeasReq(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr)
{
// TBD - Station shall perform basic measurements
if (limSendMeasReportFrame(pMac,
pMeasReqFrame,
peerMacAddr) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("fail to send Basic Meas report "));)
return;
}
}
/**
* limProcessCcaMeasReq
*
*FUNCTION:
* This function is called by limProcessMeasurementRequestFrame()
* when it received a CCA measurement Request action frame.
* Station/BP receiving this should perform CCA measurements
* and then send CCA Measurement Report. AP should not perform
* any measurements, and send report indicating refusal.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pMeasReqFrame - A pointer to CCA Meas. Req structure
* @return None
*/
static void
__limProcessCcaMeasReq(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr)
{
// TBD - Station shall perform cca measurements
if (limSendMeasReportFrame(pMac,
pMeasReqFrame,
peerMacAddr) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("fail to send CCA Meas report "));)
return;
}
}
/**
* __limProcessRpiMeasReq
*
*FUNCTION:
* This function is called by limProcessMeasurementRequestFrame()
* when it received a RPI measurement Request action frame.
* Station/BP/AP receiving this shall not perform any measurements,
* and send report indicating refusal.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pMeasReqFrame - A pointer to RPI Meas. Req structure
* @return None
*/
static void
__limProcessRpiMeasReq(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr)
{
if (limSendMeasReportFrame(pMac,
pMeasReqFrame,
peerMacAddr) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("fail to send RPI Meas report "));)
return;
}
}
/**
* __limProcessMeasurementRequestFrame
*
*FUNCTION:
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - A pointer to packet info structure
* @return None
*/
static void
__limProcessMeasurementRequestFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tpSirMacMeasReqActionFrame pMeasReqFrame;
tANI_U32 frameLen;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pMeasReqFrame = vos_mem_malloc(sizeof( tSirMacMeasReqActionFrame ));
if (NULL == pMeasReqFrame)
{
limLog(pMac, LOGE,
FL("limProcessMeasurementRequestFrame: AllocateMemory failed "));
return;
}
if (sirConvertMeasReqFrame2Struct(pMac, pBody, pMeasReqFrame, frameLen) !=
eSIR_SUCCESS)
{
PELOGW(limLog(pMac, LOGW, FL("Rcv invalid Measurement Request Action Frame "));)
return;
}
switch(pMeasReqFrame->measReqIE.measType)
{
case SIR_MAC_BASIC_MEASUREMENT_TYPE:
__limProcessBasicMeasReq(pMac, pMeasReqFrame, pHdr->sa);
break;
case SIR_MAC_CCA_MEASUREMENT_TYPE:
__limProcessCcaMeasReq(pMac, pMeasReqFrame, pHdr->sa);
break;
case SIR_MAC_RPI_MEASUREMENT_TYPE:
__limProcessRpiMeasReq(pMac, pMeasReqFrame, pHdr->sa);
break;
default:
limLog(pMac, LOG1, FL("Unknown Measurement Type %d "),
pMeasReqFrame->measReqIE.measType);
break;
}
} /*** end limProcessMeasurementRequestFrame ***/
/**
* limProcessTpcRequestFrame
*
*FUNCTION:
* This function is called upon receiving Tpc Request frame.
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - A pointer to packet info structure
* @return None
*/
static void
__limProcessTpcRequestFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tpSirMacTpcReqActionFrame pTpcReqFrame;
tANI_U32 frameLen;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
limLog(pMac, LOG1, FL("****LIM: Processing TPC Request from peer ****"));
pTpcReqFrame = vos_mem_malloc(sizeof( tSirMacTpcReqActionFrame ));
if (NULL == pTpcReqFrame)
{
PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed "));)
return;
}
if (sirConvertTpcReqFrame2Struct(pMac, pBody, pTpcReqFrame, frameLen) !=
eSIR_SUCCESS)
{
PELOGW(limLog(pMac, LOGW, FL("Rcv invalid TPC Req Action Frame "));)
return;
}
if (limSendTpcReportFrame(pMac,
pTpcReqFrame,
pHdr->sa) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("fail to send TPC Report Frame. "));)
return;
}
}
#endif
/**
* \brief Validate an ADDBA Req from peer with respect
* to our own BA configuration
*
* \sa __limValidateAddBAParameterSet
*
* \param pMac The global tpAniSirGlobal object
*
* \param baParameterSet The ADDBA Parameter Set.
*
* \param pDelBAFlag this parameter is NULL except for call from processAddBAReq
* delBAFlag is set when entry already exists.
*
* \param reqType ADDBA Req v/s ADDBA Rsp
* 1 - ADDBA Req
* 0 - ADDBA Rsp
*
* \return eSIR_SUCCESS if setup completes successfully
* eSIR_FAILURE is some problem is encountered
*/
static tSirMacStatusCodes
__limValidateAddBAParameterSet( tpAniSirGlobal pMac,
tpDphHashNode pSta,
tDot11fFfAddBAParameterSet baParameterSet,
tANI_U8 dialogueToken,
tLimAddBaValidationReqType reqType ,
tANI_U8* pDelBAFlag /*this parameter is NULL except for call from processAddBAReq*/)
{
if(baParameterSet.tid >= STACFG_MAX_TC)
{
return eSIR_MAC_WME_INVALID_PARAMS_STATUS;
}
//check if there is already a BA session setup with this STA/TID while processing AddBaReq
if((true == pSta->tcCfg[baParameterSet.tid].fUseBARx) &&
(LIM_ADDBA_REQ == reqType))
{
//There is already BA session setup for STA/TID.
limLog( pMac, LOGE,
FL( "AddBAReq rcvd when there is already a session for this StaId = %d, tid = %d\n " ),
pSta->staIndex, baParameterSet.tid);
limPrintMacAddr( pMac, pSta->staAddr, LOGW );
if(pDelBAFlag)
*pDelBAFlag = true;
}
return eSIR_MAC_SUCCESS_STATUS;
}
/**
* \brief Validate a DELBA Ind from peer with respect
* to our own BA configuration
*
* \sa __limValidateDelBAParameterSet
*
* \param pMac The global tpAniSirGlobal object
*
* \param baParameterSet The DELBA Parameter Set.
*
* \param pSta Runtime, STA-related configuration cached
* in the HashNode object
*
* \return eSIR_SUCCESS if setup completes successfully
* eSIR_FAILURE is some problem is encountered
*/
static tSirMacStatusCodes
__limValidateDelBAParameterSet( tpAniSirGlobal pMac,
tDot11fFfDelBAParameterSet baParameterSet,
tpDphHashNode pSta )
{
tSirMacStatusCodes statusCode = eSIR_MAC_STA_BLK_ACK_NOT_SUPPORTED_STATUS;
if (!(baParameterSet.tid < STACFG_MAX_TC))
return statusCode;
// Validate if a BA is active for the requested TID
if( pSta->tcCfg[baParameterSet.tid].fUseBATx ||
pSta->tcCfg[baParameterSet.tid].fUseBARx )
{
statusCode = eSIR_MAC_SUCCESS_STATUS;
limLog( pMac, LOGW,
FL("Valid DELBA Ind received. Time to send WDA_DELBA_IND to HAL..."));
}
else
limLog( pMac, LOGW,
FL("Received an INVALID DELBA Ind for TID %d..."),
baParameterSet.tid );
return statusCode;
}
/**
* \brief Process an ADDBA REQ
*
* \sa limProcessAddBAReq
*
* \param pMac The global tpAniSirGlobal object
*
* \param pRxPacketInfo Handle to the Rx packet info from HDD
*
* \return none
*
*/
static void
__limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tDot11fAddBAReq frmAddBAReq;
tpSirMacMgmtHdr pHdr;
tpDphHashNode pSta;
tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS;
tANI_U16 aid;
tANI_U32 frameLen, nStatus,val, val1;
tANI_U8 *pBody;
tANI_U8 delBAFlag =0;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
val = 0;
val1 = 0;
// Unpack the received frame
nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq );
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE,
FL("Failed to unpack and parse an ADDBA Request (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
// Without an unpacked request we cannot respond, so silently ignore the request
return;
}
else if ( DOT11F_WARNED( nStatus ) )
{
limLog( pMac, LOGW,
FL( "There were warnings while unpacking an ADDBA Request (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
psessionEntry->amsduSupportedInBA = frmAddBAReq.AddBAParameterSet.amsduSupported;
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid,
&psessionEntry->dph.dphHashTable);
if( pSta == NULL )
{
limLog( pMac, LOGE,
FL( "STA context not found - ignoring ADDBA from " ));
limPrintMacAddr( pMac, pHdr->sa, LOGE );
// FIXME - Should we do this?
status = eSIR_MAC_INABLITY_TO_CONFIRM_ASSOC_STATUS;
goto returnAfterError;
}
limLog( pMac, LOG1, FL( "ADDBA Req from STA "MAC_ADDRESS_STR " with AID %d"
" tid = %d policy = %d buffsize = %d"
" amsduSupported = %d"), MAC_ADDR_ARRAY(pHdr->sa),
aid, frmAddBAReq.AddBAParameterSet.tid,
frmAddBAReq.AddBAParameterSet.policy,
frmAddBAReq.AddBAParameterSet.bufferSize,
frmAddBAReq.AddBAParameterSet.amsduSupported);
limLog( pMac, LOG1, FL( "ssn = %d fragNumber = %d" ),
frmAddBAReq.BAStartingSequenceControl.ssn,
frmAddBAReq.BAStartingSequenceControl.fragNumber);
#ifdef WLAN_SOFTAP_VSTA_FEATURE
// we can only do BA on "hard" STAs
if (!(IS_HWSTA_IDX(pSta->staIndex)))
{
status = eSIR_MAC_REQ_DECLINED_STATUS;
limLog( pMac, LOG1,
FL( "ta Id is not HW Sta Id, Status code is %d " ), status);
goto returnAfterError;
}
#endif //WLAN_SOFTAP_VSTA_FEATURE
if (wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val1) !=
eSIR_SUCCESS)
{
limLog(pMac, LOGE,
FL("Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
val1 = 1;
}
if (!val1)
{
limLog(pMac, LOGE,
FL("aggregation disabled - ignoring ADDBA"));
goto returnAfterError;
}
if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_TX_BA_SESSIONS_2_4_G_BTC, &val) !=
eSIR_SUCCESS)
{
limLog(pMac, LOGE,
FL("Unable to get WNI_CFG_DEL_ALL_RX_TX_BA_SESSIONS_2_4_G_BTC"));
val = 0;
}
if ((SIR_BAND_2_4_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) &&
val)
{
limLog( pMac, LOGW,
FL( "BTC disabled aggregation - ignoring ADDBA from " ));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
status = eSIR_MAC_REQ_DECLINED_STATUS;
goto returnAfterError;
}
// Now, validate the ADDBA Req
if( eSIR_MAC_SUCCESS_STATUS !=
(status = __limValidateAddBAParameterSet( pMac, pSta,
frmAddBAReq.AddBAParameterSet,
0, //dialogue token is don't care in request validation.
LIM_ADDBA_REQ, &delBAFlag)))
{
limLog( pMac, LOGE,
FL( "ADDBA parameters validation failed with status %d" ), status);
goto returnAfterError;
}
//BA already set, so we need to delete it before adding new one.
if(delBAFlag)
{
if( eSIR_SUCCESS != limPostMsgDelBAInd( pMac,
pSta,
(tANI_U8)frmAddBAReq.AddBAParameterSet.tid,
eBA_RECIPIENT,psessionEntry))
{
status = eSIR_MAC_UNSPEC_FAILURE_STATUS;
limLog( pMac, LOGE,
FL( "Deletion of Existing BA session failed with status %d" ),
status);
goto returnAfterError;
}
}
// Check if the ADD BA Declined configuration is Disabled
if ((pMac->lim.gAddBA_Declined & ( 1 << frmAddBAReq.AddBAParameterSet.tid ) )) {
limLog( pMac, LOGE, FL( "Declined the ADDBA Req for the TID %d " ),
frmAddBAReq.AddBAParameterSet.tid);
status = eSIR_MAC_REQ_DECLINED_STATUS;
goto returnAfterError;
}
//
// Post WDA_ADDBA_REQ to HAL.
// If HAL/HDD decide to allow this ADDBA Req session,
// then this BA session is termed active
//
// Change the Block Ack state of this STA to wait for
// ADDBA Rsp from HAL
LIM_SET_STA_BA_STATE(pSta, frmAddBAReq.AddBAParameterSet.tid, eLIM_BA_STATE_WT_ADD_RSP);
if (wlan_cfgGetInt(pMac, WNI_CFG_NUM_BUFF_ADVERT , &val) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("Unable to get WNI_CFG_NUM_BUFF_ADVERT"));
return ;
}
if (frmAddBAReq.AddBAParameterSet.bufferSize)
{
frmAddBAReq.AddBAParameterSet.bufferSize =
VOS_MIN(val, frmAddBAReq.AddBAParameterSet.bufferSize);
}
else
{
frmAddBAReq.AddBAParameterSet.bufferSize = val;
}
limLog( pMac, LOG1, FL( "ADDBAREQ NUMBUFF %d" ),
frmAddBAReq.AddBAParameterSet.bufferSize);
if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac,
pSta,
(tANI_U8) frmAddBAReq.DialogToken.token,
(tANI_U8) frmAddBAReq.AddBAParameterSet.tid,
(tANI_U8) frmAddBAReq.AddBAParameterSet.policy,
frmAddBAReq.AddBAParameterSet.bufferSize,
frmAddBAReq.BATimeout.timeout,
(tANI_U16) frmAddBAReq.BAStartingSequenceControl.ssn,
eBA_RECIPIENT,psessionEntry))
{
status = eSIR_MAC_UNSPEC_FAILURE_STATUS;
limLog( pMac, LOGE,
FL( "Request to setup new BA session with peer "
" "MAC_ADDRESS_STR " failed" ), MAC_ADDR_ARRAY(pSta->staAddr));
}
else
return;
returnAfterError:
//
// Package LIM_MLM_ADDBA_RSP to MLME, with proper
// status code. MLME will then send an ADDBA RSP
// over the air to the peer MAC entity
//
if( eSIR_SUCCESS != limPostMlmAddBARsp( pMac,
pHdr->sa,
status,
frmAddBAReq.DialogToken.token,
(tANI_U8) frmAddBAReq.AddBAParameterSet.tid,
(tANI_U8) frmAddBAReq.AddBAParameterSet.policy,
frmAddBAReq.AddBAParameterSet.bufferSize,
frmAddBAReq.BATimeout.timeout,psessionEntry))
{
limLog( pMac, LOGW,
FL( "Failed to post LIM_MLM_ADDBA_RSP to " ));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
}
}
/**
* \brief Process an ADDBA RSP
*
* \sa limProcessAddBARsp
*
* \param pMac The global tpAniSirGlobal object
*
* \param pRxPacketInfo Handle to the packet info structure from HDD
*
* \return none
*
*/
static void
__limProcessAddBARsp( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tDot11fAddBARsp frmAddBARsp;
tpSirMacMgmtHdr pHdr;
tpDphHashNode pSta;
tSirMacReasonCodes reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON;
tANI_U16 aid;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable );
if( pSta == NULL )
{
limLog( pMac, LOGE,
FL( "STA context not found - ignoring ADDBA from " ));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
return;
}
#ifdef WLAN_SOFTAP_VSTA_FEATURE
// We can only do BA on "hard" STAs. We should not have issued an ADDBA
// Request, so we should never be processing a ADDBA Response
if (!(IS_HWSTA_IDX(pSta->staIndex)))
{
limLog( pMac, LOGE, FL( "Sta Id is not HW Sta Id " ));
return;
}
#endif //WLAN_SOFTAP_VSTA_FEATURE
// Unpack the received frame
nStatus = dot11fUnpackAddBARsp( pMac, pBody, frameLen, &frmAddBARsp );
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE,
FL( "Failed to unpack and parse an ADDBA Response (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
goto returnAfterError;
}
else if ( DOT11F_WARNED( nStatus ) )
{
limLog( pMac, LOGW,
FL( "There were warnings while unpacking an ADDBA Response (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
limLog( pMac, LOG1, FL( "ADDBA Rsp from STA "MAC_ADDRESS_STR " with AID %d "
"tid = %d policy = %d buffsize = %d "
"amsduSupported = %d status = %d"),
MAC_ADDR_ARRAY(pHdr->sa), aid,
frmAddBARsp.AddBAParameterSet.tid,
frmAddBARsp.AddBAParameterSet.policy,
frmAddBARsp.AddBAParameterSet.bufferSize,
frmAddBARsp.AddBAParameterSet.amsduSupported,
frmAddBARsp.Status.status);
//if there is no matchin dialougue token then ignore the response.
if(eSIR_SUCCESS != limSearchAndDeleteDialogueToken(pMac, frmAddBARsp.DialogToken.token,
pSta->assocId, frmAddBARsp.AddBAParameterSet.tid))
{
limLog(pMac, LOGE,
FL("dialogueToken in received addBARsp did not match with outstanding requests"));
return;
}
// Check first if the peer accepted the ADDBA Req
if( eSIR_MAC_SUCCESS_STATUS == frmAddBARsp.Status.status )
{
tANI_U32 val;
pMac->lim.staBaInfo[pSta->staIndex].
failed_count[frmAddBARsp.AddBAParameterSet.tid] = 0;
pMac->lim.staBaInfo[pSta->staIndex].
failed_timestamp[frmAddBARsp.AddBAParameterSet.tid] = 0;
if (wlan_cfgGetInt(pMac, WNI_CFG_NUM_BUFF_ADVERT , &val) != eSIR_SUCCESS)
{
limLog(pMac, LOG1, FL("Unable to get WNI_CFG_NUM_BUFF_ADVERT"));
goto returnAfterError;
}
if (0 == frmAddBARsp.AddBAParameterSet.bufferSize)
frmAddBARsp.AddBAParameterSet.bufferSize = val;
else
frmAddBARsp.AddBAParameterSet.bufferSize =
VOS_MIN(val, frmAddBARsp.AddBAParameterSet.bufferSize);
limLog( pMac, LOG1,
FL( "ADDBA RSP Buffsize = %d" ),
frmAddBARsp.AddBAParameterSet.bufferSize);
// Now, validate the ADDBA Rsp
if( eSIR_MAC_SUCCESS_STATUS !=
__limValidateAddBAParameterSet( pMac, pSta,
frmAddBARsp.AddBAParameterSet,
(tANI_U8)frmAddBARsp.DialogToken.token,
LIM_ADDBA_RSP, NULL))
{
limLog( pMac, LOGE,
FL( "ADDBA parameters validation failed" ));
goto returnAfterError;
}
}
else
{
pMac->lim.staBaInfo[pSta->staIndex].
failed_count[frmAddBARsp.AddBAParameterSet.tid]++;
pMac->lim.staBaInfo[pSta->staIndex].failed_timestamp[
frmAddBARsp.AddBAParameterSet.tid] = jiffies_to_msecs(jiffies);
goto returnAfterError;
}
// Change STA state to wait for ADDBA Rsp from HAL
LIM_SET_STA_BA_STATE(pSta, frmAddBARsp.AddBAParameterSet.tid, eLIM_BA_STATE_WT_ADD_RSP);
//
// Post WDA_ADDBA_REQ to HAL.
// If HAL/HDD decide to allow this ADDBA Rsp session,
// then this BA session is termed active
//
if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac,
pSta,
(tANI_U8) frmAddBARsp.DialogToken.token,
(tANI_U8) frmAddBARsp.AddBAParameterSet.tid,
(tANI_U8) frmAddBARsp.AddBAParameterSet.policy,
frmAddBARsp.AddBAParameterSet.bufferSize,
frmAddBARsp.BATimeout.timeout,
0,
eBA_INITIATOR,psessionEntry))
{
reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON;
limLog( pMac, LOGE,
FL( "Request to setup new BA session with peer "
" "MAC_ADDRESS_STR " failed" ), MAC_ADDR_ARRAY(pSta->staAddr));
}
else
return;
returnAfterError:
// TODO: Do we need to signal an error status to SME,
// if status != eSIR_MAC_SUCCESS_STATUS
// Restore STA "BA" State
LIM_SET_STA_BA_STATE(pSta, frmAddBARsp.AddBAParameterSet.tid, eLIM_BA_STATE_IDLE);
//
// Need to send a DELBA IND to peer, who
// would have setup a BA session with this STA
//
if( eSIR_MAC_SUCCESS_STATUS == frmAddBARsp.Status.status )
{
//
// Package LIM_MLM_DELBA_REQ to MLME, with proper
// status code. MLME will then send a DELBA IND
// over the air to the peer MAC entity
//
if( eSIR_SUCCESS != limPostMlmDelBAReq( pMac,
pSta,
eBA_INITIATOR,
(tANI_U8) frmAddBARsp.AddBAParameterSet.tid,
reasonCode, psessionEntry))
{
limLog( pMac, LOGW,
FL( "Failed to post LIM_MLM_DELBA_REQ to " ));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
}
}
}
/**
* \brief Process a DELBA Indication
*
* \sa limProcessDelBAInd
*
* \param pMac The global tpAniSirGlobal object
*
* \param pRxPacketInfo Handle to the Rx packet info from HDD
*
* \return none
*
*/
static void
__limProcessDelBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tDot11fDelBAInd frmDelBAInd;
tpSirMacMgmtHdr pHdr;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable );
if( pSta == NULL )
{
limLog( pMac, LOGE, FL( "STA context not found - ignoring DELBA from "));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
return;
}
limLog( pMac, LOG1, FL( "DELBA Ind from STA with AID %d" ), aid );
// Unpack the received frame
nStatus = dot11fUnpackDelBAInd( pMac, pBody, frameLen, &frmDelBAInd );
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE,
FL( "Failed to unpack and parse a DELBA Indication (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
return;
}
else if ( DOT11F_WARNED( nStatus ) )
{
limLog( pMac, LOGW,
FL( "There were warnings while unpacking a DELBA Indication (0x%08x, %d bytes):"),
nStatus,
frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
limLog( pMac, LOG1,
FL( "Received DELBA from: "MAC_ADDRESS_STR" for TID %d, Reason code %d" ),
MAC_ADDR_ARRAY(pHdr->sa),
frmDelBAInd.DelBAParameterSet.tid,
frmDelBAInd.Reason.code );
// Now, validate the DELBA Ind
if( eSIR_MAC_SUCCESS_STATUS != __limValidateDelBAParameterSet( pMac,
frmDelBAInd.DelBAParameterSet,
pSta ))
{
limLog( pMac, LOGE,
FL( "ADDBA parameters validation failed " ));
return;
}
//
// Post WDA_DELBA_IND to HAL and delete the
// existing BA session
//
// NOTE - IEEE 802.11-REVma-D8.0, Section 7.3.1.16
// is kind of confusing...
//
if( eSIR_SUCCESS != limPostMsgDelBAInd( pMac,
pSta,
(tANI_U8) frmDelBAInd.DelBAParameterSet.tid,
(eBA_RECIPIENT == frmDelBAInd.DelBAParameterSet.initiator)?
eBA_INITIATOR: eBA_RECIPIENT,psessionEntry))
limLog( pMac, LOGE, FL( "Posting WDA_DELBA_IND to HAL failed "));
return;
}
static void
__limProcessSMPowerSaveUpdate(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry)
{
#if 0
tpSirMacMgmtHdr pHdr;
tDot11fSMPowerSave frmSMPower;
tSirMacHTMIMOPowerSaveState state;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = SIR_MAC_BD_TO_MPDUHEADER( pBd );
pBody = SIR_MAC_BD_TO_MPDUDATA( pBd );
frameLen = SIR_MAC_BD_TO_PAYLOAD_LEN( pBd );
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable );
if( pSta == NULL ) {
limLog( pMac, LOGE,FL( "STA context not found - ignoring UpdateSM PSave Mode from " ));
limPrintMacAddr( pMac, pHdr->sa, LOGW );
return;
}
/**Unpack the received frame */
nStatus = dot11fUnpackSMPowerSave( pMac, pBody, frameLen, &frmSMPower);
if( DOT11F_FAILED( nStatus )) {
limLog( pMac, LOGE, FL( "Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
return;
}else if ( DOT11F_WARNED( nStatus ) ) {
limLog(pMac, LOGW, FL( "There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
limLog(pMac, LOGW, FL("Received SM Power save Mode update Frame with PS_Enable:%d"
"PS Mode: %d"), frmSMPower.SMPowerModeSet.PowerSave_En,
frmSMPower.SMPowerModeSet.Mode);
/** Update in the DPH Table about the Update in the SM Power Save mode*/
if (frmSMPower.SMPowerModeSet.PowerSave_En && frmSMPower.SMPowerModeSet.Mode)
state = eSIR_HT_MIMO_PS_DYNAMIC;
else if ((frmSMPower.SMPowerModeSet.PowerSave_En) && (frmSMPower.SMPowerModeSet.Mode ==0))
state = eSIR_HT_MIMO_PS_STATIC;
else if ((frmSMPower.SMPowerModeSet.PowerSave_En == 0) && (frmSMPower.SMPowerModeSet.Mode == 0))
state = eSIR_HT_MIMO_PS_NO_LIMIT;
else {
PELOGW(limLog(pMac, LOGW, FL("Received SM Power save Mode update Frame with invalid mode"));)
return;
}
if (state == pSta->htMIMOPSState) {
PELOGE(limLog(pMac, LOGE, FL("The PEER is already set in the same mode"));)
return;
}
/** Update in the HAL Station Table for the Update of the Protection Mode */
pSta->htMIMOPSState = state;
limPostSMStateUpdate(pMac,pSta->staIndex, pSta->htMIMOPSState);
#endif
}
#if defined WLAN_FEATURE_VOWIFI
static void
__limProcessRadioMeasureRequest( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry )
{
tpSirMacMgmtHdr pHdr;
tDot11fRadioMeasurementRequest frm;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
if( psessionEntry == NULL )
{
return;
}
/**Unpack the received frame */
nStatus = dot11fUnpackRadioMeasurementRequest( pMac, pBody, frameLen, &frm );
if( DOT11F_FAILED( nStatus )) {
limLog( pMac, LOGE, FL( "Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
return;
}else if ( DOT11F_WARNED( nStatus ) ) {
limLog(pMac, LOGW, FL( "There were warnings while unpacking a Radio Measure request (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
// Call rrm function to handle the request.
rrmProcessRadioMeasurementRequest( pMac, pHdr->sa, &frm, psessionEntry );
}
static void
__limProcessLinkMeasurementReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry )
{
tpSirMacMgmtHdr pHdr;
tDot11fLinkMeasurementRequest frm;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
if( psessionEntry == NULL )
{
return;
}
/**Unpack the received frame */
nStatus = dot11fUnpackLinkMeasurementRequest( pMac, pBody, frameLen, &frm );
if( DOT11F_FAILED( nStatus )) {
limLog( pMac, LOGE, FL( "Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
return;
}else if ( DOT11F_WARNED( nStatus ) ) {
limLog(pMac, LOGW, FL( "There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
// Call rrm function to handle the request.
rrmProcessLinkMeasurementRequest( pMac, pRxPacketInfo, &frm, psessionEntry );
}
static void
__limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESession psessionEntry )
{
tpSirMacMgmtHdr pHdr;
tDot11fNeighborReportResponse *pFrm;
tANI_U32 frameLen, nStatus;
tANI_U8 *pBody;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
pFrm = vos_mem_malloc(sizeof(tDot11fNeighborReportResponse));
if (NULL == pFrm)
{
limLog(pMac, LOGE, FL("Unable to allocate memory in __limProcessNeighborReport") );
return;
}
if(psessionEntry == NULL)
{
vos_mem_free(pFrm);
return;
}
/**Unpack the received frame */
nStatus = dot11fUnpackNeighborReportResponse( pMac, pBody, frameLen,pFrm );
if( DOT11F_FAILED( nStatus )) {
limLog( pMac, LOGE, FL( "Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
vos_mem_free(pFrm);
return;
}else if ( DOT11F_WARNED( nStatus ) ) {
limLog(pMac, LOGW, FL( "There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
//Call rrm function to handle the request.
rrmProcessNeighborReportResponse( pMac, pFrm, psessionEntry );
vos_mem_free(pFrm);
}
#endif
#ifdef WLAN_FEATURE_AP_HT40_24G
static void
__limProcess2040bssCoexistenceActionFrame(tpAniSirGlobal pMac,
tANI_U16 sessionId, tANI_U8 *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody , i;
tANI_U32 frameLen, nStatus;
tDot11fHT2040BSSCoexistenceManagementActionFrame *pFrm;
tpSirHT2040CoexInfoInd pSirSmeHT2040CoexInfoInd = NULL;
tANI_U16 length;
tSirMsgQ mmhMsg;
tANI_U8 num_channelList;
pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo );
pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
pFrm =
vos_mem_malloc(sizeof(tDot11fHT2040BSSCoexistenceManagementActionFrame));
if (NULL == pFrm)
{
limLog(pMac, LOGE, FL("Unable to allocate memory"));
return;
}
if(psessionEntry == NULL)
{
vos_mem_free(pFrm);
return;
}
/**Unpack the received frame */
nStatus = dot11fUnpackHT2040BSSCoexistenceManagementActionFrame( pMac,
pBody, frameLen, pFrm );
if( DOT11F_FAILED( nStatus ))
{
limLog( pMac, LOGE, FL( "Failed to unpack and parse a 20/40"
"Coex Action Frame (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
vos_mem_free(pFrm);
return;
}
else if ( DOT11F_WARNED( nStatus ))
{
limLog(pMac, LOGW, FL( "There were warnings while unpacking a"
" 20/40 Coex Action Frame (0x%08x, %d bytes):"),
nStatus, frameLen );
PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );)
}
num_channelList = pFrm->HT2040BSSIntolerantReport.num_channelList;
if (num_channelList > 0)
{
length = (sizeof(tSirHT2040CoexInfoInd) - sizeof(tANI_U8) +
(num_channelList * sizeof(tANI_U8)));
}
else
length = sizeof(tSirHT2040CoexInfoInd);
limLog(pMac, LOGW,FL("tSirHT2040CoexInfoInd: Length: %d"),length);
pSirSmeHT2040CoexInfoInd = vos_mem_malloc(length);
if (NULL == pSirSmeHT2040CoexInfoInd)
{
limLog(pMac, LOGP,
FL("AllocateMemory failed for eWNI_SME_2040_COEX_IND"));
vos_mem_free(pFrm);
return;
}
vos_mem_set((void*)pSirSmeHT2040CoexInfoInd, length, 0);
pSirSmeHT2040CoexInfoInd->messageType = eWNI_SME_2040_COEX_IND;
pSirSmeHT2040CoexInfoInd->sessionId = sessionId;
pSirSmeHT2040CoexInfoInd->length = length;
if (pFrm->HT2040BSSCoexistence.present)
{
limLog(pMac, LOGW, FL("infoRequest: %d fortyMHzIntolerant: %d"
" twentyMHzBssWidthReq: %d obssScanExemptionReq: %d"
" obssScanExemptionGrant: %d "),
pFrm->HT2040BSSCoexistence.infoRequest,
pFrm->HT2040BSSCoexistence.fortyMHzIntolerant,
pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq,
pFrm->HT2040BSSCoexistence.obssScanExemptionReq,
pFrm->HT2040BSSCoexistence.obssScanExemptionGrant);
pSirSmeHT2040CoexInfoInd->HT40MHzIntolerant =
pFrm->HT2040BSSCoexistence.fortyMHzIntolerant;
pSirSmeHT2040CoexInfoInd->HT20MHzBssWidthReq =
pFrm->HT2040BSSCoexistence.twentyMHzBssWidthReq;
}
if (pFrm->HT2040BSSIntolerantReport.present)
{
limLog(pMac, LOGW, FL("operatingClass: %d num_channelList: %d "),
pFrm->HT2040BSSIntolerantReport.operatingClass,
num_channelList);
if (num_channelList > 0)
{
vos_mem_zero(pSirSmeHT2040CoexInfoInd->HT2040BssIntoChanReport,
num_channelList);
vos_mem_copy(pSirSmeHT2040CoexInfoInd->HT2040BssIntoChanReport,
pFrm->HT2040BSSIntolerantReport.channelList,
num_channelList);
pSirSmeHT2040CoexInfoInd->channel_num = num_channelList;
}
for(i=0; i < num_channelList; i++)
{
limLog(pMac, LOGW, FL("Channel : %d "),
pSirSmeHT2040CoexInfoInd->HT2040BssIntoChanReport[i]);
}
}
mmhMsg.type = eWNI_SME_2040_COEX_IND;
mmhMsg.bodyptr = pSirSmeHT2040CoexInfoInd;
mmhMsg.bodyval = 0;
limLog(pMac, LOGW, FL("Posting eWNI_SME_2040_COEX_IND Message to SME "));
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
vos_mem_free(pFrm);
}
#endif
#ifdef WLAN_FEATURE_11W
/**
* limProcessSAQueryRequestActionFrame
*
*FUNCTION:
* This function is called by limProcessActionFrame() upon
* SA query request Action frame reception.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - Handle to the Rx packet info
* @param psessionEntry - PE session entry
*
* @return None
*/
static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tANI_U8 transId[2];
uint32_t frame_len;
/* Prima --- Below Macro not available in prima
pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd);
pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frame_len = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
if (frame_len < sizeof(struct sDot11fSaQueryReq)) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Invalid frame length"));
return;
}
/* If this is an unprotected SA Query Request, then ignore it. */
if (pHdr->fc.wep == 0)
return;
/*Extract 11w trsansId from SA query request action frame
In SA query response action frame we will send same transId
In SA query request action frame:
Category : 1 byte
Action : 1 byte
Transaction ID : 2 bytes */
vos_mem_copy(&transId[0], &pBody[2], 2);
//Send 11w SA query response action frame
if (limSendSaQueryResponseFrame(pMac,
transId,
pHdr->sa,psessionEntry) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame."));)
return;
}
}
/**
* __limProcessSAQueryResponseActionFrame
*
*FUNCTION:
* This function is called by limProcessActionFrame() upon
* SA query response Action frame reception.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - Handle to the Rx packet info
* @param psessionEntry - PE session entry
* @return None
*/
static void __limProcessSAQueryResponseActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tANI_U8 *pBody;
tpDphHashNode pSta;
tANI_U16 aid;
tANI_U16 transId;
tANI_U8 retryNum;
uint32_t frame_len;
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
frame_len = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("SA Query Response received...")) ;
if (frame_len < sizeof(struct sDot11fSaQueryRsp)) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Invalid frame length"));
return;
}
/* When a station, supplicant handles SA Query Response.
Forward to SME to HDD to wpa_supplicant. */
if (eLIM_STA_ROLE == psessionEntry->limSystemRole)
{
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo, psessionEntry,
WDA_GET_RX_RSSI_DB(pRxPacketInfo));
return;
}
/* If this is an unprotected SA Query Response, then ignore it. */
if (pHdr->fc.wep == 0)
return;
pSta = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
if (NULL == pSta)
return;
limLog(pMac, LOG1,
FL("SA Query Response source addr - %0x:%0x:%0x:%0x:%0x:%0x"),
pHdr->sa[0], pHdr->sa[1], pHdr->sa[2], pHdr->sa[3],
pHdr->sa[4], pHdr->sa[5]);
limLog(pMac, LOG1,
FL("SA Query state for station - %d"), pSta->pmfSaQueryState);
if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState)
return;
/* Extract 11w trsansId from SA query reponse action frame
In SA query response action frame:
Category : 1 byte
Action : 1 byte
Transaction ID : 2 bytes */
vos_mem_copy(&transId, &pBody[2], 2);
/* If SA Query is in progress with the station and the station
responds then the association request that triggered the SA
query is from a rogue station, just go back to initial state. */
for (retryNum = 0; retryNum <= pSta->pmfSaQueryRetryCount; retryNum++)
if (transId == pSta->pmfSaQueryStartTransId + retryNum)
{
limLog(pMac, LOG1,
FL("Found matching SA Query Request - transaction ID %d"), transId);
tx_timer_deactivate(&pSta->pmfSaQueryTimer);
pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
break;
}
}
#endif
#ifdef WLAN_FEATURE_11W
/**
* limDropUnprotectedActionFrame
*
*FUNCTION:
* This function checks if an Action frame should be dropped since it is
* a Robust Managment Frame, it is unprotected, and it is received on a
* connection where PMF is enabled.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Global MAC structure
* @param psessionEntry - PE session entry
* @param pHdr - Frame header
* @param category - Action frame category
* @return TRUE if frame should be dropped
*/
static tANI_BOOLEAN
limDropUnprotectedActionFrame (tpAniSirGlobal pMac, tpPESession psessionEntry,
tpSirMacMgmtHdr pHdr, tANI_U8 category)
{
tANI_U16 aid;
tpDphHashNode pStaDs;
tANI_BOOLEAN rmfConnection = eANI_BOOLEAN_FALSE;
if ((psessionEntry->limSystemRole == eLIM_AP_ROLE) ||
(psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE))
{
pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable);
if (pStaDs != NULL)
if (pStaDs->rmfEnabled)
rmfConnection = eANI_BOOLEAN_TRUE;
}
else if (psessionEntry->limRmfEnabled)
rmfConnection = eANI_BOOLEAN_TRUE;
if (rmfConnection && (pHdr->fc.wep == 0))
{
PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame "
"since RMF is enabled."), category);)
return eANI_BOOLEAN_TRUE;
}
else
return eANI_BOOLEAN_FALSE;
}
#endif
/**
* limProcessActionFrame
*
*FUNCTION:
* This function is called by limProcessMessageQueue() upon
* Action frame reception.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pRxPacketInfo - A pointer to packet info structure
* @return None
*/
void
limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry)
{
tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
tpSirMacActionFrameHdr pActionHdr = (tpSirMacActionFrameHdr) pBody;
tANI_U8 frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
if (frameLen < sizeof(*pActionHdr)) {
limLog(pMac, LOGE,
FL("frame_len %d less than Action Frame Hdr size"),
frameLen);
return;
}
#ifdef WLAN_FEATURE_11W
if (lim_is_robust_mgmt_action_frame(pActionHdr->category) &&
limDropUnprotectedActionFrame(pMac, psessionEntry, pHdr,
pActionHdr->category)) {
limLog(pMac, LOGE,
FL("Don't send unprotect action frame to upper layer categ %d "),
pActionHdr->category);
return;
}
#endif
switch (pActionHdr->category)
{
/*
* WARNING: If you add Action frame category case here, set the
* corresponding bit to 1 in sme_set_allowed_action_frames() for
* the FW to hand over that frame to host without dropping itself
*/
case SIR_MAC_ACTION_QOS_MGMT:
if ( (psessionEntry->limQosEnabled) ||
(pActionHdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE) )
{
switch (pActionHdr->actionID)
{
case SIR_MAC_QOS_ADD_TS_REQ:
__limProcessAddTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_ADD_TS_RSP:
__limProcessAddTsRsp(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_DEL_TS_REQ:
__limProcessDelTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_MAP_CONFIGURE:
__limProcessQosMapConfigureFrame(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
default:
limLog(pMac, LOG1,
FL("Qos action %d not handled"),
pActionHdr->actionID);
break;
}
break ;
}
break;
case SIR_MAC_ACTION_SPECTRUM_MGMT:
switch (pActionHdr->actionID)
{
#ifdef ANI_SUPPORT_11H
case SIR_MAC_ACTION_MEASURE_REQUEST_ID:
if(psessionEntry->lim11hEnable)
{
__limProcessMeasurementRequestFrame(pMac, pRxPacketInfo);
}
break;
case SIR_MAC_ACTION_TPC_REQUEST_ID:
if ((psessionEntry->limSystemRole == eLIM_STA_ROLE) ||
(pessionEntry->limSystemRole == eLIM_AP_ROLE))
{
if(psessionEntry->lim11hEnable)
{
__limProcessTpcRequestFrame(pMac, pRxPacketInfo);
}
}
break;
#endif
case SIR_MAC_ACTION_CHANNEL_SWITCH_ID:
if (psessionEntry->limSystemRole == eLIM_STA_ROLE)
{
__limProcessChannelSwitchActionFrame(pMac, pRxPacketInfo,psessionEntry);
}
break;
default:
limLog(pMac, LOG1,
FL("Spectrum mgmt action id %d not handled"),
pActionHdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_WME:
if (! psessionEntry->limWmeEnabled)
{
limLog(pMac, LOGW, FL("WME mode disabled - dropping action frame %d"),
pActionHdr->actionID);
break;
}
switch(pActionHdr->actionID)
{
case SIR_MAC_QOS_ADD_TS_REQ:
__limProcessAddTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_ADD_TS_RSP:
__limProcessAddTsRsp(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_DEL_TS_REQ:
__limProcessDelTsReq(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_QOS_MAP_CONFIGURE:
__limProcessQosMapConfigureFrame(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
default:
limLog(pMac, LOG1, FL("WME action %d not handled"),
pActionHdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_BLKACK:
// Determine the "type" of BA Action Frame
switch(pActionHdr->actionID)
{
case SIR_MAC_BLKACK_ADD_REQ:
__limProcessAddBAReq( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_BLKACK_ADD_RSP:
__limProcessAddBARsp( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
case SIR_MAC_BLKACK_DEL:
__limProcessDelBAReq( pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
default:
break;
}
break;
case SIR_MAC_ACTION_HT:
/** Type of HT Action to be performed*/
switch(pActionHdr->actionID) {
case SIR_MAC_SM_POWER_SAVE:
__limProcessSMPowerSaveUpdate(pMac, (tANI_U8 *) pRxPacketInfo,psessionEntry);
break;
default:
limLog(pMac, LOG1,
FL("Action ID %d not handled in HT Action category"),
pActionHdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_WNM:
{
PELOGE(limLog(pMac, LOG1, FL("WNM Action category %d action %d."),
pActionHdr->category, pActionHdr->actionID);)
switch (pActionHdr->actionID)
{
case SIR_MAC_WNM_BSS_TM_QUERY:
case SIR_MAC_WNM_BSS_TM_REQUEST:
case SIR_MAC_WNM_BSS_TM_RESPONSE:
case SIR_MAC_WNM_NOTIF_REQUEST:
case SIR_MAC_WNM_NOTIF_RESPONSE:
{
tANI_S8 rssi = WDA_GET_RX_RSSI_DB(pRxPacketInfo);
/* Forward to the SME to HDD to wpa_supplicant */
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo,
psessionEntry, rssi);
break;
}
}
break;
}
#if defined WLAN_FEATURE_VOWIFI
case SIR_MAC_ACTION_RRM:
/* Ignore RRM measurement request until DHCP is set */
if(pMac->rrm.rrmPEContext.rrmEnable &&
pMac->roam.roamSession[psessionEntry->smeSessionId].dhcp_done)
{
switch(pActionHdr->actionID) {
case SIR_MAC_RRM_RADIO_MEASURE_REQ:
__limProcessRadioMeasureRequest( pMac, (tANI_U8 *) pRxPacketInfo, psessionEntry );
break;
case SIR_MAC_RRM_LINK_MEASUREMENT_REQ:
__limProcessLinkMeasurementReq( pMac, (tANI_U8 *) pRxPacketInfo, psessionEntry );
break;
case SIR_MAC_RRM_NEIGHBOR_RPT:
__limProcessNeighborReport( pMac, (tANI_U8*) pRxPacketInfo, psessionEntry );
break;
default:
limLog( pMac, LOG1, FL("Action ID %d not handled in RRM"),
pActionHdr->actionID);
break;
}
}
else
{
// Else we will just ignore the RRM messages.
limLog( pMac, LOG1,
FL("RRM Action frame ignored as rrmEnable is %d or DHCP not completed %d"),
pMac->rrm.rrmPEContext.rrmEnable,
pMac->roam.roamSession[psessionEntry->smeSessionId].dhcp_done);
}
break;
#endif
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) \
|| defined (WLAN_FEATURE_RMC)
case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY:
{
tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) pActionHdr;
tANI_U8 Oui[] = { 0x00, 0x00, 0xf0 };
if(frameLen < sizeof(*pVendorSpecific)) {
limLog(pMac, LOGE,
FL("frame len %d less than Vendor Specific Hdr len"), frameLen);
break;
}
//Check if it is a vendor specific action frame.
if ((eLIM_STA_ROLE == psessionEntry->limSystemRole) &&
(VOS_TRUE == vos_mem_compare(psessionEntry->selfMacAddr,
&pHdr->da[0], sizeof(tSirMacAddr))) &&
IS_WES_MODE_ENABLED(pMac) &&
vos_mem_compare(pVendorSpecific->Oui, Oui, 3))
{
PELOGE( limLog( pMac, LOGW, FL("Received Vendor specific action frame, OUI %x %x %x"),
pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], pVendorSpecific->Oui[2]);)
/* Forward to the SME to HDD to wpa_supplicant */
// type is ACTION
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo,
psessionEntry, 0);
}
#if defined (WLAN_FEATURE_RMC)
else if ((eLIM_STA_IN_IBSS_ROLE == psessionEntry->limSystemRole) &&
((VOS_TRUE == vos_mem_compare(SIR_MAC_RMC_MCAST_ADDRESS,
&pHdr->da[0], sizeof(tSirMacAddr))) ||
(VOS_TRUE == vos_mem_compare(psessionEntry->selfMacAddr,
&pHdr->da[0], sizeof(tSirMacAddr)))) &&
vos_mem_compare(pVendorSpecific->Oui, SIR_MAC_RMC_OUI, 3))
{
tANI_U8 MagicCode[] =
{ 0x4f, 0x58, 0x59, 0x47, 0x45, 0x4e };
tpSirMacIbssExtNetworkFrameHdr pIbssExtHdr =
(tpSirMacIbssExtNetworkFrameHdr) pActionHdr;
if (vos_mem_compare(pIbssExtHdr->MagicCode,
MagicCode, sizeof(MagicCode)) &&
pIbssExtHdr->version == SIR_MAC_RMC_VER )
{
switch (pIbssExtHdr->actionID)
{
default:
PELOGE(limLog(pMac, LOGE,
FL("Action RMC actionID %d not handled"),
pIbssExtHdr->actionID);)
break;
case SIR_MAC_RMC_RULER_INFORM_SELECTED:
limLog(pMac, LOG1,
FL("Action RMC RULER_INFORM_SELECTED."));
limProcessRMCMessages(pMac,
eLIM_RMC_OTA_RULER_INFORM_SELECTED,
(tANI_U32 *)pRxPacketInfo);
break;
case SIR_MAC_RMC_RULER_INFORM_CANCELLED:
limLog(pMac, LOG1,
FL("Action RMC RULER_INFORM_CANCELLED."));
limProcessRMCMessages(pMac,
eLIM_RMC_OTA_RULER_INFORM_CANCELLED,
(tANI_U32 *)pRxPacketInfo);
break;
}
}
else
{
limLog( pMac, LOG1,
FL("Dropping the vendor specific action frame in IBSS "
"mode because of Ibss Ext Magic mismatch "
MAC_ADDRESS_STR " or Version mismatch = %d"),
MAC_ADDR_ARRAY(pIbssExtHdr->MagicCode),
pIbssExtHdr->version );
}
}
#endif /* WLAN_FEATURE_RMC */
else
{
limLog( pMac, LOG1,
FL("Dropping the vendor specific action frame because of( "
"WES Mode not enabled (WESMODE = %d) or OUI mismatch (%02x %02x %02x) or "
"not received with SelfSta Mac address) system role = %d"),
IS_WES_MODE_ENABLED(pMac),
pVendorSpecific->Oui[0], pVendorSpecific->Oui[1],
pVendorSpecific->Oui[2],
psessionEntry->limSystemRole );
}
}
break;
#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE ||
FEATURE_WLAN_LFR || WLAN_FEATURE_RMC */
case SIR_MAC_ACTION_PUBLIC_USAGE:
switch(pActionHdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
{
tpSirMacVendorSpecificPublicActionFrameHdr pPubAction = (tpSirMacVendorSpecificPublicActionFrameHdr) pActionHdr;
tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
if (frameLen < sizeof(*pActionHdr)) {
limLog(pMac, LOG1,
FL("Received action frame of invalid len %d"), frameLen);
break;
}
//Check if it is a P2P public action frame.
if (vos_mem_compare(pPubAction->Oui, P2POui, 4))
{
/* Forward to the SME to HDD to wpa_supplicant */
// type is ACTION
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo,
psessionEntry,
WDA_GET_RX_RSSI_DB(pRxPacketInfo));
}
else
{
limLog( pMac, LOG1,
FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"),
pPubAction->Oui[0], pPubAction->Oui[1],
pPubAction->Oui[2], pPubAction->Oui[3] );
}
}
break;
#ifdef WLAN_FEATURE_AP_HT40_24G
case SIR_MAC_ACTION_2040_BSS_COEXISTENCE:
{
if (pMac->roam.configParam.apHT40_24GEnabled)
{
limLog( pMac, LOGW, FL("Public Action 20/40 BSS"
"Coexistence Management frame"));
__limProcess2040bssCoexistenceActionFrame(pMac,
psessionEntry->smeSessionId, (tANI_U8 *) pRxPacketInfo,
psessionEntry);
}
break;
}
#endif
#ifdef FEATURE_WLAN_TDLS
case SIR_MAC_TDLS_DIS_RSP:
{
tANI_S8 rssi;
rssi = WDA_GET_RX_RSSI_DB(pRxPacketInfo);
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Public Action TDLS Discovery RSP ..")) ;
limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId,
pRxPacketInfo,
psessionEntry, rssi);
}
break;
#endif
case SIR_MAC_ACTION_EXT_CHANNEL_SWITCH_ID:
if (psessionEntry->limSystemRole == eLIM_STA_ROLE)
{
lim_process_ecsa_action_frame(pMac,
pRxPacketInfo, psessionEntry);
}
break;
default:
limLog(pMac, LOG1, FL("Unhandled public action frame -- %x "),
pActionHdr->actionID);
break;
}
break;
#ifdef WLAN_FEATURE_11W
case SIR_MAC_ACTION_SA_QUERY:
{
PELOGE(limLog(pMac, LOG1, FL("SA Query Action category %d action %d."), pActionHdr->category, pActionHdr->actionID);)
switch (pActionHdr->actionID)
{
case SIR_MAC_SA_QUERY_REQ:
/**11w SA query request action frame received**/
/* Respond directly to the incoming request in LIM */
__limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry );
break;
case SIR_MAC_SA_QUERY_RSP:
/**11w SA query response action frame received**/
/* Handle based on the current SA Query state */
__limProcessSAQueryResponseActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry );
break;
default:
break;
}
break;
}
#endif
#ifdef WLAN_FEATURE_11AC
case SIR_MAC_ACTION_VHT:
{
if (psessionEntry->vhtCapability)
{
switch (pActionHdr->actionID)
{
case SIR_MAC_VHT_OPMODE_NOTIFICATION:
__limProcessOperatingModeActionFrame(pMac,pRxPacketInfo,psessionEntry);
break;
default:
break;
}
}
break;
}
#endif
default:
limLog(pMac, LOG1,
FL("Action category %d not handled"), pActionHdr->category);
break;
}
}
/**
* limProcessActionFrameNoSession
*
*FUNCTION:
* This function is called by limProcessMessageQueue() upon
* Action frame reception and no session.
* Currently only public action frames can be received from
* a non-associated station.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param *pBd - A pointer to Buffer descriptor + associated PDUs
* @return None
*/
void
limProcessActionFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd)
{
tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd);
tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr = (tpSirMacVendorSpecificPublicActionFrameHdr) pBody;
tANI_U32 frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd);
limLog( pMac, LOG1, "Received a Action frame -- no session");
if (frameLen < sizeof(*pActionHdr)) {
limLog(pMac, LOGE,
FL("Received action frame of invalid len %d"), frameLen);
return;
}
switch ( pActionHdr->category )
{
case SIR_MAC_ACTION_PUBLIC_USAGE:
switch(pActionHdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
{
tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
//Check if it is a P2P public action frame.
if (vos_mem_compare(pActionHdr->Oui, P2POui, 4))
{
/* Forward to the SME to HDD to wpa_supplicant */
// type is ACTION
limSendSmeMgmtFrameInd(pMac, 0, pBd, NULL,
WDA_GET_RX_RSSI_DB(pBd));
}
else
{
limLog( pMac, LOG1,
FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"),
pActionHdr->Oui[0], pActionHdr->Oui[1],
pActionHdr->Oui[2], pActionHdr->Oui[3]);
}
}
break;
default:
limLog(pMac, LOG1,
FL("Unhandled public action frame -- %x "), pActionHdr->actionID);
break;
}
break;
default:
limLog(pMac, LOG1,
FL("Unhandled action frame without session -- %x "),
pActionHdr->category);
break;
}
}