blob: 4a795165838dc62ecf7faf849d728838e3907bf5 [file] [log] [blame]
/*
* Copyright (c) 2012-2013, 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.
*/
/*
* Copyright (c) 2012-2013, 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.
*/
/*===========================================================================
limProcessTdls.c
OVERVIEW:
DEPENDENCIES:
Are listed for each API below.
Copyright (c) 2010 QUALCOMM Incorporated.
All Rights Reserved.
Qualcomm Confidential and Proprietary
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header$$DateTime$$Author$
when who what, where, why
---------- --- --------------------------------------------------------
05/05/2010 Ashwani Initial Creation, added TDLS action frame functionality,
TDLS message exchange with SME..etc..
===========================================================================*/
/**
* \file limProcessTdls.c
*
* \brief Code for preparing,processing and sending 802.11z action frames
*
*/
#ifdef FEATURE_WLAN_TDLS
#include "sirApi.h"
#include "aniGlobal.h"
#include "sirMacProtDef.h"
#include "cfgApi.h"
#include "utilsApi.h"
#include "limTypes.h"
#include "limUtils.h"
#include "limSecurityUtils.h"
#include "dot11f.h"
#include "limStaHashApi.h"
#include "schApi.h"
#include "limSendMessages.h"
#include "utilsParser.h"
#include "limAssocUtils.h"
#include "dphHashTable.h"
#include "wlan_qct_wda.h"
#ifdef FEATURE_WLAN_TDLS_INTERNAL
/* forword declarations */
static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tSirTdlsPeerInfo *peerInfo, tpPESession psessionEntry) ;
static eHalStatus limSendSmeTdlsLinkSetupInd(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U8 status);
static eHalStatus limSendSmeTdlsDelPeerInd(tpAniSirGlobal pMac,
tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status) ;
static tSirTdlsPeerInfo *limTdlsFindDisPeerByState(tpAniSirGlobal pMac,
tANI_U8 state);
static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state,
tLimTdlsLinkSetupPeer **setupPeer) ;
static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peer_mac);
static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peer_mac);
static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tpPESession psessionEntry) ;
#endif
static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, tSirMacAddr,
tLimTdlsLinkSetupPeer *setupPeer, tpPESession psessionEntry) ;
void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry,
tDot11fIELinkIdentifier *linkIden,
tSirMacAddr peerMac , tANI_U8 reqType) ;
void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac,
tDot11fIEExtCap *extCapability) ;
/*
* TDLS data frames will go out/come in as non-qos data.
* so, eth_890d_header will be aligned access..
*/
static const tANI_U8 eth_890d_header[] =
{
0xaa, 0xaa, 0x03, 0x00,
0x00, 0x00, 0x89, 0x0d,
} ;
/*
* type of links used in TDLS
*/
enum tdlsLinks
{
TDLS_LINK_AP,
TDLS_LINK_DIRECT
} eTdlsLink ;
/*
* node status in node searching
*/
enum tdlsLinkNodeStatus
{
TDLS_NODE_NOT_FOUND,
TDLS_NODE_FOUND
} eTdlsLinkNodeStatus ;
enum tdlsReqType
{
TDLS_INITIATOR,
TDLS_RESPONDER
} eTdlsReqType ;
typedef enum tdlsLinkSetupStatus
{
TDLS_SETUP_STATUS_SUCCESS = 0,
TDLS_SETUP_STATUS_FAILURE = 37
}etdlsLinkSetupStatus ;
/* some local defines */
#define LINK_IDEN_BSSID_OFFSET (0)
#define PEER_MAC_OFFSET (12)
#define STA_MAC_OFFSET (6)
#define LINK_IDEN_ELE_ID (101)
//#define LINK_IDEN_LENGTH (18)
#define LINK_IDEN_ADDR_OFFSET(x) (&x.LinkIdentifier)
#define PTI_LINK_IDEN_OFFSET (5)
#define PTI_BUF_STATUS_OFFSET (25)
/* TODO, Move this parameters to configuration */
#define PEER_PSM_SUPPORT (0)
#define PEER_BUFFER_STA_SUPPORT (1)
#define CH_SWITCH_SUPPORT (0)
#define TDLS_SUPPORT (1)
#define TDLS_PROHIBITED (0)
#define TDLS_CH_SWITCH_PROHIBITED (1)
#ifdef LIM_DEBUG_TDLS
#define TDLS_CASE_RETURN_STRING(x) case (x): return( ((const tANI_U8*)#x) + 8); /* 8 = remove redundant SIR_MAC_ */
#ifdef FEATURE_WLAN_TDLS
#define WNI_CFG_TDLS_DISCOVERY_RSP_WAIT (100)
#define WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT (800)
#define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200)
#endif
const tANI_U8* limTraceTdlsActionString( tANI_U8 tdlsActionCode )
{
switch( tdlsActionCode )
{
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_REQ);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_RSP);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_CNF);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_TEARDOWN);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_IND);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_REQ);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_RSP);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_RSP);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_REQ);
TDLS_CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_RSP);
}
return (const tANI_U8*)"UNKNOWN";
}
#endif
#if 0
static void printMacAddr(tSirMacAddr macAddr)
{
int i = 0 ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, (" Mac Addr: "));
for(i = 0 ; i < 6; i++)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
(" %02x "), macAddr[i]);
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("\n"));
return ;
}
#endif
/*
* initialize TDLS setup list and related data structures.
*/
void limInitTdlsData(tpAniSirGlobal pMac, tpPESession pSessionEntry)
{
#ifdef FEATURE_WLAN_TDLS_INTERNAL
pMac->lim.gLimTdlsDisResultList = NULL ;
pMac->lim.gLimTdlsDisStaCount = 0 ;
palZeroMemory(pMac->hHdd, &pMac->lim.gLimTdlsDisReq,
sizeof(tSirTdlsDisReq));
palZeroMemory(pMac->hHdd, &pMac->lim.gLimTdlsLinkSetupInfo,
sizeof(tLimTdlsLinkSetupInfo));
pMac->lim.gAddStaDisRspWait = 0 ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
/* when reassociated, negative behavior will not be kept */
/* you have to explicitly enable negative behavior per (re)association */
pMac->lim.gLimTdlsNegativeBehavior = 0;
#endif
#endif
limInitPeerIdxpool(pMac, pSessionEntry) ;
return ;
}
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
void limTdlsSetNegativeBehavior(tpAniSirGlobal pMac, tANI_U8 value, tANI_BOOLEAN on)
{
if(on) {
if(value == 255)
pMac->lim.gLimTdlsNegativeBehavior = 0XFFFFFFFF;
else
pMac->lim.gLimTdlsNegativeBehavior |= (1 << (value-1));
}
else {
if(value == 255)
pMac->lim.gLimTdlsNegativeBehavior = 0;
else
pMac->lim.gLimTdlsNegativeBehavior &= ~(1 << (value-1));
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx\n"), \
value, on, pMac->lim.gLimTdlsNegativeBehavior));
}
#endif
#if 0
/*
* This function is used for creating TDLS public Action frame to
* transmit on Direct link
*/
static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame,
tANI_U8 type, tANI_U8 subType,
tANI_U8 *link_iden )
{
tpSirMacMgmtHdr pMacHdr ;
tANI_U8 *bssid = link_iden ;
#if 0
tANI_U8 *staMac = (tANI_U8 *)(bssid + sizeof(tSirMacAddr)) ;
tANI_U8 *peerMac = (tANI_U8 *) (staMac + sizeof(tSirMacAddr)) ;
#else
tANI_U8 *peerMac = (tANI_U8 *) (bssid + sizeof(tSirMacAddr)) ;
tANI_U8 *staMac = (tANI_U8 *)(peerMac + sizeof(tSirMacAddr)) ;
#endif
tANI_U8 toDs = ANI_TXDIR_IBSS ;
pMacHdr = (tpSirMacMgmtHdr) (pFrame);
/*
* prepare 802.11 header
*/
pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
pMacHdr->fc.type = type ;
pMacHdr->fc.subType = subType ;
/*
* TL is not setting up below fields, so we are doing it here
*/
pMacHdr->fc.toDS = toDs ;
pMacHdr->fc.powerMgmt = 0 ;
palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, peerMac,
sizeof( tSirMacAddr ));
palCopyMemory( pMac->hHdd,
(tANI_U8 *) pMacHdr->sa,
staMac, sizeof( tSirMacAddr ));
palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId,
bssid, sizeof( tSirMacAddr ));
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \
pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \
pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \
pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \
pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5]));
return ;
}
#endif
/*
* prepare TDLS frame header, it includes
* | | | |
* |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD
* | | | |
*/
static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame,
tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, tpPESession psessionEntry )
{
tpSirMacMgmtHdr pMacHdr ;
tANI_U32 header_offset = 0 ;
tANI_U8 *addr1 = NULL ;
tANI_U8 *addr3 = NULL ;
tANI_U8 toDs = (tdlsLinkType == TDLS_LINK_AP)
? ANI_TXDIR_TODS :ANI_TXDIR_IBSS ;
tANI_U8 *peerMac = (reqType == TDLS_INITIATOR)
? link_iden->RespStaAddr : link_iden->InitStaAddr;
tANI_U8 *staMac = (reqType == TDLS_INITIATOR)
? link_iden->InitStaAddr : link_iden->RespStaAddr;
pMacHdr = (tpSirMacMgmtHdr) (pFrame);
/*
* if TDLS frame goes through the AP link, it follows normal address
* pattern, if TDLS frame goes thorugh the direct link, then
* A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID
*/
(tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)),
(addr3 = (peerMac)))
: ((addr1 = (peerMac)),
(addr3 = (link_iden->bssid))) ;
/*
* prepare 802.11 header
*/
pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
pMacHdr->fc.type = SIR_MAC_DATA_FRAME ;
pMacHdr->fc.subType = SIR_MAC_DATA_DATA ;
/*
* TL is not setting up below fields, so we are doing it here
*/
pMacHdr->fc.toDS = toDs ;
pMacHdr->fc.powerMgmt = 0 ;
pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE)? 0 : 1;
palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, (tANI_U8 *)addr1,
sizeof( tSirMacAddr ));
palCopyMemory( pMac->hHdd,
(tANI_U8 *) pMacHdr->sa,
(tANI_U8 *) staMac,
sizeof( tSirMacAddr ));
palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId,
(tANI_U8 *) (addr3), sizeof( tSirMacAddr ));
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \
(tdlsLinkType == TDLS_LINK_AP) ? "AP" : "TD", \
pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \
pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \
pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \
pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5]));
//printMacAddr(pMacHdr->bssId) ;
//printMacAddr(pMacHdr->sa) ;
//printMacAddr(pMacHdr->da) ;
header_offset += sizeof(tSirMacMgmtHdr) ;
/*
* Now form RFC1042 header
*/
palCopyMemory(pMac->hHdd, (tANI_U8 *)(pFrame + header_offset),
(tANI_U8 *)eth_890d_header , sizeof(eth_890d_header)) ;
header_offset += sizeof(eth_890d_header) ;
/* add payload type as TDLS */
*(pFrame + header_offset) = PAYLOAD_TYPE_TDLS ;
return(header_offset += PAYLOAD_TYPE_TDLS_SIZE) ;
}
/*
* This function can be used for bacst or unicast discovery request
* We are not differentiating it here, it will all depnds on peer MAC address,
*/
tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac,
tANI_U8 dialog, tpPESession psessionEntry)
{
tDot11fTDLSDisReq tdlsDisReq ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 size = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsDisReq,
sizeof( tDot11fTDLSDisReq ) );
/*
* setup Fixed fields,
*/
tdlsDisReq.Category.category = SIR_MAC_ACTION_TDLS ;
tdlsDisReq.Action.action = SIR_MAC_TDLS_DIS_REQ ;
tdlsDisReq.DialogToken.token = dialog ;
size = sizeof(tSirMacAddr) ;
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisReq.LinkIdentifier,
peer_mac, TDLS_INITIATOR) ;
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSDisReqSize( pMac, &tdlsDisReq, &nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fTDLSDisReq );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE ;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* request frame
*/
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_REQ)
{
tdlsDisReq.LinkIdentifier.bssid[4] = 0xde;
tdlsDisReq.LinkIdentifier.bssid[5] = 0xad;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req\n"), \
tdlsDisReq.LinkIdentifier.bssid[0],
tdlsDisReq.LinkIdentifier.bssid[1],
tdlsDisReq.LinkIdentifier.bssid[2],
tdlsDisReq.LinkIdentifier.bssid[3],
tdlsDisReq.LinkIdentifier.bssid[4],
tdlsDisReq.LinkIdentifier.bssid[5]);
}
#endif
status = dot11fPackTDLSDisReq( pMac, &tdlsDisReq, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Discovery Request (0x%08x).\n") );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_DIS_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_REQ) ));
halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_TODS,
7,
limTxComplete, pFrame, 0 );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/*
* Once Discovery response is sent successfully (or failure) on air, now send
* response to PE and send del STA to HAL.
*/
eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac,
tANI_U32 txCompleteSuccess)
{
eHalStatus status = eHAL_STATUS_SUCCESS ;
#ifdef FEATURE_WLAN_TDLS_INTERNAL
tpDphHashNode pStaDs = NULL ;
tSirTdlsPeerInfo *peerInfo = 0 ;
/* find peer by looking into the list by expected state */
peerInfo = limTdlsFindDisPeerByState(pMac, TDLS_DIS_RSP_SENT_WAIT_STATE) ;
if(NULL == peerInfo)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("DisRspTxComplete: No TDLS state machine waits for this event\n"));
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_DONE_STATE ;
if(peerInfo->delStaNeeded)
{
tpPESession psessionEntry;
peerInfo->delStaNeeded = false ;
psessionEntry = peFindSessionBySessionId (pMac, peerInfo->sessionId);
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("DisRspTxComplete: sessionID %d is not found\n"), peerInfo->sessionId);
return eHAL_STATUS_FAILURE;
}
/* send del STA to remove context for this TDLS STA */
pStaDs = limTdlsDelSta(pMac, peerInfo->peerMac, psessionEntry) ;
/* now send indication to SME-->HDD->TL to remove STA from TL */
if(pStaDs)
{
limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
pStaDs, eSIR_SUCCESS) ;
}
else
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x\n"),
(peerInfo)->peerMac[0],
(peerInfo)->peerMac[1],
(peerInfo)->peerMac[2],
(peerInfo)->peerMac[3],
(peerInfo)->peerMac[4],
(peerInfo)->peerMac[5]) ;
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
}
if(!txCompleteSuccess)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TX complete failure for Dis RSP"));
limSendSmeTdlsDisRsp(pMac, eSIR_FAILURE,
eWNI_SME_TDLS_DISCOVERY_START_IND) ;
status = eHAL_STATUS_FAILURE;
}
else
{
limSendSmeTdlsDisRsp(pMac, eSIR_SUCCESS,
eWNI_SME_TDLS_DISCOVERY_START_IND) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("TX complete Success for Dis RSP"));
status = eHAL_STATUS_SUCCESS ;
}
//pMac->hal.pCBackFnTxComp = NULL ;
#endif
return status ;
}
/*
* Once setup CNF is sent successfully (or failure) on air, now send
* response to PE and send del STA to HAL.
*/
eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac,
tANI_U32 txCompleteSuccess)
{
eHalStatus status = eHAL_STATUS_SUCCESS ;
#ifdef FEATURE_WLAN_TDLS_INTERNAL
tLimTdlsLinkSetupPeer *peerInfo = 0 ;
/* find peer by looking into the list by expected state */
limTdlsFindSetupPeerByState(pMac,
TDLS_LINK_SETUP_RSP_WAIT_STATE, &peerInfo) ;
if(NULL == peerInfo)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event\n"));
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
(peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
(peerInfo)->tdls_link_state = TDLS_LINK_SETUP_DONE_STATE ;
if(!txCompleteSuccess)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TX complete Failure for setup CNF"));
limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE, (peerInfo)->peerMac,
eWNI_SME_TDLS_LINK_START_RSP) ;
status = eHAL_STATUS_FAILURE;
}
else
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"),
(peerInfo)->peerMac[0],
(peerInfo)->peerMac[1],
(peerInfo)->peerMac[2],
(peerInfo)->peerMac[3],
(peerInfo)->peerMac[4],
(peerInfo)->peerMac[5]) ;
limSendSmeTdlsLinkStartRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
eWNI_SME_TDLS_LINK_START_RSP) ;
/* tdls_hklee: prepare PTI template and send it to HAL */
limTdlsLinkEstablish(pMac, (peerInfo)->peerMac);
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("TX complete Success for setup CNF"));
status = eHAL_STATUS_SUCCESS ;
}
//pMac->hal.pCBackFnTxComp = NULL ;
#endif
return status ;
}
/*
* Tx Complete for Teardown frame
*/
eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac,
tANI_U32 txCompleteSuccess)
{
eHalStatus status = eHAL_STATUS_SUCCESS ;
#ifdef FEATURE_WLAN_TDLS_INTERNAL
tpDphHashNode pStaDs = NULL ;
tLimTdlsLinkSetupPeer *peerInfo = 0 ;
tpPESession psessionEntry = NULL ;
//tANI_U16 msgType = 0 ;
//tSirMacAddr peerMac = {0} ;
/* find peer by looking into the list by expected state */
limTdlsFindSetupPeerByState(pMac,
TDLS_LINK_TEARDOWN_START_STATE, &peerInfo) ;
if(NULL == peerInfo)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsTeardownTxComplete: No TDLS state machine waits for this event\n"));
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x\n"),
(peerInfo)->peerMac[0] ,
(peerInfo)->peerMac[1] ,
(peerInfo)->peerMac[2] ,
(peerInfo)->peerMac[3] ,
(peerInfo)->peerMac[4] ,
(peerInfo)->peerMac[5] ) ;
//pMac->hal.pCBackFnTxComp = NULL ;
psessionEntry = peFindSessionBySessionId(pMac, (peerInfo)->tdls_sessionId);
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsTeardownTxComplete: sessionID %d is not found\n"), (peerInfo)->tdls_sessionId);
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
if(!txCompleteSuccess)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TX complete failure for Teardown \n")) ;
/*
* we should be sending Teradown to AP with status code
* eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE, we are not worried if
* that is delivered or not, any way we removing this peer STA from our
* list
*/
if(NULL != psessionEntry)
{
limSendTdlsTeardownFrame(pMac, (peerInfo)->peerMac,
eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE, psessionEntry, NULL, 0) ;
}
}
if(TDLS_LINK_SETUP_WAIT_STATE != (peerInfo)->tdls_prev_link_state)
{
(peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
(peerInfo)->tdls_link_state = TDLS_LINK_TEARDOWN_DONE_STATE ;
/* send del STA to remove context for this TDLS STA */
if(NULL != psessionEntry)
{
/* tdls_hklee: send message to HAL before it is deleted */
limTdlsLinkTeardown(pMac, (peerInfo)->peerMac) ;
pStaDs = limTdlsDelSta(pMac, (peerInfo)->peerMac, psessionEntry) ;
}
/* now send indication to SME-->HDD->TL to remove STA from TL */
if(!pStaDs)
{
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
pStaDs, eSIR_SUCCESS) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("TX complete SUCCESS for Teardown\n")) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Prev State = %d\n"), (peerInfo)->tdls_prev_link_state) ;
limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
eWNI_SME_TDLS_TEARDOWN_RSP) ;
/* Delete Peer for Link Peer List */
limTdlsDelLinkPeer(pMac, (peerInfo)->peerMac) ;
}
else
{
(peerInfo)->tdls_prev_link_state = (peerInfo)->tdls_link_state ;
(peerInfo)->tdls_link_state = TDLS_LINK_TEARDOWN_DONE_STATE ;
limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac,
eWNI_SME_TDLS_TEARDOWN_IND) ;
}
#if 0
/* if previous state is link restart, then restart link setup again */
if(TDLS_LINK_SETUP_RESTART_STATE == (peerInfo)->tdls_prev_link_state)
{
tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
limTdlsPrepareSetupReqFrame(pMac, setupInfo, 37,
peerMac, psessionEntry) ;
}
#endif
status = eHAL_STATUS_SUCCESS ;
#endif
return status ;
}
/*
* Send TDLS discovery response frame on direct link.
*/
static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry)
{
tDot11fTDLSDisRsp tdlsDisRsp ;
tANI_U16 caps = 0 ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsDisRsp,
sizeof( tDot11fTDLSDisRsp ) );
/*
* setup Fixed fields,
*/
tdlsDisRsp.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE;
tdlsDisRsp.Action.action = SIR_MAC_TDLS_DIS_RSP ;
tdlsDisRsp.DialogToken.token = dialog ;
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsDisRsp.LinkIdentifier,
peerMac, TDLS_RESPONDER) ;
if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
{
/*
* Could not get Capabilities value
* from CFG. Log error.
*/
limLog(pMac, LOGP,
FL("could not retrieve Capabilities value\n"));
}
swapBitField16(caps, ( tANI_U16* )&tdlsDisRsp.Capabilities );
/* populate supported rate IE */
PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsDisRsp.SuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsDisRsp.ExtSuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fTdlsExtCapability( pMac, &tdlsDisRsp.ExtCap );
/* Include HT Capability IE */
//This does not depend on peer capabilities. If it is supported then it should be included
PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsDisRsp.HTCaps );
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSDisRspSize( pMac, &tdlsDisRsp, &nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr ) ;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* response frame
*/
/* Make public Action Frame */
#if 0
limPreparesActionFrameHdr(pMac, pFrame, SIR_MAC_MGMT_FRAME,
SIR_MAC_MGMT_ACTION,
LINK_IDEN_ADDR_OFFSET(tdlsDisRsp)) ;
#endif
limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
SIR_MAC_MGMT_ACTION, peerMac, psessionEntry->selfMacAddr);
{
tpSirMacMgmtHdr pMacHdr;
pMacHdr = ( tpSirMacMgmtHdr ) pFrame;
pMacHdr->fc.toDS = ANI_TXDIR_IBSS;
pMacHdr->fc.powerMgmt = 0 ;
sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId);
}
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_RSP)
{
tdlsDisRsp.LinkIdentifier.bssid[4] = 0xde;
tdlsDisRsp.LinkIdentifier.bssid[5] = 0xad;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp\n"), \
tdlsDisRsp.LinkIdentifier.bssid[0],
tdlsDisRsp.LinkIdentifier.bssid[1],
tdlsDisRsp.LinkIdentifier.bssid[2],
tdlsDisRsp.LinkIdentifier.bssid[3],
tdlsDisRsp.LinkIdentifier.bssid[4],
tdlsDisRsp.LinkIdentifier.bssid[5]);
}
#endif
status = dot11fPackTDLSDisRsp( pMac, &tdlsDisRsp, pFrame +
sizeof( tSirMacMgmtHdr ),
nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Discovery Request (0x%08x).\n") );
}
#if 0
if(pMac->hal.pCBackFnTxComp == NULL)
{
pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsDisRspTxComplete;
if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
{
status = eHAL_STATUS_FAILURE;
return status;
}
}
#endif
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("transmitting Discovery response on direct link\n")) ;
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_DIS_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_RSP) ));
/*
* Transmit Discovery response and watch if this is delivered to
* peer STA.
*/
halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_IBSS,
0,
limTxComplete, pFrame,
limTdlsDisRspTxComplete,
HAL_USE_SELF_STA_REQUESTED_MASK );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/*
* TDLS setup Request frame on AP link
*/
tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry,
tANI_U8 *addIe, tANI_U16 addIeLen)
{
tDot11fTDLSSetupReq tdlsSetupReq ;
tANI_U16 caps = 0 ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupReq,
sizeof( tDot11fTDLSSetupReq ) );
tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS ;
tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ ;
tdlsSetupReq.DialogToken.token = dialog ;
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupReq.LinkIdentifier,
peerMac, TDLS_INITIATOR) ;
if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
{
/*
* Could not get Capabilities value
* from CFG. Log error.
*/
limLog(pMac, LOGP,
FL("could not retrieve Capabilities value\n"));
}
swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities );
/* populate supported rate IE */
PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsSetupReq.SuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsSetupReq.ExtSuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fTdlsExtCapability( pMac, &tdlsSetupReq.ExtCap );
/*
* TODO: we need to see if we have to support conditions where we have
* EDCA parameter info element is needed a) if we need different QOS
* parameters for off channel operations or QOS is not supported on
* AP link and we wanted to QOS on direct link.
*/
/* Populate QOS info, needed for Peer U-APSD session */
/* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends on AP's capability, and
TDLS doesn't want to depend on AP's capability */
tdlsSetupReq.QOSCapsStation.present = 1;
tdlsSetupReq.QOSCapsStation.max_sp_length = 0;
tdlsSetupReq.QOSCapsStation.qack = 0;
tdlsSetupReq.QOSCapsStation.acbe_uapsd = 0;
tdlsSetupReq.QOSCapsStation.acbk_uapsd = 0;
tdlsSetupReq.QOSCapsStation.acvi_uapsd = 0;
tdlsSetupReq.QOSCapsStation.acvo_uapsd = 0;
/*
* we will always try to init TDLS link with 11n capabilities
* let TDLS setup response to come, and we will set our caps based
* of peer caps
*/
/* Include HT Capability IE */
PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsSetupReq.HTCaps );
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSSetupReqSize( pMac, &tdlsSetupReq,
&nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE
+ addIeLen;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes , ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* request frame
*/
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_REQ)
{
tdlsSetupReq.LinkIdentifier.bssid[4] = 0xde;
tdlsSetupReq.LinkIdentifier.bssid[5] = 0xad;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req\n"), \
tdlsSetupReq.LinkIdentifier.bssid[0],
tdlsSetupReq.LinkIdentifier.bssid[1],
tdlsSetupReq.LinkIdentifier.bssid[2],
tdlsSetupReq.LinkIdentifier.bssid[3],
tdlsSetupReq.LinkIdentifier.bssid[4],
tdlsSetupReq.LinkIdentifier.bssid[5]);
}
#endif
status = dot11fPackTDLSSetupReq( pMac, &tdlsSetupReq, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Discovery Request (0x%08x).\n") );
}
//Copy the additional IE.
//TODO : addIe is added at the end of the frame. This means it doesnt
//follow the order. This should be ok, but we should consider changing this
//if there is any IOT issue.
if( addIeLen != 0 )
{
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"),
addIeLen ));
palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_SETUP_REQ, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_REQ) ));
halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_TODS,
7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
limTxComplete, pFrame, 0 );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/*
* Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
*/
tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U16 reason, tpPESession psessionEntry,
tANI_U8 *addIe, tANI_U16 addIeLen)
{
tDot11fTDLSTeardown teardown ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&teardown,
sizeof( tDot11fTDLSTeardown ) );
teardown.Category.category = SIR_MAC_ACTION_TDLS ;
teardown.Action.action = SIR_MAC_TDLS_TEARDOWN ;
teardown.Reason.code = reason ;
PopulateDot11fLinkIden( pMac, psessionEntry, &teardown.LinkIdentifier,
peerMac, TDLS_INITIATOR) ;
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSTeardownSize( pMac, &teardown, &nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE
+ addIeLen;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* request frame
*/
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(teardown),
(reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE)
? TDLS_LINK_AP : TDLS_LINK_DIRECT, TDLS_INITIATOR,
psessionEntry) ;
status = dot11fPackTDLSTeardown( pMac, &teardown, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS Teardown req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Teardown Request (0x%08x).\n") );
}
#if 0
if(pMac->hal.pCBackFnTxComp == NULL)
{
pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsTeardownTxComplete;
if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
{
status = eHAL_STATUS_FAILURE;
return status;
}
}
else
{
VOS_ASSERT(0) ;
return status ;
}
#endif
if( addIeLen != 0 )
{
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"),
addIeLen ));
palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_TEARDOWN, limTraceTdlsActionString(SIR_MAC_TDLS_TEARDOWN) ));
halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_TODS,
7,
limTxComplete, pFrame,
limTdlsTeardownTxComplete,
0 );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/*
* Send Setup RSP frame on AP link.
*/
static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U8 dialog, tpPESession psessionEntry,
etdlsLinkSetupStatus setupStatus, tANI_U8 *addIe, tANI_U16 addIeLen )
{
tDot11fTDLSSetupRsp tdlsSetupRsp ;
tANI_U32 status = 0 ;
tANI_U16 caps = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupRsp,
sizeof( tDot11fTDLSSetupRsp ) );
/*
* setup Fixed fields,
*/
tdlsSetupRsp.Category.category = SIR_MAC_ACTION_TDLS;
tdlsSetupRsp.Action.action = SIR_MAC_TDLS_SETUP_RSP ;
tdlsSetupRsp.DialogToken.token = dialog;
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupRsp.LinkIdentifier,
peerMac, TDLS_RESPONDER) ;
if (cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
{
/*
* Could not get Capabilities value
* from CFG. Log error.
*/
limLog(pMac, LOGP,
FL("could not retrieve Capabilities value\n"));
}
swapBitField16(caps, ( tANI_U16* )&tdlsSetupRsp.Capabilities );
/* ipopulate supported rate IE */
PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsSetupRsp.SuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&tdlsSetupRsp.ExtSuppRates, psessionEntry );
/* Populate extended supported rates */
PopulateDot11fTdlsExtCapability( pMac, &tdlsSetupRsp.ExtCap );
/*
* TODO: we need to see if we have to support conditions where we have
* EDCA parameter info element is needed a) if we need different QOS
* parameters for off channel operations or QOS is not supported on
* AP link and we wanted to QOS on direct link.
*/
/* Populate QOS info, needed for Peer U-APSD session */
/* TODO: Now hardcoded, because PopulateDot11fQOSCapsStation() depends on AP's capability, and
TDLS doesn't want to depend on AP's capability */
tdlsSetupRsp.QOSCapsStation.present = 1;
tdlsSetupRsp.QOSCapsStation.max_sp_length = 0;
tdlsSetupRsp.QOSCapsStation.qack = 0;
tdlsSetupRsp.QOSCapsStation.acbe_uapsd = 1;
tdlsSetupRsp.QOSCapsStation.acbk_uapsd = 1;
tdlsSetupRsp.QOSCapsStation.acvi_uapsd = 1;
tdlsSetupRsp.QOSCapsStation.acvo_uapsd = 1;
/* Include HT Info IE */
// if ( setupReq->HTCaps.present)
// {
PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsSetupRsp.HTCaps );
// }
tdlsSetupRsp.Status.status = setupStatus ;
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSSetupRspSize( pMac, &tdlsSetupRsp,
&nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE
+ addIeLen;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* request frame
*/
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(tdlsSetupRsp),
TDLS_LINK_AP, TDLS_RESPONDER,
psessionEntry) ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_RSP)
{
tdlsSetupRsp.LinkIdentifier.bssid[4] = 0xde;
tdlsSetupRsp.LinkIdentifier.bssid[5] = 0xad;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp\n"), \
tdlsSetupRsp.LinkIdentifier.bssid[0],
tdlsSetupRsp.LinkIdentifier.bssid[1],
tdlsSetupRsp.LinkIdentifier.bssid[2],
tdlsSetupRsp.LinkIdentifier.bssid[3],
tdlsSetupRsp.LinkIdentifier.bssid[4],
tdlsSetupRsp.LinkIdentifier.bssid[5]);
}
#endif
status = dot11fPackTDLSSetupRsp( pMac, &tdlsSetupRsp, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Discovery Request (0x%08x).\n") );
}
//Copy the additional IE.
//TODO : addIe is added at the end of the frame. This means it doesnt
//follow the order. This should be ok, but we should consider changing this
//if there is any IOT issue.
if( addIeLen != 0 )
{
palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_SETUP_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_RSP) ));
halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_TODS,
//ANI_TXDIR_IBSS,
7,
limTxComplete, pFrame, 0 );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/*
* Send TDLS setup CNF frame on AP link
*/
tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tANI_U8 dialog, tpPESession psessionEntry, tANI_U8* addIe, tANI_U16 addIeLen)
{
tDot11fTDLSSetupCnf tdlsSetupCnf ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
/*
* The scheme here is to fill out a 'tDot11fProbeRequest' structure
* and then hand it off to 'dot11fPackProbeRequest' (for
* serialization). We start by zero-initializing the structure:
*/
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsSetupCnf,
sizeof( tDot11fTDLSSetupCnf ) );
/*
* setup Fixed fields,
*/
tdlsSetupCnf.Category.category = SIR_MAC_ACTION_TDLS;
tdlsSetupCnf.Action.action = SIR_MAC_TDLS_SETUP_CNF ;
tdlsSetupCnf.DialogToken.token = dialog ;
#if 1
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsSetupCnf.LinkIdentifier,
peerMac, TDLS_INITIATOR) ;
#else
palCopyMemory( pMac->hHdd, (tANI_U8 *)&tdlsSetupCnf.LinkIdentifier,
(tANI_U8 *)&setupRsp->LinkIdentifier, sizeof(tDot11fIELinkIdentifier)) ;
#endif
/*
* TODO: we need to see if we have to support conditions where we have
* EDCA parameter info element is needed a) if we need different QOS
* parameters for off channel operations or QOS is not supported on
* AP link and we wanted to QOS on direct link.
*/
/* Include HT Info IE */
//if ( tdlsSetupCnf.HTCaps.present)
//{
// PopulateDot11fHTInfo( pMac, &tdlsSetupCnf.HTInfo, psessionEntry );
// }
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSSetupCnfSize( pMac, &tdlsSetupCnf,
&nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size f"
"or a discovery Request (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating"
"the packed size for a discovery Request ("
"0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE
+ addIeLen;
/* Ok-- try to allocate memory from MGMT PKT pool */
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS"
"Discovery Request.\n"), nBytes );
return eSIR_MEM_ALLOC_FAILED;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, nBytes );
/*
* IE formation, memory allocation is completed, Now form TDLS discovery
* request frame
*/
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(tdlsSetupCnf), TDLS_LINK_AP, TDLS_INITIATOR,
psessionEntry) ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_STATUS_37_IN_SETUP_CNF) {
tdlsSetupCnf.StatusCode.statusCode = 37;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf\n"));
}
#endif
status = dot11fPackTDLSSetupCnf( pMac, &tdlsSetupCnf, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \
(0x%08x).\n"), status );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Discovery Request (0x%08x).\n") );
}
#if 0
if(pMac->hal.pCBackFnTxComp == NULL)
{
pMac->hal.pCBackFnTxComp = (tpCBackFnTxComp)limTdlsSetupCnfTxComplete;
if(TX_SUCCESS != tx_timer_activate(&pMac->hal.txCompTimer))
{
status = eHAL_STATUS_FAILURE;
return status;
}
}
else
{
VOS_ASSERT(0) ;
return status ;
}
#endif
//Copy the additional IE.
//TODO : addIe is added at the end of the frame. This means it doesnt
//follow the order. This should be ok, but we should consider changing this
//if there is any IOT issue.
if( addIeLen != 0 )
{
palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Send TDLS action %d (%s)"),
SIR_MAC_TDLS_SETUP_CNF, limTraceTdlsActionString(SIR_MAC_TDLS_SETUP_CNF) ));
halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
HAL_TXRX_FRM_802_11_DATA,
ANI_TXDIR_TODS,
7,
limTxComplete, pFrame,
limTdlsSetupCnfTxComplete,
0 );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" ));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
#ifdef FEATURE_WLAN_TDLS_INTERNAL
/*
* Convert HT caps to lim based HT caps
*/
static void limTdlsCovertHTCaps(tpAniSirGlobal pMac ,
tSirTdlsPeerInfo *peerInfo, tDot11fIEHTCaps *HTCaps)
{
/* HT Capability Info */
peerInfo->tdlsPeerHtCaps.advCodingCap = HTCaps->advCodingCap ;
peerInfo->tdlsPeerHtCaps.supportedChannelWidthSet =
HTCaps->supportedChannelWidthSet ;
peerInfo->tdlsPeerHtCaps.mimoPowerSave = HTCaps->mimoPowerSave ;
peerInfo->tdlsPeerHtCaps.greenField = HTCaps->greenField ;
peerInfo->tdlsPeerHtCaps.shortGI20MHz = HTCaps->shortGI20MHz ;
peerInfo->tdlsPeerHtCaps.shortGI40MHz = HTCaps->shortGI40MHz ;
peerInfo->tdlsPeerHtCaps.txSTBC = HTCaps->txSTBC ;
peerInfo->tdlsPeerHtCaps.rxSTBC = HTCaps->rxSTBC ;
peerInfo->tdlsPeerHtCaps.delayedBA = HTCaps->delayedBA;
peerInfo->tdlsPeerHtCaps.maximalAMSDUsize = HTCaps->maximalAMSDUsize ;
peerInfo->tdlsPeerHtCaps.dsssCckMode40MHz = HTCaps->dsssCckMode40MHz ;
peerInfo->tdlsPeerHtCaps.psmp = HTCaps->stbcControlFrame ;
peerInfo->tdlsPeerHtCaps.stbcControlFrame = HTCaps->stbcControlFrame ;
peerInfo->tdlsPeerHtCaps.lsigTXOPProtection =
HTCaps->lsigTXOPProtection ;
/* HT Capa parameters */
peerInfo->tdlsPeerHtParams.maxRxAMPDUFactor = HTCaps->maxRxAMPDUFactor ;
peerInfo->tdlsPeerHtParams.mpduDensity = HTCaps->mpduDensity ;
peerInfo->tdlsPeerHtParams.reserved = HTCaps->reserved1 ;
/* Extended HT caps */
peerInfo->tdlsPeerHtExtCaps.pco = HTCaps->pco ;
peerInfo->tdlsPeerHtExtCaps.transitionTime = HTCaps->transitionTime ;
peerInfo->tdlsPeerHtExtCaps.mcsFeedback = HTCaps->mcsFeedback ;
palCopyMemory(pMac->hHdd, peerInfo->supportedMCSSet,
HTCaps->supportedMCSSet, SIZE_OF_SUPPORTED_MCS_SET) ;
return ;
}
/*
* update capability info..
*/
void tdlsUpdateCapInfo(tSirMacCapabilityInfo *capabilityInfo,
tDot11fFfCapabilities *Capabilities)
{
capabilityInfo->ess = Capabilities->ess;
capabilityInfo->ibss = Capabilities->ibss;
capabilityInfo->cfPollable = Capabilities->cfPollable;
capabilityInfo->cfPollReq = Capabilities->cfPollReq;
capabilityInfo->privacy = Capabilities->privacy;
capabilityInfo->shortPreamble = Capabilities->shortPreamble;
capabilityInfo->pbcc = Capabilities->pbcc;
capabilityInfo->channelAgility = Capabilities->channelAgility;
capabilityInfo->spectrumMgt = Capabilities->spectrumMgt;
capabilityInfo->qos = Capabilities->qos;
capabilityInfo->shortSlotTime = Capabilities->shortSlotTime;
capabilityInfo->apsd = Capabilities->apsd;
capabilityInfo->rrm = Capabilities->rrm;
capabilityInfo->dsssOfdm = Capabilities->dsssOfdm;
capabilityInfo->immediateBA = Capabilities->immediateBA;
return ;
}
/*
* update Peer info from the link request frame recieved from Peer..
* in list of STA participating in TDLS link setup
*/
void limTdlsUpdateLinkReqPeerInfo(tpAniSirGlobal pMac,
tLimTdlsLinkSetupPeer *setupPeer,
tDot11fTDLSSetupReq *setupReq)
{
/* Populate peer info of tdls discovery result */
tdlsUpdateCapInfo(&setupPeer->capabilityInfo , &setupReq->Capabilities) ;
if(setupReq->SuppRates.present)
{
ConvertSuppRates( pMac, &setupPeer->supportedRates,
&setupReq->SuppRates );
}
/* update QOS info, needed for Peer U-APSD session */
if(setupReq->QOSCapsStation.present)
{
ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps,
&setupReq->QOSCapsStation) ;
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \
setupReq->QOSCapsStation.max_sp_length, setupReq->QOSCapsStation.acbe_uapsd, \
setupReq->QOSCapsStation.acbk_uapsd, setupReq->QOSCapsStation.acvi_uapsd, \
setupReq->QOSCapsStation.acvo_uapsd, setupReq->QOSCapsStation.more_data_ack, \
setupReq->QOSCapsStation.qack));
}
if(setupReq->ExtSuppRates.present)
{
setupPeer->ExtRatesPresent = 1;
ConvertExtSuppRates( pMac, &setupPeer->extendedRates,
&setupReq->ExtSuppRates );
}
/* update HT caps */
if(setupReq->HTCaps.present)
{
palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerHTCaps,
&setupReq->HTCaps, sizeof(tDot11fIEHTCaps)) ;
}
/* Update EXT caps */
if(setupReq->ExtCap.present)
{
palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerExtCaps,
&setupReq->ExtCap, sizeof(tDot11fIEExtCap)) ;
}
return ;
}
/*
* update peer Info recieved with TDLS setup RSP
*/
void limTdlsUpdateLinkRspPeerInfo(tpAniSirGlobal pMac,
tLimTdlsLinkSetupPeer *setupPeer,
tDot11fTDLSSetupRsp *setupRsp)
{
/* Populate peer info of tdls discovery result */
tdlsUpdateCapInfo(&setupPeer->capabilityInfo , &setupRsp->Capabilities) ;
if(setupRsp->SuppRates.present)
{
tDot11fIESuppRates *suppRates = &setupRsp->SuppRates ;
ConvertSuppRates( pMac, &setupPeer->supportedRates, suppRates);
}
/* update QOS info, needed for Peer U-APSD session */
if(setupRsp->QOSCapsStation.present)
{
ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps,
&setupRsp->QOSCapsStation) ;
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \
setupRsp->QOSCapsStation.max_sp_length, setupRsp->QOSCapsStation.acbe_uapsd, \
setupRsp->QOSCapsStation.acbk_uapsd, setupRsp->QOSCapsStation.acvi_uapsd, \
setupRsp->QOSCapsStation.acvo_uapsd, setupRsp->QOSCapsStation.more_data_ack, \
setupRsp->QOSCapsStation.qack));
}
if(setupRsp->ExtSuppRates.present)
{
setupPeer->ExtRatesPresent = 1;
ConvertExtSuppRates( pMac, &setupPeer->extendedRates,
&setupRsp->ExtSuppRates );
}
/* update HT caps */
if(setupRsp->HTCaps.present)
{
palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerHTCaps,
&setupRsp->HTCaps, sizeof(tDot11fIEHTCaps)) ;
}
/* update EXT caps */
if(setupRsp->ExtCap.present)
{
palCopyMemory(pMac->hHdd, &setupPeer->tdlsPeerExtCaps,
&setupRsp->ExtCap, sizeof(tDot11fIEExtCap)) ;
}
return ;
}
#endif
/*
* update HASH node entry info
*/
static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs,
tLimTdlsLinkSetupPeer *setupPeerInfo, tpPESession psessionEntry)
{
//tDot11fIEHTCaps *htCaps = &setupPeerInfo->tdlsPeerHTCaps ;
tDot11fIEHTCaps htCap, *htCaps;
tpDphHashNode pSessStaDs = NULL;
tANI_U16 aid;
//HACK- to get the session's htcaps.
PopulateDot11fHTCaps(pMac, psessionEntry, &htCap);
htCaps = &htCap;
if(htCaps->present)
{
pStaDs->mlmStaContext.htCapability = 1 ;
pStaDs->htGreenfield = htCaps->greenField ;
pStaDs->htSupportedChannelWidthSet = htCaps->supportedChannelWidthSet ;
pStaDs->htMIMOPSState = htCaps->mimoPowerSave ;
pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize;
pStaDs->htAMpduDensity = htCaps->mpduDensity;
pStaDs->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz ;
pStaDs->htShortGI20Mhz = htCaps->shortGI20MHz;
pStaDs->htShortGI40Mhz = htCaps->shortGI40MHz;
pStaDs->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor;
limFillRxHighestSupportedRate(pMac,
&pStaDs->supportedRates.rxHighestDataRate,
htCaps->supportedMCSSet);
pStaDs->baPolicyFlag = 0xFF;
pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_N ;
}
else
{
pStaDs->mlmStaContext.htCapability = 0 ;
pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_BG ;
}
pSessStaDs = dphLookupHashEntry(pMac, psessionEntry->bssId, &aid,
&psessionEntry->dph.dphHashTable) ;
/* Lets enable QOS parameter */
pStaDs->qosMode = 1;
pStaDs->wmeEnabled = 1;
pStaDs->lleEnabled = 0;
pStaDs->qos.capability.qosInfo = pSessStaDs->qos.capability.qosInfo; //setupPeerInfo->qosCaps.qosInfo;
/* populate matching rate set */
#if 0
#ifdef WLAN_FEATURE_11AC
limPopulateMatchingRateSet(pMac, pStaDs, &setupPeerInfo->supportedRates,
&setupPeerInfo->extendedRates,
(tANI_U8 *)setupPeerInfo->tdlsPeerHTCaps.supportedMCSSet,
&pStaDs->mlmStaContext.propRateSet, psessionEntry, NULL);
#else
limPopulateMatchingRateSet(pMac, pStaDs, &setupPeerInfo->supportedRates,
&setupPeerInfo->extendedRates,
(tANI_U8 *)setupPeerInfo->tdlsPeerHTCaps.supportedMCSSet,
&pStaDs->mlmStaContext.propRateSet, psessionEntry);
#endif
#else
palCopyMemory( pMac->hHdd, &pStaDs->supportedRates, &pSessStaDs->supportedRates, sizeof(pStaDs->supportedRates));
#endif
pStaDs->mlmStaContext.capabilityInfo = pSessStaDs->mlmStaContext.capabilityInfo;// setupPeerInfo->capabilityInfo;
return ;
}
#ifdef FEATURE_WLAN_TDLS_INTERNAL
/*
* find Peer in setup link list.
*/
tANI_U8 limTdlsFindLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tLimTdlsLinkSetupPeer **setupPeer)
{
tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
tLimTdlsLinkSetupPeer *linkSetupList = setupInfo->tdlsLinkSetupList ;
tANI_U8 checkNode = TDLS_NODE_NOT_FOUND ;
while (linkSetupList != NULL)
{
if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
(tANI_U8 *) linkSetupList->peerMac,
sizeof(tSirMacAddr)) )
{
checkNode = TDLS_NODE_FOUND ;
*setupPeer = linkSetupList ;
break ;
}
linkSetupList = linkSetupList->next;
}
return ((TDLS_NODE_FOUND == checkNode) ? eSIR_SUCCESS : eSIR_FAILURE ) ;
}
/*
* find peer in Discovery list.
* Dicovery list get populated in two instances, a) Recieved responses in reply
* to discovery request b) If discover request is received from TDLS peer STA
*/
tSirTdlsPeerInfo *limTdlsFindDisPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac)
{
tLimDisResultList *discoveryList = pMac->lim.gLimTdlsDisResultList ;
tSirTdlsPeerInfo *peerInfo = NULL ;
while (discoveryList != NULL)
{
peerInfo = &discoveryList->tdlsDisPeerInfo ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x \n"),
peerInfo->peerMac[0],
peerInfo->peerMac[1],
peerInfo->peerMac[2],
peerInfo->peerMac[3],
peerInfo->peerMac[4],
peerInfo->peerMac[5]) ;
if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
(tANI_U8 *) &peerInfo->peerMac, sizeof(tSirMacAddr)) )
{
break ;
}
discoveryList = discoveryList->next;
}
return peerInfo ;
}
/*
* find peer in Discovery list by looking into peer state.
* Dicovery list get populated in two instances, a) Recieved responses in reply
* to discovery request b) If discover request is received from TDLS peer STA
*/
static tSirTdlsPeerInfo *limTdlsFindDisPeerByState(tpAniSirGlobal pMac,
tANI_U8 state)
{
tLimDisResultList *discoveryList = pMac->lim.gLimTdlsDisResultList ;
tSirTdlsPeerInfo *peerInfo = NULL ;
while (discoveryList != NULL)
{
peerInfo = &discoveryList->tdlsDisPeerInfo ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peerInfo Mac = %02x, %02x, %02x, %02x, %02x, %02x "),
peerInfo->peerMac[0],
peerInfo->peerMac[1],
peerInfo->peerMac[2],
peerInfo->peerMac[3],
peerInfo->peerMac[4],
peerInfo->peerMac[5]) ;
if (peerInfo->tdlsPeerState == state)
{
break ;
}
discoveryList = discoveryList->next;
}
return peerInfo ;
}
/*
* find peer in Setup list by looking into peer state.
* setup list get populated in two instances, a) Recieved responses in reply
* to setup request b) If discover request is received from TDLS peer STA
*/
static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state,
tLimTdlsLinkSetupPeer **setupPeer)
{
tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
tLimTdlsLinkSetupPeer *linkSetupList = setupInfo->tdlsLinkSetupList ;
tANI_U8 checkNode = TDLS_NODE_NOT_FOUND ;
while (linkSetupList != NULL)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peer state = %02x\n"), (linkSetupList)->tdls_link_state) ;
if((linkSetupList)->tdls_link_state == state)
{
checkNode = TDLS_NODE_FOUND ;
*setupPeer = linkSetupList ;
break ;
}
linkSetupList = (linkSetupList)->next;
}
return ((TDLS_NODE_FOUND == checkNode) ? eSIR_SUCCESS: eSIR_FAILURE) ;
}
/*
* delete Peer from Setup Link
*/
void limTdlsDelLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac)
{
tLimTdlsLinkSetupInfo *setupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
tLimTdlsLinkSetupPeer **linkSetupList = &setupInfo->tdlsLinkSetupList ;
tLimTdlsLinkSetupPeer *currentNode = NULL ;
tLimTdlsLinkSetupPeer *prevNode = NULL ;
for(currentNode = *linkSetupList ; currentNode != NULL ;
prevNode = currentNode, currentNode = currentNode->next)
{
if (palEqualMemory( pMac->hHdd,(tANI_U8 *) peerMac,
(tANI_U8 *) currentNode->peerMac,
sizeof(tSirMacAddr)) )
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
currentNode->peerMac[0],
currentNode->peerMac[1],
currentNode->peerMac[2],
currentNode->peerMac[3],
currentNode->peerMac[4],
currentNode->peerMac[5]) ;
/* if it's first Node */
if(NULL == prevNode)
{
*linkSetupList = currentNode->next ;
}
else
{
prevNode->next = currentNode->next ;
}
palFreeMemory(pMac, currentNode) ;
return ;
}
}
return ;
}
/*
* TDLS discovery request frame received from TDLS peer STA..
*/
static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen )
{
tDot11fTDLSDisReq tdlsDisReq = {{0}} ;
tANI_U32 status = 0 ;
tLimDisResultList *tdlsDisResult = NULL ;
tLimDisResultList **disResultList = &pMac->lim.gLimTdlsDisResultList ;
tSirMacAddr peerMac = {0} ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tSirTdlsPeerInfo *peerInfo = NULL ;
tpPESession psessionEntry = NULL ;
tANI_U8 sessionId = 0 ;
status = dot11fUnpackTDLSDisReq(pMac, pBody, frmLen, &tdlsDisReq) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN,
("TDLS dis request dialog = %d\n"), tdlsDisReq.DialogToken.token);
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS discovery Request frame (0x%08x," "%d bytes):\n"),
status, frmLen );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
}
/*
* find session entry using BSSID in link identifier, not using MAC
* header beacuse, there is cases in TDLS, there may be BSSID will not
* be present in header
*/
psessionEntry = peFindSessionByBssid(pMac,
&tdlsDisReq.LinkIdentifier.bssid[0], &sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
tdlsDisReq.LinkIdentifier.bssid[0],
tdlsDisReq.LinkIdentifier.bssid[1],
tdlsDisReq.LinkIdentifier.bssid[2],
tdlsDisReq.LinkIdentifier.bssid[3],
tdlsDisReq.LinkIdentifier.bssid[4],
tdlsDisReq.LinkIdentifier.bssid[5]) ;
//VOS_ASSERT(0) ;
return eSIR_FAILURE;
}
/* varify BSSID */
status = palEqualMemory(pMac->hHdd, &psessionEntry->bssId[0],
&tdlsDisReq.LinkIdentifier.bssid[0], sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"),
psessionEntry->bssId[0],
psessionEntry->bssId[1],
psessionEntry->bssId[2],
psessionEntry->bssId[3],
psessionEntry->bssId[4],
psessionEntry->bssId[5]) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"),
tdlsDisReq.LinkIdentifier.bssid[0],
tdlsDisReq.LinkIdentifier.bssid[1],
tdlsDisReq.LinkIdentifier.bssid[2],
tdlsDisReq.LinkIdentifier.bssid[3],
tdlsDisReq.LinkIdentifier.bssid[4],
tdlsDisReq.LinkIdentifier.bssid[5]
) ;
if(!status)
{
limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ;
return eSIR_FAILURE ;
}
/*
* check if this is echo of our transmitted discovery request
* drop it here, TODO: better to drop this in TL.
*/
status = palEqualMemory(pMac->hHdd, psessionEntry->selfMacAddr,
&tdlsDisReq.LinkIdentifier.InitStaAddr[0],
sizeof(tSirMacAddr)) ;
if(status)
{
limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame\n")) ;
return eSIR_FAILURE ;
}
/*
* while processing Discovery request from Peer,
* STA_MAC--> MAC of TDLS discovery initiator
* STA_PEER_MAC--> MAC of TDLS discovery responder.
*/
palCopyMemory(pMac->hHdd, peerMac,
&tdlsDisReq.LinkIdentifier.InitStaAddr[0],
sizeof(tSirMacAddr)) ;
/* TODO, do more validation */
/* see if discovery is already in progress */
peerInfo = limTdlsFindDisPeer(pMac, peerMac) ;
if(NULL == peerInfo)
{
/*
* we are allocating peer info for individual peers found in TDLS
* discovery, we need to keep adding TDLS peers till we have timed
* out. We are freeing this memory at the time we are sending this
* collected peer info to SME.
*/
status = palAllocateMemory(pMac->hHdd, (void **)&tdlsDisResult,
sizeof(tLimDisResultList)) ;
if(status != eHAL_STATUS_SUCCESS)
{
limLog(pMac, LOGP, FL("alloc fail for TDLS discovery \
reponse info\n")) ;
return eSIR_FAILURE ;
}
peerInfo = &tdlsDisResult->tdlsDisPeerInfo ;
peerInfo->tdlsPeerState = TDLS_DIS_REQ_PROCESS_STATE ;
peerInfo->dialog = tdlsDisReq.DialogToken.token ;
peerInfo->sessionId = psessionEntry->peSessionId;
/* Populate peer info of tdls discovery result */
status = palCopyMemory(pMac->hHdd, peerInfo->peerMac, peerMac,
sizeof(tSirMacAddr)) ;
/*
* Now, as per D13, there will not be any Supp rates, ext Supp rates
* info in Discovery request frames, so we are populating this info
* locally to pass it to ADD STA.
*/
do
{
tDot11fIESuppRates suppRates = {0} ;
tDot11fIEExtSuppRates extSuppRates = {0} ;
tANI_U16 caps = 0 ;
tDot11fFfCapabilities capsInfo = {0} ;
tDot11fIEHTCaps HTCaps = {0} ;
/* populate supported rate IE */
PopulateDot11fSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&suppRates, psessionEntry );
ConvertSuppRates( pMac, &peerInfo->tdlsPeerSuppRates,
&suppRates);
/* Populate extended supported rates */
PopulateDot11fExtSuppRates( pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
&extSuppRates, psessionEntry );
peerInfo->ExtRatesPresent = 1;
ConvertExtSuppRates( pMac, &peerInfo->tdlsPeerExtRates,
&extSuppRates);
if(cfgGetCapabilityInfo(pMac, &caps, psessionEntry) != eSIR_SUCCESS)
{
/*
* Could not get Capabilities value
* from CFG. Log error.
*/
limLog(pMac, LOGP,
FL("could not retrieve Capabilities value\n"));
}
swapBitField16(caps, ( tANI_U16* )&capsInfo );
/* update Caps Info */
tdlsUpdateCapInfo(&peerInfo->capabilityInfo , &capsInfo) ;
PopulateDot11fHTCaps( pMac, psessionEntry, &HTCaps );
limTdlsCovertHTCaps(pMac, peerInfo, &HTCaps) ;
} while (0) ;
/* now add this new found discovery node into tdls discovery list */
tdlsDisResult->next = *disResultList ;
*disResultList = tdlsDisResult ;
pMac->lim.gLimTdlsDisStaCount++ ;
/* See if for this peer already entry in setup Link */
limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
/*
* if there is no entry for this peer in setup list, we need to
* do add sta for this peer to transmit discovery rsp.
*/
if(NULL == setupPeer)
{
/* To start with, send add STA request to HAL */
pMac->lim.gLimAddStaTdls = true ;
peerInfo->delStaNeeded = true ;
if(eSIR_FAILURE == limTdlsDisAddSta(pMac, peerMac,
peerInfo, psessionEntry))
{
VOS_ASSERT(0) ;
limLog(pMac, LOGE, "Add STA for dis response is failed \n") ;
return eSIR_FAILURE ;
}
} /* use setup link sta ID for discovery rsp */
else
{
peerInfo->delStaNeeded = false ;
limSendTdlsDisRspFrame(pMac, peerInfo->peerMac, peerInfo->dialog, psessionEntry) ;
peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_WAIT_STATE ;
}
}
else
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("discovery procedure in progress for this peer\n")) ;
}
return eSIR_SUCCESS ;
}
/* Process TDLS setup Request Frame */
static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen)
{
tDot11fTDLSSetupReq tdlsSetupReq = {{0}} ;
tANI_U32 status = 0 ;
tpPESession psessionEntry = NULL ;
tANI_U8 sessionId = 0 ;
tANI_U8 currentState = TDLS_LINK_SETUP_WAIT_STATE ;
tANI_U8 previousState = TDLS_LINK_IDLE_STATE ;
/* create node for Link setup */
tLimTdlsLinkSetupInfo *linkSetupInfo = &pMac->lim.gLimTdlsLinkSetupInfo ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tLimTdlsLinkSetupPeer *tmpSetupPeer = NULL ;
status = dot11fUnpackTDLSSetupReq(pMac, pBody, frmLen, &tdlsSetupReq) ;
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS setup Request frame (0x%08x," "%d bytes):\n"),
status, pBody );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
}
/*
* find session entry using BSSID in link identifier, not using MAC
* header beacuse, there is cases in TDLS, there may be BSSID will not
* be present in header
*/
psessionEntry = peFindSessionByBssid(pMac,
&tdlsSetupReq.LinkIdentifier.bssid[0], &sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
tdlsSetupReq.LinkIdentifier.bssid[0],
tdlsSetupReq.LinkIdentifier.bssid[1],
tdlsSetupReq.LinkIdentifier.bssid[2],
tdlsSetupReq.LinkIdentifier.bssid[3],
tdlsSetupReq.LinkIdentifier.bssid[4],
tdlsSetupReq.LinkIdentifier.bssid[5]) ;
//VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
/* TODO: we don;t need this check now, varify BSSID */
status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
&tdlsSetupReq.LinkIdentifier.bssid[0],
sizeof(tSirMacAddr)) ;
if(!status)
{
limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter\n")) ;
limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token , psessionEntry,
TDLS_SETUP_STATUS_FAILURE, NULL, 0 ) ;
return eSIR_FAILURE ;
}
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_RSP_TIMEOUT_TO_SETUP_REQ)
{
/* simply ignore this setup request packet */
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: ignore TDLS Setup Req packet\n"));
return eSIR_SUCCESS ;
}
if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req\n"));
/* format TDLS discovery request frame and transmit it */
limSendTdlsLinkSetupReqFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token, psessionEntry,
NULL, 0) ;
}
#endif
/* TODO, do more validation */
if(!limTdlsFindLinkPeer(pMac,
&tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
&tmpSetupPeer))
{
tANI_U32 tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Link is already setup with this peer\n" )) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("state = %d\n"), tmpSetupPeer->tdls_link_state) ;
//return eSIR_FAILURE ;
if(tmpSetupPeer == NULL)
{
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
switch(tmpSetupPeer->tdls_link_state)
{
case TDLS_LINK_SETUP_START_STATE:
{
v_SINT_t macCompare = 0 ;
macCompare= vos_mem_compare2(tmpSetupPeer->peerMac,
psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("MAC comparison Rslt = %d\n"), macCompare ) ;
if(0 > macCompare)
{
/*
* Delete our Setup Request/Peer info and honour Peer
* Setup Request, go ahead and respond for this
*/
/* Deactivate the timer */
tx_timer_deactivate(&tmpSetupPeer->gLimTdlsLinkSetupRspTimeoutTimer) ;
#ifdef FEATURE_WLAN_TDLS_NEGATIVE
if((pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
!= LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ)
#endif
limSendSmeTdlsLinkStartRsp(pMac, eSIR_FAILURE,
tmpSetupPeer->peerMac, eWNI_SME_TDLS_LINK_START_RSP);
limTdlsDelLinkPeer(pMac, tmpSetupPeer->peerMac) ;
tdlsStateStatus = TDLS_LINK_IDLE_STATE ;
}
else if(0 < macCompare)
{
/*
* Go ahead with current setup as peer is going to
* respond for setup request
*/
tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ;
}
else
{
/* same MAC, not possible */
VOS_ASSERT(0) ;
}
break ;
}
#if 1
case TDLS_LINK_SETUP_DONE_STATE:
{
tpDphHashNode pStaDs = NULL ;
previousState = TDLS_LINK_SETUP_WAIT_STATE ;
currentState = TDLS_LINK_TEARDOWN_START_STATE ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("link Setup Done state " )) ;
tmpSetupPeer->tdls_prev_link_state = previousState ;
tmpSetupPeer->tdls_link_state = currentState ;
setupPeer = tmpSetupPeer ;
#if 0
/* Send Teardown to this Peer and Initiate new TDLS Setup */
limSendTdlsTeardownFrame(pMac,
&tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON, psessionEntry) ;
#else
/* tdls_hklee: send message to HAL before it is deleted, cause */
limTdlsLinkTeardown(pMac, (setupPeer)->peerMac) ;
/* send del STA to remove context for this TDLS STA */
pStaDs = limTdlsDelSta(pMac, (setupPeer)->peerMac, psessionEntry) ;
/* now send indication to SME-->HDD->TL to remove STA from TL */
if(pStaDs)
{
limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
pStaDs, eSIR_SUCCESS) ;
/* send Teardown Ind to SME */
limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (setupPeer)->peerMac,
eWNI_SME_TDLS_TEARDOWN_IND) ;
/* remove node from setup list */
limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
}
#endif
//setupPeer->tdls_prev_link_state = TDLS_LINK_SETUP_RESTART_STATE;
tdlsStateStatus = TDLS_LINK_IDLE_STATE ;
break ;
}
default:
{
VOS_ASSERT(0) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("link Setup is Recieved in unknown state\n" )) ;
break ;
}
#endif
}
if(tdlsStateStatus == TDLS_LINK_SETUP_START_STATE)
return eSIR_FAILURE ;
}
if(currentState != TDLS_LINK_TEARDOWN_START_STATE)
{
/*
* Now we are sure to send discovery response frame to TDLS discovery
* initiator, we don't care, if this request is unicast ro broadcast,
* we simply, send discovery response frame on direct link.
*/
if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
(void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer )))
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
( "Unable to allocate memory during ADD_STA\n" ));
return eSIR_MEM_ALLOC_FAILED;
}
setupPeer->dialog = tdlsSetupReq.DialogToken.token ;
//setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
//setupPeer->tdls_link_state = TDLS_LINK_SETUP_WAIT_STATE ;
setupPeer->tdls_prev_link_state = previousState ;
setupPeer->tdls_link_state = currentState ;
/* TDLS_sessionize: remember sessionId for future */
setupPeer->tdls_sessionId = psessionEntry->peSessionId;
setupPeer->tdls_bIsResponder = 0;
palCopyMemory(pMac->hHdd, setupPeer->peerMac,
&tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"),
setupPeer->peerMac[0],
setupPeer->peerMac[1],
setupPeer->peerMac[2],
setupPeer->peerMac[3],
setupPeer->peerMac[4],
setupPeer->peerMac[5] ) ;
limTdlsUpdateLinkReqPeerInfo(pMac, setupPeer, &tdlsSetupReq) ;
pMac->lim.gLimAddStaTdls = true ;
/* To start with, send add STA request to HAL */
if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, setupPeer->peerMac,
setupPeer, psessionEntry))
{
VOS_ASSERT(0) ;
palFreeMemory(pMac->hHdd, (void **) &setupPeer) ;
return eSIR_FAILURE ;
}
limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr,
tdlsSetupReq.DialogToken.token , psessionEntry,
TDLS_SETUP_STATUS_SUCCESS, NULL, 0) ;
limStartTdlsTimer(pMac, psessionEntry->peSessionId,
&setupPeer->gLimTdlsLinkSetupCnfTimeoutTimer,
(tANI_U32)setupPeer->peerMac,
WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT,
SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT) ;
/* update setup peer list */
setupPeer->next = linkSetupInfo->tdlsLinkSetupList ;
linkSetupInfo->tdlsLinkSetupList = setupPeer ;
}
else
{
setupPeer->dialog = tdlsSetupReq.DialogToken.token ;
//setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
//setupPeer->tdls_link_state = TDLS_LINK_SETUP_WAIT_STATE ;
setupPeer->tdls_prev_link_state = previousState ;
setupPeer->tdls_link_state = currentState ;
/* TDLS_sessionize: remember sessionId for future */
setupPeer->tdls_sessionId = psessionEntry->peSessionId;
setupPeer->tdls_bIsResponder = 0;
palCopyMemory(pMac->hHdd, setupPeer->peerMac,
&tdlsSetupReq.LinkIdentifier.InitStaAddr[0],
sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"),
setupPeer->peerMac[0],
setupPeer->peerMac[1],
setupPeer->peerMac[2],
setupPeer->peerMac[3],
setupPeer->peerMac[4],
setupPeer->peerMac[5] ) ;
limTdlsUpdateLinkReqPeerInfo(pMac, setupPeer, &tdlsSetupReq) ;
limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr,
tdlsSetupReq.DialogToken.token , psessionEntry,
TDLS_SETUP_STATUS_SUCCESS, NULL, 0) ;
limStartTdlsTimer(pMac, psessionEntry->peSessionId,
&setupPeer->gLimTdlsLinkSetupCnfTimeoutTimer,
(tANI_U32)setupPeer->peerMac,
WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT,
SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT) ;
}
return eSIR_SUCCESS ;
}
/*
* TDLS discovery request frame received from TDLS peer STA..
*/
static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen )
{
tDot11fTDLSSetupRsp tdlsSetupRsp = {{0}} ;
tANI_U32 status = 0 ;
tSirMacAddr peerMac = {0} ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tpPESession psessionEntry = NULL ;
tANI_U8 sessionId = 0 ;
status = dot11fUnpackTDLSSetupRsp(pMac, pBody, frmLen, &tdlsSetupRsp) ;
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS discovery Request frame (0x%08x," "%d bytes):\n"),
status, frmLen );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
}
/*
* find session entry using BSSID in link identifier, not using MAC
* header beacuse, there is cases in TDLS, there may be BSSID will not
* be present in header
*/
psessionEntry = peFindSessionByBssid(pMac,
&tdlsSetupRsp.LinkIdentifier.bssid[0], &sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
tdlsSetupRsp.LinkIdentifier.bssid[0],
tdlsSetupRsp.LinkIdentifier.bssid[1],
tdlsSetupRsp.LinkIdentifier.bssid[2],
tdlsSetupRsp.LinkIdentifier.bssid[3],
tdlsSetupRsp.LinkIdentifier.bssid[4],
tdlsSetupRsp.LinkIdentifier.bssid[5]) ;
//VOS_ASSERT(0) ;
return eSIR_FAILURE;
}
/* varify BSSID */
status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
&tdlsSetupRsp.LinkIdentifier.bssid[0],
sizeof(tSirMacAddr)) ;
if(!status)
{
limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ;
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
palCopyMemory(pMac->hHdd, peerMac,
&tdlsSetupRsp.LinkIdentifier.RespStaAddr[0],
sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
peerMac[0],
peerMac[1],
peerMac[2],
peerMac[3],
peerMac[4],
peerMac[5]) ;
limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
if(NULL == setupPeer)
{
limLog( pMac, LOGE, FL(" unknown setup Response frame \
other BSS\n")) ;
return eSIR_FAILURE ;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("deactivating Setup RSP timer\n")) ;
/* Deactivate the timer */
tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupRspTimeoutTimer) ;
/*
* TDLS Setup RSP is recieved with Failure, Delete this STA entry
* don't respond with TDLS CNF frame.
*/
if(TDLS_SETUP_STATUS_SUCCESS != tdlsSetupRsp.Status.status)
{
limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("setup RSP with Failure Code\n")) ;
return eSIR_FAILURE ;
}
/* update Link Info */
limTdlsUpdateLinkRspPeerInfo(pMac, setupPeer, &tdlsSetupRsp) ;
/* TODO, do more validation */
/*
* Now we are sure to send link setup CNF frame to TDLS link setup
* reponded, now we will create dph hash entry and send add STA to HAL
*/
pMac->lim.gLimAddStaTdls = true ;
if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, peerMac,
setupPeer, psessionEntry))
{
/* through error */
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
/* TDLS_HKLEE_FIXME: now we add some delay for AddSta_Rsp comes */
/* send TDLS confim frame to TDLS Peer STA */
limSendTdlsLinkSetupCnfFrame(pMac, peerMac, tdlsSetupRsp.DialogToken.token, psessionEntry, NULL, 0) ;
/*
* set the tdls_link_state to TDLS_LINK_SETUP_RSP_WAIT_STATE, and
* wait for Setup CNF transmission on air, once we receive tx complete
* message, we will change the peer state and send message to SME
* callback..
*/
(setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
(setupPeer)->tdls_link_state = TDLS_LINK_SETUP_RSP_WAIT_STATE ;
return eSIR_SUCCESS ;
}
/*
* TDLS setup CNF frame processing ..
*/
static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen)
{
tDot11fTDLSSetupCnf tdlsSetupCnf = {{0}} ;
tANI_U32 status = 0 ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tpPESession psessionEntry = NULL ;
tANI_U8 sessionId = 0 ;
status = dot11fUnpackTDLSSetupCnf(pMac, pBody, frmLen, &tdlsSetupCnf) ;
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
status, frmLen );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
}
/*
* find session entry using BSSID in link identifier, not using MAC
* header beacuse, there is cases in TDLS, there may be BSSID will not
* be present in header
*/
psessionEntry = peFindSessionByBssid(pMac,
&tdlsSetupCnf.LinkIdentifier.bssid[0], &sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
tdlsSetupCnf.LinkIdentifier.bssid[0],
tdlsSetupCnf.LinkIdentifier.bssid[1],
tdlsSetupCnf.LinkIdentifier.bssid[2],
tdlsSetupCnf.LinkIdentifier.bssid[3],
tdlsSetupCnf.LinkIdentifier.bssid[4],
tdlsSetupCnf.LinkIdentifier.bssid[5]) ;
//VOS_ASSERT(0) ;
return eSIR_FAILURE;
}
/* varify BSSID */
status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
&tdlsSetupCnf.LinkIdentifier.bssid[0],
sizeof(tSirMacAddr)) ;
if(!status)
{
limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter\n")) ;
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
/* TODO, do more validation */
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x\n"),
tdlsSetupCnf.LinkIdentifier.InitStaAddr[0],
tdlsSetupCnf.LinkIdentifier.InitStaAddr[1],
tdlsSetupCnf.LinkIdentifier.InitStaAddr[2],
tdlsSetupCnf.LinkIdentifier.InitStaAddr[3],
tdlsSetupCnf.LinkIdentifier.InitStaAddr[4],
tdlsSetupCnf.LinkIdentifier.InitStaAddr[5]
) ;
limTdlsFindLinkPeer(pMac,
&tdlsSetupCnf.LinkIdentifier.InitStaAddr[0],
&setupPeer) ;
if(NULL == setupPeer)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
(" unknown setup CNF frame\n")) ;
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"),
(setupPeer)->peerMac[0],
(setupPeer)->peerMac[1],
(setupPeer)->peerMac[2],
(setupPeer)->peerMac[3],
(setupPeer)->peerMac[4],
(setupPeer)->peerMac[5]) ;
/*T match dialog token, before proceeding further */
if((setupPeer)->dialog != tdlsSetupCnf.DialogToken.token)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("setup CNF frame not matching with setup RSP\n")) ;
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
/*
* Now we are sure that, this set CNF is for us, now stop
* the running timer..
*/
tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupCnfTimeoutTimer) ;
/* change TDLS peer State */
(setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
(setupPeer)->tdls_link_state = TDLS_LINK_SETUP_DONE_STATE ;
/* send indication to SME that, new link is setup */
limSendSmeTdlsLinkSetupInd(pMac, (setupPeer)->peerMac, eSIR_SUCCESS) ;
/* tdls_hklee: prepare PTI template and send it to HAL */
limTdlsLinkEstablish(pMac, (setupPeer)->peerMac);
return eSIR_SUCCESS ;
}
/*
* TDLS discovery response frame processing ..
*/
static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen,
tANI_S8 rssi, tpPESession psessionEntry)
{
tDot11fTDLSDisRsp tdlsDisRsp = {{0}} ;
tANI_U32 status = 0 ;
tLimDisResultList *tdlsDisResult = NULL ;
tLimDisResultList **disResultList = &pMac->lim.gLimTdlsDisResultList ;
tSirTdlsDisReq *prevDisReq = &pMac->lim.gLimTdlsDisReq ;
status = dot11fUnpackTDLSDisRsp(pMac, pBody, frmLen, &tdlsDisRsp) ;
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
status, frmLen );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
}
/*TODO: match dialog token, before proceeding further */
/* varify BSSID */
status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
&tdlsDisRsp.LinkIdentifier.bssid[0],
sizeof(tSirMacAddr)) ;
if(!status)
{
limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS\n")) ;
return eSIR_FAILURE ;
}
/* TODO, do more validation */
if(tdlsDisRsp.DialogToken.token != prevDisReq->dialog)
{
limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame\n")) ;
return eSIR_FAILURE ;
}
pMac->lim.gLimTdlsDisStaCount++ ;
/*
* we are allocating peer info for individual peers found in TDLS
* discovery, we need to keep adding TDLS peers till we have timed
* out. We are freeing this memory at the time we are sending this
* collected peer info to SME.
*/
status = palAllocateMemory(pMac->hHdd, (void **)&tdlsDisResult,
sizeof(tLimDisResultList)) ;
if(status != eHAL_STATUS_SUCCESS)
{
limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info\n")) ;
return eSIR_FAILURE ;
}
do
{
tSirTdlsPeerInfo *peerInfo = &tdlsDisResult->tdlsDisPeerInfo ;
/* Populate peer info of tdls discovery result */
peerInfo->sessionId = psessionEntry->peSessionId;
/*
* When we receive DIS RSP from peer MAC,
* STA_MAC_OFFSET will carry peer MAC address and PEER MAC OFFSET
* will carry our MAC.
*/
status = palCopyMemory(pMac->hHdd, peerInfo->peerMac,
&tdlsDisRsp.LinkIdentifier.RespStaAddr[0],
sizeof(tSirMacAddr)) ;
/* update RSSI for this TDLS peer STA */
peerInfo->tdlsPeerRssi = rssi ;
/* update Caps Info */
tdlsUpdateCapInfo(&peerInfo->capabilityInfo ,
&tdlsDisRsp.Capabilities) ;
/* update Supp rates */
if(tdlsDisRsp.SuppRates.present)
{
ConvertSuppRates( pMac, &peerInfo->tdlsPeerSuppRates,
&tdlsDisRsp.SuppRates );
}
/* update EXT supp rates */
if(tdlsDisRsp.ExtSuppRates.present)
{
peerInfo->ExtRatesPresent = 1;
ConvertExtSuppRates( pMac, &peerInfo->tdlsPeerExtRates,
&tdlsDisRsp.ExtSuppRates );
}
/* update HT caps */
if (tdlsDisRsp.HTCaps.present)
{
palCopyMemory( pMac, &peerInfo->tdlsPeerHtCaps, &tdlsDisRsp.HTCaps,
sizeof( tDot11fIEHTCaps ) );
}
/* update EXT caps */
if (tdlsDisRsp.ExtCap.present)
{
//palCopyMemory( pMac, &peerInfo->tdlsPeerExtenCaps,
// &tdlsDisRsp.ExtCap,
// sizeof( tDot11fIEExtCap ) );
}
} while(0) ;
/* now add this new found discovery node into tdls discovery list */
tdlsDisResult->next = *disResultList ;
*disResultList = tdlsDisResult ;
return eSIR_SUCCESS ;
}
/*
* Process TDLS Teardown request frame from TDLS peer STA
*/
static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac,
tANI_U8 *pBody, tANI_U32 frmLen )
{
tDot11fTDLSTeardown tdlsTeardown = {{0}} ;
tANI_U32 status = 0 ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tpPESession psessionEntry = NULL ;
tANI_U8 sessionId = 0 ;
status = dot11fUnpackTDLSTeardown(pMac, pBody, frmLen, &tdlsTeardown) ;
if ( DOT11F_FAILED( status ) )
{
limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \
frame (0x%08x, %d bytes):\n"),status, frmLen);
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while unpacking an\
TDLS discovery Response frame (0x%08x," "%d bytes):\n"),
status, frmLen );
PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);)
}
/*
* find session entry using BSSID in link identifier, not using MAC
* header beacuse, there is cases in TDLS, there may be BSSID will not
* be present in header
*/
psessionEntry = peFindSessionByBssid(pMac,
&tdlsTeardown.LinkIdentifier.bssid[0], &sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \
("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \
tdlsTeardown.LinkIdentifier.bssid[0],
tdlsTeardown.LinkIdentifier.bssid[1],
tdlsTeardown.LinkIdentifier.bssid[2],
tdlsTeardown.LinkIdentifier.bssid[3],
tdlsTeardown.LinkIdentifier.bssid[4],
tdlsTeardown.LinkIdentifier.bssid[5]) ;
//VOS_ASSERT(0) ;
return eSIR_FAILURE;
}
/* varify BSSID */
status = palEqualMemory(pMac->hHdd, psessionEntry->bssId,
&tdlsTeardown.LinkIdentifier.bssid[0],
sizeof(tSirMacAddr)) ;
if(!status)
{
limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter\n")) ;
VOS_ASSERT(0) ;
return eSIR_FAILURE ;
}
limTdlsFindLinkPeer(pMac,
&tdlsTeardown.LinkIdentifier.InitStaAddr[0],
&setupPeer) ;
if(NULL == setupPeer)
{
//ignore
//VOS_ASSERT(0) ;
limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored\n") );
return eSIR_FAILURE ;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x\n"),
(setupPeer)->peerMac[0],
(setupPeer)->peerMac[1],
(setupPeer)->peerMac[2],
(setupPeer)->peerMac[3],
(setupPeer)->peerMac[4],
(setupPeer)->peerMac[5]) ;
switch(tdlsTeardown.Reason.code)
{
case eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON:
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("teardown with unspecified reason\n")) ;
break ;
}
case eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE:
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
(" Teardown from AP, TDLS peer unreachable\n")) ;
break ;
}
default:
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
(" unknown teardown\n")) ;
break ;
}
}
/* change TDLS peer State */
(setupPeer)->tdls_prev_link_state = (setupPeer)->tdls_link_state ;
(setupPeer)->tdls_link_state = TDLS_LINK_TEARDOWN_START_STATE ;
do
{
tpDphHashNode pStaDs = NULL ;
/* tdls_hklee: send message to HAL before it is deleted, cause */
limTdlsLinkTeardown(pMac, (setupPeer)->peerMac) ;
/* send del STA to remove context for this TDLS STA */
pStaDs = limTdlsDelSta(pMac, (setupPeer)->peerMac, psessionEntry) ;
/* now send indication to SME-->HDD->TL to remove STA from TL */
if(pStaDs)
{
limSendSmeTdlsDelPeerInd(pMac, psessionEntry->smeSessionId,
pStaDs, eSIR_SUCCESS) ;
/* send Teardown Ind to SME */
limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (setupPeer)->peerMac,
eWNI_SME_TDLS_TEARDOWN_IND) ;
/* remove node from setup list */
limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ;
}
}while(0) ;
return status ;
}
/*
* Common processing of TDLS action frames recieved
*/
void limProcessTdlsFrame(tpAniSirGlobal pMac, tANI_U32 *pBd)
{
tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd);
tANI_U8 pOffset = ((0 == WDA_GET_RX_FT_DONE(pBd))
? (( sizeof( eth_890d_header ))) :(0)) ;
tANI_U8 category = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE)[0] ;
tANI_U8 action = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE)[1] ;
tANI_U32 frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd) ;
tANI_U8 *tdlsFrameBody = (pBody + pOffset + PAYLOAD_TYPE_TDLS_SIZE) ;
//tANI_S8 rssi = (tANI_S8)SIR_MAC_BD_TO_RSSI_DB(pBd);
if(category != SIR_MAC_ACTION_TDLS)
{
limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored\n"), category );
return ;
}
frameLen -= (pOffset + PAYLOAD_TYPE_TDLS_SIZE) ;
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Received TDLS action %d (%s)"), \
action, limTraceTdlsActionString(action) ));
switch(action)
{
case SIR_MAC_TDLS_SETUP_REQ:
{
limProcessTdlsSetupReqFrame(pMac, tdlsFrameBody, frameLen) ;
break ;
}
case SIR_MAC_TDLS_SETUP_RSP:
{
limProcessTdlsSetupRspFrame(pMac, tdlsFrameBody, frameLen) ;
break ;
}
case SIR_MAC_TDLS_SETUP_CNF:
{
limProcessTdlsSetupCnfFrame(pMac, tdlsFrameBody, frameLen) ;
break ;
}
case SIR_MAC_TDLS_TEARDOWN:
{
limProcessTdlsTeardownFrame(pMac, tdlsFrameBody, frameLen) ;
break ;
}
case SIR_MAC_TDLS_DIS_REQ:
{
limProcessTdlsDisReqFrame(pMac, tdlsFrameBody, frameLen) ;
break ;
}
case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
case SIR_MAC_TDLS_CH_SWITCH_REQ:
case SIR_MAC_TDLS_CH_SWITCH_RSP:
case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
default:
{
break ;
}
}
return ;
}
/*
* ADD sta for dis response fame sent on direct link
*/
static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tSirTdlsPeerInfo *peerInfo, tpPESession psessionEntry)
{
tpDphHashNode pStaDs = NULL ;
tSirRetStatus status = eSIR_SUCCESS ;
tANI_U16 aid = 0 ;
if(NULL == peerInfo)
{
VOS_ASSERT(0) ;
return status ;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"),
peerMac[0],
peerMac[1],
peerMac[2],
peerMac[3],
peerMac[4],
peerMac[5]) ;
if(NULL != dphLookupHashEntry(pMac, peerMac,
&aid, &psessionEntry->dph.dphHashTable))
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
(" there is hash entry for this client\n")) ;
status = eSIR_FAILURE ;
VOS_ASSERT(0) ;
return status ;
}
aid = limAssignPeerIdx(pMac, psessionEntry) ;
pStaDs = dphGetHashEntry(pMac, aid, &psessionEntry->dph.dphHashTable);
if (pStaDs)
{
(void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry);
limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry);
}
pStaDs = dphAddHashEntry(pMac, peerMac, aid,
&psessionEntry->dph.dphHashTable) ;
if(NULL == pStaDs)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
(" add hash entry failed\n")) ;
status = eSIR_FAILURE ;
VOS_ASSERT(0) ;
return status;
}
if(eSIR_SUCCESS == status)
{
#ifdef TDLS_RATE_DEBUG
tSirMacRateSet *suppRates = &peerInfo->tdlsPeerSuppRates ;
tSirMacRateSet *extRates = &peerInfo->tdlsPeerExtRates ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("pSta DS [%p] \n"), pStaDs) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peerInfo->tdlsPeerSuppRates = [%p]\n"),
(tANI_U8 *)&peerInfo->tdlsPeerSuppRates) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peerInfo->tdlsPeerExtRates = [%p]\n"),
(tANI_U8 *)&peerInfo->tdlsPeerExtRates) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peerInfo->tdlsPeerPropRates = [%p]\n"),
(tANI_U8 *)&pStaDs->mlmStaContext.propRateSet) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("peerInfo->mcs = [%p]\n"),
(tANI_U8 *)peerInfo->supportedMCSSet) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("num of supp rates = %02x\n"), suppRates->numRates) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("num of ext rates = %01x\n"), extRates->numRates) ;
#endif
/* Populate matching rate set */
#ifdef WLAN_FEATURE_11AC
if(eSIR_FAILURE == limPopulateMatchingRateSet(pMac, pStaDs,
&peerInfo->tdlsPeerSuppRates,
&peerInfo->tdlsPeerExtRates,
peerInfo->supportedMCSSet,
&pStaDs->mlmStaContext.propRateSet,
psessionEntry, NULL))
#else
if(eSIR_FAILURE == limPopulateMatchingRateSet(pMac, pStaDs,
&peerInfo->tdlsPeerSuppRates,
&peerInfo->tdlsPeerExtRates,
peerInfo->supportedMCSSet,
&pStaDs->mlmStaContext.propRateSet,
psessionEntry))
#endif
{
VOS_ASSERT(0) ;
}
pStaDs->mlmStaContext.capabilityInfo = peerInfo->capabilityInfo;
palCopyMemory(pMac->hHdd, pStaDs->staAddr, peerMac,
sizeof(tSirMacAddr)) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x\n"),
pStaDs->staAddr[0],
pStaDs->staAddr[1],
pStaDs->staAddr[2],
pStaDs->staAddr[3],
pStaDs->staAddr[4],
pStaDs->staAddr[5]) ;
pStaDs->staType = STA_ENTRY_TDLS_PEER ;
status = limAddSta(pMac, pStaDs, psessionEntry);
if(eSIR_SUCCESS != status)
{
/* should not fail */
VOS_ASSERT(0) ;
}
}
return status ;
}
#endif
/*
* Add STA for TDLS setup procedure
*/
static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tLimTdlsLinkSetupPeer *setupPeer,
tpPESession psessionEntry)
{
tpDphHashNode pStaDs = NULL ;
tSirRetStatus status = eSIR_SUCCESS ;
tANI_U16 aid = 0 ;
if(NULL != dphLookupHashEntry(pMac, peerMac, &aid,
&psessionEntry->dph.dphHashTable))
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
(" there is hash entry for this client\n")) ;
status = eSIR_FAILURE ;
/* TDLS_TODO: I have seen this VOS ASSERT happened. must handle this (called from limProcessTdlsSetupReqFrame) */
VOS_ASSERT(0) ;
return status ;
}
aid = limAssignPeerIdx(pMac, psessionEntry) ;
if( !aid )
{
//Reject request.
return eSIR_FAILURE;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Aid = %d, for peer = %02x,%02x,%02x,%02x,%02x,%02x\n"),
aid, peerMac[0],peerMac[1],peerMac[2],
peerMac[3],peerMac[4],peerMac[5]) ;
pStaDs = dphGetHashEntry(pMac, aid, &psessionEntry->dph.dphHashTable);
if (pStaDs)
{
(void) limDelSta(pMac, pStaDs, false /*asynchronous*/, psessionEntry);
limDeleteDphHashEntry(pMac, pStaDs->staAddr, aid, psessionEntry);
}
pStaDs = dphAddHashEntry(pMac, peerMac, aid,
&psessionEntry->dph.dphHashTable) ;
if(NULL == pStaDs)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
(" add hash entry failed\n")) ;
status = eSIR_FAILURE ;
VOS_ASSERT(0) ;
}
limTdlsUpdateHashNodeInfo(pMac, pStaDs, setupPeer, psessionEntry) ;
pStaDs->staType = STA_ENTRY_TDLS_PEER ;
status = limAddSta(pMac, pStaDs, psessionEntry);
if(eSIR_SUCCESS != status)
{
/* should not fail */
VOS_ASSERT(0) ;
}
return status ;
}
/*
* Del STA, after Link is teardown or discovery response sent on direct link
*/
static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
tpPESession psessionEntry)
{
tSirRetStatus status = eSIR_SUCCESS ;
tANI_U16 peerIdx = 0 ;
tpDphHashNode pStaDs = NULL ;
pStaDs = dphLookupHashEntry(pMac, peerMac, &peerIdx,
&psessionEntry->dph.dphHashTable) ;
if(pStaDs)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x \n"),
pStaDs->staAddr[0],
pStaDs->staAddr[1],
pStaDs->staAddr[2],
pStaDs->staAddr[3],
pStaDs->staAddr[4],
pStaDs->staAddr[5]
) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("STA type = %x, sta idx = %x\n"),pStaDs->staType,
pStaDs->staIndex) ;
status = limDelSta(pMac, pStaDs, false, psessionEntry) ;
if(eSIR_SUCCESS == status)
{
limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx, psessionEntry) ;
limReleasePeerIdx(pMac, peerIdx, psessionEntry) ;
}
else
{
VOS_ASSERT(0) ;
}
}
return pStaDs ;
}
#ifdef FEATURE_WLAN_TDLS_INTERNAL
/*
* Prepare link establish message for HAL, construct PTI template.
*
*/
static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerMac)
{
tANI_U8 pFrame[64] ;
tDot11fTDLSPeerTrafficInd tdlsPtiTemplate ;
tANI_U32 status = 0 ;
tANI_U32 nPayload = 0 ;
tANI_U32 nBytes = 0 ;
tANI_U32 header_offset = 0 ;
tANI_U16 aid = 0 ;
tDphHashNode *pStaDs = NULL ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tpPESession psessionEntry = NULL ;
limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
if(NULL == setupPeer) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \
peerMac[0], peerMac[1], peerMac[2], \
peerMac[3], peerMac[4], peerMac[5]);
return eSIR_FAILURE;
}
psessionEntry = peFindSessionBySessionId(pMac,
setupPeer->tdls_sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkEstablish: sessionID %d is not found\n"), setupPeer->tdls_sessionId);
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
/* */
pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable) ;
if(pStaDs == NULL) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \
peerMac[0], peerMac[1], peerMac[2], \
peerMac[3], peerMac[4], peerMac[5]);
return eSIR_FAILURE;
}
palZeroMemory( pMac->hHdd, ( tANI_U8* )&tdlsPtiTemplate,
sizeof( tDot11fTDLSPeerTrafficInd ) );
/*
* setup Fixed fields,
*/
tdlsPtiTemplate.Category.category = SIR_MAC_ACTION_TDLS;
tdlsPtiTemplate.Action.action = SIR_MAC_TDLS_PEER_TRAFFIC_IND;
tdlsPtiTemplate.DialogToken.token = 0 ; /* filled by firmware at the time of transmission */
#if 1
/* CHECK_PTI_LINK_IDENTIFIER_INITIATOR_ADDRESS: initator address should be TDLS link setup's initiator address,
then below code makes such an way */
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsPtiTemplate.LinkIdentifier,
peerMac, !setupPeer->tdls_bIsResponder) ;
#else
/* below code will make PTI's linkIdentifier's initiator address be selfAddr */
PopulateDot11fLinkIden( pMac, psessionEntry, &tdlsPtiTemplate.LinkIdentifier,
peerMac, TDLS_INITIATOR) ;
#endif
/* PUBufferStatus will be filled by firmware at the time of transmission */
tdlsPtiTemplate.PUBufferStatus.present = 1;
/* TODO: get ExtendedCapabilities IE */
/*
* now we pack it. First, how much space are we going to need?
*/
status = dot11fGetPackedTDLSPeerTrafficIndSize ( pMac, &tdlsPtiTemplate, &nPayload);
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x).\n"), status );
/* We'll fall back on the worst case scenario: */
nPayload = sizeof( tdlsPtiTemplate );
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x).\n"), status );
}
/*
* This frame is going out from PE as data frames with special ethertype
* 89-0d.
* 8 bytes of RFC 1042 header
*/
nBytes = nPayload + sizeof( tSirMacMgmtHdr )
+ sizeof( eth_890d_header )
+ PAYLOAD_TYPE_TDLS_SIZE ;
if(nBytes > 64) {
limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64.\n"), nBytes);
nBytes = 64;
}
/* zero out the memory */
palZeroMemory( pMac->hHdd, pFrame, sizeof(pFrame) );
/* fill out the buffer descriptor */
header_offset = limPrepareTdlsFrameHeader(pMac, pFrame,
LINK_IDEN_ADDR_OFFSET(tdlsPtiTemplate), TDLS_LINK_AP, !setupPeer->tdls_bIsResponder, psessionEntry) ;
status = dot11fPackTDLSPeerTrafficInd ( pMac, &tdlsPtiTemplate, pFrame
+ header_offset, nPayload, &nPayload );
if ( DOT11F_FAILED( status ) )
{
limLog( pMac, LOGE, FL("Failed to pack a PTI template \
(0x%08x).\n"), status );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( status ) )
{
limLog( pMac, LOGW, FL("There were warnings while packing TDLS"
"Peer Traffic Indication (0x%08x).\n") );
}
LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d \n"), \
setupPeer->tdls_bIsResponder, header_offset, PTI_LINK_IDEN_OFFSET, PTI_BUF_STATUS_OFFSET));
limSendTdlsLinkEstablish(pMac, setupPeer->tdls_bIsResponder,
header_offset+PTI_LINK_IDEN_OFFSET, header_offset+PTI_BUF_STATUS_OFFSET,
nBytes, pFrame, (tANI_U8 *)&setupPeer->tdlsPeerExtCaps);
return eSIR_SUCCESS;
}
/*
* Prepare link teardown message for HAL from peer_mac
*
*/
static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMac)
{
tDphHashNode *pStaDs = NULL ;
tANI_U16 aid = 0 ;
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
tpPESession psessionEntry = NULL ;
limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ;
if(NULL == setupPeer) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \
peerMac[0], peerMac[1], peerMac[2], \
peerMac[3], peerMac[4], peerMac[5]);
return eSIR_FAILURE;
}
psessionEntry = peFindSessionBySessionId(pMac,
setupPeer->tdls_sessionId) ;
if(NULL == psessionEntry)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkTeardown: sessionID %d is not found\n"), setupPeer->tdls_sessionId);
VOS_ASSERT(0) ;
return eHAL_STATUS_FAILURE;
}
/* */
pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable);
if(pStaDs == NULL) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \
peerMac[0], peerMac[1], peerMac[2], \
peerMac[3], peerMac[4], peerMac[5]);
return eSIR_FAILURE;
}
limSendTdlsLinkTeardown(pMac, pStaDs->staIndex);
return eSIR_SUCCESS;
}
/*
* Prepare Discovery RSP message for SME, collect peerINfo for all the
* peers discovered and delete/clean discovery lists in PE.
*/
static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac,
tSirTdlsDisRsp *disRsp, tANI_U8 disStaCount)
{
tANI_U32 disMsgRspSize = sizeof(tSirTdlsDisRsp);
tANI_U8 status = eHAL_STATUS_SUCCESS ;
/*
* allocate memory for tdls discovery response, allocated memory should
* be alloc_mem = tdlsStaCount * sizeof(peerinfo)
* + siezeof tSirTdlsDisRsp.
*/
disMsgRspSize += (disStaCount * sizeof(tSirTdlsPeerInfo));
/* now allocate memory */
status = palAllocateMemory( pMac->hHdd, (void **)&disRsp, disMsgRspSize ) ;
if(eHAL_STATUS_FAILURE == status)
{
limLog(pMac, LOGP, FL("palAllocateMemory failed for DIS RSP"));
return NULL ;
}
if(disStaCount)
{
tLimDisResultList *tdlsDisRspList = pMac->lim.gLimTdlsDisResultList ;
tSirTdlsPeerInfo *peerInfo = &disRsp->tdlsDisPeerInfo[0] ;
tLimDisResultList *currentNode = tdlsDisRspList ;
while(tdlsDisRspList != NULL)
{
palCopyMemory( pMac->hHdd, (tANI_U8 *)peerInfo,
(tANI_U8 *) &tdlsDisRspList->tdlsDisPeerInfo,
sizeof(tSirTdlsPeerInfo));
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"),
peerInfo->peerMac[0] ,
peerInfo->peerMac[1] ,
peerInfo->peerMac[2] ,
peerInfo->peerMac[3] ,
peerInfo->peerMac[4] ,
peerInfo->peerMac[5]) ;
disStaCount-- ;
peerInfo++ ;
currentNode = tdlsDisRspList ;
tdlsDisRspList = tdlsDisRspList->next ;
palFreeMemory(pMac->hHdd, currentNode) ;
/* boundary condition check, may be fatal */
if(((!disStaCount) && (tdlsDisRspList))
|| ((!tdlsDisRspList) && disStaCount))
{
limLog(pMac, LOG1, FL("mismatch in dis sta count and\
and number of nodes in list\n")) ;
VOS_ASSERT(0) ;
return NULL ;
}
} /* end of while */
/* All discovery STA processed */
pMac->lim.gLimTdlsDisResultList = NULL ;
} /* end of if dis STA count */
return (disRsp) ;
}
/* Send Teardown response back to PE */
void limSendSmeTdlsTeardownRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode,
tSirMacAddr peerMac, tANI_U16 msgType)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsTeardownRsp *teardownRspMsg = NULL ;
tANI_U8 status = eHAL_STATUS_SUCCESS ;
mmhMsg.type = msgType ;
status = palAllocateMemory( pMac->hHdd, (void **)&teardownRspMsg,
sizeof(tSirTdlsTeardownRsp)) ;
if(eHAL_STATUS_SUCCESS != status)
{
VOS_ASSERT(0) ;
}
palCopyMemory( pMac->hHdd, teardownRspMsg->peerMac, (tANI_U8 *)peerMac,
sizeof(tSirMacAddr)) ;
teardownRspMsg->statusCode = statusCode ;
mmhMsg.bodyptr = teardownRspMsg ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return ;
}
/*
* Send Link start RSP back to SME after link is setup or failed
*/
void limSendSmeTdlsLinkStartRsp(tpAniSirGlobal pMac,
tSirResultCodes statusCode,
tSirMacAddr peerMac,
tANI_U16 msgType)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsLinksetupRsp *setupRspMsg = NULL ;
tANI_U8 status = eHAL_STATUS_SUCCESS ;
mmhMsg.type = msgType ;
status = palAllocateMemory( pMac->hHdd, (void **)&setupRspMsg,
sizeof(tSirTdlsLinksetupRsp)) ;
if(eHAL_STATUS_SUCCESS != status)
{
VOS_ASSERT(0) ;
}
palCopyMemory( pMac->hHdd, setupRspMsg->peerMac, (tANI_U8 *)peerMac,
sizeof(tSirMacAddr)) ;
setupRspMsg->statusCode = statusCode ;
mmhMsg.bodyptr = setupRspMsg ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return ;
}
/*
* Send TDLS discovery RSP back to SME
*/
void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode,
tANI_U16 msgType)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsDisRsp *tdlsDisRsp = NULL ;
mmhMsg.type = msgType ;
if(eSIR_SME_SUCCESS == statusCode)
{
tANI_U8 tdlsStaCount = pMac->lim.gLimTdlsDisStaCount ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("no of TDLS STA discovered: %d\n"), tdlsStaCount) ;
tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, tdlsStaCount) ;
if(tdlsDisRsp)
{
tdlsDisRsp->numDisSta = tdlsStaCount ;
}
else
{
limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP\n"));
VOS_ASSERT(0) ;
return ;
}
/* all Discovery STA is processed */
pMac->lim.gLimTdlsDisStaCount = 0 ;
}
else
{
tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, 0) ;
}
tdlsDisRsp->statusCode = statusCode ;
mmhMsg.bodyptr = tdlsDisRsp ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return ;
}
/*
* Once Link is setup with PEER, send Add STA ind to SME
*/
static eHalStatus limSendSmeTdlsAddPeerInd(tpAniSirGlobal pMac,
tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsPeerInd *peerInd = NULL ;
mmhMsg.type = eWNI_SME_ADD_TDLS_PEER_IND ;
if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &peerInd,
(sizeof(tSirTdlsPeerInd))))
{
PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
return eSIR_FAILURE;
}
palCopyMemory( pMac->hHdd, peerInd->peerMac,
(tANI_U8 *) pStaDs->staAddr, sizeof(tSirMacAddr));
peerInd->sessionId = sessionId;
peerInd->staId = pStaDs->staIndex ;
peerInd->ucastSig = pStaDs->ucUcastSig ;
peerInd->bcastSig = pStaDs->ucBcastSig ;
peerInd->length = sizeof(tSmeIbssPeerInd) ;
mmhMsg.bodyptr = peerInd ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return eSIR_SUCCESS ;
}
/*
* Once link is teardown, send Del Peer Ind to SME
*/
static eHalStatus limSendSmeTdlsDelPeerInd(tpAniSirGlobal pMac,
tANI_U8 sessionId, tDphHashNode *pStaDs, tANI_U8 status)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsPeerInd *peerInd = NULL ;
mmhMsg.type = eWNI_SME_DELETE_TDLS_PEER_IND ;
if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &peerInd,
(sizeof(tSirTdlsPeerInd))))
{
PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
return eSIR_FAILURE;
}
palCopyMemory( pMac->hHdd, peerInd->peerMac,
(tANI_U8 *) pStaDs->staAddr, sizeof(tSirMacAddr));
peerInd->sessionId = sessionId;
peerInd->staId = pStaDs->staIndex ;
peerInd->ucastSig = pStaDs->ucUcastSig ;
peerInd->bcastSig = pStaDs->ucBcastSig ;
peerInd->length = sizeof(tSmeIbssPeerInd) ;
mmhMsg.bodyptr = peerInd ;
//peerInd->statusCode = status ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return eSIR_SUCCESS ;
}
/*
* Send Link setup Ind to SME, This is the case where, link setup is
* initiated by peer STA
*/
static eHalStatus limSendSmeTdlsLinkSetupInd(tpAniSirGlobal pMac,
tSirMacAddr peerMac, tANI_U8 status)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsLinkSetupInd *setupInd = NULL ;
mmhMsg.type = eWNI_SME_TDLS_LINK_START_IND ;
if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &setupInd,
(sizeof(tSirTdlsLinkSetupInd))))
{
PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
return eSIR_FAILURE;
}
palCopyMemory( pMac->hHdd, setupInd->peerMac,
(tANI_U8 *) peerMac, sizeof(tSirMacAddr));
setupInd->length = sizeof(tSirTdlsLinkSetupInd);
setupInd->statusCode = status ;
mmhMsg.bodyptr = setupInd ;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return eSIR_SUCCESS ;
}
/*
* Setup RSP timer handler
*/
void limTdlsLinkSetupRspTimerHandler(void *pMacGlobal, tANI_U32 timerId)
{
tANI_U32 statusCode;
tSirMsgQ msg;
tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
/* Prepare and post message to LIM Message Queue */
msg.type = SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT;
msg.bodyptr = NULL ;
msg.bodyval = timerId ;
if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS)
limLog(pMac, LOGE,
FL("posting message %X to LIM failed, reason=%d\n"),
msg.type, statusCode);
return ;
}
/*
* Link setup CNF timer
*/
void limTdlsLinkSetupCnfTimerHandler(void *pMacGlobal, tANI_U32 timerId)
{
tANI_U32 statusCode;
tSirMsgQ msg;
tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
// Prepare and post message to LIM Message Queue
msg.type = SIR_LIM_TDLS_LINK_SETUP_CNF_TIMEOUT;
msg.bodyptr = NULL ;
msg.bodyval = timerId ;
if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS)
limLog(pMac, LOGE,
FL("posting message %X to LIM failed, reason=%d\n"),
msg.type, statusCode);
return ;
}
/*
* start TDLS timer
*/
void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer,
tANI_U32 timerId, tANI_U16 timerType, tANI_U32 timerMsg)
{
tANI_U32 cfgValue = (timerMsg == SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT)
? WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT
: WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT ;
void *timerFunc = (timerMsg == SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT)
? (limTdlsLinkSetupRspTimerHandler)
: limTdlsLinkSetupCnfTimerHandler ;
/* TODO: Read timer vals from CFG */
cfgValue = SYS_MS_TO_TICKS(cfgValue);
/*
* create TDLS discovery response wait timer and activate it
*/
if (tx_timer_create(timer, "TDLS link setup timers", timerFunc,
timerId, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS)
{
limLog(pMac, LOGP,
FL("could not create TDLS discovery response wait timer\n"));
return;
}
//assign appropriate sessionId to the timer object
timer->sessionId = sessionId;
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0,
eLIM_TDLS_DISCOVERY_RSP_WAIT));
if (tx_timer_activate(timer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!\n"));
return ;
}
return ;
}
#endif
/*
* Once Link is setup with PEER, send Add STA ind to SME
*/
static eHalStatus limSendSmeTdlsAddStaRsp(tpAniSirGlobal pMac,
tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs,
tANI_U8 status)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsAddStaRsp *addStaRsp = NULL ;
mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP ;
if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &addStaRsp,
(sizeof(tSirTdlsAddStaRsp))))
{
PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
return eSIR_FAILURE;
}
addStaRsp->sessionId = sessionId;
addStaRsp->statusCode = status;
if( pStaDs )
{
addStaRsp->staId = pStaDs->staIndex ;
addStaRsp->ucastSig = pStaDs->ucUcastSig ;
addStaRsp->bcastSig = pStaDs->ucBcastSig ;
}
if( peerMac )
{
palCopyMemory( pMac->hHdd, addStaRsp->peerMac,
(tANI_U8 *) peerMac, sizeof(tSirMacAddr));
}
addStaRsp->length = sizeof(tSirTdlsAddStaRsp) ;
addStaRsp->messageType = eWNI_SME_TDLS_ADD_STA_RSP ;
mmhMsg.bodyptr = addStaRsp;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return eSIR_SUCCESS ;
}
/*
* STA RSP received from HAL
*/
eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg,
tpPESession psessionEntry)
{
tAddStaParams *pAddStaParams = (tAddStaParams *) msg ;
tANI_U8 status = eSIR_SUCCESS ;
tDphHashNode *pStaDs = NULL ;
tANI_U16 aid = 0 ;
SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("ADD_STA_RSP received :staIdx=%d, staMac=%02x:%02x:%02x:%02x:%02x:%02x"), pAddStaParams->staIdx, \
pAddStaParams->staMac[0],
pAddStaParams->staMac[1],
pAddStaParams->staMac[2],
pAddStaParams->staMac[3],
pAddStaParams->staMac[4],
pAddStaParams->staMac[5] ) ;
if (pAddStaParams->status != eHAL_STATUS_SUCCESS)
{
VOS_ASSERT(0) ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Add sta failed \n")) ;
status = eSIR_FAILURE;
goto add_sta_error;
}
pStaDs = dphLookupHashEntry(pMac, pAddStaParams->staMac, &aid,
&psessionEntry->dph.dphHashTable);
if(NULL == pStaDs)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("pStaDs is NULL \n")) ;
status = eSIR_FAILURE;
goto add_sta_error;
}
pStaDs->bssId = pAddStaParams->bssIdx;
pStaDs->staIndex = pAddStaParams->staIdx;
pStaDs->ucUcastSig = pAddStaParams->ucUcastSig;
pStaDs->ucBcastSig = pAddStaParams->ucBcastSig;
pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
pStaDs->valid = 1 ;
#ifdef FEATURE_WLAN_TDLS_INTERNAL
status = limSendSmeTdlsAddPeerInd(pMac, psessionEntry->smeSessionId,
pStaDs, eSIR_SUCCESS ) ;
if(eSIR_FAILURE == status)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Peer IND msg to SME failed\n")) ;
palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
return eSIR_FAILURE ;
}
/*
* Now, there is two things a) ADD STA RSP for ADD STA request sent
* after recieving discovery request from Peer.
* now we have to send discovery response, if there is any pending
* discovery equest..
*/
do
{
tSirTdlsPeerInfo *peerInfo = limTdlsFindDisPeer(pMac,
pAddStaParams->staMac) ;
if(peerInfo)
{
/*
* send TDLS discovery response frame on direct link, state machine
* is rolling.., once discovery response is get Acked, we will
* send response to SME based on TxComplete callback results
*/
limSendTdlsDisRspFrame(pMac, peerInfo->peerMac, peerInfo->dialog, psessionEntry) ;
peerInfo->tdlsPeerState = TDLS_DIS_RSP_SENT_WAIT_STATE ;
}
} while(0) ;
#else
status = limSendSmeTdlsAddStaRsp(pMac, psessionEntry->smeSessionId,
pAddStaParams->staMac, pStaDs, status) ;
if(eSIR_FAILURE == status)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
("Peer IND msg to SME failed\n")) ;
palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
}
return status;
#endif
add_sta_error:
status = limSendSmeTdlsAddStaRsp(pMac, psessionEntry->smeSessionId,
pAddStaParams->staMac, NULL, status) ;
palFreeMemory( pMac->hHdd, (void *) pAddStaParams );
return status ;
}
/*
* FUNCTION: Populate Link Identifier element IE
*
*/
void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry,
tDot11fIELinkIdentifier *linkIden,
tSirMacAddr peerMac, tANI_U8 reqType)
{
//tANI_U32 size = sizeof(tSirMacAddr) ;
tANI_U8 *initStaAddr = NULL ;
tANI_U8 *respStaAddr = NULL ;
(reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr),
(respStaAddr = linkIden->RespStaAddr))
: ((respStaAddr = linkIden->InitStaAddr ),
(initStaAddr = linkIden->RespStaAddr)) ;
palCopyMemory( pMac->hHdd, (tANI_U8 *)linkIden->bssid,
(tANI_U8 *) psessionEntry->bssId, sizeof(tSirMacAddr)) ;
palCopyMemory( pMac->hHdd, (tANI_U8 *)initStaAddr,
psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ;
palCopyMemory( pMac->hHdd, (tANI_U8 *)respStaAddr, (tANI_U8 *) peerMac,
sizeof( tSirMacAddr ));
linkIden->present = 1 ;
return ;
}
void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac,
tDot11fIEExtCap *extCapability)
{
extCapability->TDLSPeerPSMSupp = PEER_PSM_SUPPORT ;
extCapability->TDLSPeerUAPSDBufferSTA = PEER_BUFFER_STA_SUPPORT ;
extCapability->TDLSChannelSwitching = CH_SWITCH_SUPPORT ;
extCapability->TDLSSupport = TDLS_SUPPORT ;
extCapability->TDLSProhibited = TDLS_PROHIBITED ;
extCapability->TDLSChanSwitProhibited = TDLS_CH_SWITCH_PROHIBITED ;
extCapability->present = 1 ;
return ;
}
#ifdef FEATURE_WLAN_TDLS_INTERNAL
/*
* Public Action frame common processing
* This Function will be moved/merged to appropriate place
* once other public action frames (particularly 802.11k)
* is in place
*/
void limProcessTdlsPublicActionFrame(tpAniSirGlobal pMac, tANI_U32 *pBd,
tpPESession psessionEntry)
{
tANI_U32 frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd) ;
tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pBd) ;
tANI_S8 rssi = (tANI_S8)WDA_GET_RX_RSSI_DB(pBd) ;
limProcessTdlsDisRspFrame(pMac, pBody, frameLen, rssi, psessionEntry) ;
return ;
}
eHalStatus limTdlsPrepareSetupReqFrame(tpAniSirGlobal pMac,
tLimTdlsLinkSetupInfo *linkSetupInfo,
tANI_U8 dialog, tSirMacAddr peerMac,
tpPESession psessionEntry)
{
tLimTdlsLinkSetupPeer *setupPeer = NULL ;
/*
* we allocate the TDLS setup Peer Memory here, we will free'd this
* memory after teardown, if the link is successfully setup or
* free this memory if any timeout is happen in link setup procedure
*/
if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd,
(void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer )))
{
limLog( pMac, LOGP,
FL( "Unable to allocate memory during ADD_STA\n" ));
VOS_ASSERT(0) ;
return eSIR_MEM_ALLOC_FAILED;
}
setupPeer->dialog = dialog ;
setupPeer->tdls_prev_link_state = setupPeer->tdls_link_state ;
setupPeer->tdls_link_state = TDLS_LINK_SETUP_START_STATE ;
/* TDLS_sessionize: remember sessionId for future */
setupPeer->tdls_sessionId = psessionEntry->peSessionId;
setupPeer->tdls_bIsResponder = 1;
/*
* we only populate peer MAC, so it can assit us to find the
* TDLS peer after response/or after response timeout
*/
palCopyMemory(pMac->hHdd, setupPeer->peerMac, peerMac,
sizeof(tSirMacAddr)) ;
/* format TDLS discovery request frame and transmit it */
limSendTdlsLinkSetupReqFrame(pMac, peerMac, dialog, psessionEntry, NULL, 0) ;
limStartTdlsTimer(pMac, psessionEntry->peSessionId,
&setupPeer->gLimTdlsLinkSetupRspTimeoutTimer,
(tANI_U32)setupPeer->peerMac,
WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT,
SIR_LIM_TDLS_LINK_SETUP_RSP_TIMEOUT) ;
/* update setup peer list */
setupPeer->next = linkSetupInfo->tdlsLinkSetupList ;
linkSetupInfo->tdlsLinkSetupList = setupPeer ;
/* in case of success, eWNI_SME_TDLS_LINK_START_RSP is sent back to
* SME later when TDLS setup cnf TX complete is successful. --> see
* limTdlsSetupCnfTxComplete()
*/
return eSIR_SUCCESS ;
}
#endif
/*
* Process Send Mgmt Request from SME and transmit to AP.
*/
tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
/* get all discovery request parameters */
tSirTdlsSendMgmtReq *pSendMgmtReq = (tSirTdlsSendMgmtReq*) pMsgBuf ;
tpPESession psessionEntry;
tANI_U8 sessionId;
tSirResultCodes resultCode = eSIR_SME_INVALID_PARAMETERS;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Send Mgmt Recieved\n")) ;
if((psessionEntry = peFindSessionByBssid(pMac, pSendMgmtReq->bssid, &sessionId))
== NULL)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"PE Session does not exist for given sme sessionId %d\n",
pSendMgmtReq->sessionId);
goto lim_tdls_send_mgmt_error;
}
/* check if we are in proper state to work as TDLS client */
if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"send mgmt received in wrong system Role %d\n",
psessionEntry->limSystemRole);
goto lim_tdls_send_mgmt_error;
}
/*
* if we are still good, go ahead and check if we are in proper state to
* do TDLS discovery req/rsp/....frames.
*/
if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
(psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
{
limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \
state (%d)\n", psessionEntry->limSmeState);
goto lim_tdls_send_mgmt_error;
}
switch( pSendMgmtReq->reqType )
{
case SIR_MAC_TDLS_DIS_REQ:
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
"Transmit Discovery Request Frame\n") ;
/* format TDLS discovery request frame and transmit it */
limSendTdlsDisReqFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog,
psessionEntry) ;
resultCode = eSIR_SME_SUCCESS;
break;
case SIR_MAC_TDLS_DIS_RSP:
{
//Send a response mgmt action frame
limSendTdlsDisRspFrame(pMac, pSendMgmtReq->peerMac,
pSendMgmtReq->dialog, psessionEntry) ;
resultCode = eSIR_SME_SUCCESS;
}
break;
case SIR_MAC_TDLS_SETUP_REQ:
{
limSendTdlsLinkSetupReqFrame(pMac,
pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry,
&pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
resultCode = eSIR_SME_SUCCESS;
}
break;
case SIR_MAC_TDLS_SETUP_RSP:
{
limSendTdlsSetupRspFrame(pMac,
pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry, pSendMgmtReq->statusCode,
&pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
resultCode = eSIR_SME_SUCCESS;
}
break;
case SIR_MAC_TDLS_SETUP_CNF:
{
limSendTdlsLinkSetupCnfFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog,
psessionEntry, &pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
resultCode = eSIR_SME_SUCCESS;
}
break;
case SIR_MAC_TDLS_TEARDOWN:
{
limSendTdlsTeardownFrame(pMac,
pSendMgmtReq->peerMac, pSendMgmtReq->statusCode, psessionEntry,
&pSendMgmtReq->addIe[0], (pSendMgmtReq->length - sizeof(tSirTdlsSendMgmtReq)));
resultCode = eSIR_SME_SUCCESS;
}
break;
case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
{
}
break;
case SIR_MAC_TDLS_CH_SWITCH_REQ:
{
}
break;
case SIR_MAC_TDLS_CH_SWITCH_RSP:
{
}
break;
case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
{
}
break;
default:
break;
}
lim_tdls_send_mgmt_error:
limSendSmeRsp( pMac, eWNI_SME_TDLS_SEND_MGMT_RSP,
resultCode, pSendMgmtReq->sessionId, pSendMgmtReq->transactionId);
return eSIR_SUCCESS;
}
/*
* Once link is teardown, send Del Peer Ind to SME
*/
static eHalStatus limSendSmeTdlsDelStaRsp(tpAniSirGlobal pMac,
tANI_U8 sessionId, tSirMacAddr peerMac, tDphHashNode *pStaDs,
tANI_U8 status)
{
tSirMsgQ mmhMsg = {0} ;
tSirTdlsDelStaRsp *pDelSta = NULL ;
mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP ;
if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd,(void * *) &pDelSta,
(sizeof(tSirTdlsDelStaRsp))))
{
PELOGE(limLog(pMac, LOGE, FL("Failed to allocate memory"));)
return eSIR_FAILURE;
}
pDelSta->sessionId = sessionId;
pDelSta->statusCode = status ;
if( pStaDs )
{
pDelSta->staId = pStaDs->staIndex ;
}
if( peerMac )
{
palCopyMemory(pMac->hHdd, pDelSta->peerMac, peerMac, sizeof(tSirMacAddr));
}
pDelSta->length = sizeof(tSirTdlsDelStaRsp) ;
pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP ;
mmhMsg.bodyptr = pDelSta;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return eSIR_SUCCESS ;
}
/*
* Process Send Mgmt Request from SME and transmit to AP.
*/
tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
/* get all discovery request parameters */
tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq*) pMsgBuf ;
tpPESession psessionEntry;
tANI_U8 sessionId;
tLimTdlsLinkSetupPeer setupPeer = {0};
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Send Mgmt Recieved\n")) ;
if((psessionEntry = peFindSessionByBssid(pMac, pAddStaReq->bssid, &sessionId))
== NULL)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"PE Session does not exist for given sme sessionId %d\n",
pAddStaReq->sessionId);
goto lim_tdls_add_sta_error;
}
/* check if we are in proper state to work as TDLS client */
if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"send mgmt received in wrong system Role %d\n",
psessionEntry->limSystemRole);
goto lim_tdls_add_sta_error;
}
/*
* if we are still good, go ahead and check if we are in proper state to
* do TDLS discovery req/rsp/....frames.
*/
if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
(psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
{
limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \
state (%d)\n", psessionEntry->limSmeState);
goto lim_tdls_add_sta_error;
}
pMac->lim.gLimAddStaTdls = true ;
/* To start with, send add STA request to HAL */
if(eSIR_FAILURE == limTdlsSetupAddSta(pMac, pAddStaReq->peerMac,
&setupPeer, psessionEntry))
{
VOS_ASSERT(0) ;
goto lim_tdls_add_sta_error;
}
return eSIR_SUCCESS;
lim_tdls_add_sta_error:
limSendSmeTdlsAddStaRsp(pMac,
pAddStaReq->sessionId, pAddStaReq->peerMac, NULL, eSIR_FAILURE );
return eSIR_SUCCESS;
}
/*
* Process Del Sta Request from SME .
*/
tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
/* get all discovery request parameters */
tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq*) pMsgBuf ;
tpPESession psessionEntry;
tANI_U8 sessionId;
tpDphHashNode pStaDs = NULL ;
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
("Send Mgmt Recieved\n")) ;
if((psessionEntry = peFindSessionByBssid(pMac, pDelStaReq->bssid, &sessionId))
== NULL)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"PE Session does not exist for given sme sessionId %d\n",
pDelStaReq->sessionId);
limSendSmeTdlsDelStaRsp(pMac, 0, pDelStaReq->peerMac,
NULL, eSIR_FAILURE) ;
return eSIR_FAILURE;
}
/* check if we are in proper state to work as TDLS client */
if (psessionEntry->limSystemRole != eLIM_STA_ROLE)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
"Del sta received in wrong system Role %d\n",
psessionEntry->limSystemRole);
goto lim_tdls_del_sta_error;
}
/*
* if we are still good, go ahead and check if we are in proper state to
* do TDLS discovery req/rsp/....frames.
*/
if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
(psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE))
{
limLog(pMac, LOGE, "Del Sta received in invalid LIMsme \
state (%d)\n", psessionEntry->limSmeState);
goto lim_tdls_del_sta_error;
}
pStaDs = limTdlsDelSta(pMac, pDelStaReq->peerMac, psessionEntry) ;
/* now send indication to SME-->HDD->TL to remove STA from TL */
if(pStaDs)
{
limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac,
pStaDs, eSIR_SUCCESS) ;
return eSIR_SUCCESS;
}
lim_tdls_del_sta_error:
limSendSmeTdlsDelStaRsp(pMac, psessionEntry->smeSessionId, pDelStaReq->peerMac,
NULL, eSIR_FAILURE) ;
return eSIR_SUCCESS;
}
#endif