/** * @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; }
/* * Function definition: ixEthAccCodeletSwBridgeQoSStart() * * Configure QoS and Start bridge datapath */ IX_STATUS ixEthAccCodeletSwBridgeQoSStart(IxEthAccPortId firstPortId, IxEthAccPortId secondPortId) { UINT32 firstPortCbTag = firstPortId | (secondPortId << 16); UINT32 secondPortCbTag = secondPortId | (firstPortId << 16); IxEthDBPriorityTable priorityTable = { 0,1,2,3,4,5,6,7}; IxEthDBFeature featureSet = 0; if (firstPortId == secondPortId) { printf("SwBridgeQoS: Cannot configure a Bridge Operation between port %u and port %u (ports must be different)\n", firstPortId, secondPortId); return (IX_FAIL); } /* initialize pendingTx for both ports */ pendingTx[firstPortId] = pendingTx[secondPortId] = 0; /* register the rx/tx callback */ if ( ixEthAccCodeletPortConfigure(firstPortId, ixEthAccCodeletSwBridgeQoSTaggedToUntaggedRxCB, (IxEthAccPortMultiBufferRxCallback) NULL, ixEthAccCodeletSwBridgeQoSTxCB, firstPortCbTag) != IX_SUCCESS) { printf("SwBridgeQoS: Failed to configure the Bridge Operation for port %u\n", firstPortId); return (IX_FAIL); } if ( ixEthAccCodeletPortConfigure(secondPortId, ixEthAccCodeletSwBridgeQoSUntaggedToTaggedRxCB, NULL, ixEthAccCodeletSwBridgeQoSTxCB, secondPortCbTag) != IX_SUCCESS) { printf("SwBridgeQoS: Failed to configure the Bridge Operation for port %u\n", secondPortId); return (IX_FAIL); } /* Enable the VLAN/QoS Feature in EthDB for each port but first * check that the Firmware downloaded to the NPE can support it */ ixEthDBFeatureCapabilityGet((IxEthDBPortId)firstPortId, &featureSet); if ((featureSet & IX_ETH_DB_VLAN_QOS) == 0) { printf("SwBridgeQoS: Port %u NPE image not VLAN/QoS capable\n", firstPortId); return (IX_FAIL); } if ( ixEthDBFeatureEnable((IxEthDBPortId)firstPortId, IX_ETH_DB_VLAN_QOS, TRUE) != IX_ETH_DB_SUCCESS ) { printf("SwBridgeQoS: Failed to enable VLAN/QoS on port %u\n", firstPortId); return (IX_FAIL); } /* Enable the EthDB Port in order to configure and download the * VLAN/QoS configuration information */ if ((ixEthDBPortEnable(firstPortId)) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQoS: Cannot enable port %u\n", firstPortId); return (IX_FAIL); } if ((ixEthDBPortEnable(secondPortId)) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Cannot enable port %u\n", secondPortId); return (IX_FAIL); } /* Configure Xscale QoS : the access layer datapath * prioritizes the different classes of traffic. */ printf("Set Tx Scheduling discipline...\n"); if (ixEthAccTxSchedulingDisciplineSet(firstPortId, FIFO_PRIORITY) != IX_ETH_ACC_SUCCESS) { printf("SwBridgeQos: Failed to set Tx Scheduling for discipline port %u\n", (UINT32)firstPortId); return (IX_FAIL); } if (ixEthAccTxSchedulingDisciplineSet(secondPortId, FIFO_PRIORITY) != IX_ETH_ACC_SUCCESS) { printf("SwBridgeQos: Failed to set Tx Scheduling for discipline port %u\n", (UINT32)secondPortId); return (IX_FAIL); } printf("Set Rx Scheduling discipline...\n"); if (ixEthAccRxSchedulingDisciplineSet(FIFO_PRIORITY) != IX_ETH_ACC_SUCCESS) { printf("SwBridgeQos: Failed to set Rx Scheduling discipline!\n"); return (IX_FAIL); } /* NPE QoS : Configure VLAN traffic for highest priority * on first port. Tagging is enabled on Egress (use default tag * for this port) and untagging is enabled on ingress. * The traffic running on this bridge will be untagged. */ printf("Set VLAN default tag...\n"); if (ixEthDBPortVlanTagSet(firstPortId, IX_ETHACC_CODELET_VLANID_DEFAULT) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to set the default VLAN ID for port %u\n", firstPortId); return (IX_FAIL); } printf("Enable tagged frames...\n"); if (ixEthDBAcceptableFrameTypeSet(firstPortId, IX_ETH_DB_VLAN_TAGGED_FRAMES | IX_ETH_DB_UNTAGGED_FRAMES) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to set the acceptable frame type for port %u\n", firstPortId); return (IX_FAIL); } printf("Setting VLAN membership...\n"); /* by default the entire VLAN range 0-4094 is included in the port VLAN membership table, therefore we need to remove all VLAN IDs but 0 (which is required to accept untagged frames) */ if (ixEthDBPortVlanMembershipRangeRemove(firstPortId, 1, IX_ETH_DB_802_1Q_MAX_VLAN_ID) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to set VLAN membership for port %u\n", firstPortId); return (IX_FAIL); } /* now add the range used by this codelet */ if (ixEthDBPortVlanMembershipRangeAdd(firstPortId, IX_ETHACC_CODELET_VLANID_MIN, IX_ETHACC_CODELET_VLANID_MAX) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to set VLAN membership for port %u\n", firstPortId); return (IX_FAIL); } printf("Enable Egress VLAN tagging...\n"); if (ixEthDBEgressVlanRangeTaggingEnabledSet(firstPortId, IX_ETHACC_CODELET_VLANID_MIN, IX_ETHACC_CODELET_VLANID_MAX, TRUE) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to enable VLAN Egress tagging for port %u\n", firstPortId); return (IX_FAIL); } printf("Enable Ingress VLAN untagging...\n"); if (ixEthDBIngressVlanTaggingEnabledSet(firstPortId, IX_ETH_DB_REMOVE_TAG) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to enable VLAN Ingress untagging for port %u\n", firstPortId); return (IX_FAIL); } printf("Setup priority mapping table...\n"); if (ixEthDBPriorityMappingTableSet(firstPortId, priorityTable) != IX_ETH_DB_SUCCESS) { printf("SwBridgeQos: Failed to set the priority mapping Table for port %u\n", firstPortId); return (IX_FAIL); } /* Configure 10 mb/s on second port to create a * traffic congestion on the bridge : the high * priority traffic should pass, the low priority * traffic should starve. */ if (ixEthAccCodeletLinkSlowSpeedSet(secondPortId) != IX_SUCCESS) { printf("SwBridgeQos: Failed to set port %u to 10 Mbit\n", secondPortId); return (IX_FAIL); } /* Allow RX and TX traffic to run */ if ( ixEthAccPortEnable(firstPortId) != IX_SUCCESS) { printf("SwBridgeQos: Failed to start the Bridge Operation for port %u\n", firstPortId); return (IX_FAIL); } if ( ixEthAccPortEnable(secondPortId) != IX_SUCCESS) { printf("SwBridgeQos: Failed to start the Bridge Operation for port %u\n", secondPortId); return (IX_FAIL); } /* display the default settings for both ports */ printf("Port %u configuration:\n", (UINT32)firstPortId); printf("- Accept Ingress VLAN-tagged traffic, VLAN tag range is [%u-%u]\n", (UINT32)IX_ETHACC_CODELET_VLANID_MIN, (UINT32)IX_ETHACC_CODELET_VLANID_MAX); printf("- Strip tag from ingress traffic\n"); printf("- Bridge Ingress to port %u without tag\n", (UINT32)secondPortId); printf("- Frame priorities may change the frame order (QoS enabled)\n"); printf("- Insert a default tag [%u] to egress traffic\n", (UINT32)IX_ETHACC_CODELET_VLANID_DEFAULT); printf("Port %u configuration:\n", (UINT32)secondPortId); printf("- Set as default\n\n"); return (IX_SUCCESS); }