/** * @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; }
/** * @brief enables a port * * @param portID ID of the port to enable * * This function is fully documented in the main * header file, IxEthDB.h * * @return IX_ETH_DB_SUCCESS if enabling was * accomplished, or a meaningful error message otherwise */ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) { IxEthDBPortMap triggerPorts; PortInfo *portInfo; 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; } SET_DEPENDENCY_MAP(triggerPorts, portID); /* mark as enabled */ portInfo->enabled = TRUE; /* 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; } if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded) { IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID); /* must use UnicastAddressSet() before enabling an NPE port */ return IX_ETH_DB_MAC_UNINITIALIZED; } if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID); if (!portInfo->updateMethod.userControlled && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)) { portInfo->updateMethod.updateEnabled = TRUE; } /* if this is first time initialization then we already have write access to the tree and can AccessRelease directly */ if (!portInfo->updateMethod.treeInitialized) { IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID); /* create an initial tree and release access into it */ ixEthDBUpdatePortLearningTrees(triggerPorts); /* mark tree as being initialized */ portInfo->updateMethod.treeInitialized = TRUE; } } if (ixEthDBPortState[portID].saved) { /* previous configuration data stored, restore state */ if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0) { ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode); ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled); } if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) { ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter); ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction); ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo); ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership); ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable); } if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0) { ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked); } ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize); ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize); /* discard previous save */ ixEthDBPortState[portID].saved = FALSE; } IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID); return IX_ETH_DB_SUCCESS; }
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); } }