| /** |
| * @file IxEthDBAPISupport.c |
| * |
| * @brief Public API support functions |
| * |
| * @par |
| * IXP400 SW Release version 2.0 |
| * |
| * -- Copyright Notice -- |
| * |
| * @par |
| * Copyright 2001-2005, Intel Corporation. |
| * All rights reserved. |
| * |
| * @par |
| * SPDX-License-Identifier: BSD-3-Clause |
| * @par |
| * -- End of Copyright Notice -- |
| */ |
| |
| #include <IxEthDB.h> |
| #include <IxNpeMh.h> |
| #include <IxFeatureCtrl.h> |
| |
| #include "IxEthDB_p.h" |
| #include "IxEthDBMessages_p.h" |
| #include "IxEthDB_p.h" |
| #include "IxEthDBLog_p.h" |
| |
| #ifdef IX_UNIT_TEST |
| |
| int dbAccessCounter = 0; |
| int overflowEvent = 0; |
| |
| #endif |
| |
| /* |
| * External declaration |
| */ |
| extern HashTable dbHashtable; |
| |
| /* |
| * Internal declaration |
| */ |
| IX_ETH_DB_PUBLIC |
| PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS]; |
| |
| IX_ETH_DB_PRIVATE |
| struct |
| { |
| BOOL saved; |
| IxEthDBPriorityTable priorityTable; |
| IxEthDBVlanSet vlanMembership; |
| IxEthDBVlanSet transmitTaggingInfo; |
| IxEthDBFrameFilter frameFilter; |
| IxEthDBTaggingAction taggingAction; |
| IxEthDBFirewallMode firewallMode; |
| BOOL stpBlocked; |
| BOOL srcAddressFilterEnabled; |
| UINT32 maxRxFrameSize; |
| UINT32 maxTxFrameSize; |
| } ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS]; |
| |
| #define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518) |
| |
| /** |
| * @brief initializes a port |
| * |
| * @param portID ID of the port to be initialized |
| * |
| * Note that redundant initializations are silently |
| * dealt with and do not constitute an error |
| * |
| * This function is fully documented in the main |
| * header file, IxEthDB.h |
| */ |
| IX_ETH_DB_PUBLIC |
| void ixEthDBPortInit(IxEthDBPortId portID) |
| { |
| PortInfo *portInfo; |
| |
| if (portID >= IX_ETH_DB_NUMBER_OF_PORTS) |
| { |
| return; |
| } |
| |
| portInfo = &ixEthDBPortInfo[portID]; |
| |
| if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS) |
| { |
| WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID); |
| |
| return; |
| } |
| |
| if (portInfo->initialized) |
| { |
| /* redundant */ |
| return; |
| } |
| |
| /* initialize core fields */ |
| portInfo->portID = portID; |
| SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID); |
| |
| /* default values */ |
| portInfo->agingEnabled = false; |
| portInfo->enabled = false; |
| portInfo->macAddressUploaded = false; |
| portInfo->maxRxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE; |
| portInfo->maxTxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE; |
| |
| /* default update control values */ |
| portInfo->updateMethod.searchTree = NULL; |
| portInfo->updateMethod.searchTreePendingWrite = false; |
| portInfo->updateMethod.treeInitialized = false; |
| portInfo->updateMethod.updateEnabled = false; |
| portInfo->updateMethod.userControlled = false; |
| |
| /* default WiFi parameters */ |
| memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid)); |
| portInfo->frameControlDurationID = 0; |
| |
| /* Ethernet NPE-specific initializations */ |
| if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) |
| { |
| /* update handler */ |
| portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler; |
| } |
| |
| /* initialize state save */ |
| ixEthDBPortState[portID].saved = false; |
| |
| portInfo->initialized = true; |
| } |
| |
| /** |
| * @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 0 /* test-only */ |
| 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); |
| } |
| #endif |
| |
| 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; |
| } |
| |
| /** |
| * @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; |
| #if 0 /* test-only */ |
| IxEthDBPriorityTable classZeroTable; |
| #endif |
| |
| 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 */ |
| |
| #if 0 /* test-only */ |
| /* 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); |
| } |
| #endif |
| |
| /* 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; |
| } |
| |
| /** |
| * @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_ETH_DB_PORT_ID_TO_NPE(portID), message, result); |
| |
| return result; |
| } |
| |
| /** |
| * @brief sets the port maximum Rx frame size |
| * |
| * @param portID ID of the port to set the frame size on |
| * @param maximumRxFrameSize maximum Rx frame size |
| * |
| * This function updates the internal data structures and |
| * calls ixEthDBPortFrameLengthsUpdate() for NPE update. |
| * |
| * This function is fully documented in the main header |
| * file, IxEthDB.h. |
| * |
| * @return IX_ETH_DB_SUCCESS if the operation was |
| * successfull or an appropriate error message otherwise |
| */ |
| IX_ETH_DB_PUBLIC |
| IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize) |
| { |
| IX_ETH_DB_CHECK_PORT_EXISTS(portID); |
| |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); |
| |
| if (!ixEthDBPortInfo[portID].initialized) |
| { |
| return IX_ETH_DB_PORT_UNINITIALIZED; |
| } |
| |
| if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) |
| { |
| if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) || |
| (maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE)) |
| { |
| return IX_ETH_DB_INVALID_ARG; |
| } |
| } |
| else |
| { |
| return IX_ETH_DB_NO_PERMISSION; |
| } |
| |
| /* update internal structure */ |
| ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize; |
| |
| /* update the maximum frame size in the NPE */ |
| return ixEthDBPortFrameLengthsUpdate(portID); |
| } |
| |
| /** |
| * @brief sets the port maximum Tx frame size |
| * |
| * @param portID ID of the port to set the frame size on |
| * @param maximumTxFrameSize maximum Tx frame size |
| * |
| * This function updates the internal data structures and |
| * calls ixEthDBPortFrameLengthsUpdate() for NPE update. |
| * |
| * This function is fully documented in the main header |
| * file, IxEthDB.h. |
| * |
| * @return IX_ETH_DB_SUCCESS if the operation was |
| * successfull or an appropriate error message otherwise |
| */ |
| IX_ETH_DB_PUBLIC |
| IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize) |
| { |
| IX_ETH_DB_CHECK_PORT_EXISTS(portID); |
| |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); |
| |
| if (!ixEthDBPortInfo[portID].initialized) |
| { |
| return IX_ETH_DB_PORT_UNINITIALIZED; |
| } |
| |
| if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) |
| { |
| if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) || |
| (maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE)) |
| { |
| return IX_ETH_DB_INVALID_ARG; |
| } |
| } |
| else |
| { |
| return IX_ETH_DB_NO_PERMISSION; |
| } |
| |
| /* update internal structure */ |
| ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize; |
| |
| /* update the maximum frame size in the NPE */ |
| return ixEthDBPortFrameLengthsUpdate(portID); |
| } |
| |
| /** |
| * @brief sets the port maximum Tx and Rx frame sizes |
| * |
| * @param portID ID of the port to set the frame size on |
| * @param maximumFrameSize maximum Tx and Rx frame sizes |
| * |
| * This function updates the internal data structures and |
| * calls ixEthDBPortFrameLengthsUpdate() for NPE update. |
| * |
| * Note that both the maximum Tx and Rx frame size are set |
| * to the same value. This function is kept for compatibility |
| * reasons. |
| * |
| * This function is fully documented in the main header |
| * file, IxEthDB.h. |
| * |
| * @return IX_ETH_DB_SUCCESS if the operation was |
| * successfull or an appropriate error message otherwise |
| */ |
| IX_ETH_DB_PUBLIC |
| IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize) |
| { |
| IX_ETH_DB_CHECK_PORT_EXISTS(portID); |
| |
| IX_ETH_DB_CHECK_SINGLE_NPE(portID); |
| |
| if (!ixEthDBPortInfo[portID].initialized) |
| { |
| return IX_ETH_DB_PORT_UNINITIALIZED; |
| } |
| |
| if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) |
| { |
| if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) || |
| (maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE)) |
| { |
| return IX_ETH_DB_INVALID_ARG; |
| } |
| } |
| else |
| { |
| return IX_ETH_DB_NO_PERMISSION; |
| } |
| |
| /* update internal structure */ |
| ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize; |
| ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize; |
| |
| /* update the maximum frame size in the NPE */ |
| return ixEthDBPortFrameLengthsUpdate(portID); |
| } |
| |
| /** |
| * @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; |
| 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; |
| } |
| |
| /* 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_ETH_DB_PORT_ID_TO_NPE(portID), message, result); |
| |
| if (result == IX_SUCCESS) |
| { |
| ixEthDBPortInfo[portID].macAddressUploaded = true; |
| } |
| |
| return result; |
| } |