blob: c77ae536ae9339ded143524bf8f989df40a7be65 [file] [log] [blame]
/*
* Copyright (c) 2012-2015 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 lim_process_action_frame.cc contains the code
* for processing Action Frame.
* Author: Michael Lui
* Date: 05/23/03
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "cds_api.h"
#include "wni_api.h"
#include "sir_api.h"
#include "ani_global.h"
#include "wni_cfg.h"
#include "sch_api.h"
#include "utils_api.h"
#include "lim_types.h"
#include "lim_utils.h"
#include "lim_assoc_utils.h"
#include "lim_security_utils.h"
#include "lim_ser_des_utils.h"
#include "lim_send_sme_rsp_messages.h"
#include "parser_api.h"
#include "lim_admit_control.h"
#include "wmm_apsd.h"
#include "lim_send_messages.h"
#if defined WLAN_FEATURE_VOWIFI
#include "rrm_api.h"
#endif
#include "lim_session_utils.h"
#include "wma_types.h"
#define BA_DEFAULT_TX_BUFFER_SIZE 64
/* 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 lim_stop_tx_and_switch_channel
\brief Stops the transmission if channel switch mode is silent and
starts the channel switch timer.
\param pMac
\return NONE
-----------------------------------------------------------------*/
void lim_stop_tx_and_switch_channel(tpAniSirGlobal pMac, uint8_t sessionId)
{
tpPESession psessionEntry;
psessionEntry = pe_find_session_by_session_id(pMac, sessionId);
if (NULL == psessionEntry) {
lim_log(pMac, LOGE, FL("Session %d not active"), sessionId);
return;
}
PELOG1(lim_log(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 */
lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_STOP_TX);
} else {
/* Resume the transmission */
lim_frame_transmission_control(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
*/
if (psessionEntry->gLimChannelSwitch.switchCount == 0) {
lim_process_channel_switch_timeout(pMac);
return;
}
MTRACE(mac_trace
(pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId,
eLIM_CHANNEL_SWITCH_TIMER));
if (tx_timer_activate(&pMac->lim.limTimers.gLimChannelSwitchTimer) !=
TX_SUCCESS) {
lim_log(pMac, LOGP, FL("tx_timer_activate failed"));
}
return;
}
/**------------------------------------------------------------
\fn lim_start_channel_switch
\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 lim_start_channel_switch(tpAniSirGlobal pMac,
tpPESession psessionEntry)
{
PELOG1(lim_log(pMac, LOG1, FL("Starting the channel switch"));)
/*If channel switch is already running and it is on a different session, just return */
/*This need to be removed for MCC */
if ((lim_is_chan_switch_running(pMac) &&
psessionEntry->gLimSpecMgmt.dot11hChanSwState !=
eLIM_11H_CHANSW_RUNNING) || psessionEntry->csaOffloadEnable) {
lim_log(pMac, LOGW, FL("Ignoring channel switch on session %d"),
psessionEntry->peSessionId);
return eSIR_SUCCESS;
}
/* Deactivate and change reconfigure the timeout value */
/* lim_deactivate_and_change_timer(pMac, eLIM_CHANNEL_SWITCH_TIMER); */
MTRACE(mac_trace
(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId,
eLIM_CHANNEL_SWITCH_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) !=
eSIR_SUCCESS) {
lim_log(pMac, LOGP, FL("tx_timer_deactivate failed!"));
return eSIR_FAILURE;
}
if (tx_timer_change(&pMac->lim.limTimers.gLimChannelSwitchTimer,
psessionEntry->gLimChannelSwitch.switchTimeoutValue,
0) != TX_SUCCESS) {
lim_log(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(mac_trace
(pMac, TRACE_CODE_TIMER_DEACTIVATE,
psessionEntry->peSessionId, eLIM_QUIET_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) !=
TX_SUCCESS) {
lim_log(pMac, LOGP, FL("tx_timer_deactivate failed"));
return eSIR_FAILURE;
}
} else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) {
MTRACE(mac_trace
(pMac, TRACE_CODE_TIMER_DEACTIVATE,
psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)
!= TX_SUCCESS) {
lim_log(pMac, LOGP, FL("tx_timer_deactivate failed"));
return eSIR_FAILURE;
}
}
psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
/* Prepare for 11h channel switch */
lim_prepare_for11h_channel_switch(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;
}
/**
* __lim_process_channel_switch_action_frame() - to process channel switch
* @mac_ctx: Pointer to Global MAC structure
* @rx_pkt_info: A pointer to packet info structure
*
* This routine will be called to process channel switch action frame
*
* Return: None
*/
static void __lim_process_channel_switch_action_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
tpSirMacMgmtHdr mac_hdr;
uint8_t *body_ptr;
tDot11fChannelSwitch *chnl_switch_frame;
uint16_t bcn_period;
uint32_t val, frame_len, status;
tLimChannelSwitchInfo *ch_switch_params;
struct sDot11fIEWiderBWChanSwitchAnn *wbw_chnlswitch_ie = NULL;
struct sLimWiderBWChannelSwitch *lim_wbw_chnlswitch_info = NULL;
struct sDot11fIEsec_chan_offset_ele *sec_chnl_offset = NULL;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
PELOG3(lim_log(mac_ctx, LOG3,
FL("Received Channel switch action frame"));)
if (!session->lim11hEnable)
return;
chnl_switch_frame = cdf_mem_malloc(sizeof(*chnl_switch_frame));
if (NULL == chnl_switch_frame) {
lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
return;
}
/* Unpack channel switch frame */
status = dot11f_unpack_channel_switch(mac_ctx, body_ptr, frame_len,
chnl_switch_frame);
if (DOT11F_FAILED(status)) {
lim_log(mac_ctx, LOGE,
FL("Failed to unpack and parse (0x%08x, %d bytes)"),
status, frame_len);
cdf_mem_free(chnl_switch_frame);
return;
} else if (DOT11F_WARNED(status)) {
lim_log(mac_ctx, LOGW,
FL("warning: unpack 11h-CHANSW Req(0x%08x, %d bytes)"),
status, frame_len);
}
if (!(cdf_mem_compare((uint8_t *) &session->bssId,
(uint8_t *) &mac_hdr->sa, sizeof(tSirMacAddr)))) {
lim_log(mac_ctx, LOG1,
FL("Rcvd action frame not from our BSS, dropping..."));
cdf_mem_free(chnl_switch_frame);
return;
}
/* copy the beacon interval from session */
val = session->beaconParams.beaconInterval;
ch_switch_params = &session->gLimChannelSwitch;
bcn_period = (uint16_t)val;
ch_switch_params->primaryChannel =
chnl_switch_frame->ChanSwitchAnn.newChannel;
ch_switch_params->switchCount =
chnl_switch_frame->ChanSwitchAnn.switchCount;
ch_switch_params->switchTimeoutValue =
SYS_MS_TO_TICKS(bcn_period) *
session->gLimChannelSwitch.switchCount;
ch_switch_params->switchMode =
chnl_switch_frame->ChanSwitchAnn.switchMode;
/* Only primary channel switch element is present */
ch_switch_params->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
ch_switch_params->ch_width = CH_WIDTH_20MHZ;
if (chnl_switch_frame->WiderBWChanSwitchAnn.present
&& session->vhtCapability) {
wbw_chnlswitch_ie = &chnl_switch_frame->WiderBWChanSwitchAnn;
session->gLimWiderBWChannelSwitch.newChanWidth =
wbw_chnlswitch_ie->newChanWidth;
session->gLimWiderBWChannelSwitch.newCenterChanFreq0 =
wbw_chnlswitch_ie->newCenterChanFreq0;
session->gLimWiderBWChannelSwitch.newCenterChanFreq1 =
wbw_chnlswitch_ie->newCenterChanFreq1;
}
lim_log(mac_ctx, LOG3,
FL("Rcv Chnl Swtch Frame: Timeout in %d ticks"),
session->gLimChannelSwitch.switchTimeoutValue);
if (session->htSupportedChannelWidthSet) {
sec_chnl_offset = &chnl_switch_frame->sec_chan_offset_ele;
if (sec_chnl_offset->secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
ch_switch_params->state =
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
ch_switch_params->ch_width = CH_WIDTH_40MHZ;
ch_switch_params->ch_center_freq_seg0 =
ch_switch_params->primaryChannel + 2;
} else if (sec_chnl_offset->secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
ch_switch_params->state =
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
ch_switch_params->ch_width = CH_WIDTH_40MHZ;
ch_switch_params->ch_center_freq_seg0 =
ch_switch_params->primaryChannel - 2;
}
if (session->vhtCapability &&
chnl_switch_frame->WiderBWChanSwitchAnn.present) {
wbw_chnlswitch_ie =
&chnl_switch_frame->WiderBWChanSwitchAnn;
ch_switch_params->ch_width =
wbw_chnlswitch_ie->newChanWidth + 1;
lim_wbw_chnlswitch_info =
&session->gLimWiderBWChannelSwitch;
ch_switch_params->ch_center_freq_seg0 =
lim_wbw_chnlswitch_info->newCenterChanFreq0;
ch_switch_params->ch_center_freq_seg1 =
lim_wbw_chnlswitch_info->newCenterChanFreq1;
}
}
if (CH_WIDTH_20MHZ == ch_switch_params->ch_width) {
session->htSupportedChannelWidthSet =
WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
session->htRecommendedTxWidthSet =
session->htSupportedChannelWidthSet;
}
if (eSIR_SUCCESS != lim_start_channel_switch(mac_ctx, session))
lim_log(mac_ctx, LOG1,
FL("Could not start channel switch"));
cdf_mem_free(chnl_switch_frame);
return;
}
#ifdef WLAN_FEATURE_11AC
/**
* __lim_process_operating_mode_action_frame() - To process op mode frames
* @mac_ctx: pointer to mac context
* @rx_pkt_info: pointer to received packet info
* @session: pointer to session
*
* This routine is called to process operating mode action frames
*
* Return: None
*/
static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
tpSirMacMgmtHdr mac_hdr;
uint8_t *body_ptr;
tDot11fOperatingMode *operating_mode_frm;
uint32_t frame_len;
uint32_t status;
tpDphHashNode sta_ptr;
uint16_t aid;
uint8_t oper_mode;
uint8_t cb_mode;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
lim_log(mac_ctx, LOG1,
FL("Received Operating Mode action frame"));
if (RF_CHAN_14 >= session->currentOperChannel)
cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
else
cb_mode = mac_ctx->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 == cb_mode) {
lim_log(mac_ctx, LOGW, FL("channel bonding disabled"));
return;
}
operating_mode_frm = cdf_mem_malloc(sizeof(*operating_mode_frm));
if (NULL == operating_mode_frm) {
lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
return;
}
/* Unpack channel switch frame */
status = dot11f_unpack_operating_mode(mac_ctx, body_ptr, frame_len,
operating_mode_frm);
if (DOT11F_FAILED(status)) {
lim_log(mac_ctx, LOGE,
FL("Failed to unpack and parse (0x%08x, %d bytes)"),
status, frame_len);
cdf_mem_free(operating_mode_frm);
return;
} else if (DOT11F_WARNED(status)) {
lim_log(mac_ctx, LOGW,
FL("warnings while unpacking (0x%08x, %d bytes):"),
status, frame_len);
}
sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
&session->dph.dphHashTable);
if (sta_ptr->htSupportedChannelWidthSet) {
if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ <
sta_ptr->vhtSupportedChannelWidthSet)
oper_mode = eHT_CHANNEL_WIDTH_160MHZ;
else
oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1;
} else {
oper_mode = eHT_CHANNEL_WIDTH_20MHZ;
}
if (oper_mode != operating_mode_frm->OperatingMode.chanWidth) {
lim_log(mac_ctx, LOGE,
FL(" received Chanwidth %d, staIdx = %d"),
(operating_mode_frm->OperatingMode.chanWidth),
sta_ptr->staIndex);
lim_log(mac_ctx, LOGE,
FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
if (operating_mode_frm->OperatingMode.chanWidth ==
eHT_CHANNEL_WIDTH_160MHZ) {
sta_ptr->vhtSupportedChannelWidthSet =
WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
sta_ptr->htSupportedChannelWidthSet =
eHT_CHANNEL_WIDTH_40MHZ;
} else if (operating_mode_frm->OperatingMode.chanWidth ==
eHT_CHANNEL_WIDTH_80MHZ) {
sta_ptr->vhtSupportedChannelWidthSet =
WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
sta_ptr->htSupportedChannelWidthSet =
eHT_CHANNEL_WIDTH_40MHZ;
} else if (operating_mode_frm->OperatingMode.chanWidth ==
eHT_CHANNEL_WIDTH_40MHZ) {
sta_ptr->vhtSupportedChannelWidthSet =
WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
sta_ptr->htSupportedChannelWidthSet =
eHT_CHANNEL_WIDTH_40MHZ;
} else if (operating_mode_frm->OperatingMode.chanWidth ==
eHT_CHANNEL_WIDTH_20MHZ) {
sta_ptr->vhtSupportedChannelWidthSet =
WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
sta_ptr->htSupportedChannelWidthSet =
eHT_CHANNEL_WIDTH_20MHZ;
}
lim_check_vht_op_mode_change(mac_ctx, session,
operating_mode_frm->OperatingMode.chanWidth,
sta_ptr->staIndex, mac_hdr->sa);
}
if (sta_ptr->vhtSupportedRxNss !=
(operating_mode_frm->OperatingMode.rxNSS + 1)) {
sta_ptr->vhtSupportedRxNss =
operating_mode_frm->OperatingMode.rxNSS + 1;
lim_set_nss_change(mac_ctx, session, sta_ptr->vhtSupportedRxNss,
sta_ptr->staIndex, mac_hdr->sa);
}
cdf_mem_free(operating_mode_frm);
return;
}
/**
* __lim_process_gid_management_action_frame() - To process group-id mgmt frames
* @mac_ctx: Pointer to mac context
* @rx_pkt_info: Rx packet info
* @session: pointer to session
*
* This routine will be called to process group id management frames
*
* Return: none
*/
static void __lim_process_gid_management_action_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
uint8_t *body_ptr;
uint16_t aid;
uint32_t frame_len, status, membership = 0, usr_position = 0;
uint32_t *mem_lower, *mem_upper, *mem_cur;
tpSirMacMgmtHdr mac_hdr;
tDot11fVHTGidManagementActionFrame *gid_mgmt_frame;
tpDphHashNode sta_ptr;
struct sDot11fFfVhtMembershipStatusArray *vht_member_status = NULL;
struct sDot11fFfVhtUserPositionArray *vht_user_position = NULL;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
lim_log(mac_ctx, LOG3, FL("Received GID Management action frame"));
gid_mgmt_frame = cdf_mem_malloc(sizeof(*gid_mgmt_frame));
if (NULL == gid_mgmt_frame) {
lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
return;
}
/* Unpack Gid Mangement Action frame */
status = dot11f_unpack_vht_gid_management_action_frame(mac_ctx,
body_ptr, frame_len, gid_mgmt_frame);
if (DOT11F_FAILED(status)) {
lim_log(mac_ctx, LOGE,
FL("Fail to parse an Grp id frame (0x%08x, %d bytes):"),
status, frame_len);
cdf_mem_free(gid_mgmt_frame);
return;
} else if (DOT11F_WARNED(status)) {
lim_log(mac_ctx, LOGW,
FL("warnings while unpacking Grp id frm (0x%08x, %d bytes):"),
status, frame_len);
}
sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
&session->dph.dphHashTable);
lim_log(mac_ctx, LOGE,
FL("received Gid Management Action Frame , staIdx = %d"),
sta_ptr->staIndex);
lim_log(mac_ctx, LOGE,
FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
vht_member_status = &gid_mgmt_frame->VhtMembershipStatusArray;
mem_lower = (uint32_t *) vht_member_status->membershipStatusArray;
mem_upper = (uint32_t *) &vht_member_status->membershipStatusArray[4];
if (*mem_lower && *mem_upper) {
lim_log(mac_ctx, LOGE,
FL("rcved frame with mult group ID set, staIdx = %d"),
sta_ptr->staIndex);
goto out;
}
if (*mem_lower) {
mem_cur = mem_lower;
} else if (*mem_upper) {
mem_cur = mem_upper;
membership += sizeof(uint32_t);
} else {
lim_log(mac_ctx, LOGE,
FL("rcved Gid frame with no group ID set, staIdx = %d"),
sta_ptr->staIndex);
goto out;
}
while (!(*mem_cur & 1)) {
*mem_cur >>= 1;
++membership;
}
if (*mem_cur) {
lim_log(mac_ctx, LOGE,
FL("rcved frame with mult group ID set, staIdx = %d"),
sta_ptr->staIndex);
goto out;
}
/*Just read the last two bits */
vht_user_position = &gid_mgmt_frame->VhtUserPositionArray;
usr_position = vht_user_position->userPositionArray[membership] & 0x3;
lim_check_membership_user_position(mac_ctx, session, membership,
usr_position, sta_ptr->staIndex);
out:
cdf_mem_free(gid_mgmt_frame);
return;
}
#endif
static void
__lim_process_add_ts_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
}
/**
* __lim_process_add_ts_rsp() - To process add ts response frame
* @mac_ctx: pointer to mac context
* @rx_pkt_info: Received packet info
* @session: pointer to session
*
* This routine is to handle add ts response frame
*
* Return: none
*/
static void __lim_process_add_ts_rsp(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
tSirAddtsRspInfo addts;
tSirRetStatus retval;
tpSirMacMgmtHdr mac_hdr;
tpDphHashNode sta_ptr;
uint16_t aid;
uint32_t frameLen;
uint8_t *body_ptr;
tpLimTspecInfo tspec_info;
uint8_t ac;
tpDphHashNode sta_ds_ptr = NULL;
uint8_t rsp_reqd = 1;
uint32_t cfg_len;
tSirMacAddr peer_macaddr;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frameLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
lim_log(mac_ctx, LOGW, "Recv AddTs Response");
if (LIM_IS_AP_ROLE(session) ||
LIM_IS_BT_AMP_AP_ROLE(session)) {
lim_log(mac_ctx, LOGW,
FL("AddTsRsp recvd at AP: ignoring"));
return;
}
sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
&session->dph.dphHashTable);
if (sta_ptr == NULL) {
lim_log(mac_ctx, LOGE,
FL("Station context not found - ignoring AddTsRsp"));
return;
}
retval = sir_convert_addts_rsp2_struct(mac_ctx, body_ptr,
frameLen, &addts);
if (retval != eSIR_SUCCESS) {
lim_log(mac_ctx, 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 (!mac_ctx->lim.gLimAddtsSent) {
/* we never sent an addts request! */
lim_log(mac_ctx, LOGW,
FL("rx AddTsRsp but no req was ever sent-ignoring"));
return;
}
if (mac_ctx->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken) {
lim_log(mac_ctx, LOGW,
FL("token mismatch (got %d, exp %d) - ignoring"),
addts.dialogToken,
mac_ctx->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 */
lim_log(mac_ctx, LOGE,
FL("Sta %d: Too many Tclas (%d), 1 supported"),
aid, addts.numTclas);
return;
} else if (addts.numTclas == 1) {
lim_log(mac_ctx, LOGW,
FL("Response from STA %d: tsid %d, UP %d, OK!"),
aid, addts.tspec.tsinfo.traffic.tsid,
addts.tspec.tsinfo.traffic.userPrio);
}
}
lim_log(mac_ctx, LOGW, FL("Recv AddTsRsp: tsid %d, UP %d, status %d "),
addts.tspec.tsinfo.traffic.tsid,
addts.tspec.tsinfo.traffic.userPrio, addts.status);
/* deactivate the response timer */
lim_deactivate_and_change_timer(mac_ctx, eLIM_ADDTS_RSP_TIMER);
if (addts.status != eSIR_MAC_SUCCESS_STATUS) {
lim_log(mac_ctx, LOGW,
FL("Recv AddTsRsp: tsid %d, UP %d, status %d "),
addts.tspec.tsinfo.traffic.tsid,
addts.tspec.tsinfo.traffic.userPrio, addts.status);
lim_send_sme_addts_rsp(mac_ctx, true, addts.status, session,
addts.tspec, session->smeSessionId,
session->transactionId);
/* clear the addts flag */
mac_ctx->lim.gLimAddtsSent = false;
return;
}
#ifdef FEATURE_WLAN_ESE
if (addts.tsmPresent) {
lim_log(mac_ctx, LOGW, "TSM IE Present");
session->eseContext.tsm.tid =
addts.tspec.tsinfo.traffic.userPrio;
cdf_mem_copy(&session->eseContext.tsm.tsmInfo,
&addts.tsmIE, sizeof(tSirMacESETSMIE));
#ifdef FEATURE_WLAN_ESE_UPLOAD
lim_send_sme_tsm_ie_ind(mac_ctx, session, addts.tsmIE.tsid,
addts.tsmIE.state,
addts.tsmIE.msmt_interval);
#else
limActivateTSMStatsTimer(mac_ctx, session);
#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)
lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
&addts.tspec.tsinfo,
SET_UAPSD_MASK);
else
lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
&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) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
} else if (addts.tspec.tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_DNLINK) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
} else if (addts.tspec.tsinfo.traffic.direction ==
SIR_MAC_DIRECTION_BIDIR) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
(1 << ac);
session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
(1 << ac);
}
lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
session);
sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
&session->dph.dphHashTable);
if (sta_ds_ptr != NULL)
lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
sta_ds_ptr->bssId);
else
lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table "));
sir_copy_mac_addr(peer_macaddr, session->bssId);
/* if schedule is not present then add TSPEC with svcInterval as 0. */
if (!addts.schedulePresent)
addts.schedule.svcInterval = 0;
if (eSIR_SUCCESS !=
lim_tspec_add(mac_ctx, sta_ptr->staAddr, sta_ptr->assocId,
&addts.tspec, addts.schedule.svcInterval, &tspec_info)) {
lim_log(mac_ctx, LOGE,
FL("Adding entry in lim Tspec Table failed "));
lim_send_delts_req_action_frame(mac_ctx, peer_macaddr, rsp_reqd,
&addts.tspec.tsinfo,
&addts.tspec, session);
mac_ctx->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))) {
#ifdef FEATURE_WLAN_ESE
retval = lim_send_hal_msg_add_ts(mac_ctx,
sta_ptr->staIndex, tspec_info->idx,
addts.tspec, session->peSessionId,
addts.tsmIE.msmt_interval);
#else
retval = lim_send_hal_msg_add_ts(mac_ctx,
sta_ptr->staIndex, tspec_info->idx,
addts.tspec, session->peSessionId);
#endif
if (eSIR_SUCCESS != retval) {
lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId,
&addts.tspec.tsinfo, NULL, &tspec_info->idx);
/* Send DELTS action frame to AP */
cfg_len = sizeof(tSirMacAddr);
lim_send_delts_req_action_frame(mac_ctx, peer_macaddr,
rsp_reqd, &addts.tspec.tsinfo,
&addts.tspec, session);
lim_send_sme_addts_rsp(mac_ctx, true, retval,
session, addts.tspec,
session->smeSessionId,
session->transactionId);
mac_ctx->lim.gLimAddtsSent = false;
return;
}
lim_log(mac_ctx, LOGW,
FL("AddTsRsp received successfully(UP %d, TSID %d)"),
addts.tspec.tsinfo.traffic.userPrio,
addts.tspec.tsinfo.traffic.tsid);
} else {
lim_log(mac_ctx, LOGW,
FL("AddTsRsp received successfully(UP %d, TSID %d)"),
addts.tspec.tsinfo.traffic.userPrio,
addts.tspec.tsinfo.traffic.tsid);
lim_log(mac_ctx, LOGW,
FL("no ACM: Bypass sending WMA_ADD_TS_REQ to HAL "));
/*
* Use the smesessionId and smetransactionId from the PE
* session context
*/
lim_send_sme_addts_rsp(mac_ctx, true, eSIR_SME_SUCCESS,
session, addts.tspec, session->smeSessionId,
session->transactionId);
}
/* clear the addts flag */
mac_ctx->lim.gLimAddtsSent = false;
return;
}
/**
* __lim_process_del_ts_req() - To process del ts response frame
* @mac_ctx: pointer to mac context
* @rx_pkt_info: Received packet info
* @session: pointer to session
*
* This routine is to handle del ts request frame
*
* Return: none
*/
static void __lim_process_del_ts_req(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
tSirRetStatus retval;
tSirDeltsReqInfo delts;
tpSirMacMgmtHdr mac_hdr;
tpDphHashNode sta_ptr;
uint32_t frame_len;
uint16_t aid;
uint8_t *body_ptr;
uint8_t ts_status;
tSirMacTSInfo *tsinfo;
uint8_t tspec_idx;
uint8_t ac;
tpDphHashNode sta_ds_ptr = NULL;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
&session->dph.dphHashTable);
if (sta_ptr == NULL) {
lim_log(mac_ctx, LOGE,
FL("Station context not found - ignoring DelTs"));
return;
}
/* parse the delts request */
retval = sir_convert_delts_req2_struct(mac_ctx, body_ptr,
frame_len, &delts);
if (retval != eSIR_SUCCESS) {
lim_log(mac_ctx, LOGW,
FL("DelTs parsing failed (error %d)"), retval);
return;
}
if (delts.wmeTspecPresent) {
if ((!session->limWmeEnabled) || (!sta_ptr->wmeEnabled)) {
lim_log(mac_ctx, LOGW,
FL("Ignore delts req: wme not enabled"));
return;
}
lim_log(mac_ctx, LOG2, FL("WME Delts received"));
} else if ((session->limQosEnabled) && sta_ptr->lleEnabled) {
lim_log(mac_ctx, LOG2, FL("11e QoS Delts received"));
} else if ((session->limWsmEnabled) && sta_ptr->wsmEnabled) {
lim_log(mac_ctx, LOG2, FL("WSM Delts received"));
} else {
lim_log(mac_ctx, 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) {
lim_log(mac_ctx, LOGW,
FL("DelTs with UP %d has no AC - ignoring req"),
tsinfo->traffic.userPrio);
return;
}
}
if (!LIM_IS_AP_ROLE(session) &&
!LIM_IS_BT_AMP_AP_ROLE(session))
lim_send_sme_delts_ind(mac_ctx, &delts, aid, session);
/* try to delete the TS */
if (eSIR_SUCCESS !=
lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId, tsinfo,
&ts_status, &tspec_idx)) {
lim_log(mac_ctx, LOGW, FL("Unable to Delete TS"));
return;
} else if (!((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA)
|| (tsinfo->traffic.accessPolicy ==
SIR_MAC_ACCESSPOLICY_BOTH))){
/* send message to HAL to delete TS */
if (eSIR_SUCCESS != lim_send_hal_msg_del_ts(mac_ctx,
sta_ptr->staIndex, tspec_idx,
delts, session->peSessionId,
session->bssId)) {
lim_log(mac_ctx, LOGW,
FL("DelTs with UP %d failed 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.
*/
lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
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) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
~(1 << ac);
} else if (tsinfo->traffic.direction ==
SIR_MAC_DIRECTION_DNLINK) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
~(1 << ac);
} else if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) {
session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
~(1 << ac);
session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
~(1 << ac);
}
lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
session);
sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
&session->dph.dphHashTable);
if (sta_ds_ptr != NULL)
lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
sta_ds_ptr->bssId);
else
lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table "));
lim_log(mac_ctx, LOG1, FL("DeleteTS succeeded"));
#ifdef FEATURE_WLAN_ESE
#ifdef FEATURE_WLAN_ESE_UPLOAD
lim_send_sme_tsm_ie_ind(mac_ctx, session, 0, 0, 0);
#else
lim_deactivate_and_change_timer(mac_ctx, eLIM_TSM_TIMER);
#endif /* FEATURE_WLAN_ESE_UPLOAD */
#endif
}
/**
* __lim_process_qos_map_configure_frame() - to process QoS map configure frame
* @mac_ctx: pointer to mac context
* @rx_pkt_info: pointer to received packet info
* @session: pointer to session
*
* This routine will called to process qos map configure frame
*
* Return: none
*/
static void __lim_process_qos_map_configure_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
tpSirMacMgmtHdr mac_hdr;
uint32_t frame_len;
uint8_t *body_ptr;
tSirRetStatus retval;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
retval = sir_convert_qos_map_configure_frame2_struct(mac_ctx,
body_ptr, frame_len, &session->QosMapSet);
if (retval != eSIR_SUCCESS) {
lim_log(mac_ctx, LOGE,
FL("QosMapConfigure frame parsing fail(error %d)"),
retval);
return;
}
lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
(uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr), 0,
WMA_GET_RX_CH(rx_pkt_info), session, 0);
}
#ifdef ANI_SUPPORT_11H
static void
__lim_process_basic_meas_req(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr, tpPESession psessionEntry)
{
if (lim_send_meas_report_frame(pMac,
pMeasReqFrame,
peerMacAddr, psessionEntry) != eSIR_SUCCESS)
{
PELOGE(lim_log
(pMac, LOGE, FL("fail to send Basic Meas report "));
)
return;
}
}
static void
__lim_process_cca_meas_req(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr, tpPESession psessionEntry)
{
if (lim_send_meas_report_frame(pMac,
pMeasReqFrame,
peerMacAddr, psessionEntry) != eSIR_SUCCESS)
{
PELOGE(lim_log(pMac, LOGE, FL("fail to send CCA Meas report "));)
return;
}
}
static void
__lim_process_rpi_meas_req(tpAniSirGlobal pMac,
tpSirMacMeasReqActionFrame pMeasReqFrame,
tSirMacAddr peerMacAddr, tpPESession psessionEntry)
{
if (lim_send_meas_report_frame(pMac,
pMeasReqFrame,
peerMacAddr, psessionEntry) != eSIR_SUCCESS)
{
PELOGE(lim_log(pMac, LOGE, FL("fail to send RPI Meas report "));)
return;
}
}
static void
__lim_process_measurement_request_frame(tpAniSirGlobal pMac,
uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
uint8_t *pBody;
tpSirMacMeasReqActionFrame pMeasReqFrame;
uint32_t frameLen;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pMeasReqFrame = cdf_mem_malloc(sizeof(tSirMacMeasReqActionFrame));
if (NULL == pMeasReqFrame) {
lim_log(pMac, LOGE,
FL
("limProcessMeasurementRequestFrame: AllocateMemory failed "));
return;
}
if (sir_convert_meas_req_frame2_struct(pMac, pBody, pMeasReqFrame, frameLen)
!= eSIR_SUCCESS) {
PELOGW(lim_log
(pMac, LOGW,
FL("Rcv invalid Measurement Request Action Frame "));
)
return;
}
switch (pMeasReqFrame->measReqIE.measType) {
case SIR_MAC_BASIC_MEASUREMENT_TYPE:
__lim_process_basic_meas_req(pMac, pMeasReqFrame, pHdr->sa,
psessionEntry);
break;
case SIR_MAC_CCA_MEASUREMENT_TYPE:
__lim_process_cca_meas_req(pMac, pMeasReqFrame, pHdr->sa,
psessionEntry);
break;
case SIR_MAC_RPI_MEASUREMENT_TYPE:
__lim_process_rpi_meas_req(pMac, pMeasReqFrame, pHdr->sa,
psessionEntry);
break;
default:
PELOG1(lim_log(pMac, LOG1, FL("Unknown Measurement Type %d "),
pMeasReqFrame->measReqIE.measType);
)
break;
}
} /*** end limProcessMeasurementRequestFrame ***/
static void
__lim_process_tpc_request_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
uint8_t *pBody;
tpSirMacTpcReqActionFrame pTpcReqFrame;
uint32_t frameLen;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
PELOG1(lim_log
(pMac, LOG1,
FL("****LIM: Processing TPC Request from peer ****"));
)
pTpcReqFrame = cdf_mem_malloc(sizeof(tSirMacTpcReqActionFrame));
if (NULL == pTpcReqFrame) {
PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory failed "));)
return;
}
if (sir_convert_tpc_req_frame2_struct(pMac, pBody, pTpcReqFrame, frameLen) !=
eSIR_SUCCESS) {
PELOGW(lim_log
(pMac, LOGW, FL("Rcv invalid TPC Req Action Frame "));
)
return;
}
if (lim_send_tpc_report_frame(pMac,
pTpcReqFrame,
pHdr->sa, psessionEntry) != eSIR_SUCCESS) {
PELOGE(lim_log
(pMac, LOGE, FL("fail to send TPC Report Frame. "));
)
return;
}
}
#endif
static void
__lim_process_sm_power_save_update(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tDot11fSMPowerSave frmSMPower;
tSirMacHTMIMOPowerSaveState state;
tpDphHashNode pSta;
uint16_t aid;
uint32_t frameLen, nStatus;
uint8_t *pBody;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pSta =
dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
&psessionEntry->dph.dphHashTable);
if (pSta == NULL) {
lim_log(pMac, LOGE,
FL
("STA context not found - ignoring UpdateSM PSave Mode from "));
lim_print_mac_addr(pMac, pHdr->sa, LOGW);
return;
}
/**Unpack the received frame */
nStatus = dot11f_unpack_sm_power_save(pMac, pBody, frameLen, &frmSMPower);
if (DOT11F_FAILED(nStatus)) {
lim_log(pMac, LOGE,
FL
("Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
return;
} else if (DOT11F_WARNED(nStatus)) {
lim_log(pMac, LOGW,
FL
("There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
}
lim_log(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(lim_log
(pMac, LOGW,
FL
("Received SM Power save Mode update Frame with invalid mode"));
)
return;
}
if (state == pSta->htMIMOPSState) {
PELOGE(lim_log
(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;
lim_post_sm_state_update(pMac, pSta->staIndex, pSta->htMIMOPSState,
pSta->staAddr, psessionEntry->smeSessionId);
}
#if defined WLAN_FEATURE_VOWIFI
static void
__lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tDot11fRadioMeasurementRequest frm;
uint32_t frameLen, nStatus;
uint8_t *pBody;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
if (psessionEntry == NULL) {
return;
}
lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *)pHdr,
frameLen + sizeof(tSirMacMgmtHdr), 0,
WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, 0);
/**Unpack the received frame */
nStatus =
dot11f_unpack_radio_measurement_request(pMac, pBody, frameLen, &frm);
if (DOT11F_FAILED(nStatus)) {
lim_log(pMac, LOGE,
FL
("Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
return;
} else if (DOT11F_WARNED(nStatus)) {
lim_log(pMac, LOGW,
FL
("There were warnings while unpacking a Radio Measure request (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
}
/* Call rrm function to handle the request. */
rrm_process_radio_measurement_request(pMac, pHdr->sa, &frm, psessionEntry);
}
static void
__lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tDot11fLinkMeasurementRequest frm;
uint32_t frameLen, nStatus;
uint8_t *pBody;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
if (psessionEntry == NULL) {
return;
}
/**Unpack the received frame */
nStatus =
dot11f_unpack_link_measurement_request(pMac, pBody, frameLen, &frm);
if (DOT11F_FAILED(nStatus)) {
lim_log(pMac, LOGE,
FL
("Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
return;
} else if (DOT11F_WARNED(nStatus)) {
lim_log(pMac, LOGW,
FL
("There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
}
/* Call rrm function to handle the request. */
rrm_process_link_measurement_request(pMac, pRxPacketInfo, &frm,
psessionEntry);
}
static void
__lim_process_neighbor_report(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
tDot11fNeighborReportResponse *pFrm;
uint32_t frameLen, nStatus;
uint8_t *pBody;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pFrm = cdf_mem_malloc(sizeof(tDot11fNeighborReportResponse));
if (NULL == pFrm) {
lim_log(pMac, LOGE,
FL
("Unable to allocate memory in __lim_process_neighbor_report"));
return;
}
if (psessionEntry == NULL) {
cdf_mem_free(pFrm);
return;
}
/**Unpack the received frame */
nStatus =
dot11f_unpack_neighbor_report_response(pMac, pBody, frameLen, pFrm);
if (DOT11F_FAILED(nStatus)) {
lim_log(pMac, LOGE,
FL
("Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
cdf_mem_free(pFrm);
return;
} else if (DOT11F_WARNED(nStatus)) {
lim_log(pMac, LOGW,
FL
("There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):"),
nStatus, frameLen);
PELOG2(sir_dump_buf
(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
)
}
/* Call rrm function to handle the request. */
rrm_process_neighbor_report_response(pMac, pFrm, psessionEntry);
cdf_mem_free(pFrm);
}
#endif
#ifdef WLAN_FEATURE_11W
/**
* limProcessSAQueryRequestActionFrame
*
***FUNCTION:
* This function is called by lim_process_action_frame() 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 __lim_process_sa_query_request_action_frame(tpAniSirGlobal pMac,
uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
uint8_t *pBody;
uint8_t transId[2];
/* Prima --- Below Macro not available in prima
pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd);
pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
/* 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 */
cdf_mem_copy(&transId[0], &pBody[2], 2);
/* Send 11w SA query response action frame */
if (lim_send_sa_query_response_frame(pMac,
transId,
pHdr->sa,
psessionEntry) != eSIR_SUCCESS) {
PELOGE(lim_log
(pMac, LOGE,
FL("fail to send SA query response action frame."));
)
return;
}
}
/**
* __lim_process_sa_query_response_action_frame
*
***FUNCTION:
* This function is called by lim_process_action_frame() 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 __lim_process_sa_query_response_action_frame(tpAniSirGlobal pMac,
uint8_t *pRxPacketInfo,
tpPESession psessionEntry)
{
tpSirMacMgmtHdr pHdr;
uint32_t frameLen;
uint8_t *pBody;
tpDphHashNode pSta;
uint16_t aid;
uint16_t transId;
uint8_t retryNum;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
("SA Query Response received..."));
/* When a station, supplicant handles SA Query Response.
* Forward to SME to HDD to wpa_supplicant.
*/
if (LIM_IS_STA_ROLE(psessionEntry)) {
lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *) pHdr,
frameLen + sizeof(tSirMacMgmtHdr), 0,
WMA_GET_RX_CH(pRxPacketInfo),
psessionEntry, 0);
return;
}
/* If this is an unprotected SA Query Response, then ignore it. */
if (pHdr->fc.wep == 0)
return;
pSta =
dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
&psessionEntry->dph.dphHashTable);
if (NULL == pSta)
return;
lim_log(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]);
lim_log(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 */
cdf_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) {
lim_log(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
/**
* lim_drop_unprotected_action_frame
*
***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 bool
lim_drop_unprotected_action_frame(tpAniSirGlobal pMac, tpPESession psessionEntry,
tpSirMacMgmtHdr pHdr, uint8_t category)
{
uint16_t aid;
tpDphHashNode pStaDs;
bool rmfConnection = false;
if (LIM_IS_AP_ROLE(psessionEntry) ||
LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
pStaDs =
dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
&psessionEntry->dph.dphHashTable);
if (pStaDs != NULL)
if (pStaDs->rmfEnabled)
rmfConnection = true;
} else if (psessionEntry->limRmfEnabled)
rmfConnection = true;
if (rmfConnection && (pHdr->fc.wep == 0)) {
PELOGE(lim_log
(pMac, LOGE,
FL("Dropping unprotected Action category %d frame "
"since RMF is enabled."), category);
)
return true;
} else
return false;
}
#endif
/**
* lim_process_action_frame() - to process action frames
* @mac_ctx: Pointer to Global MAC structure
* @rx_pkt_info: A pointer to packet info structure
*
* This function is called by limProcessMessageQueue() upon
* Action frame reception.
*
* Return: none
*/
void lim_process_action_frame(tpAniSirGlobal mac_ctx,
uint8_t *rx_pkt_info, tpPESession session)
{
uint8_t *body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) body_ptr;
#ifdef WLAN_FEATURE_11W
tpSirMacMgmtHdr mac_hdr_11w = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
#endif
tpSirMacMgmtHdr mac_hdr = NULL;
int8_t rssi;
uint32_t frame_len;
tpSirMacVendorSpecificFrameHdr vendor_specific;
uint8_t oui[] = { 0x00, 0x00, 0xf0 };
tpSirMacVendorSpecificPublicActionFrameHdr pub_action;
uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x09 };
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
switch (action_hdr->category) {
case SIR_MAC_ACTION_QOS_MGMT:
#ifdef WLAN_FEATURE_11W
if (lim_drop_unprotected_action_frame(mac_ctx, session,
mac_hdr_11w, action_hdr->category))
break;
#endif
if ((session->limQosEnabled) ||
(action_hdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE)) {
switch (action_hdr->actionID) {
case SIR_MAC_QOS_ADD_TS_REQ:
__lim_process_add_ts_req(mac_ctx,
(uint8_t *) rx_pkt_info,
session);
break;
case SIR_MAC_QOS_ADD_TS_RSP:
__lim_process_add_ts_rsp(mac_ctx,
(uint8_t *) rx_pkt_info,
session);
break;
case SIR_MAC_QOS_DEL_TS_REQ:
__lim_process_del_ts_req(mac_ctx,
(uint8_t *) rx_pkt_info,
session);
break;
case SIR_MAC_QOS_MAP_CONFIGURE:
__lim_process_qos_map_configure_frame(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
default:
lim_log(mac_ctx, LOGE,
FL("Qos action %d not handled"),
action_hdr->actionID);
break;
}
break;
}
break;
case SIR_MAC_ACTION_SPECTRUM_MGMT:
#ifdef WLAN_FEATURE_11W
if (lim_drop_unprotected_action_frame(mac_ctx, session,
mac_hdr_11w, action_hdr->category))
break;
#endif
switch (action_hdr->actionID) {
#ifdef ANI_SUPPORT_11H
case SIR_MAC_ACTION_MEASURE_REQUEST_ID:
if (session->lim11hEnable)
__lim_process_measurement_request_frame(mac_ctx,
rx_pkt_info,
session);
break;
case SIR_MAC_ACTION_TPC_REQUEST_ID:
if ((LIM_IS_STA_ROLE(session) ||
LIM_IS_AP_ROLE(session)) &&
session->lim11hEnable)
__lim_process_tpc_request_frame(mac_ctx,
rx_pkt_info, session);
break;
#endif
case SIR_MAC_ACTION_CHANNEL_SWITCH_ID:
if (LIM_IS_STA_ROLE(session))
__lim_process_channel_switch_action_frame(
mac_ctx, rx_pkt_info, session);
break;
default:
lim_log(mac_ctx, LOGE,
FL("Spectrum mgmt action id %d not handled"),
action_hdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_WME:
if (!session->limWmeEnabled) {
lim_log(mac_ctx, LOGW,
FL("WME mode disabled - dropping frame %d"),
action_hdr->actionID);
break;
}
switch (action_hdr->actionID) {
case SIR_MAC_QOS_ADD_TS_REQ:
__lim_process_add_ts_req(mac_ctx,
(uint8_t *) rx_pkt_info, session);
break;
case SIR_MAC_QOS_ADD_TS_RSP:
__lim_process_add_ts_rsp(mac_ctx,
(uint8_t *) rx_pkt_info, session);
break;
case SIR_MAC_QOS_DEL_TS_REQ:
__lim_process_del_ts_req(mac_ctx,
(uint8_t *) rx_pkt_info, session);
break;
case SIR_MAC_QOS_MAP_CONFIGURE:
__lim_process_qos_map_configure_frame(mac_ctx,
(uint8_t *)rx_pkt_info, session);
break;
default:
lim_log(mac_ctx, LOGE,
FL("WME action %d not handled"),
action_hdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_HT:
/** Type of HT Action to be performed*/
switch (action_hdr->actionID) {
case SIR_MAC_SM_POWER_SAVE:
if (LIM_IS_AP_ROLE(session))
__lim_process_sm_power_save_update(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
default:
lim_log(mac_ctx, LOGE,
FL("Action ID %d not handled in HT category"),
action_hdr->actionID);
break;
}
break;
case SIR_MAC_ACTION_WNM:
#ifdef WLAN_FEATURE_11W
if ((session->limRmfEnabled) && (mac_hdr_11w->fc.wep == 0)) {
lim_log(mac_ctx, LOGE,
FL("Dropping unprot action %d frm (PMF on)"),
action_hdr->category);
break;
}
#endif
lim_log(mac_ctx, LOG1,
FL("WNM Action category %d action %d."),
action_hdr->category, action_hdr->actionID);
switch (action_hdr->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:
rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
/* Forward to the SME to HDD to wpa_supplicant */
lim_send_sme_mgmt_frame_ind(mac_ctx,
mac_hdr->fc.subType,
(uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info),
session, rssi);
break;
default:
lim_log(mac_ctx, LOGE,
FL("Action ID %d not handled in WNM category"),
action_hdr->actionID);
break;
}
break;
#if defined WLAN_FEATURE_VOWIFI
case SIR_MAC_ACTION_RRM:
#ifdef WLAN_FEATURE_11W
if (lim_drop_unprotected_action_frame(mac_ctx, session,
mac_hdr_11w, action_hdr->category))
break;
#endif
if (mac_ctx->rrm.rrmPEContext.rrmEnable) {
switch (action_hdr->actionID) {
case SIR_MAC_RRM_RADIO_MEASURE_REQ:
__lim_process_radio_measure_request(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
case SIR_MAC_RRM_LINK_MEASUREMENT_REQ:
__lim_process_link_measurement_req(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
case SIR_MAC_RRM_NEIGHBOR_RPT:
__lim_process_neighbor_report(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
default:
lim_log(mac_ctx, LOGE,
FL("Action ID %d not handled in RRM"),
action_hdr->actionID);
break;
}
} else {
/* Else we will just ignore the RRM messages. */
lim_log(mac_ctx, LOGE,
FL("RRM frm ignored, it is disabled in cfg"));
}
break;
#endif
#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \
defined(FEATURE_WLAN_LFR)
case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY:
vendor_specific = (tpSirMacVendorSpecificFrameHdr) action_hdr;
mac_hdr = NULL;
frame_len = 0;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
/* Check if it is a vendor specific action frame. */
if (LIM_IS_STA_ROLE(session) &&
(true == cdf_mem_compare(session->selfMacAddr,
&mac_hdr->da[0], sizeof(tSirMacAddr)))
&& IS_WES_MODE_ENABLED(mac_ctx)
&& cdf_mem_compare(vendor_specific->Oui, oui, 3)) {
lim_log(mac_ctx, LOGW,
FL("Rcvd Vendor specific frame, OUI %x %x %x"),
vendor_specific->Oui[0],
vendor_specific->Oui[1],
vendor_specific->Oui[2]);
/*
* Forward to the SME to HDD to wpa_supplicant
* type is ACTION
*/
lim_send_sme_mgmt_frame_ind(mac_ctx,
mac_hdr->fc.subType,
(uint8_t *) mac_hdr,
frame_len +
sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info),
session, 0);
} else {
lim_log(mac_ctx, LOGE,
FL("Dropping the vendor specific action frame"
"beacause of (WES Mode not enabled "
"(WESMODE = %d) or OUI mismatch "
"(%02x %02x %02x) or not received with"
"SelfSta address) system role = %d"),
IS_WES_MODE_ENABLED(mac_ctx),
vendor_specific->Oui[0],
vendor_specific->Oui[1],
vendor_specific->Oui[2],
GET_LIM_SYSTEM_ROLE(session));
}
break;
#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE ||
FEATURE_WLAN_LFR */
case SIR_MAC_ACTION_PUBLIC_USAGE:
switch (action_hdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
pub_action =
(tpSirMacVendorSpecificPublicActionFrameHdr)
action_hdr;
mac_hdr = NULL;
frame_len = 0;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
/* Check if it is a P2P public action frame. */
if (cdf_mem_compare(pub_action->Oui, p2p_oui, 4)) {
/*
* Forward to the SME to HDD to wpa_supplicant
* type is ACTION
*/
lim_send_sme_mgmt_frame_ind(mac_ctx,
mac_hdr->fc.subType,
(uint8_t *) mac_hdr,
frame_len +
sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info),
session, 0);
} else {
lim_log(mac_ctx, LOGE,
FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"),
pub_action->Oui[0], pub_action->Oui[1],
pub_action->Oui[2], pub_action->Oui[3]);
}
break;
case SIR_MAC_ACTION_2040_BSS_COEXISTENCE:
mac_hdr = NULL;
frame_len = 0;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
lim_send_sme_mgmt_frame_ind(mac_ctx,
mac_hdr->fc.subType,
(uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info), session, 0);
break;
#ifdef FEATURE_WLAN_TDLS
case SIR_MAC_TDLS_DIS_RSP:
mac_hdr = NULL;
frame_len = 0;
rssi = 0;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
("Public Action TDLS Discovery RSP .."));
lim_send_sme_mgmt_frame_ind(mac_ctx,
mac_hdr->fc.subType, (uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info), session, rssi);
break;
#endif
default:
lim_log(mac_ctx, LOGE,
FL("Unhandled public action frame -- %x "),
action_hdr->actionID);
break;
}
break;
#ifdef WLAN_FEATURE_11W
case SIR_MAC_ACTION_SA_QUERY:
lim_log(mac_ctx, LOG1,
FL("SA Query Action category %d action %d."),
action_hdr->category, action_hdr->actionID);
if (lim_drop_unprotected_action_frame(mac_ctx, session,
mac_hdr_11w, action_hdr->category))
break;
switch (action_hdr->actionID) {
case SIR_MAC_SA_QUERY_REQ:
/**11w SA query request action frame received**/
/* Respond directly to the incoming request in LIM */
__lim_process_sa_query_request_action_frame(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
case SIR_MAC_SA_QUERY_RSP:
/**11w SA query response action frame received**/
/* Handle based on the current SA Query state */
__lim_process_sa_query_response_action_frame(mac_ctx,
(uint8_t *)rx_pkt_info,
session);
break;
default:
break;
}
break;
#endif
#ifdef WLAN_FEATURE_11AC
case SIR_MAC_ACTION_VHT:
if (!session->vhtCapability)
break;
switch (action_hdr->actionID) {
case SIR_MAC_VHT_OPMODE_NOTIFICATION:
__lim_process_operating_mode_action_frame(mac_ctx,
rx_pkt_info, session);
break;
case SIR_MAC_VHT_GID_NOTIFICATION:
/* Only if ini supports it */
if (session->enableVhtGid)
__lim_process_gid_management_action_frame(
mac_ctx, rx_pkt_info, session);
break;
default:
break;
}
break;
#endif
default:
lim_log(mac_ctx, LOGE,
FL("Action category %d not handled"),
action_hdr->category);
break;
}
}
/**
* lim_process_action_frame_no_session
*
***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 lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
{
uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd);
tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr =
(tpSirMacVendorSpecificPublicActionFrameHdr) pBody;
lim_log(pMac, LOG1, "Received a Action frame -- no session");
switch (pActionHdr->category) {
case SIR_MAC_ACTION_PUBLIC_USAGE:
switch (pActionHdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
{
tpSirMacMgmtHdr pHdr;
uint32_t frameLen;
uint8_t P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
pHdr = WMA_GET_RX_MAC_HEADER(pBd);
frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd);
/* Check if it is a P2P public action frame. */
if (cdf_mem_compare(pActionHdr->Oui, P2POui, 4)) {
/* Forward to the SME to HDD to wpa_supplicant */
/* type is ACTION */
lim_send_sme_mgmt_frame_ind(pMac,
pHdr->fc.subType,
(uint8_t *) pHdr,
frameLen +
sizeof
(tSirMacMgmtHdr),
0,
WMA_GET_RX_CH
(pBd), NULL, 0);
} else {
lim_log(pMac, LOGE,
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:
PELOGE(lim_log
(pMac, LOGE,
FL("Unhandled public action frame -- %x "),
pActionHdr->actionID);
)
break;
}
break;
default:
PELOGE(lim_log
(pMac, LOG1,
FL("Unhandled action frame without session -- %x "),
pActionHdr->category);
)
break;
}
}