/* * Function definition: ixEthAccCodeletSwBridgeStart() * * Start bridge datapath */ IX_STATUS ixEthAccCodeletSwBridgeStart(IxEthAccPortId firstPortId, IxEthAccPortId secondPortId) { UINT32 firstPortCbTag = firstPortId | (secondPortId << 16); UINT32 secondPortCbTag = secondPortId | (firstPortId << 16); if (firstPortId == secondPortId) { printf("SwBridge: Cannot configure a bridge between Port %u and Port %u (ports must be different)\n", firstPortId, secondPortId); return (IX_FAIL); } /* Configure and register the traffic callbacks for both ports */ if ( ixEthAccCodeletPortConfigure(firstPortId, ixEthAccCodeletBridgeRxCB, (IxEthAccPortMultiBufferRxCallback) NULL, ixEthAccCodeletBridgeTxCB, firstPortCbTag) != IX_SUCCESS) { printf("SwBridge: Failed to configure Port %u\n", firstPortId); return (IX_FAIL); } if ( ixEthAccCodeletPortConfigure(secondPortId, ixEthAccCodeletBridgeRxCB, NULL, ixEthAccCodeletBridgeTxCB, secondPortCbTag) != IX_SUCCESS) { printf("SwBridge: Failed to configure Port %u\n", secondPortId); return (IX_FAIL); } /* Enable the traffic over both ports */ if ( ixEthAccPortEnable(firstPortId) != IX_SUCCESS) { printf("SwBridge: Failed to enable Port %u\n", firstPortId); return (IX_FAIL); } if ( ixEthAccPortEnable(secondPortId) != IX_SUCCESS) { printf("SwBridge: Failed to enable Port %u\n", secondPortId); return (IX_FAIL); } return (IX_SUCCESS); }
/* * Function definition: ixEthAccCodeletRxSinkStart() * * Start datapath traffic for RX Sink demo. */ IX_STATUS ixEthAccCodeletRxSinkStart(IxEthAccPortId portId) { if (ixEthAccCodeletPortConfigure(portId, NULL, ixEthAccCodeletRxSinkRxCB, ixEthAccCodeletMemPoolFreeTxCB, portId) != IX_ETH_ACC_SUCCESS) { printf("Loopbacks: Failed to configure the port %u\n", (UINT32)portId); return IX_FAIL; } /* ready to get traffic */ if(ixEthAccPortEnable(portId) != IX_ETH_ACC_SUCCESS) { printf("Loopbacks: Error enabling port %u\n", (UINT32)portId); return (IX_FAIL); } return (IX_SUCCESS); }
PRIVATE IX_STATUS ixEthAccCodeletTxGenRxSinkStart(IxEthAccPortId portId) { IX_OSAL_MBUF *mBufPtr; UINT32 numBufs; IxEthDBStatus status; /* port transmits as fast as possible and drops rx traffic */ if (ixEthAccCodeletPortConfigure(portId, NULL, ixEthAccCodeletRxSinkRxCB, ixEthAccCodeletTxGenTxCB, portId) != IX_ETH_ACC_SUCCESS) { printf("Loopbacks: Failed to start the Tx-Gen Rx-Sink Operation port %u\n", (UINT32)portId); return IX_FAIL; } /* Disable MAC learning and filtering at the port that sinks the frame. With learning enabled at both ports, TxGenRxSink will report buffer underrun and overruns as this mode generates a heavy load of MAC address migrations in the learning/filtering database. */ status = ixEthDBFeatureEnable (portId, IX_ETH_DB_FILTERING, FALSE); if (IX_ETH_DB_SUCCESS == status) { status = ixEthDBFeatureEnable (portId, IX_ETH_DB_LEARNING, FALSE); } if (IX_ETH_DB_SUCCESS == status) { printf("\nMAC learning & filtering are disabled at port %d\n", portId); printf("This is to prohibit the MAC address from being migrated back and forth\n"); printf("between two connected ports in the learning/filtering database.\n\n"); } else { printf("\nFailed to disable MAC learning & filtering at port %d.\n", portId); printf("TxGenRxSink will report buffer underrun and overruns as this mode generates \n"); printf("a heavy load of MAC address migrations in the learning/filtering database. \n"); printf("With learning enabled at both ports, buffer underrun and overruns are expected.\n"); } /* Generate our random data for the payload */ IX_ETHACC_CODELET_DATAGEN(compData); /* Now start the loopback by transmitting the first few frames */ for (numBufs=0; numBufs<IX_ETHACC_CODELET_TXGEN_PCKS; numBufs++) { IX_ETHACC_CODELET_REMOVE_MBUF_FROM_Q_HEAD(ixEthAccCodeletFreeBufQ, mBufPtr); if (mBufPtr == NULL) { printf("Loopbacks: Buffer queue empty. Not enough free buffers to transmit in TxGen-RxSink Loopback!\n"); return (IX_FAIL); } IX_OSAL_MBUF_MLEN(mBufPtr) = IX_ETHACC_CODELET_TXGEN_PCK_LEN; IX_OSAL_MBUF_PKT_LEN(mBufPtr) = IX_ETHACC_CODELET_TXGEN_PCK_LEN; memcpy(IX_OSAL_MBUF_MDATA(mBufPtr), &compData[0], IX_ETHACC_CODELET_TXGEN_PCK_LEN); IX_OSAL_CACHE_FLUSH(IX_OSAL_MBUF_MDATA(mBufPtr), IX_OSAL_MBUF_MLEN(mBufPtr)); if(ixEthAccPortTxFrameSubmit(portId, mBufPtr, IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS) { printf("Loopbacks: Error Submitting frame for transmission on port %u\n", portId); return (IX_FAIL); } } printf("Port %d Tx pool has %d buffers\n", portId, numBufs); /* enable traffic */ if(ixEthAccPortEnable(portId) != IX_ETH_ACC_SUCCESS) { printf("Loopbacks: Error Enabling port %u\n", (UINT32)portId); return (IX_FAIL); } return (IX_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); }
/* * Function definition: ixEthAccCodeletDBLearningRun() * * Run ethDB demo for all ports passed as parameters */ IX_STATUS ixEthAccCodeletDBLearningRun(BOOL validPorts[]) { IxEthAccPortId portId; IxEthDBPortId portPtr; IxEthDBMacAddr staticMacAddress[IX_ETHACC_CODELET_MAX_PORT] = {{{0,1,2,3,4,5}}, {{6,7,8,9,0,1}}}; IxEthDBMacAddr dynamMacAddress[IX_ETHACC_CODELET_MAX_PORT] = {{{0xa,0xb,0xc,0xd,0xe,0xf}}, {{0x0,0xb,0x3,0xc,0x4,0xd}}}; if (ixEthAccCodeletDBMaintenanceStart() != IX_SUCCESS) { printf("DbLearning: Error spawning DB maintenance task\n"); return (IX_FAIL); } /* configure all existing ports */ for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (validPorts[portId]) { /* Configure the port */ printf("Configuring the port...\n"); if (ixEthAccCodeletPortConfigure(portId, ixEthAccCodeletMemPoolFreeRxCB, (IxEthAccPortMultiBufferRxCallback) NULL, ixEthAccCodeletMemPoolFreeTxCB, portId) != IX_ETH_ACC_SUCCESS) { printf("DbLearning: Failed to configure the port %u\n", (UINT32)portId); return IX_FAIL; } /* Enable the port */ printf("Enabling the port...\n"); if(ixEthAccPortEnable(portId) != IX_ETH_ACC_SUCCESS) { printf("DbLearning: Error enabling port %u\n", (UINT32)portId); return (IX_FAIL); } /* Add some static entries */ printf("Adding static entries...\n"); if (ixEthDBFilteringStaticEntryProvision(portId, &staticMacAddress[portId]) != IX_ETH_DB_SUCCESS) { printf("DbLearning: Failed to add static MAC to port %u\n", (UINT32)portId); return (IX_FAIL); } ixOsalSleep(100); /* Verify that the address has successfully been added */ if (ixEthDBFilteringDatabaseSearch(&portPtr, &staticMacAddress[portId]) == IX_ETH_DB_NO_SUCH_ADDR) { printf("DbLearning: Static MAC address not found in Database\n"); return (IX_FAIL); } /* Add some dynamic entries */ printf("Adding dynamic entries...\n"); if (ixEthDBFilteringDynamicEntryProvision(portId, &dynamMacAddress[portId]) != IX_ETH_DB_SUCCESS) { printf("DbLearning: Failed to add dynamic MAC to port %u\n", (UINT32)portId); } printf("Enabling aging...\n"); if (ixEthDBPortAgingEnable(portId) != IX_ETH_DB_SUCCESS) { printf("DbLearning: Failed to enable aging for port %u\n", (UINT32)portId); return (IX_FAIL); } } } ixEthDBFilteringDatabaseShowAll(); /* Wait 4 minutes over aging time (for safety) and verify that the * dynamic entries have been removed */ printf("Aging entries.\nWaiting for %d minutes...\n", IX_ETH_DB_LEARNING_ENTRY_AGE_TIME / 60 + 3); ixOsalSleep((IX_ETH_DB_LEARNING_ENTRY_AGE_TIME + 180) * 1000); ixEthDBFilteringDatabaseShowAll(); for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (validPorts[portId]) { if(ixEthDBFilteringEntryDelete(&staticMacAddress[portId]) != IX_ETH_DB_SUCCESS) { printf("DbLearning: Failed to remove static MAC on port %u\n", (UINT32)portId); } /* Disable ports */ if(ixEthAccPortDisable(portId) != IX_ETH_ACC_SUCCESS) { printf("DbLearning: Error disabling port %u\n", (UINT32)portId); return (IX_FAIL); } } } /* wait for pending traffic to be completely received */ if (ixEthAccCodeletRecoverBuffers() != IX_SUCCESS) { printf("Warning : Not all buffers are accounted for!\n"); } return (IX_SUCCESS); }