| /* |
| * rx.c |
| * |
| * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Texas Instruments nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /***************************************************************************/ |
| /* */ |
| /* MODULE: Rx.c */ |
| /* PURPOSE: Rx module functions */ |
| /* */ |
| /***************************************************************************/ |
| #define __FILE_ID__ FILE_ID_54 |
| #include "tidef.h" |
| #include "paramOut.h" |
| #include "rx.h" |
| #include "osApi.h" |
| #include "timer.h" |
| #include "DataCtrl_Api.h" |
| #include "Ctrl.h" |
| #include "802_11Defs.h" |
| #include "Ethernet.h" |
| #include "report.h" |
| #include "rate.h" |
| #include "mlmeApi.h" |
| #include "rsnApi.h" |
| #include "smeApi.h" |
| #include "siteMgrApi.h" |
| #include "GeneralUtil.h" |
| #include "EvHandler.h" |
| #ifdef XCC_MODULE_INCLUDED |
| #include "XCCMngr.h" |
| #endif |
| #include "TWDriver.h" |
| #include "RxBuf.h" |
| #include "DrvMainModules.h" |
| #include "bmtrace_api.h" |
| #include "PowerMgr_API.h" |
| |
| |
| #define EAPOL_PACKET 0x888E |
| #define IAPP_PACKET 0x0000 |
| #define PREAUTH_EAPOL_PACKET 0x88C7 |
| |
| |
| #define RX_DATA_FILTER_FLAG_NO_BIT_MASK 0 |
| #define RX_DATA_FILTER_FLAG_USE_BIT_MASK 1 |
| #define RX_DATA_FILTER_FLAG_IP_HEADER 0 |
| #define RX_DATA_FILTER_FLAG_ETHERNET_HEADER 2 |
| #define RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY 14 |
| |
| #define PADDING_ETH_PACKET_SIZE 2 |
| |
| /* CallBack for recieving packet from rxXfer */ |
| static void rxData_ReceivePacket (TI_HANDLE hRxData, void *pBuffer); |
| |
| static ERxBufferStatus rxData_RequestForBuffer (TI_HANDLE hRxData, void **pBuf, TI_UINT16 aLength, TI_UINT32 uEncryptionFlag,PacketClassTag_e ePacketClassTag); |
| |
| #if 0 |
| static TI_STATUS rxData_checkBssIdAndBssType(TI_HANDLE hRxData, |
| dot11_header_t* dot11_header, |
| TMacAddr **rxBssid, |
| ScanBssType_e *currBssType, |
| TMacAddr *currBssId); |
| #endif |
| static TI_STATUS rxData_convertWlanToEthHeader (TI_HANDLE hRxData, void *pBuffer, TI_UINT16 * etherType); |
| static TI_STATUS rxData_ConvertAmsduToEthPackets (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_dataPacketDisptcher (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_discardPacket (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_discardPacketVlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_rcvPacketInOpenNotify (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_rcvPacketEapol (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| static void rxData_rcvPacketData (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| |
| static TI_STATUS rxData_enableDisableRxDataFilters(TI_HANDLE hRxData, TI_BOOL enabled); |
| static TI_STATUS rxData_addRxDataFilter(TI_HANDLE hRxData, TRxDataFilterRequest* request); |
| static TI_STATUS rxData_removeRxDataFilter(TI_HANDLE hRxData, TRxDataFilterRequest* request); |
| |
| |
| #ifdef XCC_MODULE_INCLUDED |
| static void rxData_rcvPacketIapp(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr); |
| #endif |
| #ifdef TI_DBG |
| static void rxData_printRxThroughput(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured); |
| #endif |
| |
| static void rxData_StartReAuthActiveTimer(TI_HANDLE hRxData); |
| static void reAuthTimeout(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured); |
| static void rxData_ReauthEnablePriority(TI_HANDLE hRxData); |
| |
| |
| /************************************************************************* |
| * rxData_create * |
| ************************************************************************** |
| * DESCRIPTION: This function initializes the Rx data module. |
| * |
| * INPUT: hOs - handle to Os Abstraction Layer |
| * |
| * OUTPUT: |
| * |
| * RETURN: Handle to the allocated Rx data control block |
| ************************************************************************/ |
| TI_HANDLE rxData_create (TI_HANDLE hOs) |
| { |
| rxData_t *pRxData; |
| |
| /* check parameters validity */ |
| if (hOs == NULL) |
| { |
| WLAN_OS_REPORT(("FATAL ERROR: rxData_create(): OS handle Error - Aborting\n")); |
| return NULL; |
| } |
| |
| |
| /* alocate Rx module control block */ |
| pRxData = os_memoryAlloc(hOs, (sizeof(rxData_t))); |
| |
| if (!pRxData) |
| { |
| WLAN_OS_REPORT(("FATAL ERROR: rxData_create(): Error Creating Rx Module - Aborting\n")); |
| return NULL; |
| } |
| |
| /* reset Rx control block */ |
| os_memoryZero (hOs, pRxData, (sizeof(rxData_t))); |
| |
| pRxData->RxEventDistributor = DistributorMgr_Create (hOs, MAX_RX_NOTIF_REQ_ELMENTS); |
| |
| pRxData->hOs = hOs; |
| |
| return (TI_HANDLE)pRxData; |
| } |
| |
| /*************************************************************************** |
| * rxData_config * |
| **************************************************************************** |
| * DESCRIPTION: This function configures the Rx Data module |
| * |
| * INPUTS: pStadHandles - The driver modules handles |
| * |
| * OUTPUT: |
| * |
| * RETURNS: void |
| ***************************************************************************/ |
| void rxData_init (TStadHandlesList *pStadHandles) |
| { |
| rxData_t *pRxData = (rxData_t *)(pStadHandles->hRxData); |
| |
| pRxData->hCtrlData = pStadHandles->hCtrlData; |
| pRxData->hTWD = pStadHandles->hTWD; |
| pRxData->hMlme = pStadHandles->hMlmeSm; |
| pRxData->hRsn = pStadHandles->hRsn; |
| pRxData->hSiteMgr = pStadHandles->hSiteMgr; |
| pRxData->hOs = pStadHandles->hOs; |
| pRxData->hReport = pStadHandles->hReport; |
| pRxData->hXCCMgr = pStadHandles->hXCCMngr; |
| pRxData->hEvHandler = pStadHandles->hEvHandler; |
| pRxData->hTimer = pStadHandles->hTimer; |
| pRxData->hPowerMgr = pStadHandles->hPowerMgr; |
| |
| pRxData->rxDataExcludeUnencrypted = DEF_EXCLUDE_UNENCYPTED; |
| pRxData->rxDataExludeBroadcastUnencrypted = DEF_EXCLUDE_UNENCYPTED; |
| pRxData->rxDataEapolDestination = DEF_EAPOL_DESTINATION; |
| pRxData->rxDataPortStatus = DEF_RX_PORT_STATUS; |
| pRxData->genericEthertype = EAPOL_PACKET; |
| |
| /* |
| * configure rx data dispatcher |
| */ |
| |
| /* port status close */ |
| pRxData->rxData_dispatchBuffer[CLOSE][DATA_DATA_PACKET] = &rxData_discardPacket; /* data */ |
| pRxData->rxData_dispatchBuffer[CLOSE][DATA_EAPOL_PACKET] = &rxData_discardPacket; /* eapol */ |
| pRxData->rxData_dispatchBuffer[CLOSE][DATA_IAPP_PACKET] = &rxData_discardPacket; /* Iapp */ |
| pRxData->rxData_dispatchBuffer[CLOSE][DATA_VLAN_PACKET] = &rxData_discardPacketVlan; /* VLAN */ |
| |
| /* port status open notify */ |
| pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_DATA_PACKET] = &rxData_rcvPacketInOpenNotify; /* data */ |
| pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_EAPOL_PACKET] = &rxData_rcvPacketInOpenNotify; /* eapol */ |
| pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_IAPP_PACKET] = &rxData_rcvPacketInOpenNotify; /* Iapp */ |
| pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_VLAN_PACKET] = &rxData_discardPacketVlan; /* VLAN */ |
| |
| /* port status open eapol */ |
| pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_DATA_PACKET] = &rxData_discardPacket; /* data */ |
| pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_EAPOL_PACKET] = &rxData_rcvPacketEapol; /* eapol */ |
| pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_IAPP_PACKET] = &rxData_discardPacket; /* Iapp */ |
| pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_VLAN_PACKET] = &rxData_discardPacketVlan; /* VLAN */ |
| |
| /* port status open */ |
| pRxData->rxData_dispatchBuffer[OPEN][DATA_DATA_PACKET] = &rxData_rcvPacketData; /* data */ |
| pRxData->rxData_dispatchBuffer[OPEN][DATA_EAPOL_PACKET] = &rxData_rcvPacketEapol; /* eapol */ |
| #ifdef XCC_MODULE_INCLUDED |
| pRxData->rxData_dispatchBuffer[OPEN][DATA_IAPP_PACKET] = &rxData_rcvPacketIapp; /* Iapp */ |
| #else |
| pRxData->rxData_dispatchBuffer[OPEN][DATA_IAPP_PACKET] = &rxData_rcvPacketData; /* Iapp */ |
| #endif |
| pRxData->rxData_dispatchBuffer[OPEN][DATA_VLAN_PACKET] = &rxData_discardPacketVlan;/* VLAN */ |
| |
| /* register CB's for request buffer and receive CB to the lower layers */ |
| TWD_RegisterCb (pRxData->hTWD, |
| TWD_EVENT_RX_RECEIVE_PACKET, |
| (void *)rxData_ReceivePacket, |
| pStadHandles->hRxData); |
| |
| TWD_RegisterCb (pRxData->hTWD, |
| TWD_EVENT_RX_REQUEST_FOR_BUFFER, |
| (void*)rxData_RequestForBuffer, |
| pStadHandles->hRxData); |
| } |
| |
| |
| TI_STATUS rxData_SetDefaults (TI_HANDLE hRxData, rxDataInitParams_t * rxDataInitParams) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| int i; |
| |
| /* init rx data filters */ |
| pRxData->filteringEnabled = rxDataInitParams->rxDataFiltersEnabled; |
| pRxData->filteringDefaultAction = rxDataInitParams->rxDataFiltersDefaultAction; |
| TWD_CfgEnableRxDataFilter (pRxData->hTWD, pRxData->filteringEnabled, pRxData->filteringDefaultAction); |
| |
| for (i = 0; i < MAX_DATA_FILTERS; ++i) |
| { |
| if (rxDataInitParams->rxDataFilterRequests[i].maskLength > 0) |
| { |
| if (rxData_addRxDataFilter(hRxData, &rxDataInitParams->rxDataFilterRequests[i]) != TI_OK) |
| { |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid Rx Data Filter configured at init stage (at index %d)!\n", i); |
| } |
| } |
| } |
| |
| pRxData->reAuthActiveTimer = tmr_CreateTimer (pRxData->hTimer); |
| if (pRxData->reAuthActiveTimer == NULL) |
| { |
| WLAN_OS_REPORT(("rxData_SetDefaults(): Failed to create reAuthActiveTimer!\n")); |
| return TI_NOK; |
| } |
| |
| pRxData->reAuthActiveTimeout = rxDataInitParams->reAuthActiveTimeout; |
| |
| rxData_SetReAuthInProgress(pRxData, TI_FALSE); |
| |
| #ifdef TI_DBG |
| /* reset counters */ |
| rxData_resetCounters(pRxData); |
| rxData_resetDbgCounters(pRxData); |
| |
| /* allocate timer for debug throughput */ |
| pRxData->hThroughputTimer = tmr_CreateTimer (pRxData->hTimer); |
| if (pRxData->hThroughputTimer == NULL) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_SetDefaults(): Failed to create hThroughputTimer!\n"); |
| return TI_NOK; |
| } |
| pRxData->rxThroughputTimerEnable = TI_FALSE; |
| #endif |
| |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INIT, ".....Rx Data configured successfully\n"); |
| |
| return TI_OK; |
| } |
| |
| /*************************************************************************** |
| * rxData_unLoad * |
| **************************************************************************** |
| * DESCRIPTION: This function unload the Rx data module. |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: |
| * |
| * RETURNS: TI_OK - Unload succesfull |
| * TI_NOK - Unload unsuccesfull |
| ***************************************************************************/ |
| TI_STATUS rxData_unLoad(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| /* check parameters validity */ |
| if (pRxData == NULL) |
| { |
| return TI_NOK; |
| } |
| |
| DistributorMgr_Destroy(pRxData->RxEventDistributor); |
| |
| #ifdef TI_DBG |
| /* destroy periodic rx throughput timer */ |
| if (pRxData->hThroughputTimer) |
| { |
| tmr_DestroyTimer (pRxData->hThroughputTimer); |
| } |
| #endif |
| |
| if (pRxData->reAuthActiveTimer) |
| { |
| tmr_DestroyTimer (pRxData->reAuthActiveTimer); |
| } |
| |
| /* free Rx Data controll block */ |
| os_memoryFree(pRxData->hOs, pRxData, sizeof(rxData_t)); |
| |
| return TI_OK; |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_stop * |
| **************************************************************************** |
| * DESCRIPTION: this function stop the rx data. |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: |
| * |
| * RETURNS: TI_OK - stop succesfull |
| * TI_NOK - stop unsuccesfull |
| ***************************************************************************/ |
| TI_STATUS rxData_stop (TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| /* check parameters validity */ |
| if (pRxData == NULL) |
| { |
| return TI_NOK; |
| } |
| |
| pRxData->rxDataExcludeUnencrypted = DEF_EXCLUDE_UNENCYPTED; |
| pRxData->rxDataExludeBroadcastUnencrypted = DEF_EXCLUDE_UNENCYPTED; |
| pRxData->rxDataEapolDestination = DEF_EAPOL_DESTINATION; |
| pRxData->rxDataPortStatus = DEF_RX_PORT_STATUS; |
| |
| #ifdef TI_DBG |
| /* reset counters */ |
| /*rxData_resetCounters(pRxData);*/ |
| /*rxData_resetDbgCounters(pRxData);*/ |
| |
| /* stop throughput timer */ |
| if (pRxData->rxThroughputTimerEnable) |
| { |
| tmr_StopTimer (pRxData->hThroughputTimer); |
| pRxData->rxThroughputTimerEnable = TI_FALSE; |
| } |
| #endif |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_stop() : Succeeded.\n"); |
| |
| return TI_OK; |
| |
| } |
| |
| /*************************************************************************** |
| * rxData_getParam * |
| **************************************************************************** |
| * DESCRIPTION: get a specific parameter |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: pParamInfo - structure which include the value of |
| * the requested parameter |
| * |
| * RETURNS: TI_OK |
| * TI_NOK |
| ***************************************************************************/ |
| TI_STATUS rxData_getParam(TI_HANDLE hRxData, paramInfo_t *pParamInfo) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| /* check handle validity */ |
| if (pRxData == NULL) |
| { |
| return TI_NOK; |
| } |
| |
| switch (pParamInfo->paramType) |
| { |
| case RX_DATA_EXCLUDE_UNENCRYPTED_PARAM: |
| pParamInfo->content.rxDataExcludeUnencrypted = pRxData->rxDataExcludeUnencrypted; |
| break; |
| |
| case RX_DATA_EAPOL_DESTINATION_PARAM: |
| pParamInfo->content.rxDataEapolDestination = pRxData->rxDataEapolDestination; |
| break; |
| |
| case RX_DATA_PORT_STATUS_PARAM: |
| pParamInfo->content.rxDataPortStatus = pRxData->rxDataPortStatus; |
| break; |
| |
| case RX_DATA_COUNTERS_PARAM: |
| pParamInfo->content.siteMgrTiWlanCounters.RecvOk = pRxData->rxDataCounters.RecvOk; |
| pParamInfo->content.siteMgrTiWlanCounters.DirectedBytesRecv = pRxData->rxDataCounters.DirectedBytesRecv; |
| pParamInfo->content.siteMgrTiWlanCounters.DirectedFramesRecv = pRxData->rxDataCounters.DirectedFramesRecv; |
| pParamInfo->content.siteMgrTiWlanCounters.MulticastBytesRecv = pRxData->rxDataCounters.MulticastBytesRecv; |
| pParamInfo->content.siteMgrTiWlanCounters.MulticastFramesRecv = pRxData->rxDataCounters.MulticastFramesRecv; |
| pParamInfo->content.siteMgrTiWlanCounters.BroadcastBytesRecv = pRxData->rxDataCounters.BroadcastBytesRecv; |
| pParamInfo->content.siteMgrTiWlanCounters.BroadcastFramesRecv = pRxData->rxDataCounters.BroadcastFramesRecv; |
| break; |
| |
| case RX_DATA_GET_RX_DATA_FILTERS_STATISTICS: |
| TWD_ItrDataFilterStatistics (pRxData->hTWD, |
| pParamInfo->content.interogateCmdCBParams.fCb, |
| pParamInfo->content.interogateCmdCBParams.hCb, |
| pParamInfo->content.interogateCmdCBParams.pCb); |
| break; |
| |
| case RX_DATA_RATE_PARAM: |
| pParamInfo->content.siteMgrCurrentRxRate = pRxData->uLastDataPktRate; |
| break; |
| |
| default: |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_getParam() : PARAMETER NOT SUPPORTED \n"); |
| return (PARAM_NOT_SUPPORTED); |
| } |
| |
| return TI_OK; |
| } |
| |
| /*************************************************************************** |
| * rxData_setParam * |
| **************************************************************************** |
| * DESCRIPTION: set a specific parameter |
| * |
| * INPUTS: hRxData - the object |
| * pParamInfo - structure which include the value to set for |
| * the requested parameter |
| * |
| * OUTPUT: |
| * |
| * RETURNS: TI_OK |
| * TI_NOK |
| ***************************************************************************/ |
| TI_STATUS rxData_setParam(TI_HANDLE hRxData, paramInfo_t *pParamInfo) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| /* check handle validity */ |
| if( pRxData == NULL ) |
| { |
| return TI_NOK; |
| } |
| |
| switch (pParamInfo->paramType) |
| { |
| case RX_DATA_EXCLUDE_UNENCRYPTED_PARAM: |
| pRxData->rxDataExcludeUnencrypted = pParamInfo->content.rxDataExcludeUnencrypted; |
| break; |
| case RX_DATA_EXCLUDE_BROADCAST_UNENCRYPTED_PARAM: |
| pRxData->rxDataExludeBroadcastUnencrypted = pParamInfo->content.rxDataExcludeUnencrypted; |
| break; |
| case RX_DATA_EAPOL_DESTINATION_PARAM: |
| pRxData->rxDataEapolDestination = pParamInfo->content.rxDataEapolDestination; |
| break; |
| |
| case RX_DATA_PORT_STATUS_PARAM: |
| pRxData->rxDataPortStatus = pParamInfo->content.rxDataPortStatus; |
| break; |
| |
| case RX_DATA_ENABLE_DISABLE_RX_DATA_FILTERS: |
| return rxData_enableDisableRxDataFilters(hRxData, pParamInfo->content.rxDataFilterEnableDisable); |
| |
| case RX_DATA_ADD_RX_DATA_FILTER: |
| { |
| TRxDataFilterRequest* pRequest = &pParamInfo->content.rxDataFilterRequest; |
| |
| return rxData_addRxDataFilter(hRxData, pRequest); |
| } |
| |
| case RX_DATA_REMOVE_RX_DATA_FILTER: |
| { |
| TRxDataFilterRequest* pRequest = &pParamInfo->content.rxDataFilterRequest; |
| |
| return rxData_removeRxDataFilter(hRxData, pRequest); |
| } |
| |
| case RX_DATA_GENERIC_ETHERTYPE_PARAM: |
| pRxData->genericEthertype = pParamInfo->content.rxGenericEthertype; |
| break; |
| |
| default: |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_setParam() : PARAMETER NOT SUPPORTED \n"); |
| return (PARAM_NOT_SUPPORTED); |
| } |
| |
| return TI_OK; |
| } |
| |
| /*************************************************************************** |
| * rxData_enableDisableRxDataFilters * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static TI_STATUS rxData_enableDisableRxDataFilters(TI_HANDLE hRxData, TI_BOOL enabled) |
| { |
| rxData_t * pRxData = (rxData_t *) hRxData; |
| |
| /* assert 0 or 1 */ |
| if (enabled != TI_FALSE) |
| enabled = 1; |
| |
| if (enabled == pRxData->filteringEnabled) |
| return TI_OK; |
| |
| pRxData->filteringEnabled = enabled; |
| |
| return TWD_CfgEnableRxDataFilter (pRxData->hTWD, pRxData->filteringEnabled, pRxData->filteringDefaultAction); |
| } |
| |
| /*************************************************************************** |
| * findFilterRequest * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static int findFilterRequest(TI_HANDLE hRxData, TRxDataFilterRequest* request) |
| { |
| rxData_t * pRxData = (rxData_t *) hRxData; |
| int i; |
| |
| for (i = 0; i < MAX_DATA_FILTERS; ++i) |
| { |
| if (pRxData->isFilterSet[i]) |
| { |
| if ((pRxData->filterRequests[i].offset == request->offset) && |
| (pRxData->filterRequests[i].maskLength == request->maskLength) && |
| (pRxData->filterRequests[i].patternLength == request->patternLength)) |
| { |
| if ((os_memoryCompare(pRxData->hOs, pRxData->filterRequests[i].mask, request->mask, request->maskLength) == 0) && |
| (os_memoryCompare(pRxData->hOs, pRxData->filterRequests[i].pattern, request->pattern, request->patternLength) == 0)) |
| return i; |
| } |
| } |
| } |
| |
| return -1; |
| } |
| |
| /*************************************************************************** |
| * closeFieldPattern * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static void closeFieldPattern (rxData_t * pRxData, rxDataFilterFieldPattern_t * fieldPattern, TI_UINT8 * fieldPatterns, TI_UINT8 * lenFieldPatterns) |
| { |
| //fieldPatterns[*lenFieldPatterns] = fieldPattern->offset; |
| os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, (TI_UINT8 *)&fieldPattern->offset, sizeof(fieldPattern->offset)); |
| *lenFieldPatterns += sizeof(fieldPattern->offset); |
| |
| fieldPatterns[*lenFieldPatterns] = fieldPattern->length; |
| *lenFieldPatterns += sizeof(fieldPattern->length); |
| |
| fieldPatterns[*lenFieldPatterns] = fieldPattern->flag; |
| *lenFieldPatterns += sizeof(fieldPattern->flag); |
| |
| os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, fieldPattern->pattern, fieldPattern->length); |
| *lenFieldPatterns += fieldPattern->length; |
| |
| /* if the pattern bit mask is enabled add it to the end of the request */ |
| if ((fieldPattern->flag & RX_DATA_FILTER_FLAG_USE_BIT_MASK) == RX_DATA_FILTER_FLAG_USE_BIT_MASK) |
| { |
| os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, fieldPattern->mask, fieldPattern->length); |
| *lenFieldPatterns += fieldPattern->length; |
| } |
| |
| TRACE3(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Closed field pattern, length = %d, total length = %d, pattern bit mask = %d.\n", fieldPattern->length, *lenFieldPatterns, ((fieldPattern->flag & RX_DATA_FILTER_FLAG_USE_BIT_MASK) == RX_DATA_FILTER_FLAG_USE_BIT_MASK)); |
| } |
| |
| |
| /*************************************************************************** |
| * parseRxDataFilterRequest * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static int parseRxDataFilterRequest(TI_HANDLE hRxData, TRxDataFilterRequest* request, TI_UINT8 * numFieldPatterns, TI_UINT8 * lenFieldPatterns, TI_UINT8 * fieldPatterns) |
| { |
| rxData_t * pRxData = (rxData_t *) hRxData; |
| |
| int maskIter; |
| int patternIter = 0; |
| |
| /* used to store field patterns while they are built */ |
| TI_BOOL isBuildingFieldPattern = TI_FALSE; |
| rxDataFilterFieldPattern_t fieldPattern; |
| |
| for (maskIter = 0; maskIter < request->maskLength * 8; ++maskIter) |
| { |
| /* which byte in the mask and which bit in the byte we're at */ |
| int bit = maskIter % 8; |
| int byte = maskIter / 8; |
| |
| /* is the bit in the mask set */ |
| TI_BOOL isSet = ((request->mask[byte] & (1 << bit)) == (1 << bit)); |
| |
| TRACE4(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": MaskIter = %d, Byte = %d, Bit = %d, isSet = %d\n", maskIter, byte, bit, isSet); |
| |
| /* if we're in the midst of building a field pattern, we need to close in case */ |
| /* the current bit is not set or we've reached the ethernet header boundary */ |
| if (isBuildingFieldPattern) |
| { |
| if ((isSet == TI_FALSE) || (request->offset + maskIter == RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY)) |
| { |
| closeFieldPattern(hRxData, &fieldPattern, fieldPatterns, lenFieldPatterns); |
| |
| isBuildingFieldPattern = TI_FALSE; |
| } |
| } |
| |
| /* nothing to do in case the bit is not set */ |
| if (isSet) |
| { |
| /* if not already building a field pattern, create a new one */ |
| if (isBuildingFieldPattern == TI_FALSE) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Creating a new field pattern.\n"); |
| |
| isBuildingFieldPattern = TI_TRUE; |
| ++(*numFieldPatterns); |
| |
| if (*numFieldPatterns > RX_DATA_FILTER_MAX_FIELD_PATTERNS) |
| { |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, too many field patterns, maximum of %u is allowed!\n", RX_DATA_FILTER_MAX_FIELD_PATTERNS); |
| |
| return TI_NOK; |
| } |
| |
| fieldPattern.offset = request->offset + maskIter; |
| fieldPattern.length = 0; |
| |
| /* we don't support the mask per bit feature yet. */ |
| fieldPattern.flag = RX_DATA_FILTER_FLAG_NO_BIT_MASK; |
| |
| /* first 14 bits are used for the Ethernet header, rest for the IP header */ |
| if (fieldPattern.offset < RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY) |
| { |
| fieldPattern.flag |= RX_DATA_FILTER_FLAG_ETHERNET_HEADER; |
| } |
| else |
| { |
| fieldPattern.flag |= RX_DATA_FILTER_FLAG_IP_HEADER; |
| fieldPattern.offset -= RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY; |
| } |
| |
| TRACE2(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": offset = %d, flag = %d.\n", fieldPattern.offset, fieldPattern.flag); |
| } |
| |
| /* check that the pattern is long enough */ |
| if (patternIter > request->patternLength) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, mask and pattern length are not consistent!\n"); |
| |
| return TI_NOK; |
| } |
| |
| /* add the current pattern byte to the field pattern */ |
| fieldPattern.pattern[fieldPattern.length++] = request->pattern[patternIter++]; |
| |
| /* check pattern matching boundary */ |
| if (fieldPattern.offset + fieldPattern.length >= RX_DATA_FILTER_FILTER_BOUNDARY) |
| { |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, pattern matching cannot exceed first %u characters.\n", RX_DATA_FILTER_FILTER_BOUNDARY); |
| |
| return TI_NOK; |
| } |
| } |
| } |
| |
| /* check that the pattern is long enough */ |
| if (patternIter != request->patternLength) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, mask and pattern lengths are not consistent!\n"); |
| |
| return TI_NOK; |
| } |
| |
| /* close the last field pattern if needed */ |
| if (isBuildingFieldPattern) |
| { |
| closeFieldPattern (hRxData, &fieldPattern, fieldPatterns, lenFieldPatterns); |
| } |
| |
| return TI_OK; |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_setRxDataFilter * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static TI_STATUS rxData_addRxDataFilter (TI_HANDLE hRxData, TRxDataFilterRequest* request) |
| { |
| rxData_t * pRxData = (rxData_t *) hRxData; |
| |
| /* firmware request fields */ |
| TI_UINT8 index = 0; |
| TI_UINT8 numFieldPatterns = 0; |
| TI_UINT8 lenFieldPatterns = 0; |
| TI_UINT8 fieldPatterns[MAX_DATA_FILTER_SIZE]; |
| |
| /* does the filter already exist? */ |
| if (findFilterRequest(hRxData, request) >= 0) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Filter already exists.\n"); |
| |
| return RX_FILTER_ALREADY_EXISTS; |
| } |
| |
| /* find place for insertion */ |
| for (index = 0; index < MAX_DATA_FILTERS; ++index) |
| { |
| if (pRxData->isFilterSet[index] == TI_FALSE) |
| break; |
| } |
| |
| /* are all filter slots taken? */ |
| if (index == MAX_DATA_FILTERS) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": No place to insert filter!\n"); |
| |
| return RX_NO_AVAILABLE_FILTERS; |
| } |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Inserting filter at index %d.\n", index); |
| |
| /* parse the filter request into discrete field patterns */ |
| if (parseRxDataFilterRequest(hRxData, request, &numFieldPatterns, &lenFieldPatterns, fieldPatterns) != TI_OK) |
| return TI_NOK; |
| |
| if (numFieldPatterns == 0) |
| return TI_NOK; |
| |
| /* Store configuration for future manipulation */ |
| pRxData->isFilterSet[index] = TI_TRUE; |
| os_memoryCopy(pRxData->hOs, &pRxData->filterRequests[index], request, sizeof(pRxData->filterRequests[index])); |
| |
| /* Send configuration to firmware */ |
| return TWD_CfgRxDataFilter (pRxData->hTWD, |
| index, |
| ADD_FILTER, |
| FILTER_SIGNAL, |
| numFieldPatterns, |
| lenFieldPatterns, |
| fieldPatterns); |
| |
| } |
| |
| /*************************************************************************** |
| * rxData_removeRxDataFilter * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static TI_STATUS rxData_removeRxDataFilter (TI_HANDLE hRxData, TRxDataFilterRequest* request) |
| { |
| rxData_t * pRxData = (rxData_t *) hRxData; |
| |
| int index = findFilterRequest(hRxData, request); |
| |
| /* does the filter exist? */ |
| if (index < 0) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, ": Remove data filter request received but the specified filter was not found!"); |
| |
| return RX_FILTER_DOES_NOT_EXIST; |
| } |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Removing filter at index %d.", index); |
| |
| pRxData->isFilterSet[index] = TI_FALSE; |
| |
| return TWD_CfgRxDataFilter (pRxData->hTWD, |
| index, |
| REMOVE_FILTER, |
| FILTER_SIGNAL, |
| 0, |
| 0, |
| NULL); |
| } |
| |
| /*************************************************************************** |
| * rxData_DistributorRxEvent * |
| **************************************************************************** |
| * DESCRIPTION: |
| * |
| * |
| * INPUTS: |
| * |
| * |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| * |
| ***************************************************************************/ |
| static void rxData_DistributorRxEvent (rxData_t *pRxData, TI_UINT16 Mask, int DataLen) |
| { |
| DistributorMgr_EventCall (pRxData->RxEventDistributor, Mask, DataLen); |
| } |
| |
| /*************************************************************************** |
| * rxData_RegNotif * |
| ****************************************************************************/ |
| TI_HANDLE rxData_RegNotif (TI_HANDLE hRxData, TI_UINT16 EventMask, GeneralEventCall_t CallBack, TI_HANDLE context, TI_UINT32 Cookie) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (!hRxData) |
| return NULL; |
| |
| return DistributorMgr_Reg (pRxData->RxEventDistributor, EventMask, (TI_HANDLE)CallBack, context, Cookie); |
| } |
| |
| /*************************************************************************** |
| * rxData_AddToNotifMask * |
| ****************************************************************************/ |
| TI_STATUS rxData_AddToNotifMask (TI_HANDLE hRxData, TI_HANDLE Notifh, TI_UINT16 EventMask) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (!hRxData) |
| return TI_NOK; |
| |
| return DistributorMgr_AddToMask (pRxData->RxEventDistributor, Notifh, EventMask); |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_UnRegNotif * |
| ****************************************************************************/ |
| TI_STATUS rxData_UnRegNotif(TI_HANDLE hRxData,TI_HANDLE RegEventHandle) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (!hRxData) |
| return TI_NOK; |
| |
| return DistributorMgr_UnReg (pRxData->RxEventDistributor, RegEventHandle); |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_receivePacketFromWlan * |
| **************************************************************************** |
| * DESCRIPTION: this function is called by the GWSI for each received Buffer. |
| * It filter and distribute the received Buffer. |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| void rxData_receivePacketFromWlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| TMacAddr address3; |
| dot11_header_t *pDot11Hdr; |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_receivePacketFromWlan() : pRxAttr->packetType = %d\n", pRxAttr->ePacketType); |
| |
| switch (pRxAttr->ePacketType) |
| { |
| case TAG_CLASS_MANAGEMENT: |
| case TAG_CLASS_BCN_PRBRSP: |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_receivePacketFromWlan(): Received management Buffer len = %d\n", RX_BUF_LEN(pBuffer)); |
| |
| /* update siteMngr |
| * |
| * the BSSID in mgmt frames is always addr3 in the header |
| * must copy address3 since Buffer is freed in mlmeParser_recv |
| */ |
| pDot11Hdr = (dot11_header_t*)RX_BUF_DATA(pBuffer); |
| |
| os_memoryCopy(pRxData->hOs, &address3, &pDot11Hdr->address3, sizeof(address3)); |
| |
| /* distribute mgmt pBuffer to mlme */ |
| if( mlmeParser_recv(pRxData->hMlme, pBuffer, pRxAttr) != TI_OK ) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_receivePacketFromWlan() : MLME returned error \n"); |
| } |
| break; |
| |
| case TAG_CLASS_DATA: |
| case TAG_CLASS_QOS_DATA: |
| case TAG_CLASS_AMSDU: |
| case TAG_CLASS_EAPOL: |
| { |
| CL_TRACE_START_L3(); |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_receivePacketFromWlan() : Received Data Buffer len = %d\n", RX_BUF_LEN(pBuffer)); |
| |
| /* send pBuffer to data dispatcher */ |
| rxData_dataPacketDisptcher(hRxData, pBuffer, pRxAttr); |
| CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "RX", ".DataPacket"); |
| break; |
| } |
| |
| default: |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_receivePacketFromWlan(): Received unspecified packet type !!! \n"); |
| RxBufFree(pRxData->hOs, pBuffer); |
| break; |
| } |
| } |
| |
| /*************************************************************************** |
| * rxData_dataPacketDisptcher * |
| **************************************************************************** |
| * DESCRIPTION: this function is called upon receving data Buffer, |
| * it dispatches the packet to the approciate function according to |
| * data packet type and rx port status. |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| |
| static void rxData_dataPacketDisptcher (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| portStatus_e DataPortStatus; |
| rxDataPacketType_e DataPacketType; |
| |
| /* get rx port status */ |
| DataPortStatus = pRxData->rxDataPortStatus; |
| |
| /* discard data packets received while rx data port is closed */ |
| if (DataPortStatus == CLOSE) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Data Buffer while Rx data port is closed \n"); |
| |
| rxData_discardPacket (hRxData, pBuffer, pRxAttr); |
| return; |
| } |
| |
| /* get data packet type */ |
| |
| pRxData->uLastDataPktRate = pRxAttr->Rate; /* save Rx packet rate for statistics */ |
| |
| #ifdef XCC_MODULE_INCLUDED |
| if (XCCMngr_isIappPacket (pRxData->hXCCMgr, pBuffer) == TI_TRUE) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Iapp Buffer \n"); |
| |
| DataPacketType = DATA_IAPP_PACKET; |
| |
| /* dispatch Buffer according to packet type and current rx data port status */ |
| pRxData->rxData_dispatchBuffer[DataPortStatus][DataPacketType] (hRxData, pBuffer, pRxAttr); |
| } |
| else |
| #endif |
| { |
| /* A-MSDU ? */ |
| if (TAG_CLASS_AMSDU == pRxAttr->ePacketType) |
| { |
| rxData_ConvertAmsduToEthPackets (hRxData, pBuffer, pRxAttr); |
| } |
| else |
| { |
| TI_UINT16 etherType = 0; |
| TEthernetHeader * pEthernetHeader; |
| |
| /* |
| * if Host processes received packets, the header translation |
| * from WLAN to ETH is done here. The conversion has been moved |
| * here so that IAPP packets aren't converted. |
| */ |
| rxData_convertWlanToEthHeader (hRxData, pBuffer, ðerType); |
| |
| pEthernetHeader = (TEthernetHeader *)RX_ETH_PKT_DATA(pBuffer); |
| |
| if (etherType == ETHERTYPE_802_1D) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received VLAN packet \n"); |
| |
| DataPacketType = DATA_VLAN_PACKET; |
| } |
| else if ((HTOWLANS(pEthernetHeader->type) == EAPOL_PACKET) || |
| (HTOWLANS(pEthernetHeader->type) == pRxData->genericEthertype)) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Eapol packet \n"); |
| |
| if (rxData_IsReAuthInProgress(pRxData)) |
| { |
| /* ReAuth already in progress, restart timer */ |
| rxData_StopReAuthActiveTimer(pRxData); |
| rxData_StartReAuthActiveTimer(pRxData); |
| } |
| else |
| { |
| if (PowerMgr_getReAuthActivePriority(pRxData->hPowerMgr)) |
| { |
| /* ReAuth not in progress yet, force active, set flag, restart timer, send event */ |
| rxData_SetReAuthInProgress(pRxData, TI_TRUE); |
| rxData_StartReAuthActiveTimer(pRxData); |
| rxData_ReauthEnablePriority(pRxData); |
| EvHandlerSendEvent(pRxData->hEvHandler, IPC_EVENT_RE_AUTH_STARTED, NULL, 0); |
| } |
| } |
| |
| DataPacketType = DATA_EAPOL_PACKET; |
| } |
| else |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Data packet \n"); |
| |
| DataPacketType = DATA_DATA_PACKET; |
| } |
| |
| /* dispatch Buffer according to packet type and current rx data port status */ |
| pRxData->rxData_dispatchBuffer[DataPortStatus][DataPacketType] (hRxData, pBuffer, pRxAttr); |
| } |
| } |
| |
| } |
| |
| /*************************************************************************** |
| * rxData_discardPacket * |
| **************************************************************************** |
| * DESCRIPTION: this function is called to discard Buffer |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| static void rxData_discardPacket (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE2(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_discardPacket: rx port status = %d , Buffer status = %d \n", pRxData->rxDataPortStatus, pRxAttr->status); |
| |
| pRxData->rxDataDbgCounters.excludedFrameCounter++; |
| |
| /* free Buffer */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| |
| } |
| |
| /*************************************************************************** |
| * rxData_discardPacketVlan * |
| **************************************************************************** |
| * DESCRIPTION: this function is called to discard Buffer |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| static void rxData_discardPacketVlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_discardPacketVlan : drop packet that contains VLAN tag\n"); |
| |
| pRxData->rxDataDbgCounters.rxDroppedDueToVLANIncludedCnt++; |
| |
| /* free Buffer */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_rcvPacketInOpenNotify * |
| **************************************************************************** |
| * DESCRIPTION: this function is called upon receving data Eapol packet type |
| * while rx port status is "open notify" |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| static void rxData_rcvPacketInOpenNotify (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_rcvPacketInOpenNotify: receiving data packet while in rx port status is open notify\n"); |
| |
| pRxData->rxDataDbgCounters.rcvUnicastFrameInOpenNotify++; |
| |
| /* free Buffer */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_rcvPacketEapol * |
| **************************************************************************** |
| * DESCRIPTION: this function is called upon receving data Eapol packet type |
| * while rx port status is "open eapol" |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| static void rxData_rcvPacketEapol(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketEapol() : Received an EAPOL frame tranferred to OS\n"); |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketEapol() : Received an EAPOL frame tranferred to OS\n"); |
| |
| EvHandlerSendEvent (pRxData->hEvHandler, IPC_EVENT_EAPOL, NULL, 0); |
| os_receivePacket (pRxData->hOs, (struct RxIfDescriptor_t*)pBuffer, pBuffer, (TI_UINT16)RX_ETH_PKT_LEN(pBuffer)); |
| |
| } |
| |
| /*************************************************************************** |
| * rxData_rcvPacketData * |
| **************************************************************************** |
| * DESCRIPTION: this function is called upon receving data "data" packet type |
| * while rx port status is "open" |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| static void rxData_rcvPacketData(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| TEthernetHeader *pEthernetHeader; |
| TI_UINT16 EventMask = 0; |
| TFwInfo *pFwInfo; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketData() : Received DATA frame tranferred to OS\n"); |
| |
| /* check encryption status */ |
| pEthernetHeader = (TEthernetHeader *)RX_ETH_PKT_DATA(pBuffer); |
| if (!MAC_MULTICAST (pEthernetHeader->dst)) |
| { /* unicast frame */ |
| if((pRxData->rxDataExcludeUnencrypted) && (!(pRxAttr->packetInfo & RX_DESC_ENCRYPT_MASK))) |
| { |
| pRxData->rxDataDbgCounters.excludedFrameCounter++; |
| /* free Buffer */ |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_rcvPacketData() : exclude unicast unencrypted is TI_TRUE & packet encryption is OFF\n"); |
| |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| } |
| else |
| { /* broadcast frame */ |
| if ((pRxData->rxDataExludeBroadcastUnencrypted) && (!(pRxAttr->packetInfo & RX_DESC_ENCRYPT_MASK))) |
| { |
| pRxData->rxDataDbgCounters.excludedFrameCounter++; |
| /* free Buffer */ |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_rcvPacketData() : exclude broadcast unencrypted is TI_TRUE & packet encryption is OFF\n"); |
| |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| |
| /* |
| * Discard multicast/broadcast frames that we sent ourselves. |
| * Per IEEE 802.11-2007 section 9.2.7: "STAs shall filter out |
| * broadcast/multicast messages that contain their address as |
| * the source address." |
| */ |
| pFwInfo = TWD_GetFWInfo (pRxData->hTWD); |
| if (MAC_EQUAL(pFwInfo->macAddress, pEthernetHeader->src)) |
| { |
| pRxData->rxDataDbgCounters.excludedFrameCounter++; |
| /* free Buffer */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| } |
| |
| /* update traffic monitor parameters */ |
| pRxData->rxDataCounters.RecvOk++; |
| EventMask |= RECV_OK; |
| |
| if (!MAC_MULTICAST (pEthernetHeader->dst)) |
| { |
| /* Directed frame */ |
| pRxData->rxDataCounters.DirectedFramesRecv++; |
| pRxData->rxDataCounters.DirectedBytesRecv += RX_ETH_PKT_LEN(pBuffer); |
| EventMask |= DIRECTED_BYTES_RECV; |
| EventMask |= DIRECTED_FRAMES_RECV; |
| } |
| else if (MAC_BROADCAST (pEthernetHeader->dst)) |
| { |
| /* Broadcast frame */ |
| pRxData->rxDataCounters.BroadcastFramesRecv++; |
| pRxData->rxDataCounters.BroadcastBytesRecv += RX_ETH_PKT_LEN(pBuffer); |
| EventMask |= BROADCAST_BYTES_RECV; |
| EventMask |= BROADCAST_FRAMES_RECV; |
| } |
| else |
| { |
| /* Multicast Address */ |
| pRxData->rxDataCounters.MulticastFramesRecv++; |
| pRxData->rxDataCounters.MulticastBytesRecv += RX_ETH_PKT_LEN(pBuffer); |
| EventMask |= MULTICAST_BYTES_RECV; |
| EventMask |= MULTICAST_FRAMES_RECV; |
| } |
| pRxData->rxDataCounters.LastSecBytesRecv += RX_ETH_PKT_LEN(pBuffer); |
| |
| /*Handle PREAUTH_EAPOL_PACKET*/ |
| if (HTOWLANS(pEthernetHeader->type) == PREAUTH_EAPOL_PACKET) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketData() : Received an Pre-Auth EAPOL frame tranferred to OS\n"); |
| } |
| |
| rxData_DistributorRxEvent (pRxData, EventMask, RX_ETH_PKT_LEN(pBuffer)); |
| |
| /* deliver packet to os */ |
| os_receivePacket (pRxData->hOs, (struct RxIfDescriptor_t*)pBuffer, pBuffer, (TI_UINT16)RX_ETH_PKT_LEN(pBuffer)); |
| } |
| |
| |
| /*************************************************************************** |
| * rxData_rcvPacketIapp * |
| **************************************************************************** |
| * DESCRIPTION: this function is called upon receving data IAPP packet type |
| * while rx port status is "open" |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received Buffer. |
| * pRxAttr - Rx attributes |
| * |
| * OUTPUT: |
| * |
| * RETURNS: |
| ***************************************************************************/ |
| #ifdef XCC_MODULE_INCLUDED |
| |
| static void rxData_rcvPacketIapp(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketIapp() : Received IAPP frame tranferred to XCCMgr\n"); |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketIapp() : Received IAPP frame tranferred to XCCMgr\n"); |
| |
| /* tranfer packet to XCCMgr */ |
| XCCMngr_recvIAPPPacket (pRxData->hXCCMgr, pBuffer, pRxAttr); |
| |
| /* free Buffer */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| } |
| |
| #endif |
| |
| |
| /**************************************************************************** |
| * rxData_convertWlanToEthHeader * |
| ***************************************************************************** |
| * DESCRIPTION: this function convert the Packet header from 802.11 header |
| * format to ethernet format |
| * |
| * INPUTS: hRxData - the object |
| * pBuffer - the received pBuffer in 802.11 format |
| * |
| * OUTPUT: pEthPacket - pointer to the received pBuffer in ethernet format |
| * uEthLength - ethernet packet length |
| * |
| * RETURNS: TI_OK/TI_NOK |
| ***************************************************************************/ |
| static TI_STATUS rxData_convertWlanToEthHeader (TI_HANDLE hRxData, void *pBuffer, TI_UINT16 * etherType) |
| { |
| TEthernetHeader EthHeader; |
| Wlan_LlcHeader_T *pWlanSnapHeader; |
| TI_UINT8 *dataBuf; |
| dot11_header_t *pDot11Header; |
| TI_UINT32 lengthDelta; |
| TI_UINT16 swapedTypeLength; |
| TI_UINT32 headerLength; |
| TI_UINT8 createEtherIIHeader; |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| dataBuf = (TI_UINT8 *)RX_BUF_DATA(pBuffer); |
| |
| /* Setting the mac header len according to the received FrameControl field in the Mac Header */ |
| GET_MAX_HEADER_SIZE (dataBuf, &headerLength); |
| pDot11Header = (dot11_header_t*) dataBuf; |
| pWlanSnapHeader = (Wlan_LlcHeader_T*)((TI_UINT32)dataBuf + (TI_UINT32)headerLength); |
| |
| swapedTypeLength = WLANTOHS (pWlanSnapHeader->Type); |
| *etherType = swapedTypeLength; |
| |
| /* Prepare the Ethernet header. */ |
| if( ENDIAN_HANDLE_WORD(pDot11Header->fc) & DOT11_FC_FROM_DS) |
| { /* Infrastructure bss */ |
| MAC_COPY (EthHeader.dst, pDot11Header->address1); |
| MAC_COPY (EthHeader.src, pDot11Header->address3); |
| } |
| else |
| { /* Independent bss */ |
| MAC_COPY (EthHeader.dst, pDot11Header->address1); |
| MAC_COPY (EthHeader.src, pDot11Header->address2); |
| } |
| |
| createEtherIIHeader = TI_FALSE; |
| /* See if the LLC header in the frame shows the SAP SNAP... */ |
| if((SNAP_CHANNEL_ID == pWlanSnapHeader->DSAP) && |
| (SNAP_CHANNEL_ID == pWlanSnapHeader->SSAP) && |
| (LLC_CONTROL_UNNUMBERED_INFORMATION == pWlanSnapHeader->Control)) |
| { |
| /* Check for the Bridge Tunnel OUI in the SNAP Header... */ |
| if((SNAP_OUI_802_1H_BYTE0 == pWlanSnapHeader->OUI[ 0 ]) && |
| (SNAP_OUI_802_1H_BYTE1 == pWlanSnapHeader->OUI[ 1 ]) && |
| (SNAP_OUI_802_1H_BYTE2 == pWlanSnapHeader->OUI[ 2 ])) |
| { |
| /* Strip the SNAP header by skipping over it. */ |
| /* Start moving data from the Ethertype field in the SNAP */ |
| /* header. Move to the TypeLength field in the 802.3 header. */ |
| createEtherIIHeader = TI_TRUE; |
| } |
| /* Check for the RFC 1042 OUI in the SNAP Header */ |
| else |
| { |
| /* Check for the RFC 1042 OUI in the SNAP Header */ |
| if( (SNAP_OUI_RFC1042_BYTE0 == pWlanSnapHeader->OUI[ 0 ]) && |
| (SNAP_OUI_RFC1042_BYTE1 == pWlanSnapHeader->OUI[ 1 ]) && |
| (SNAP_OUI_RFC1042_BYTE2 == pWlanSnapHeader->OUI[ 2 ])) |
| { |
| /* See if the Ethertype is in our selective translation table */ |
| /* (Appletalk AARP and DIX II IPX are the two protocols in */ |
| /* our 'table') */ |
| if((ETHERTYPE_APPLE_AARP != swapedTypeLength) && |
| (ETHERTYPE_DIX_II_IPX != swapedTypeLength)) |
| { |
| /* Strip the SNAP header by skipping over it. */ |
| createEtherIIHeader = TI_TRUE; |
| } |
| } |
| } |
| } |
| |
| if( createEtherIIHeader == TI_TRUE ) |
| { |
| /* The LEN/TYPE bytes are set to TYPE, the entire WLAN+SNAP is removed.*/ |
| lengthDelta = headerLength + WLAN_SNAP_HDR_LEN - ETHERNET_HDR_LEN; |
| EthHeader.type = pWlanSnapHeader->Type; |
| } |
| else |
| { |
| /* The LEN/TYPE bytes are set to frame LEN, only the WLAN header is removed, */ |
| /* the entire 802.3 or 802.2 header is not removed.*/ |
| lengthDelta = headerLength - ETHERNET_HDR_LEN; |
| EthHeader.type = WLANTOHS((TI_UINT16)(RX_BUF_LEN(pBuffer) - headerLength)); |
| } |
| |
| /* Replace the 802.11 header and the LLC with Ethernet packet. */ |
| dataBuf += lengthDelta; |
| os_memoryCopy (pRxData->hOs, dataBuf, (void*)&EthHeader, ETHERNET_HDR_LEN); |
| RX_ETH_PKT_DATA(pBuffer) = dataBuf; |
| RX_ETH_PKT_LEN(pBuffer) = RX_BUF_LEN(pBuffer) - lengthDelta; |
| |
| return TI_OK; |
| } |
| |
| |
| /** |
| * \brief convert A-MSDU to several ethernet packets |
| * |
| * \param hRxData - the object |
| * \param pBuffer - the received Buffer in A-MSDU 802.11n format |
| * \param pRxAttr - Rx attributes |
| * \return TI_OK on success or TI_NOK on failure |
| * |
| * \par Description |
| * Static function |
| * This function convert the A-MSDU Packet from A-MSDU 802.11n packet |
| * format to several ethernet packets format and pass them to the OS layer |
| * |
| * \sa |
| */ |
| static TI_STATUS rxData_ConvertAmsduToEthPackets (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr) |
| { |
| |
| TEthernetHeader *pMsduEthHeader; |
| TEthernetHeader *pEthHeader; |
| Wlan_LlcHeader_T *pWlanSnapHeader; |
| TI_UINT8 *pAmsduDataBuf; |
| TI_UINT16 uAmsduDataLen; |
| void *pDataBuf; |
| TI_UINT16 uDataLen; |
| TI_UINT32 lengthDelta; |
| TI_UINT16 swapedTypeLength; |
| TI_UINT32 headerLength; |
| rxDataPacketType_e DataPacketType; |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| /* total AMPDU header */ |
| pAmsduDataBuf = (TI_UINT8 *)RX_BUF_DATA(pBuffer); |
| /* Setting the mac header len according to the received FrameControl field in the Mac Header */ |
| GET_MAX_HEADER_SIZE (pAmsduDataBuf, &headerLength); |
| |
| /* |
| * init loop setting |
| */ |
| /* total AMPDU size */ |
| uAmsduDataLen = (TI_UINT16)(RX_BUF_LEN(pBuffer) - headerLength); |
| /* ETH header */ |
| pMsduEthHeader = (TEthernetHeader *)(pAmsduDataBuf + headerLength); |
| /* ETH length, in A-MSDU the MSDU header type contain the MSDU length and not the type */ |
| uDataLen = WLANTOHS(pMsduEthHeader->type); |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ConvertAmsduToEthPackets(): A-MSDU received in length %d \n",uAmsduDataLen); |
| |
| /* if we have another packet at the AMSDU */ |
| while((uDataLen < uAmsduDataLen) && (uAmsduDataLen > ETHERNET_HDR_LEN + FCS_SIZE)) |
| { |
| /* allocate a new buffer */ |
| /* RxBufAlloc() add an extra word for alignment the MAC payload */ |
| rxData_RequestForBuffer (hRxData, &pDataBuf, sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen, 0, TAG_CLASS_AMSDU); |
| if (NULL == pDataBuf) |
| { |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ConvertAmsduToEthPackets(): cannot alloc MSDU packet. length %d \n",uDataLen); |
| rxData_discardPacket (hRxData, pBuffer, pRxAttr); |
| return TI_NOK; |
| } |
| |
| /* read packet type from LLC */ |
| pWlanSnapHeader = (Wlan_LlcHeader_T*)((TI_UINT8*)pMsduEthHeader + ETHERNET_HDR_LEN); |
| swapedTypeLength = WLANTOHS (pWlanSnapHeader->Type); |
| |
| /* copy the RxIfDescriptor */ |
| os_memoryCopy (pRxData->hOs, pDataBuf, pBuffer, sizeof(RxIfDescriptor_t)); |
| |
| /* update length, in the RxIfDescriptor the Len in words (4B) */ |
| ((RxIfDescriptor_t *)pDataBuf)->length = (sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen) >> 2; |
| ((RxIfDescriptor_t *)pDataBuf)->extraBytes = 4 - ((sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen) & 0x3); |
| |
| /* Prepare the Ethernet header pointer. */ |
| /* add padding in the start of the buffer in order to align ETH payload */ |
| pEthHeader = (TEthernetHeader *)((TI_UINT8 *)(RX_BUF_DATA(pDataBuf)) + |
| WLAN_SNAP_HDR_LEN + |
| PADDING_ETH_PACKET_SIZE); |
| |
| /* copy the Ethernet header */ |
| os_memoryCopy (pRxData->hOs, pEthHeader, pMsduEthHeader, ETHERNET_HDR_LEN); |
| |
| /* The LEN/TYPE bytes are set to TYPE */ |
| pEthHeader->type = pWlanSnapHeader->Type; |
| |
| /* Delta length for the next packet */ |
| lengthDelta = ETHERNET_HDR_LEN + uDataLen; |
| |
| /* copy the packet payload */ |
| if (uDataLen > WLAN_SNAP_HDR_LEN) |
| os_memoryCopy (pRxData->hOs, |
| (((TI_UINT8*)pEthHeader) + ETHERNET_HDR_LEN), |
| ((TI_UINT8*)pMsduEthHeader) + ETHERNET_HDR_LEN + WLAN_SNAP_HDR_LEN, |
| uDataLen - WLAN_SNAP_HDR_LEN); |
| |
| /* set the packet type */ |
| if (swapedTypeLength == ETHERTYPE_802_1D) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received VLAN Buffer \n"); |
| |
| DataPacketType = DATA_VLAN_PACKET; |
| } |
| else if (HTOWLANS(pEthHeader->type) == EAPOL_PACKET) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received Eapol pBuffer \n"); |
| |
| DataPacketType = DATA_EAPOL_PACKET; |
| } |
| else |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received Data pBuffer \n"); |
| |
| DataPacketType = DATA_DATA_PACKET; |
| } |
| |
| /* update buffer setting */ |
| /* save the ETH packet address */ |
| RX_ETH_PKT_DATA(pDataBuf) = pEthHeader; |
| /* save the ETH packet size */ |
| RX_ETH_PKT_LEN(pDataBuf) = uDataLen + ETHERNET_HDR_LEN - WLAN_SNAP_HDR_LEN; |
| |
| /* star of MSDU packet always align acceding to 11n spec */ |
| lengthDelta = (lengthDelta + ALIGN_4BYTE_MASK) & ~ALIGN_4BYTE_MASK; |
| pMsduEthHeader = (TEthernetHeader *)(((TI_UINT8*)pMsduEthHeader) + lengthDelta); |
| |
| if(uAmsduDataLen > lengthDelta) |
| { |
| /* swich to the next MSDU */ |
| uAmsduDataLen = uAmsduDataLen - lengthDelta; |
| |
| /* Clear the EndOfBurst flag for all packets except the last one */ |
| ((RxIfDescriptor_t *)pDataBuf)->driverFlags &= ~DRV_RX_FLAG_END_OF_BURST; |
| } |
| else |
| { |
| /* no more MSDU */ |
| uAmsduDataLen = 0; |
| } |
| |
| |
| /* in A-MSDU the MSDU header type contain the MSDU length and not the type */ |
| uDataLen = WLANTOHS(pMsduEthHeader->type); |
| |
| |
| /* dispatch Buffer according to packet type and current rx data port status */ |
| pRxData->rxData_dispatchBuffer[pRxData->rxDataPortStatus][DataPacketType] (hRxData, pDataBuf, pRxAttr); |
| |
| } /* while end */ |
| |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ConvertAmsduToEthPackets(): A-MSDU Packe conversion done.\n"); |
| |
| /* free the A-MSDU packet */ |
| RxBufFree(pRxData->hOs, pBuffer); |
| |
| return TI_OK; |
| } |
| |
| /**************************************************************************************** |
| * rxData_ReceivePacket * |
| **************************************************************************************** |
| DESCRIPTION: receive packet CB from RxXfer. |
| parse the status and other parameters and forward the frame to |
| rxData_receivePacketFromWlan() |
| |
| INPUT: Rx frame with its parameters |
| |
| OUTPUT: |
| |
| RETURN: |
| |
| ************************************************************************/ |
| static void rxData_ReceivePacket (TI_HANDLE hRxData, |
| void *pBuffer) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ReceivePacket: Received BUF %x\n", pBuffer); |
| |
| if (pBuffer) |
| { |
| RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; |
| TRxAttr RxAttr; |
| ERate appRate; |
| dot11_header_t *pHdr; |
| |
| /* |
| * First thing we do is getting the dot11_header, and than we check the status, since the header is |
| * needed for RX_MIC_FAILURE_ERROR |
| */ |
| |
| pHdr = (dot11_header_t *)RX_BUF_DATA(pBuffer); |
| |
| /* Check status */ |
| switch (pRxParams->status & RX_DESC_STATUS_MASK) |
| { |
| case RX_DESC_STATUS_SUCCESS: |
| break; |
| |
| case RX_DESC_STATUS_DECRYPT_FAIL: |
| { |
| /* This error is not important before the Connection, so we ignore it when portStatus is not OPEN */ |
| if (pRxData->rxDataPortStatus == OPEN) |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, "rxData_ReceivePacket: Received Packet with RX_DESC_DECRYPT_FAIL\n"); |
| } |
| |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| case RX_DESC_STATUS_MIC_FAIL: |
| { |
| TI_UINT8 uKeyType; |
| paramInfo_t Param; |
| TMacAddr* pMac = &pHdr->address1; /* hold the first mac address */ |
| /* Get BSS type */ |
| Param.paramType = SITE_MGR_CURRENT_BSS_TYPE_PARAM; |
| siteMgr_getParam (pRxData->hSiteMgr, &Param); |
| |
| /* For multicast/broadcast frames or in IBSS the key used is GROUP, else - it's Pairwise */ |
| if (MAC_MULTICAST(*pMac) || Param.content.siteMgrCurrentBSSType == BSS_INDEPENDENT) |
| { |
| uKeyType = (TI_UINT8)KEY_TKIP_MIC_GROUP; |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet MIC failure. Type = Group\n"); |
| } |
| /* Unicast on infrastructure */ |
| else |
| { |
| uKeyType = (TI_UINT8)KEY_TKIP_MIC_PAIRWISE; |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet MIC failure. Type = Pairwise\n"); |
| } |
| |
| |
| rsn_reportMicFailure (pRxData->hRsn, &uKeyType, sizeof(uKeyType)); |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| |
| case RX_DESC_STATUS_DRIVER_RX_Q_FAIL: |
| { |
| /* Rx queue error - free packet and return */ |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet with Rx queue error \n"); |
| |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| |
| default: |
| /* Unknown error - free packet and return */ |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet with unknown status = %d\n", (pRxParams->status & RX_DESC_STATUS_MASK)); |
| |
| RxBufFree(pRxData->hOs, pBuffer); |
| return; |
| } |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Receive good Packet\n"); |
| |
| if (rate_PolicyToDrv ((ETxRateClassId)(pRxParams->rate), &appRate) != TI_OK) |
| { |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR , "rxData_ReceivePacket: can't convert hwRate=0x%x\n", pRxParams->rate); |
| } |
| |
| /* |
| * Set rx attributes |
| */ |
| RxAttr.channel = pRxParams->channel; |
| RxAttr.packetInfo = pRxParams->flags; |
| RxAttr.ePacketType= pRxParams->packet_class_tag; |
| RxAttr.Rate = appRate; |
| RxAttr.Rssi = pRxParams->rx_level; |
| RxAttr.SNR = pRxParams->rx_snr; |
| RxAttr.status = pRxParams->status & RX_DESC_STATUS_MASK; |
| /* for now J band not implemented */ |
| RxAttr.band = ((pRxParams->flags & RX_DESC_BAND_MASK) == RX_DESC_BAND_A) ? |
| RADIO_BAND_5_0_GHZ : RADIO_BAND_2_4_GHZ ; |
| RxAttr.eScanTag = (EScanResultTag)(pRxParams->proccess_id_tag); |
| /* timestamp is 32 bit so do bytes copy to avoid exception in case the RxInfo is in 2 bytes offset */ |
| os_memoryCopy (pRxData->hOs, |
| (void *)&(RxAttr.TimeStamp), |
| (void *)&(pRxParams->timestamp), |
| sizeof(pRxParams->timestamp) ); |
| RxAttr.TimeStamp = ENDIAN_HANDLE_LONG(RxAttr.TimeStamp); |
| |
| TRACE8(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ReceivePacket: channel=%d, info=0x%x, type=%d, rate=0x%x, RSSI=%d, SNR=%d, status=%d, scan tag=%d\n", RxAttr.channel, RxAttr.packetInfo, RxAttr.ePacketType, RxAttr.Rate, RxAttr.Rssi, RxAttr.SNR, RxAttr.status, RxAttr.eScanTag); |
| |
| rxData_receivePacketFromWlan (hRxData, pBuffer, &RxAttr); |
| |
| /* |
| * Buffer MUST be freed until now |
| */ |
| } |
| else |
| { |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR , "rxData_ReceivePacket: null Buffer received"); |
| } |
| } |
| |
| |
| /**************************************************************************************** |
| * rxData_RequestForBuffer * |
| **************************************************************************************** |
| DESCRIPTION: RX request for buffer |
| uEncryptionflag API are for GWSI use. |
| INPUT: |
| |
| OUTPUT: |
| |
| RETURN: |
| |
| ************************************************************************/ |
| static ERxBufferStatus rxData_RequestForBuffer (TI_HANDLE hRxData, |
| void **pBuf, |
| TI_UINT16 aLength, |
| TI_UINT32 uEncryptionflag, |
| PacketClassTag_e ePacketClassTag) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION , " RequestForBuffer, length = %d \n",aLength); |
| |
| *pBuf = RxBufAlloc (pRxData->hOs, aLength, ePacketClassTag); |
| |
| if (*pBuf) |
| { |
| return RX_BUF_ALLOC_COMPLETE; |
| } |
| else |
| { |
| return RX_BUF_ALLOC_OUT_OF_MEM; |
| } |
| } |
| |
| |
| /******************************************************************* |
| * DEBUG FUNCTIONS * |
| *******************************************************************/ |
| |
| #ifdef TI_DBG |
| |
| /*************************************************************************** |
| * rxData_resetCounters * |
| **************************************************************************** |
| * DESCRIPTION: This function reset the Rx Data module counters |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: |
| * |
| * RETURNS: void |
| ***************************************************************************/ |
| void rxData_resetCounters(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| os_memoryZero(pRxData->hOs, &pRxData->rxDataCounters, sizeof(rxDataCounters_t)); |
| } |
| |
| /*************************************************************************** |
| * rxData_resetDbgCounters * |
| **************************************************************************** |
| * DESCRIPTION: This function reset the Rx Data module debug counters |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: |
| * |
| * RETURNS: void |
| ***************************************************************************/ |
| |
| void rxData_resetDbgCounters(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| os_memoryZero(pRxData->hOs, &pRxData->rxDataDbgCounters, sizeof(rxDataDbgCounters_t)); |
| } |
| |
| |
| /*************************************************************************** |
| * test functions * |
| ***************************************************************************/ |
| void rxData_printRxCounters (TI_HANDLE hRxData) |
| { |
| #ifdef REPORT_LOG |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (pRxData) |
| { |
| WLAN_OS_REPORT(("RecvOk = %d\n", pRxData->rxDataCounters.RecvOk)); |
| WLAN_OS_REPORT(("DirectedBytesRecv = %d\n", pRxData->rxDataCounters.DirectedBytesRecv)); |
| WLAN_OS_REPORT(("DirectedFramesRecv = %d\n", pRxData->rxDataCounters.DirectedFramesRecv)); |
| WLAN_OS_REPORT(("MulticastBytesRecv = %d\n", pRxData->rxDataCounters.MulticastBytesRecv)); |
| WLAN_OS_REPORT(("MulticastFramesRecv = %d\n", pRxData->rxDataCounters.MulticastFramesRecv)); |
| WLAN_OS_REPORT(("BroadcastBytesRecv = %d\n", pRxData->rxDataCounters.BroadcastBytesRecv)); |
| WLAN_OS_REPORT(("BroadcastFramesRecv = %d\n", pRxData->rxDataCounters.BroadcastFramesRecv)); |
| |
| /* debug counters */ |
| WLAN_OS_REPORT(("excludedFrameCounter = %d\n", pRxData->rxDataDbgCounters.excludedFrameCounter)); |
| WLAN_OS_REPORT(("rxDroppedDueToVLANIncludedCnt = %d\n", pRxData->rxDataDbgCounters.rxDroppedDueToVLANIncludedCnt)); |
| WLAN_OS_REPORT(("rxWrongBssTypeCounter = %d\n", pRxData->rxDataDbgCounters.rxWrongBssTypeCounter)); |
| WLAN_OS_REPORT(("rxWrongBssIdCounter = %d\n", pRxData->rxDataDbgCounters.rxWrongBssIdCounter)); |
| WLAN_OS_REPORT(("rcvUnicastFrameInOpenNotify = %d\n", pRxData->rxDataDbgCounters.rcvUnicastFrameInOpenNotify)); |
| } |
| #endif |
| } |
| |
| |
| void rxData_printRxBlock(TI_HANDLE hRxData) |
| { |
| #ifdef REPORT_LOG |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pRxData->hCtrlData)); |
| WLAN_OS_REPORT(("hMlme = 0x%X\n", pRxData->hMlme)); |
| WLAN_OS_REPORT(("hOs = 0x%X\n", pRxData->hOs)); |
| WLAN_OS_REPORT(("hReport = 0x%X\n", pRxData->hReport)); |
| WLAN_OS_REPORT(("hRsn = 0x%X\n", pRxData->hRsn)); |
| WLAN_OS_REPORT(("hSiteMgr = 0x%X\n", pRxData->hSiteMgr)); |
| |
| WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pRxData->hCtrlData)); |
| WLAN_OS_REPORT(("hMlme = 0x%X\n", pRxData->hMlme)); |
| WLAN_OS_REPORT(("hOs = 0x%X\n", pRxData->hOs)); |
| WLAN_OS_REPORT(("hReport = 0x%X\n", pRxData->hReport)); |
| WLAN_OS_REPORT(("hRsn = 0x%X\n", pRxData->hRsn)); |
| WLAN_OS_REPORT(("hSiteMgr = 0x%X\n", pRxData->hSiteMgr)); |
| |
| WLAN_OS_REPORT(("rxDataPortStatus = %d\n", pRxData->rxDataPortStatus)); |
| WLAN_OS_REPORT(("rxDataExcludeUnencrypted = %d\n", pRxData->rxDataExcludeUnencrypted)); |
| WLAN_OS_REPORT(("rxDataEapolDestination = %d\n", pRxData->rxDataEapolDestination)); |
| #endif |
| } |
| |
| |
| void rxData_startRxThroughputTimer (TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (!pRxData->rxThroughputTimerEnable) |
| { |
| /* reset throughput counter */ |
| pRxData->rxDataCounters.LastSecBytesRecv = 0; |
| pRxData->rxThroughputTimerEnable = TI_TRUE; |
| |
| /* start 1 sec throughput timer */ |
| tmr_StartTimer (pRxData->hThroughputTimer, |
| rxData_printRxThroughput, |
| (TI_HANDLE)pRxData, |
| 1000, |
| TI_TRUE); |
| } |
| } |
| |
| |
| void rxData_stopRxThroughputTimer (TI_HANDLE hRxData) |
| { |
| |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| if (pRxData->rxThroughputTimerEnable) |
| { |
| tmr_StopTimer (pRxData->hThroughputTimer); |
| pRxData->rxThroughputTimerEnable = TI_FALSE; |
| } |
| } |
| |
| |
| static void rxData_printRxThroughput (TI_HANDLE hRxData, TI_BOOL bTwdInitOccured) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| WLAN_OS_REPORT (("\n")); |
| WLAN_OS_REPORT (("-------------- Rx Throughput Statistics ---------------\n")); |
| WLAN_OS_REPORT (("Throughput = %d KBits/sec\n", pRxData->rxDataCounters.LastSecBytesRecv * 8 / 1024)); |
| |
| /* reset throughput counter */ |
| pRxData->rxDataCounters.LastSecBytesRecv = 0; |
| } |
| |
| void rxData_printRxDataFilter (TI_HANDLE hRxData) |
| { |
| TI_UINT32 index; |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| for (index=0; index<MAX_DATA_FILTERS; index++) |
| { |
| if (pRxData->isFilterSet[index]) |
| { |
| WLAN_OS_REPORT (("index=%d, pattern & mask\n", index)); |
| report_PrintDump(pRxData->filterRequests[index].pattern, pRxData->filterRequests[index].patternLength); |
| report_PrintDump(pRxData->filterRequests[index].mask, pRxData->filterRequests[index].maskLength); |
| } |
| else |
| { |
| WLAN_OS_REPORT (("No Filter defined for index-%d\n", index)); |
| } |
| } |
| } |
| |
| #endif /*TI_DBG*/ |
| |
| /**************************************************************************** |
| * rxData_SetReAuthInProgress() |
| **************************************************************************** |
| * DESCRIPTION: Sets the ReAuth flag value |
| * |
| * INPUTS: hRxData - the object |
| * value - value to set the flag to |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: OK or NOK |
| ****************************************************************************/ |
| void rxData_SetReAuthInProgress(TI_HANDLE hRxData, TI_BOOL value) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Set ReAuth flag to %d\n", value); |
| |
| pRxData->reAuthInProgress = value; |
| } |
| |
| /**************************************************************************** |
| * rxData_IsReAuthInProgress() |
| **************************************************************************** |
| * DESCRIPTION: Returns the ReAuth flag value |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: ReAuth flag value |
| ****************************************************************************/ |
| TI_BOOL rxData_IsReAuthInProgress(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| return pRxData->reAuthInProgress; |
| } |
| |
| /**************************************************************************** |
| * rxData_StartReAuthActiveTimer * |
| ***************************************************************************** |
| * DESCRIPTION: this function starts the ReAuthActive timer |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: None |
| ***************************************************************************/ |
| static void rxData_StartReAuthActiveTimer(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Start ReAuth Active Timer\n"); |
| tmr_StartTimer (pRxData->reAuthActiveTimer, |
| reAuthTimeout, |
| (TI_HANDLE)pRxData, |
| pRxData->reAuthActiveTimeout, |
| TI_FALSE); |
| } |
| |
| /**************************************************************************** |
| * rxData_StopReAuthActiveTimer * |
| ***************************************************************************** |
| * DESCRIPTION: this function stops the ReAuthActive timer |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: None |
| ***************************************************************************/ |
| void rxData_StopReAuthActiveTimer(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Stop ReAuth Active Timer\n"); |
| tmr_StopTimer (pRxData->reAuthActiveTimer); |
| } |
| |
| /**************************************************************************** |
| * reAuthTimeout * |
| ***************************************************************************** |
| * DESCRIPTION: this function ia called when the ReAuthActive timer elapses |
| * It resets the Reauth flag and restore the PS state. |
| * It also sends RE_AUTH_TERMINATED event to upper layer. |
| * |
| * INPUTS: hRxData - the object |
| * |
| * OUTPUT: None |
| * |
| * RETURNS: None |
| ***************************************************************************/ |
| static void reAuthTimeout(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| |
| TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "ReAuth Active Timeout\n"); |
| rxData_SetReAuthInProgress(pRxData, TI_FALSE); |
| rxData_ReauthDisablePriority(pRxData); |
| EvHandlerSendEvent(pRxData->hEvHandler, IPC_EVENT_RE_AUTH_TERMINATED, NULL, 0); |
| } |
| |
| void rxData_ReauthEnablePriority(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| paramInfo_t param; |
| |
| param.paramType = POWER_MGR_ENABLE_PRIORITY; |
| param.content.powerMngPriority = POWER_MANAGER_REAUTH_PRIORITY; |
| powerMgr_setParam(pRxData->hPowerMgr,¶m); |
| } |
| |
| void rxData_ReauthDisablePriority(TI_HANDLE hRxData) |
| { |
| rxData_t *pRxData = (rxData_t *)hRxData; |
| paramInfo_t param; |
| |
| param.paramType = POWER_MGR_DISABLE_PRIORITY; |
| param.content.powerMngPriority = POWER_MANAGER_REAUTH_PRIORITY; |
| powerMgr_setParam(pRxData->hPowerMgr,¶m); |
| } |