/* * 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; }