/**
 * @brief sends the updated maximum Tx/Rx frame lengths to the NPE
 *
 * @param portID ID of the port to update
 *
 * @return IX_ETH_DB_SUCCESS if the update completed
 * successfully or an appropriate error message otherwise
 * 
 * @internal
 */
IX_ETH_DB_PRIVATE
IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
{
    IxNpeMhMessage message;
    PortInfo *portInfo = &ixEthDBPortInfo[portID];
    IX_STATUS result;
    
    FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);

    IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID), message, result);
    
    return result;
}
/**
 * @brief sets the MAC address of an NPE port
 *
 * @param portID port ID to set the MAC address on
 * @param macAddr pointer to the 6-byte MAC address
 *
 * This function is called by the EthAcc 
 * ixEthAccUnicastMacAddressSet() and should not be
 * manually invoked unless required by special circumstances.
 *
 * @return IX_ETH_DB_SUCCESS if the operation succeeded
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
{
    IxNpeMhMessage message;
    IxOsalMutex *ackPortAddressLock;
    IX_STATUS result;

    /* use this macro instead CHECK_PORT
       as the port doesn't need to be enabled */
    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_REFERENCE(macAddr);

    if (!ixEthDBPortInfo[portID].initialized)
    {
        return IX_ETH_DB_PORT_UNINITIALIZED;
    }

    ackPortAddressLock = &ixEthDBPortInfo[portID].npeAckLock;

    /* Operation stops here when Ethernet Learning is not enabled */
    if(IX_FEATURE_CTRL_SWCONFIG_DISABLED == 
       ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING)) 
    {
        return IX_ETH_DB_SUCCESS;
    }

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    /* exit if the port is not an Ethernet NPE */
    if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
    {
        return IX_ETH_DB_INVALID_PORT;
    }

    /* populate message */
    FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);
    
    IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);

    /* send a SetPortAddress message */
    IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID), message, result);

    if (result == IX_SUCCESS)
    {
        ixEthDBPortInfo[portID].macAddressUploaded = TRUE;
    }

    return result;
}
Exemple #3
0
/**
 * @brief sets the STP blocking state of a port
 *
 * @param portID ID of the port
 * @param blocked TRUE to block the port or FALSE to unblock it
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBSpanningTreeBlockingStateSet(IxEthDBPortId portID, BOOL blocked)
{
    IxNpeMhMessage message;
    IX_STATUS result;

    IX_ETH_DB_CHECK_PORT(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_SPANNING_TREE_PROTOCOL);

    ixEthDBPortInfo[portID].stpBlocked = blocked;

    FILL_SETBLOCKINGSTATE_MSG(message, portID, blocked);

    IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID), message, result);

    return result;
}
Exemple #4
0
IX_ETH_DB_PUBLIC
void ixEthDBELTShow(IxEthDBPortId portID)
{
    IxNpeMhMessage message;
    IX_STATUS result;
    
    /* send EDB_GetMACAddressDatabase message */
    FILL_GETMACADDRESSDATABASE(message, 
        0 /* reserved */, 
        IX_OSAL_MMU_VIRT_TO_PHYS(ixEthDBPortInfo[portID].updateMethod.npeUpdateZone));

    IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID), message, result);

    if (result == IX_SUCCESS)
    {
        /* analyze NPE copy */
        UINT32 eltEntryOffset;
        UINT32 entryPortID;

        UINT32 eltBaseAddress = (UINT32) ixEthDBPortInfo[portID].updateMethod.npeUpdateZone;
        UINT32 eltSize        = FULL_ELT_BYTE_SIZE;

        /* invalidate cache */
        IX_OSAL_CACHE_INVALIDATE((void *) eltBaseAddress, eltSize);

        printf("Listing records in main learning tree for port %d\n", portID);

        for (eltEntryOffset = ELT_ROOT_OFFSET ; eltEntryOffset < eltSize ; eltEntryOffset += ELT_ENTRY_SIZE)
        {
            /* (eltBaseAddress + eltEntryOffset) points to a valid NPE tree node
            *
            * the format of the node is MAC[6 bytes]:PortID[1 byte]:Reserved[6 bits]:Active[1 bit]:Valid[1 bit]
            * therefore we can just use the pointer for database searches as only the first 6 bytes are checked
            */
            void *eltNodeAddress = (void *) ((UINT32) eltBaseAddress + eltEntryOffset);

            if (IX_EDB_NPE_NODE_VALID(eltNodeAddress))
            {
                HashNode *node;

                entryPortID = IX_ETHNPE_LOGICAL_ID_TO_PHYSICAL_ID(IX_EDB_NPE_NODE_PORT_ID(eltNodeAddress));

                /* search record */
                node = ixEthDBSearch((IxEthDBMacAddr *) eltNodeAddress, IX_ETH_DB_ALL_RECORD_TYPES);

                printf("%s - port %d - %s ", mac2string((unsigned char *) eltNodeAddress), entryPortID, 
                    IX_EDB_NPE_NODE_ACTIVE(eltNodeAddress) ? "active" : "inactive");

                /* safety check, maybe user deleted record right before sync? */
                if (node != NULL)
                {
                    /* found record */
                    MacDescriptor *descriptor = (MacDescriptor *) node->data;

                    printf("- %s ",
                        descriptor->type == IX_ETH_DB_FILTERING_RECORD ? "filtering" :
                        descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD ? "vlan" :
                        descriptor->type == IX_ETH_DB_WIFI_RECORD ? "wifi" : "other (check main DB)");

                    if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) printf("- age %d - %s ", 
                        descriptor->recordData.filteringData.age,
                        descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");

                    if (descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) printf("- age %d - %s - tci %d ",
                        descriptor->recordData.filteringVlanData.age,
                        descriptor->recordData.filteringVlanData.staticEntry ? "static" : "dynamic",
                        descriptor->recordData.filteringVlanData.ieee802_1qTag);

                    /* end transaction */
                    ixEthDBReleaseHashNode(node);
                }
                else
                {
                    printf("- not synced");
                }

                printf("\n");
            }
        }
    }
    else
    {
        ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT, 
            "EthDB: (ShowELT) Could not complete action (communication failure)\n",
            portID, 0, 0, 0, 0, 0);
    }
}
Exemple #5
0
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBSingleEthNpeCheck(IxEthDBPortId portID)
{
    UINT8 functionalityId;

    IxEthNpeNodeId npeId = IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID);

    if (IX_SUCCESS != ixNpeDlLoadedImageFunctionalityGet(npeId, &functionalityId))
    {
        return IX_ETH_DB_FAIL;
    }
    else
    {

        /* If not IXP42X A0 stepping, proceed to check for existence of NPEs and ethernet coprocessors */
        if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
                (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
                || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
        {
            switch(npeId)
            {
            case IX_NPEDL_NPEID_NPEA:
                if ((ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA) ==
                        IX_FEATURE_CTRL_COMPONENT_DISABLED) ||
                        ((ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
                          IX_FEATURE_CTRL_COMPONENT_DISABLED) ||
                         (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
                          IX_FEATURE_CTRL_COMPONENT_DISABLED)))
                {
                    return IX_ETH_DB_FAIL;
                }
                break;

            case IX_NPEDL_NPEID_NPEB:
                if ( (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB) ==
                        IX_FEATURE_CTRL_COMPONENT_DISABLED) )
                {
                    return IX_ETH_DB_FAIL;
                }
                if (portID == 0)
                {
                    if( ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
                            IX_FEATURE_CTRL_COMPONENT_DISABLED)
                    {
                        return IX_ETH_DB_FAIL;
                    }
                }
                else /* ports 1-3 */
                {
                    if( ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEB_ETH) ==
                            IX_FEATURE_CTRL_COMPONENT_DISABLED)
                    {
                        return IX_ETH_DB_FAIL;
                    }

                }
                break;

            case IX_NPEDL_NPEID_NPEC:
                if ((ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEC) ==
                        IX_FEATURE_CTRL_COMPONENT_DISABLED) ||
                        ((ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
                          IX_FEATURE_CTRL_COMPONENT_DISABLED) ||
                         (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
                          IX_FEATURE_CTRL_COMPONENT_DISABLED)))
                {
                    return IX_ETH_DB_FAIL;
                }
                break;

            default: /* invalid NPE */
                return IX_ETH_DB_FAIL;
            }
        }

        return IX_ETH_DB_SUCCESS;
    }
}
Exemple #6
0
/**
 * @brief scans the capabilities of the loaded NPE images
 *
 * This function MUST be called by the ixEthDBInit() function.
 * No EthDB features (including learning and filtering) are enabled
 * before this function is called.
 *
 * @return none
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBFeatureCapabilityScan(void)
{
    UINT8 functionalityId, npeAFunctionalityId;
    IxEthDBPortId portIndex;
    PortInfo *portInfo;
    IxEthDBPriorityTable defaultPriorityTable;
    IX_STATUS result;
    UINT32 queueIndex;
    UINT32 queueStructureIndex;
    UINT32 trafficClassDefinitionIndex, totalTrafficClass;

    totalTrafficClass = sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]);

    /* ensure there's at least 2 traffic class records in the definition table, otherwise we have no default cases, hence no queues */
    IX_ENSURE(totalTrafficClass >= 2, 
	"DB: no traffic class definitions found, check IxEthDBQoS.h");

    /* read version of NPE A - required to set the AQM queues for B and C */
    npeAFunctionalityId = 0;

    if(IX_FAIL == ixNpeDlLoadedImageFunctionalityGet(IX_NPEDL_NPEID_NPEA, &npeAFunctionalityId))
    {
        /* IX_FAIL is returned when there is no image loaded in NPEA.  Then we can use all 8 queues */
        trafficClassDefinitionIndex = 1; /* the second record is the default if no image loaded */
    } 
    else 
    {
        /* find the traffic class definition index compatible with the current NPE A functionality ID */
        for (trafficClassDefinitionIndex = 0 ; 
             trafficClassDefinitionIndex < totalTrafficClass ;
             trafficClassDefinitionIndex++)
        {
            if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAFunctionalityId)
            {
                /* found it */
                break;
            }
        }

        /* select the default case if we went over the array boundary */
        if (trafficClassDefinitionIndex == totalTrafficClass)
        {
            trafficClassDefinitionIndex = 0; /* the first record is the default case */
        }
    }

    /* To decide port definition for NPE A - IX_ETH_NPE or IX_ETH_GENERIC 
       IX_ETH_NPE will be set for NPE A when the functionality id is ranged from 0x80 to 0x8F
       and ethernet + hss co-exists images range from 0x90 to 0x9F. For the rest of functionality 
       Ids, the port type will be set to IX_ETH_GENERIC. */
    if ((npeAFunctionalityId & 0xF0) != 0x80 && (npeAFunctionalityId & 0xF0) != 0x90)
    {
        /* NPEA is not Ethernet capable. Override default port definition */
	ixEthDBPortDefinitions[IX_NPEA_PORT].type = IX_ETH_GENERIC;
    }

    /* select queue assignment structure based on the traffic class configuration index */
    queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX];

    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
    {
        IxNpeMhMessage msg;

        portInfo = &ixEthDBPortInfo[portIndex];

        /* check and bypass if NPE A, B or C is fused out */
        if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue;
        
        /* all ports are capable of LEARNING by default */
        portInfo->featureCapability = IX_ETH_DB_LEARNING;
        portInfo->featureStatus     = IX_ETH_DB_LEARNING;

        if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
        {

            if (IX_SUCCESS != ixNpeDlLoadedImageFunctionalityGet(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), &functionalityId))
            {
                WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex);
            }
            else
            {
                /* initialize and empty NPE response mutex */
                ixOsalMutexInit(&portInfo->npeAckLock);
		ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER);
                /* check NPE response to GetStatus */
                msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24;
                msg.data[1] = 0;
                IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), msg, result);
                if (result != IX_SUCCESS)
                {
                    WARNING_LOG("DB: (FeatureScan) warning, %d port could not send message to the NPE\n", portIndex);
                    continue;
                }

                if (functionalityId == 0x00
                    || functionalityId == 0x03
                    || functionalityId == 0x04
                    || functionalityId == 0x80)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                }
                else if (functionalityId == 0x01
                         || functionalityId == 0x81
                         || functionalityId == 0x0B
                         || functionalityId == 0x8B
                         || functionalityId == 0x90)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x02
                         || functionalityId == 0x82
                         || functionalityId == 0x0D
                         || functionalityId == 0x8D
                         || functionalityId == 0x91)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x0C
			 || functionalityId == 0x8C)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }

                /* check if image supports mask based firewall */
                if (functionalityId == 0x0B
                    || functionalityId == 0x8B
                    || functionalityId == 0x0D
                    || functionalityId == 0x8D
                    || functionalityId == 0x90
                    || functionalityId == 0x91)
                {
                    /* this feature is always on and is based on the NPE */
                    portInfo->featureStatus |= IX_ETH_DB_ADDRESS_MASKING;
                    portInfo->featureCapability |= IX_ETH_DB_ADDRESS_MASKING;
                }

                /* reset AQM queues */
                ixOsalMemSet(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments));

                /* only traffic class 0 is active at initialization time */
                portInfo->ixEthDBTrafficClassCount = 1;

                /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */
                portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus |= IX_ETH_DB_FIREWALL;
                portInfo->enabled        = TRUE;

                /* set VLAN initial configuration (permissive) */
                if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */
                {
                    /* QoS capable */
                    portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX];

                    /* set AQM queues */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex];
                    }

                    /* set default PVID (0) and default traffic class 0 */
                    ixEthDBPortVlanTagSet(portIndex, 0);

                    /* enable reception of all frames */
                    ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES);

                    /* clear full VLAN membership */
                    ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);

                    /* clear TTI table - no VLAN tagged frames will be transmitted */
                    ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE);

                    /* set membership on 0, otherwise no Tx or Rx is working */
                    ixEthDBPortVlanMembershipAdd(portIndex, 0);
                }
                else /* QoS not available in this image */
                {
                    /* initialize traffic class availability (only class 0 is available) */
                    portInfo->ixEthDBTrafficClassAvailable = 1;

                    /* point all AQM queues to traffic class 0 */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = 
                            ixEthDBQueueAssignments[queueStructureIndex][0];
                    }
                }

                /* download priority mapping table and Rx queue configuration */
                ixOsalMemSet (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
                ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable);

                /* by default we turn on invalid source MAC address filtering */
                ixEthDBFirewallInvalidAddressFilterEnable(portIndex, TRUE);

                /* Notify VLAN tagging is disabled */
		if (ixEthDBIngressVlanTaggingEnabledSet(portIndex, IX_ETH_DB_DISABLE_VLAN)
		    != IX_SUCCESS)
		{
		  WARNING_LOG("DB: (FeatureScan) warning, %d port could not disable VLAN \n", portIndex);
		  continue;		  
		}

                /* disable port, VLAN, Firewall feature bits */
                portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL;
                portInfo->enabled        = FALSE;

                /* enable filtering by default if present */
                if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)
                {
                    portInfo->featureStatus |= IX_ETH_DB_FILTERING;
                }
            }
        } 
    }
}
Exemple #7
0
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_ETHNPE_PHYSICAL_ID_TO_NODE(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
                {
                     ixOsalLog(IX_OSAL_LOG_LVL_WARNING,
                        IX_OSAL_LOG_DEV_STDOUT, 
                        "EthDB: (Maintenance) warning, Clearing Database records for all types for port %d\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);
    }
}
/**
 * @brief standard NPE update handler
 *
 * @param portID id of the port to be updated
 * @param type record type to be pushed during this update
 *
 * The NPE update handler manages updating the NPE databases
 * given a certain record type.
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBNPEUpdateHandler(IxEthDBPortId portID, IxEthDBRecordType type)
{
    UINT32 epDelta, blockCount;
    IxNpeMhMessage message;
    UINT32 treeSize = 0;
    PortInfo *port = &ixEthDBPortInfo[portID];

    /* size selection and type check */
    if (type == IX_ETH_DB_FILTERING_RECORD || type == IX_ETH_DB_WIFI_RECORD)
    {
        treeSize = FULL_ELT_BYTE_SIZE;
    }
    else if (type == IX_ETH_DB_FIREWALL_RECORD)
    {
        treeSize = FULL_FW_BYTE_SIZE;
    }
    else if (type == IX_ETH_DB_MASKED_FIREWALL_RECORD)
    {
        treeSize = FULL_FW_M_BYTE_SIZE;
    }
    else
    {
        return IX_ETH_DB_INVALID_ARG;
    }
    
    /* serialize tree into memory */
    ixEthDBNPETreeWrite(type, treeSize, port->updateMethod.npeUpdateZone, port->updateMethod.searchTree, &epDelta, &blockCount);

    /* free internal copy */
    if (port->updateMethod.searchTree != NULL)
    {
        ixEthDBFreeMacTreeNode(port->updateMethod.searchTree);
    }

    /* forget last used search tree */
    port->updateMethod.searchTree             = NULL;
    port->updateMethod.searchTreePendingWrite = FALSE;

    /* dependending on the update type we do different things */
    if (type == IX_ETH_DB_FILTERING_RECORD || type == IX_ETH_DB_WIFI_RECORD)
    {
        IX_STATUS result;

        FILL_SETMACADDRESSDATABASE_MSG(message, IX_ETHNPE_PHYSICAL_ID_TO_NODE_LOGICAL_ID(portID), 
            epDelta, blockCount, 
            IX_OSAL_MMU_VIRT_TO_PHYS(port->updateMethod.npeUpdateZone));

        IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portID), message, result);

        if (result == IX_SUCCESS)
	{
            IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) Finished downloading NPE tree on port %d\n", portID);
        }
        else
        {
            ixEthDBPortInfo[portID].agingEnabled                = FALSE;
            ixEthDBPortInfo[portID].updateMethod.updateEnabled  = FALSE;
            ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE;

            ERROR_LOG("EthDB: (PortUpdate) disabling aging and updates on port %d (assumed dead)\n", portID);

            ixEthDBDatabaseClear(portID, IX_ETH_DB_ALL_RECORD_TYPES);

            return IX_ETH_DB_FAIL;
        }

	return IX_ETH_DB_SUCCESS;
    }
    else if (type & IX_ETH_DB_FIREWALL_RECORD)
    {
        return ixEthDBFirewallUpdate(portID, port->updateMethod.npeUpdateZone, epDelta);
    }
    
    return IX_ETH_DB_INVALID_ARG;
}