/** * @brief enables or disables a port capability * * @param portID ID of the port * @param feature feature to enable or disable * @param enabled TRUE to enable the selected feature or FALSE to disable 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 ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enable) { PortInfo *portInfo; IxEthDBPriorityTable defaultPriorityTable; IxEthDBVlanSet vlanSet; IxEthDBStatus status = IX_ETH_DB_SUCCESS; BOOL portEnabled; IX_ETH_DB_CHECK_PORT_INITIALIZED(portID); portInfo = &ixEthDBPortInfo[portID]; portEnabled = portInfo->enabled; /* check that only one feature is selected */ if (!ixEthDBCheckSingleBitValue(feature)) { return IX_ETH_DB_FEATURE_UNAVAILABLE; } /* port capable of this feature? */ if ((portInfo->featureCapability & feature) == 0) { return IX_ETH_DB_FEATURE_UNAVAILABLE; } /* mutual exclusion between learning and WiFi header conversion */ if (enable && ((feature | portInfo->featureStatus) & (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION)) == (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION)) { return IX_ETH_DB_NO_PERMISSION; } /* learning must be enabled before filtering */ if (enable && (feature == IX_ETH_DB_FILTERING) && ((portInfo->featureStatus & IX_ETH_DB_LEARNING) == 0)) { return IX_ETH_DB_NO_PERMISSION; } /* filtering must be disabled before learning */ if (!enable && (feature == IX_ETH_DB_LEARNING) && ((portInfo->featureStatus & IX_ETH_DB_FILTERING) != 0)) { return IX_ETH_DB_NO_PERMISSION; } /* redundant enabling or disabling */ if ((!enable && ((portInfo->featureStatus & feature) == 0)) || (enable && ((portInfo->featureStatus & feature) != 0))) { /* do nothing */ return IX_ETH_DB_SUCCESS; } /* force port enabled */ portInfo->enabled = TRUE; if (enable) { /* turn on enable bit */ portInfo->featureStatus |= feature; #ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ /* if this is VLAN/QoS set the default priority table */ if (feature == IX_ETH_DB_VLAN_QOS) { /* turn on VLAN/QoS (most permissive mode): - set default 802.1Q priority mapping table, in accordance to the availability of traffic classes - set the acceptable frame filter to accept all - set the Ingress tagging mode to pass-through - set full VLAN membership list - set full TTI table - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0) - enable TPID port extraction */ portInfo->ixEthDBTrafficClassCount = portInfo->ixEthDBTrafficClassAvailable; /* set default 802.1Q priority mapping table - note that C indexing starts from 0, so we substract 1 here */ memcpy (defaultPriorityTable, (const void *) ixEthIEEE802_1QUserPriorityToTrafficClassMapping[portInfo->ixEthDBTrafficClassCount - 1], sizeof (defaultPriorityTable)); /* update priority mapping and AQM queue assignments */ status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH); } /* set membership and TTI tables */ memset (vlanSet, 0xFF, sizeof (vlanSet)); if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet); } if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet); } /* reset the PVID */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBPortVlanTagSet(portID, 0); } /* enable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBVlanPortExtractionEnable(portID, TRUE); } } else if (feature == IX_ETH_DB_FIREWALL) #endif { /* firewall starts in black-list mode unless otherwise configured before * * note that invalid source MAC address filtering is disabled by default */ if (portInfo->firewallMode != IX_ETH_DB_FIREWALL_BLACK_LIST && portInfo->firewallMode != IX_ETH_DB_FIREWALL_WHITE_LIST) { status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); } } } if (status != IX_ETH_DB_SUCCESS) { /* checks failed, disable */ portInfo->featureStatus &= ~feature; } } else { /* turn off features */ if (feature == IX_ETH_DB_FIREWALL) { /* turning off the firewall is equivalent to: - set to black-list mode - clear all the entries and download the new table - turn off the invalid source address checking */ status = ixEthDBDatabaseClear(portID, IX_ETH_DB_FIREWALL_RECORD); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallTableDownload(portID); } } else if (feature == IX_ETH_DB_WIFI_HEADER_CONVERSION) { /* turn off header conversion */ status = ixEthDBDatabaseClear(portID, IX_ETH_DB_WIFI_RECORD); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBWiFiConversionTableDownload(portID); } } #ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ else if (feature == IX_ETH_DB_VLAN_QOS) { /* turn off VLAN/QoS: - set a priority mapping table with one traffic class - set the acceptable frame filter to accept all - set the Ingress tagging mode to pass-through - clear the VLAN membership list - clear the TTI table - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0) - disable TPID port extraction */ /* initialize all => traffic class 0 priority mapping table */ memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable)); portInfo->ixEthDBTrafficClassCount = 1; status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH); } /* clear membership and TTI tables */ memset (vlanSet, 0, sizeof (vlanSet)); if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet); } if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet); } /* reset the PVID */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBPortVlanTagSet(portID, 0); } /* disable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBVlanPortExtractionEnable(portID, FALSE); } } #endif if (status == IX_ETH_DB_SUCCESS) { /* checks passed, disable */ portInfo->featureStatus &= ~feature; } } /* restore port enabled state */ portInfo->enabled = portEnabled; return status; }
/** * @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; }
/** * @brief Restore the states of EthDB Features * * @param portID ID of the port * * See IxEthDB.h for more details. */ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBFeatureStatesRestore(IxEthDBPortId portID) { PortInfo *portInfo = &ixEthDBPortInfo[portID]; /* Check whether port if enabled */ IX_ETH_DB_CHECK_PORT_INITIALIZED(portID); IX_ETH_DB_CHECK_PORT(portID); /* ======================== Basic ========================== * Set up Port MAC Address */ if (ixEthDBPortAddressSet(portID, &(portInfo->macAddr)) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* * Set up Port Max Rx/Tx frame lengths */ if(ixEthDBPortFrameLengthsUpdate(portID) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* ======================== VLAN/QoS ========================== * Only performs VLAN feature update if it is enabled before */ if ((portInfo->featureStatus & IX_ETH_DB_VLAN_QOS) != 0) { /* Set VLAN Rx tag mode */ if (ixEthDBIngressVlanModeUpdate(portID) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* Set Default Rx VID */ if (ixEthDBPortVlanTagSet(portID, portInfo->vlanTag) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* Set PortID extraction mode */ if (ixEthDBVlanPortExtractionEnable(portID, portInfo->portIdExtractionEnable) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* Set VLAN Table */ if (ixEthDBVlanTableRangeUpdate(portID) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } } /* VLAN/QoS */ /* ======================== Firewall ========================== * Only performs Firewall feature update if it is enabled before */ if ((portInfo->featureStatus & IX_ETH_DB_FIREWALL) != 0) { if(ixEthDBFirewallTableDownload(portID) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } } /* Firewall */ /* ===================== Header Conversion ========================== * Only performs Header Conversion feature update if it is enabled before */ if ((portInfo->featureStatus & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0) { /* Update WiFi FC & DID */ if (ixEthDBWiFiFrameControlDurationIDUpdate(portID) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* Update BSSID */ if (ixEthDBWiFiBSSIDSet(portID, (IxEthDBMacAddr *) portInfo->bssid) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } /* Update Header Conversion Table & AP MAC Table */ if (ixEthDBWiFiConversionTableDownload(portID) != IX_ETH_DB_SUCCESS) { return IX_ETH_DB_FAIL; } } /* Header Conversion */ /* ====================== Learning & Filtering ========================== * Learning & Filtering feature update is not neccessary as we can rely * on EthNPE to learn the src address again. As for the entry added by client * earlier, it will be lost. This is the constraint as the mechanism to retrieve * the entry that has been added by client from NPE is not trivial. */ /* ============================== STP =================================== * Only performs STP feature update if it is enabled before */ if ((portInfo->featureStatus & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0) { if (ixEthDBSpanningTreeBlockingStateSet(portID, portInfo->stpBlocked) != IX_SUCCESS) { return IX_ETH_DB_FAIL; } } return IX_ETH_DB_SUCCESS; }