/*
* siteHash.c
*
* Copyright(c) 1998 - 2009 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.
*/
/** \file siteHash.c
* \brief Site Hash implementation
*
* \see siteHash.h
*/
/****************************************************************************/
/* */
/* MODULE: siteHash.c */
/* PURPOSE: Site Hash implementation */
/* */
/***************************************************************************/
#define __FILE_ID__ FILE_ID_84
#include "tidef.h"
#include "report.h"
#include "osApi.h"
#include "siteMgrApi.h"
#include "siteHash.h"
#include "smeApi.h"
/****************************************************************************************************************
This file implements the site hash mechanism. This mechanism is used for faster access to the sites information.
It is compound of the following:
1. hash function - which maps the 4 last bits of the BSSID to an entry in the hash table.
2. hash table - each entry in the table points to a linked list of site entries
3. site table - each entry holds a site information
In order to find a site in the site table, we operate the hash function on the site's BSSID.
We receive a hash entry. We go over the linked list pointed by this hash entry until we find the site entry.
*****************************************************************************************************************/
#define WLAN_NUM_OF_MISSED_SACNS_BEFORE_AGING 2
/********************************************/
/* Functions Implementations */
/********************************************/
/************************************************************************
* siteMgr_resetSiteTable *
************************************************************************
DESCRIPTION: reset the following things:
- Mgmt parameters structure
- Site table
- Hash table
- Primary site pointer
- Number of sites
INPUT: hSiteMgr - Handle to site mgr
OUTPUT:
RETURN: TI_OK
************************************************************************/
TI_STATUS siteMgr_resetSiteTable(TI_HANDLE hSiteMgr, siteTablesParams_t *pSiteTableParams)
{
int i;
siteMgr_t *pSiteMgr = (siteMgr_t *)hSiteMgr;
/* It looks like it never happens. Anyway decided to check */
if ( pSiteTableParams->maxNumOfSites > MAX_SITES_BG_BAND )
{
TRACE2( pSiteMgr->hReport, REPORT_SEVERITY_ERROR,
"siteMgr_resetSiteTable. pScanMngr->currentBSSBand=%d exceeds the limit %d\n",
pSiteTableParams->maxNumOfSites, MAX_SITES_BG_BAND);
handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION);
return TI_NOK;
}
os_memoryZero(pSiteMgr->hOs, &pSiteTableParams->siteTable[0], sizeof(siteEntry_t)*pSiteTableParams->maxNumOfSites);
for (i = 0; i < pSiteTableParams->maxNumOfSites; i++)
{
pSiteTableParams->siteTable[i].index = i;
pSiteTableParams->siteTable[i].siteType = SITE_NULL;
pSiteTableParams->siteTable[i].beaconRecv = TI_FALSE;
pSiteTableParams->siteTable[i].dtimPeriod = 1;
}
pSiteTableParams->numOfSites = 0;
pSiteMgr->pSitesMgmtParams->pPrimarySite = NULL;
return TI_OK;
}
/************************************************************************
* findSiteEntry *
************************************************************************
DESCRIPTION: Perform the following things:
- Compute the site's hash entry based on the site BSSID and hash function
- Look fotr the site entry in the linked list pointed by the hash entry
- If the site is found in the site table, returns a pointer to the site entry
- If the site is not found, return NULL.
INPUT: pSiteMgr - Handle to site mgr
mac - The site BSSID
OUTPUT:
RETURN: Pointer to the site entry if site found, NULL otherwise
************************************************************************/
siteEntry_t *findSiteEntry(siteMgr_t *pSiteMgr,
TMacAddr *mac)
{
siteTablesParams_t *pCurrentSiteTable = pSiteMgr->pSitesMgmtParams->pCurrentSiteTable;
siteEntry_t *pSiteEntry;
TI_UINT8 tableIndex=2, i;
/* It looks like it never happens. Anyway decided to check */
if ( pCurrentSiteTable->maxNumOfSites > MAX_SITES_BG_BAND )
{
TRACE2( pSiteMgr->hReport, REPORT_SEVERITY_ERROR,
"findSiteEntry. pCurrentSiteTable->maxNumOfSites=%d exceeds the limit %d\n",
pCurrentSiteTable->maxNumOfSites, MAX_SITES_BG_BAND);
handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION);
return NULL;
}
do
{
tableIndex--;
for (i = 0; i < pCurrentSiteTable->maxNumOfSites; i++)
{
pSiteEntry = &(pCurrentSiteTable->siteTable[i]);
if (MAC_EQUAL (pSiteEntry->bssid, *mac))
{
TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION,
"FIND success, bssid: %X-%X-%X-%X-%X-%X\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]);
return pSiteEntry;
}
}
if ((pSiteMgr->pDesiredParams->siteMgrDesiredDot11Mode == DOT11_DUAL_MODE) &&
(tableIndex==1))
{ /* change site table */
if (pCurrentSiteTable == &pSiteMgr->pSitesMgmtParams->dot11BG_sitesTables)
{
pCurrentSiteTable = (siteTablesParams_t *)&pSiteMgr->pSitesMgmtParams->dot11A_sitesTables;
}
else
{
pCurrentSiteTable = &pSiteMgr->pSitesMgmtParams->dot11BG_sitesTables;
}
}
} while (tableIndex>0);
TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "FIND failure, bssid: %X-%X-%X-%X-%X-%X\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]);
return NULL;
}
/************************************************************************
* findAndInsertSiteEntry *
************************************************************************
DESCRIPTION: Perform the following things:
- Compute the site's hash entry based on the site BSSID and hash function
- Look for the site entry in the linked list pointed by the hash entry
- If the site is found in the site table, returns a pointer to the site entry
- If the site is not found in the site table, tries to add the site
- If succeeds, returns a pointer to the site entry
- Otherwise, returns NULL
INPUT: pSiteMgr - Handle to site mgr
mac - The site BSSID
band - The site band
OUTPUT:
RETURN: Pointer to the site entry if site found/inserted, NULL otherwise
************************************************************************/
siteEntry_t *findAndInsertSiteEntry(siteMgr_t *pSiteMgr,
TMacAddr *mac,
ERadioBand band)
{
TI_UINT8 i, emptySiteIndex=0, nextSite2Remove=0;
siteEntry_t *pSiteEntry, *pPrimarySite=pSiteMgr->pSitesMgmtParams->pPrimarySite;
sitesMgmtParams_t *pSitesMgmtParams = pSiteMgr->pSitesMgmtParams;
siteTablesParams_t *pCurrentSiteTable;
TI_BOOL firstEmptySiteFound = TI_FALSE;
TI_UINT32 oldestTS;
/* choose site table according to AP's band */
if ( RADIO_BAND_2_4_GHZ == band )
{
pCurrentSiteTable = &(pSitesMgmtParams->dot11BG_sitesTables);
}
else if (RADIO_BAND_5_0_GHZ == band)
{
pCurrentSiteTable = (siteTablesParams_t*) &(pSitesMgmtParams->dot11A_sitesTables);
}
else
{
TRACE1(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "Bad band: %d\n\n", band);
pCurrentSiteTable = &(pSitesMgmtParams->dot11BG_sitesTables);
}
/* Set the first TS to a site which is not the Primary site */
if (pPrimarySite != &(pCurrentSiteTable->siteTable[0]))
{
oldestTS = pCurrentSiteTable->siteTable[0].localTimeStamp;
}
else
{
oldestTS = pCurrentSiteTable->siteTable[1].localTimeStamp;
}
/* It looks like it never happens. Anyway decided to check */
if ( pCurrentSiteTable->maxNumOfSites > MAX_SITES_BG_BAND )
{
TRACE2( pSiteMgr->hReport, REPORT_SEVERITY_ERROR,
"findAndInsertSiteEntry. pCurrentSiteTable->maxNumOfSites=%d exceeds the limit %d\n",
pCurrentSiteTable->maxNumOfSites, MAX_SITES_BG_BAND);
handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION);
return NULL;
}
/* Loop all the sites till the desired MAC is found */
for (i = 0; i < pCurrentSiteTable->maxNumOfSites; i++)
{
pSiteEntry = &(pCurrentSiteTable->siteTable[i]);
if (MAC_EQUAL (pSiteEntry->bssid, *mac))
{
TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "FIND success, bssid: %X-%X-%X-%X-%X-%X\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]);
return pSiteEntry;
}
else if (pSiteEntry->siteType == SITE_NULL)
{ /* Save the first empty site, in case the
desired MAC is not found */
if (!firstEmptySiteFound)
{
emptySiteIndex = i;
firstEmptySiteFound=TI_TRUE;
}
}
else if (oldestTS == pSiteEntry->localTimeStamp)
{ /* Save the oldest site's index, according to TS */
nextSite2Remove = i;
}
}
TRACE4(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT failure, no free entry!, oldestTS=%d, nextSite2Remove=%d, "
"[0].localTimeStamp=%d, [1]localTimeStamp%d \n",
oldestTS, nextSite2Remove,
pCurrentSiteTable->siteTable[0].localTimeStamp,
pCurrentSiteTable->siteTable[1].localTimeStamp);
if ((!firstEmptySiteFound) || (pCurrentSiteTable->numOfSites>=pCurrentSiteTable->maxNumOfSites))
{
/* No NULL entry has been found. Remove the oldest site */
pSiteEntry = &(pCurrentSiteTable->siteTable[nextSite2Remove]);
TRACE9(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT failure, no free entry!, numOfSites=%d, removing site index=%d,\n bssid: %X-%X-%X-%X-%X-%X, ts=%d \n", pCurrentSiteTable->numOfSites, nextSite2Remove, pSiteEntry->bssid[0], pSiteEntry->bssid[1], pSiteEntry->bssid[2], pSiteEntry->bssid[3], pSiteEntry->bssid[4], pSiteEntry->bssid[5], pSiteEntry->localTimeStamp);
removeSiteEntry(pSiteMgr, pCurrentSiteTable, pSiteEntry);
emptySiteIndex = nextSite2Remove;
}
pCurrentSiteTable->numOfSites++;
pSiteEntry = &(pCurrentSiteTable->siteTable[emptySiteIndex]);
/* fill the entry with the station mac */
MAC_COPY (pSiteEntry->bssid, *mac);
/* Some parameters have to be initialized immediately after entry allocation */
if(pSiteMgr->siteMgrOperationalMode == DOT11_G_MODE)
pSiteEntry->currentSlotTime = pSiteMgr->pDesiredParams->siteMgrDesiredSlotTime;
TRACE8(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT success, bssid: %X-%X-%X-%X-%X-%X, band=%d, index=%d\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], band, emptySiteIndex);
return pSiteEntry;
}
/************************************************************************
* removeSiteEntry *
************************************************************************
DESCRIPTION: Removes the site entry from the site table
INPUT: pSiteMgr - Handle to site mgr
pCurrSiteTblParams - Pointer to current site table parameters
hashPtr - Pointer to the site entry
OUTPUT:
RETURN:
************************************************************************/
void removeSiteEntry(siteMgr_t *pSiteMgr,
siteTablesParams_t *pCurrSiteTblParams,
siteEntry_t *pSiteEntry)
{
TI_UINT8 index;
if (pSiteEntry == NULL)
{
TRACE0(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "REMOVAL failure, site is NULL\n\n");
return;
}
if (pCurrSiteTblParams->numOfSites == 0)
{
TRACE0(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "REMOVAL failure, site table is empty\n\n");
return;
}
TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "removeSiteEntry REMOVE ssid=, bssid= 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x\n\n", pSiteEntry->bssid[0], pSiteEntry->bssid[1], pSiteEntry->bssid[2], pSiteEntry->bssid[3], pSiteEntry->bssid[4], pSiteEntry->bssid[5] );
pCurrSiteTblParams->numOfSites--;
/* Now remove (exclude) hashPtr entry from the linked list */
TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "REMOVAL success, bssid: %X-%X-%X-%X-%X-%X\n\n", pSiteEntry->bssid[0], pSiteEntry->bssid[1], pSiteEntry->bssid[2], pSiteEntry->bssid[3], pSiteEntry->bssid[4], pSiteEntry->bssid[5]);
TRACE1(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, " SITE TABLE remaining entries number %d \n", pCurrSiteTblParams->numOfSites);
/* Clean the rest of the entry structure */
index = pSiteEntry->index; /* keep the index of the siteTable entry */
os_memoryZero(pSiteMgr->hOs, pSiteEntry, sizeof(siteEntry_t));
/* This is not required!!!! - Remove!!*/
pSiteEntry->dtimPeriod = 1;
pSiteEntry->siteType = SITE_NULL;
pSiteEntry->index = index; /* restore the index of the siteTable */
/* if removing previous primary site - update the link */
if (pSiteEntry == pSiteMgr->pSitesMgmtParams->pPrevPrimarySite)
{
pSiteMgr->pSitesMgmtParams->pPrevPrimarySite = NULL;
}
return;
}