| /** | |
| * @file IxEthDBAPI.c | |
| * | |
| * @brief Implementation of the public API | |
| * | |
| * @par | |
| * IXP400 SW Release version 2.0 | |
| * | |
| * -- Copyright Notice -- | |
| * | |
| * @par | |
| * Copyright 2001-2005, Intel Corporation. | |
| * All rights reserved. | |
| * | |
| * @par | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. 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. | |
| * 3. Neither the name of the Intel Corporation nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * @par | |
| * 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. | |
| * | |
| * @par | |
| * -- End of Copyright Notice -- | |
| */ | |
| #include "IxEthDB_p.h" | |
| #include "IxFeatureCtrl.h" | |
| extern HashTable dbHashtable; | |
| extern IxEthDBPortMap overflowUpdatePortList; | |
| extern BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1]; | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
| return ixEthDBTriggerAddPortUpdate(macAddr, portID, true); | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
| return ixEthDBTriggerAddPortUpdate(macAddr, portID, false); | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr) | |
| { | |
| HashNode *searchResult; | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
| if (searchResult == NULL) | |
| { | |
| return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
| } | |
| ixEthDBReleaseHashNode(searchResult); | |
| /* build a remove event and place it on the event queue */ | |
| return ixEthDBTriggerRemovePortUpdate(macAddr, ((MacDescriptor *) searchResult->data)->portID); | |
| } | |
| IX_ETH_DB_PUBLIC | |
| void ixEthDBDatabaseMaintenance() | |
| { | |
| HashIterator iterator; | |
| UINT32 portIndex; | |
| BOOL agingRequired = false; | |
| /* ports who will have deleted records and therefore will need updating */ | |
| IxEthDBPortMap triggerPorts; | |
| if (IX_FEATURE_CTRL_SWCONFIG_ENABLED != | |
| ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING)) | |
| { | |
| return; | |
| } | |
| SET_EMPTY_DEPENDENCY_MAP(triggerPorts); | |
| /* check if there's at least a port that needs aging */ | |
| for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) | |
| { | |
| if (ixEthDBPortInfo[portIndex].agingEnabled && ixEthDBPortInfo[portIndex].enabled) | |
| { | |
| agingRequired = true; | |
| } | |
| } | |
| if (agingRequired) | |
| { | |
| /* ask each NPE port to write back the database for aging inspection */ | |
| for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) | |
| { | |
| if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE | |
| && ixEthDBPortInfo[portIndex].agingEnabled | |
| && ixEthDBPortInfo[portIndex].enabled) | |
| { | |
| IxNpeMhMessage message; | |
| IX_STATUS result; | |
| /* send EDB_GetMACAddressDatabase message */ | |
| FILL_GETMACADDRESSDATABASE(message, | |
| 0 /* unused */, | |
| IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone)); | |
| IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), message, result); | |
| if (result == IX_SUCCESS) | |
| { | |
| /* analyze NPE copy */ | |
| ixEthDBNPESyncScan(portIndex, ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone, FULL_ELT_BYTE_SIZE); | |
| IX_ETH_DB_SUPPORT_TRACE("DB: (API) Finished scanning NPE tree on port %d\n", portIndex); | |
| } | |
| else | |
| { | |
| ixEthDBPortInfo[portIndex].agingEnabled = false; | |
| ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = false; | |
| ixEthDBPortInfo[portIndex].updateMethod.userControlled = true; | |
| ixOsalLog(IX_OSAL_LOG_LVL_FATAL, | |
| IX_OSAL_LOG_DEV_STDOUT, | |
| "EthDB: (Maintenance) warning, disabling aging and updates for port %d (assumed dead)\n", | |
| portIndex, 0, 0, 0, 0, 0); | |
| ixEthDBDatabaseClear(portIndex, IX_ETH_DB_ALL_RECORD_TYPES); | |
| } | |
| } | |
| } | |
| /* browse database and age entries */ | |
| BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator)); | |
| while (IS_ITERATOR_VALID(&iterator)) | |
| { | |
| MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; | |
| UINT32 *age = NULL; | |
| BOOL staticEntry = true; | |
| if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) | |
| { | |
| age = &descriptor->recordData.filteringData.age; | |
| staticEntry = descriptor->recordData.filteringData.staticEntry; | |
| } | |
| else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) | |
| { | |
| age = &descriptor->recordData.filteringVlanData.age; | |
| staticEntry = descriptor->recordData.filteringVlanData.staticEntry; | |
| } | |
| else | |
| { | |
| staticEntry = true; | |
| } | |
| if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == false)) | |
| { | |
| /* manually increment the age if the port has no such capability */ | |
| if ((ixEthDBPortDefinitions[descriptor->portID].capabilities & IX_ETH_ENTRY_AGING) == 0) | |
| { | |
| *age += (IX_ETH_DB_MAINTENANCE_TIME / 60); | |
| } | |
| /* age entry if it exceeded the maximum time to live */ | |
| if (*age >= (IX_ETH_DB_LEARNING_ENTRY_AGE_TIME / 60)) | |
| { | |
| /* add port to the set of update trigger ports */ | |
| JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID); | |
| /* delete entry */ | |
| BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator)); | |
| } | |
| else | |
| { | |
| /* move to the next record */ | |
| BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
| } | |
| } | |
| else | |
| { | |
| /* move to the next record */ | |
| BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
| } | |
| } | |
| /* update ports which lost records */ | |
| ixEthDBUpdatePortLearningTrees(triggerPorts); | |
| } | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType) | |
| { | |
| IxEthDBPortMap triggerPorts; | |
| HashIterator iterator; | |
| if (portID >= IX_ETH_DB_NUMBER_OF_PORTS && portID != IX_ETH_DB_ALL_PORTS) | |
| { | |
| return IX_ETH_DB_INVALID_PORT; | |
| } | |
| /* check if the user passes some extra bits */ | |
| if ((recordType | IX_ETH_DB_ALL_RECORD_TYPES) != IX_ETH_DB_ALL_RECORD_TYPES) | |
| { | |
| return IX_ETH_DB_INVALID_ARG; | |
| } | |
| SET_EMPTY_DEPENDENCY_MAP(triggerPorts); | |
| /* browse database and age entries */ | |
| BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator)); | |
| while (IS_ITERATOR_VALID(&iterator)) | |
| { | |
| MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; | |
| if (((descriptor->portID == portID) || (portID == IX_ETH_DB_ALL_PORTS)) | |
| && ((descriptor->type & recordType) != 0)) | |
| { | |
| /* add to trigger if automatic updates are required */ | |
| if (ixEthDBPortUpdateRequired[descriptor->type]) | |
| { | |
| /* add port to the set of update trigger ports */ | |
| JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID); | |
| } | |
| /* delete entry */ | |
| BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator)); | |
| } | |
| else | |
| { | |
| /* move to the next record */ | |
| BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); | |
| } | |
| } | |
| /* update ports which lost records */ | |
| ixEthDBUpdatePortLearningTrees(triggerPorts); | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr) | |
| { | |
| HashNode *searchResult; | |
| IxEthDBStatus result = IX_ETH_DB_NO_SUCH_ADDR; | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
| searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
| if (searchResult == NULL) | |
| { | |
| return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
| } | |
| if (((MacDescriptor *) (searchResult->data))->portID == portID) | |
| { | |
| result = IX_ETH_DB_SUCCESS; /* address and port match */ | |
| } | |
| ixEthDBReleaseHashNode(searchResult); | |
| return result; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) | |
| { | |
| HashNode *searchResult; | |
| IX_ETH_DB_CHECK_REFERENCE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
| if (searchResult == NULL) | |
| { | |
| return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
| } | |
| /* return the port ID */ | |
| *portID = ((MacDescriptor *) searchResult->data)->portID; | |
| ixEthDBReleaseHashNode(searchResult); | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
| ixEthDBPortInfo[portID].agingEnabled = false; | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); | |
| ixEthDBPortInfo[portID].agingEnabled = true; | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr) | |
| { | |
| HashNode *searchResult; | |
| MacDescriptor *descriptor; | |
| IX_ETH_DB_CHECK_REFERENCE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(macAddr); | |
| searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS); | |
| if (searchResult == NULL) | |
| { | |
| return IX_ETH_DB_NO_SUCH_ADDR; /* not found */ | |
| } | |
| descriptor = (MacDescriptor *) searchResult->data; | |
| /* return the port ID */ | |
| *portID = descriptor->portID; | |
| /* reset entry age */ | |
| if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) | |
| { | |
| descriptor->recordData.filteringData.age = 0; | |
| } | |
| else | |
| { | |
| descriptor->recordData.filteringVlanData.age = 0; | |
| } | |
| ixEthDBReleaseHashNode(searchResult); | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
| /* force bit at offset 255 to 0 (reserved) */ | |
| dependencyPortMap[31] &= 0xFE; | |
| COPY_DEPENDENCY_MAP(ixEthDBPortInfo[portID].dependencyPortMap, dependencyPortMap); | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
| COPY_DEPENDENCY_MAP(dependencyPortMap, ixEthDBPortInfo[portID].dependencyPortMap); | |
| return IX_ETH_DB_SUCCESS; | |
| } | |
| IX_ETH_DB_PUBLIC | |
| IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate) | |
| { | |
| IX_ETH_DB_CHECK_PORT(portID); | |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); | |
| IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); | |
| ixEthDBPortInfo[portID].updateMethod.updateEnabled = enableUpdate; | |
| ixEthDBPortInfo[portID].updateMethod.userControlled = true; | |
| return IX_ETH_DB_SUCCESS; | |
| } |