uboot/arch/arm/cpu/ixp/npe/IxEthDBAPI.c
<<
>>
Prefs
   1/**
   2 * @file IxEthDBAPI.c
   3 *
   4 * @brief Implementation of the public API
   5 * 
   6 * @par
   7 * IXP400 SW Release version 2.0
   8 * 
   9 * -- Copyright Notice --
  10 * 
  11 * @par
  12 * Copyright 2001-2005, Intel Corporation.
  13 * All rights reserved.
  14 * 
  15 * @par
  16 * Redistribution and use in source and binary forms, with or without
  17 * modification, are permitted provided that the following conditions
  18 * are met:
  19 * 1. Redistributions of source code must retain the above copyright
  20 *    notice, this list of conditions and the following disclaimer.
  21 * 2. Redistributions in binary form must reproduce the above copyright
  22 *    notice, this list of conditions and the following disclaimer in the
  23 *    documentation and/or other materials provided with the distribution.
  24 * 3. Neither the name of the Intel Corporation nor the names of its contributors
  25 *    may be used to endorse or promote products derived from this software
  26 *    without specific prior written permission.
  27 * 
  28 * @par
  29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  39 * SUCH DAMAGE.
  40 * 
  41 * @par
  42 * -- End of Copyright Notice --
  43 */
  44
  45#include "IxEthDB_p.h"
  46#include "IxFeatureCtrl.h"
  47
  48extern HashTable dbHashtable;
  49extern IxEthDBPortMap overflowUpdatePortList;
  50extern BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1];
  51
  52IX_ETH_DB_PUBLIC
  53IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
  54{
  55    IX_ETH_DB_CHECK_PORT(portID);
  56    
  57    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
  58    
  59    IX_ETH_DB_CHECK_REFERENCE(macAddr);
  60    
  61    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
  62
  63    return ixEthDBTriggerAddPortUpdate(macAddr, portID, TRUE);
  64}
  65    
  66IX_ETH_DB_PUBLIC
  67IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
  68{
  69    IX_ETH_DB_CHECK_PORT(portID);
  70    
  71    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
  72        
  73    IX_ETH_DB_CHECK_REFERENCE(macAddr);
  74
  75    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
  76
  77    return ixEthDBTriggerAddPortUpdate(macAddr, portID, FALSE);
  78}
  79
  80IX_ETH_DB_PUBLIC
  81IxEthDBStatus ixEthDBFilteringEntryDelete(IxEthDBMacAddr *macAddr)
  82{
  83    HashNode *searchResult;
  84
  85    IX_ETH_DB_CHECK_REFERENCE(macAddr);
  86
  87    searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
  88
  89    if (searchResult == NULL)
  90    {
  91        return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
  92    }
  93    
  94    ixEthDBReleaseHashNode(searchResult);
  95    
  96    /* build a remove event and place it on the event queue */
  97    return ixEthDBTriggerRemovePortUpdate(macAddr, ((MacDescriptor *) searchResult->data)->portID);
  98}
  99       
 100IX_ETH_DB_PUBLIC
 101void ixEthDBDatabaseMaintenance()
 102{
 103    HashIterator iterator;
 104    UINT32 portIndex;
 105    BOOL agingRequired = FALSE;
 106
 107    /* ports who will have deleted records and therefore will need updating */
 108    IxEthDBPortMap triggerPorts;
 109
 110    if (IX_FEATURE_CTRL_SWCONFIG_ENABLED !=
 111        ixFeatureCtrlSwConfigurationCheck (IX_FEATURECTRL_ETH_LEARNING))
 112    {
 113        return;
 114    }
 115
 116    SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
 117
 118    /* check if there's at least a port that needs aging */
 119    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
 120    {
 121        if (ixEthDBPortInfo[portIndex].agingEnabled && ixEthDBPortInfo[portIndex].enabled)
 122        {
 123            agingRequired = TRUE;
 124        }
 125    }
 126
 127    if (agingRequired)
 128    {
 129        /* ask each NPE port to write back the database for aging inspection */
 130        for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
 131        {
 132            if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE
 133                && ixEthDBPortInfo[portIndex].agingEnabled
 134                && ixEthDBPortInfo[portIndex].enabled)
 135            {
 136                IxNpeMhMessage message;
 137                IX_STATUS result;
 138                
 139                /* send EDB_GetMACAddressDatabase message */
 140                FILL_GETMACADDRESSDATABASE(message, 
 141                    0 /* unused */, 
 142                    IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone));
 143
 144                IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), message, result);
 145
 146                if (result == IX_SUCCESS)
 147                {
 148                    /* analyze NPE copy */
 149                    ixEthDBNPESyncScan(portIndex, ixEthDBPortInfo[portIndex].updateMethod.npeUpdateZone, FULL_ELT_BYTE_SIZE);
 150
 151                    IX_ETH_DB_SUPPORT_TRACE("DB: (API) Finished scanning NPE tree on port %d\n", portIndex);
 152                }
 153                else
 154                {
 155                    ixEthDBPortInfo[portIndex].agingEnabled                = FALSE;
 156                    ixEthDBPortInfo[portIndex].updateMethod.updateEnabled  = FALSE;
 157                    ixEthDBPortInfo[portIndex].updateMethod.userControlled = TRUE;
 158
 159                    ixOsalLog(IX_OSAL_LOG_LVL_FATAL,
 160                        IX_OSAL_LOG_DEV_STDOUT, 
 161                        "EthDB: (Maintenance) warning, disabling aging and updates for port %d (assumed dead)\n",
 162                        portIndex, 0, 0, 0, 0, 0);
 163
 164                    ixEthDBDatabaseClear(portIndex, IX_ETH_DB_ALL_RECORD_TYPES);
 165                }
 166            }
 167        }
 168
 169        /* browse database and age entries */
 170        BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
 171
 172        while (IS_ITERATOR_VALID(&iterator))
 173        {
 174            MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
 175            UINT32 *age               = NULL;
 176            BOOL staticEntry          = TRUE;
 177
 178            if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
 179            {
 180                age         = &descriptor->recordData.filteringData.age;
 181                staticEntry = descriptor->recordData.filteringData.staticEntry;
 182            }
 183            else if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
 184            {
 185                age         = &descriptor->recordData.filteringVlanData.age;
 186                staticEntry = descriptor->recordData.filteringVlanData.staticEntry;
 187            }
 188            else
 189            {
 190                staticEntry = TRUE;
 191            }
 192
 193            if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == FALSE))
 194            {
 195                /* manually increment the age if the port has no such capability */
 196                if ((ixEthDBPortDefinitions[descriptor->portID].capabilities & IX_ETH_ENTRY_AGING) == 0)
 197                {
 198                    *age += (IX_ETH_DB_MAINTENANCE_TIME / 60);
 199                }
 200
 201                /* age entry if it exceeded the maximum time to live */
 202                if (*age >= (IX_ETH_DB_LEARNING_ENTRY_AGE_TIME / 60))
 203                {
 204                    /* add port to the set of update trigger ports */
 205                    JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID);
 206
 207                    /* delete entry */
 208                    BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
 209                }
 210                else
 211                {
 212                    /* move to the next record */
 213                    BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
 214                }
 215            }
 216            else
 217            {
 218                /* move to the next record */
 219                BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
 220            }
 221        }
 222
 223        /* update ports which lost records */
 224        ixEthDBUpdatePortLearningTrees(triggerPorts);
 225    }
 226}
 227
 228IX_ETH_DB_PUBLIC
 229IxEthDBStatus ixEthDBDatabaseClear(IxEthDBPortId portID, IxEthDBRecordType recordType)
 230{
 231    IxEthDBPortMap triggerPorts;
 232    HashIterator iterator;
 233
 234    if (portID >= IX_ETH_DB_NUMBER_OF_PORTS && portID != IX_ETH_DB_ALL_PORTS)
 235    {
 236        return IX_ETH_DB_INVALID_PORT;
 237    }
 238
 239    /* check if the user passes some extra bits */
 240    if ((recordType | IX_ETH_DB_ALL_RECORD_TYPES) != IX_ETH_DB_ALL_RECORD_TYPES)
 241    {
 242        return IX_ETH_DB_INVALID_ARG;
 243    }
 244
 245    SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
 246    
 247    /* browse database and age entries */
 248    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));
 249
 250    while (IS_ITERATOR_VALID(&iterator))
 251    {
 252        MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;
 253
 254        if (((descriptor->portID == portID) || (portID == IX_ETH_DB_ALL_PORTS))
 255            && ((descriptor->type & recordType) != 0))
 256        {
 257            /* add to trigger if automatic updates are required */
 258            if (ixEthDBPortUpdateRequired[descriptor->type])
 259            {
 260                /* add port to the set of update trigger ports */
 261                JOIN_PORT_TO_MAP(triggerPorts, descriptor->portID);
 262            }
 263
 264            /* delete entry */
 265            BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
 266        }
 267        else
 268        {
 269            /* move to the next record */
 270            BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
 271        }
 272    }
 273
 274    /* update ports which lost records */
 275    ixEthDBUpdatePortLearningTrees(triggerPorts);
 276    
 277    return IX_ETH_DB_SUCCESS;
 278}
 279
 280IX_ETH_DB_PUBLIC
 281IxEthDBStatus ixEthDBFilteringPortSearch(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
 282{
 283    HashNode *searchResult;
 284    IxEthDBStatus result = IX_ETH_DB_NO_SUCH_ADDR;
 285
 286    IX_ETH_DB_CHECK_PORT(portID);
 287    
 288    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
 289    
 290    IX_ETH_DB_CHECK_REFERENCE(macAddr);
 291
 292    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
 293
 294    searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
 295
 296    if (searchResult == NULL)
 297    {
 298        return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
 299    }
 300
 301    if (((MacDescriptor *) (searchResult->data))->portID == portID)
 302    {
 303        result = IX_ETH_DB_SUCCESS; /* address and port match */
 304    }
 305
 306    ixEthDBReleaseHashNode(searchResult);
 307
 308    return result;
 309}
 310
 311IX_ETH_DB_PUBLIC
 312IxEthDBStatus ixEthDBFilteringDatabaseSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr)
 313{
 314    HashNode *searchResult;
 315
 316    IX_ETH_DB_CHECK_REFERENCE(portID);
 317    
 318    IX_ETH_DB_CHECK_REFERENCE(macAddr);
 319
 320    searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
 321
 322    if (searchResult == NULL)
 323    {
 324        return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
 325    }
 326
 327    /* return the port ID */
 328    *portID = ((MacDescriptor *) searchResult->data)->portID;
 329
 330    ixEthDBReleaseHashNode(searchResult);
 331
 332    return IX_ETH_DB_SUCCESS;
 333}
 334
 335IX_ETH_DB_PUBLIC
 336IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID)
 337{
 338    IX_ETH_DB_CHECK_PORT(portID);
 339
 340    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
 341
 342    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
 343
 344    ixEthDBPortInfo[portID].agingEnabled = FALSE;
 345
 346    return IX_ETH_DB_SUCCESS;
 347}
 348
 349IX_ETH_DB_PUBLIC
 350IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID)
 351{
 352    IX_ETH_DB_CHECK_PORT(portID);
 353
 354    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
 355
 356    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING);
 357
 358    ixEthDBPortInfo[portID].agingEnabled = TRUE;
 359
 360    return IX_ETH_DB_SUCCESS;
 361}
 362
 363IX_ETH_DB_PUBLIC
 364IxEthDBStatus ixEthDBFilteringPortUpdatingSearch(IxEthDBPortId *portID, IxEthDBMacAddr *macAddr)
 365{
 366    HashNode *searchResult;
 367    MacDescriptor *descriptor;
 368
 369    IX_ETH_DB_CHECK_REFERENCE(portID);
 370    
 371    IX_ETH_DB_CHECK_REFERENCE(macAddr);
 372
 373    searchResult = ixEthDBSearch(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS);
 374
 375    if (searchResult == NULL)
 376    {
 377        return IX_ETH_DB_NO_SUCH_ADDR; /* not found */
 378    }
 379    
 380    descriptor = (MacDescriptor *) searchResult->data;
 381
 382    /* return the port ID */
 383    *portID = descriptor->portID;
 384
 385    /* reset entry age */
 386    if (descriptor->type == IX_ETH_DB_FILTERING_RECORD)
 387    {
 388        descriptor->recordData.filteringData.age = 0;
 389    }
 390    else
 391    {
 392        descriptor->recordData.filteringVlanData.age = 0;
 393    }
 394
 395    ixEthDBReleaseHashNode(searchResult);
 396
 397    return IX_ETH_DB_SUCCESS;
 398}
 399
 400IX_ETH_DB_PUBLIC
 401IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap)
 402{
 403    IX_ETH_DB_CHECK_PORT(portID);
 404    
 405    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
 406    
 407    IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap);
 408    
 409    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
 410
 411    /* force bit at offset 255 to 0 (reserved) */
 412    dependencyPortMap[31] &= 0xFE;
 413
 414    COPY_DEPENDENCY_MAP(ixEthDBPortInfo[portID].dependencyPortMap, dependencyPortMap);
 415
 416    return IX_ETH_DB_SUCCESS;
 417}
 418
 419IX_ETH_DB_PUBLIC
 420IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap)
 421{
 422    IX_ETH_DB_CHECK_PORT(portID);
 423    
 424    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
 425    
 426    IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap);
 427    
 428    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
 429
 430    COPY_DEPENDENCY_MAP(dependencyPortMap, ixEthDBPortInfo[portID].dependencyPortMap);
 431
 432    return IX_ETH_DB_SUCCESS;
 433}
 434
 435IX_ETH_DB_PUBLIC
 436IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate)
 437{
 438    IX_ETH_DB_CHECK_PORT(portID);
 439
 440    IX_ETH_DB_CHECK_SINGLE_NPE(portID);    
 441
 442    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING);
 443
 444    ixEthDBPortInfo[portID].updateMethod.updateEnabled  = enableUpdate;
 445    ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE;
 446
 447    return IX_ETH_DB_SUCCESS;
 448}
 449