예제 #1
0
/**
 * @brief queries the database for a set of records to be inserted into a given tree
 *
 * @param searchTree pointer to a tree where insertions will be performed; can be NULL
 * @param query set of ports that a database record must match to be inserted into the tree
 *
 * The query method browses through the database, extracts all the descriptors matching
 * the given query parameter and inserts them into the given learning tree.
 * Note that this is an append procedure, the given tree needs not to be empty.
 * A "descriptor matching the query" is a descriptor whose port id is in the query map.
 * If the given tree is empty (NULL) a new tree is created and returned.
 * 
 * @return the tree root
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
MacTreeNode* ixEthDBQuery(MacTreeNode *searchTree, IxEthDBPortMap query, IxEthDBRecordType recordFilter, UINT32 maxEntries)
{
    HashIterator iterator;
    UINT32 entryCount = 0;

    /* browse database */
    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));

    while (IS_ITERATOR_VALID(&iterator))
    {
        MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;

        IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) querying [%s]:%d on port map ... ", 
            mac2string(descriptor->macAddress), 
            descriptor->portID);

	if ((descriptor->type & recordFilter) != 0 
            && IS_PORT_INCLUDED(descriptor->portID, query))
	{
            MacDescriptor *descriptorClone = ixEthDBCloneMacDescriptor(descriptor);

            IX_ETH_DB_UPDATE_TRACE("match\n");

            if (descriptorClone != NULL)
            {
                /* add descriptor to tree */
                searchTree = ixEthDBTreeInsert(searchTree, descriptorClone);

                entryCount++;
            }
        }
        else
        {
            IX_ETH_DB_UPDATE_TRACE("no match\n");
        }

        if (entryCount < maxEntries)
        {
            /* advance to the next record */
	        BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
        }
        else
        {
            /* the NPE won't accept more entries so we can stop now */
            ixEthDBReleaseHashIterator(&iterator);

            IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) number of elements reached maximum supported by port\n");

            break;
        }
    }

    IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) query inserted %d records in the search tree\n", entryCount);

    return ixEthDBTreeRebalance(searchTree);
}
예제 #2
0
파일: IxEthDBAPI.c 프로젝트: cilynx/dd-wrt
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;
}
예제 #3
0
/**
 * @brief disables a port
 *
 * @param portID ID of the port to disable
 *
 * This function is fully documented in the
 * main header file, IxEthDB.h
 *
 * @return IX_ETH_DB_SUCCESS if disabling was
 * successful or an appropriate error message 
 * otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
{
    HashIterator iterator;
    IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
    BOOL result;
    PortInfo *portInfo;
    IxEthDBFeature learningEnabled;
    IxEthDBPriorityTable classZeroTable;

    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    portInfo = &ixEthDBPortInfo[portID];

    if (!portInfo->enabled)
    {
        /* redundant */
        return IX_ETH_DB_SUCCESS;
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        /* save filtering state */
        ixEthDBPortState[portID].firewallMode            = portInfo->firewallMode;
        ixEthDBPortState[portID].frameFilter             = portInfo->frameFilter;
        ixEthDBPortState[portID].taggingAction           = portInfo->taggingAction;
        ixEthDBPortState[portID].stpBlocked              = portInfo->stpBlocked;
        ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
        ixEthDBPortState[portID].maxRxFrameSize          = portInfo->maxRxFrameSize;
        ixEthDBPortState[portID].maxTxFrameSize          = portInfo->maxTxFrameSize;

        memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
        memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
        memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));

        ixEthDBPortState[portID].saved = TRUE;

        /* now turn off all EthDB filtering features on the port */

        /* VLAN & QoS */
        if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
        {
            ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
            ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, FALSE);
            ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
            ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);

            memset(classZeroTable, 0, sizeof (classZeroTable));
            ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
        }

        /* STP */
        if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
        {
            ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, FALSE);
        }

        /* Firewall */
        if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
        {
            ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
            ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
            ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, FALSE);
        }

        /* Frame size filter */
        ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);

        /* WiFi */
        if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
        {
            ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
        }

        /* save and disable the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
        portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
    }
    else
    {
        /* save the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
    }
    
    SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
    
    ixEthDBUpdateLock();
    
    /* wipe out current entries for this port */
    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));

    while (IS_ITERATOR_VALID(&iterator))
    {
        MacDescriptor *descriptor =  (MacDescriptor *) iterator.node->data;
    
        /* check if the port match. If so, remove the entry  */
        if (descriptor->portID == portID 
                && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
                && !descriptor->recordData.filteringData.staticEntry)
        {
            /* delete entry */
            BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
            
            /* add port to the set of update trigger ports */
            JOIN_PORT_TO_MAP(triggerPorts, portID);
        }
        else
        {
            /* move to the next record */
            BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
        }
    }
    
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (portInfo->updateMethod.searchTree != NULL)
        {
            ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
            portInfo->updateMethod.searchTree = NULL;
        }

        ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
    }

    /* mark as disabled */
    portInfo->enabled = FALSE;
    
    /* disable updates unless the user has specifically altered the default behavior */
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (!portInfo->updateMethod.userControlled)
        {  
            portInfo->updateMethod.updateEnabled = FALSE;
        }
            
        /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
        portInfo->updateMethod.treeInitialized = FALSE;
    }

    ixEthDBUpdateUnlock();

    /* restore learning feature bit */
    portInfo->featureStatus |= learningEnabled;

    /* if we've removed any records or lost any events make sure to force an update */
    IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);

    if (!result)
    {
        ixEthDBUpdatePortLearningTrees(triggerPorts);
    }
    
    return IX_ETH_DB_SUCCESS;
}
예제 #4
0
파일: IxEthDBAPI.c 프로젝트: cilynx/dd-wrt
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 displays all the filtering records belonging to a port
 *
 * @param portID ID of the port to display
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @warning deprecated, use @ref ixEthDBFilteringDatabaseShowRecords() 
 * instead. Calling this function is equivalent to calling
 * ixEthDBFilteringDatabaseShowRecords(portID, IX_ETH_DB_FILTERING_RECORD)
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBFilteringDatabaseShow(IxEthDBPortId portID)
{
    IxEthDBStatus local_result;
    HashIterator iterator;
    PortInfo *portInfo;
    UINT32 recordCount = 0;

    IX_ETH_DB_CHECK_PORT(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    portInfo = &ixEthDBPortInfo[portID];

    /* display table header */
    printf("Ethernet database records for port ID [%d]\n", portID);
    
    ixEthDBDependencyPortMapShow(portID, portInfo->dependencyPortMap);
    
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        printf("NPE updates are %s\n\n", portInfo->updateMethod.updateEnabled ? "enabled" : "disabled");
    }
    else
    {
        printf("updates disabled (not an NPE)\n\n");
    }

    printf("    MAC address    |   Age  | Type \n");
    printf("___________________________________\n");

    /* browse database */
    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));

    while (IS_ITERATOR_VALID(&iterator))
    {
      MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data;

      if (descriptor->portID == portID && descriptor->type == IX_ETH_DB_FILTERING_RECORD)
      {
          recordCount++;

          /* display entry */
          printf(" %02X:%02X:%02X:%02X:%02X:%02X | %5d  | %s\n",
              descriptor->macAddress[0],
              descriptor->macAddress[1],
              descriptor->macAddress[2],
              descriptor->macAddress[3],
              descriptor->macAddress[4],
              descriptor->macAddress[5],
              descriptor->recordData.filteringData.age,
              descriptor->recordData.filteringData.staticEntry ? "static" : "dynamic");
      }

      /* move to the next record */
      BUSY_RETRY_WITH_RESULT(ixEthDBIncrementHashIterator(&dbHashtable, &iterator), local_result);

      /* debug */
      if (local_result == IX_ETH_DB_BUSY)
      {
          return IX_ETH_DB_FAIL;
      }
    }

    /* display number of records */
    printf("\nFound %d records\n", recordCount);

    return IX_ETH_DB_SUCCESS;
}