PRIVATE void ixEthAccCodeletLoopbackRxCB(UINT32 cbTag, IX_OSAL_MBUF** mBufPtr) { /* Transmit the buffer back on the port it was received on*/ if(cbTag < IX_ETHACC_CODELET_MAX_PORT ) { while (NULL != *mBufPtr) { ixEthAccCodeletStats[cbTag].rxCount++; /* transmit the frame on the same port */ if(ixEthAccPortTxFrameSubmit(cbTag, *mBufPtr, IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Tx Buffer submission failure port %d\n", cbTag, 0, 0, 0, 0, 0); } /* move to next buffer received */ mBufPtr++; } } else { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Invalid Rx callback tag %d in Sw Loopback Operation\n", cbTag, 0, 0, 0, 0, 0); } }
PRIVATE void ixEthAccCodeletSwBridgeQoSUntaggedToTaggedRxCB(UINT32 cbTag, IX_OSAL_MBUF* mBufPtr, UINT32 destPortId) { IxEthAccPortId thisPortId = (IxEthAccPortId)(cbTag & 0xffff); IxEthAccPortId otherPortId = (IxEthAccPortId)(cbTag>>16); IxEthAccTxPriority priority = (IX_ETH_DB_GET_QOS_PRIORITY(IX_ETHACC_CODELET_VLANID_DEFAULT)); ixEthAccCodeletStats[thisPortId].rxCount++; /* Set the VLAN information for this frame : the outgoing frame * is tagged with the default tagging rules for this port */ IX_ETHACC_NE_FLAGS(mBufPtr) = IX_ETHACC_NE_VLANENABLEMASK; IX_ETHACC_NE_VLANTCI(mBufPtr) = IX_ETHACC_CODELET_VLANID_DEFAULT; /* Transmit the buffer on the other port */ if(ixEthAccPortTxFrameSubmit(otherPortId, mBufPtr, priority) !=IX_ETH_ACC_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "SwBridgeQos: Tx Buffer submission failed on port %u\n", (UINT32)(1 - cbTag), 0, 0, 0, 0, 0); } }
/** * @fn void ixEthAccCodeletTxGenTxCB() * * Transmit callback for TxGen operation. Transmitted frames are re- * transmitted. * * @return void */ PRIVATE void ixEthAccCodeletTxGenTxCB(UINT32 cbTag, IX_OSAL_MBUF* mBufPtr) { ixEthAccCodeletStats[cbTag].txCount++; /* Re-transmit the frame on same port */ if(ixEthAccPortTxFrameSubmit(cbTag, mBufPtr, IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Tx Buffer submission failure in TxGen-RxSink\n", 0, 0, 0, 0, 0, 0); } }
PRIVATE void ixEthAccCodeletSwBridgeQoSTaggedToUntaggedRxCB(UINT32 cbTag, IX_OSAL_MBUF* mBufPtr, UINT32 destPortId) { IxEthAccPortId thisPortId = (IxEthAccPortId)(cbTag & 0xffff); IxEthAccPortId otherPortId = (IxEthAccPortId)(cbTag>>16); /* Extract the priority of the incoming buffer header */ IxEthAccTxPriority priority = (IX_ETH_DB_GET_QOS_PRIORITY(IX_ETHACC_NE_VLANTCI(mBufPtr))); ixEthAccCodeletStats[thisPortId].rxCount++; /* This frame is untagged on Rx, just clear the flags * to bypass VLAN processing on the Tx path */ IX_ETHACC_NE_FLAGS(mBufPtr) = 0; /* this while loop is what throttles the receive processing to keep the RxFree queue * form becoming empty when we receive faster than transmitting */ while(pendingTx[otherPortId] >= IX_ETHACC_CODELET_QOS_BRIDGE_MAX_PENDING_TX) { ixEthTxFrameDoneQMCallback(0,0); } /* Transmit the buffer on the other port with its own priority */ if(ixEthAccPortTxFrameSubmit(otherPortId, mBufPtr, priority) !=IX_ETH_ACC_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "SwBridgeQos: Tx Buffer submission failed on port %u\n", (UINT32)(1 - cbTag), 0, 0, 0, 0, 0); } /* incriment pendingTx */ pendingTx[otherPortId]++; }
void ixEthAccCodeletBridgeRxCB(UINT32 cbTag, IX_OSAL_MBUF* mBufPtr, UINT32 destPortId) { IxEthAccPortId thisPortId = (IxEthAccPortId)(cbTag & 0xffff); IxEthAccPortId otherPortId = (IxEthAccPortId)(cbTag>>16); /* Transmit the buffer on the other port */ ixEthAccCodeletStats[thisPortId].rxCount++; if(ixEthAccPortTxFrameSubmit(otherPortId, mBufPtr, IX_ETH_ACC_TX_DEFAULT_PRIORITY) !=IX_ETH_ACC_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Tx Buffer submission failed on port 2\n", 0, 0, 0, 0, 0, 0); } }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletPTPMsgTransmit () * * @brief Transmit Sync message from master port and Delay_Req message * from slave port every 2 seconds. * * @return void */ PRIVATE void ixTimeSyncAccCodeletPTPMsgTransmit () { IX_OSAL_MBUF *mBufPtr; IxEthAccPortId portId = 0; IxTimeSyncAcc1588PTPPort tsChannel; IxTimeSyncAcc1588PTPMsgType txMsgType; IxTimeSyncAcc1588PTPPortMode tsChannelMode; /* clear PTP message transmission halt flag */ ixTimeSyncAccCodeletTxHalt = FALSE; for (tsChannel = IX_TIMESYNCACC_NPE_A_1588PTP_PORT; tsChannel < IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS; tsChannel++) { portId = ixTimeSyncAccCodeletPortIdList[tsChannel]; tsChannelMode = ixTimeSyncAccCodeletConfigPtr->tsChannelMode[tsChannel]; txMsgType = ixTimeSyncAccCodeletPTPMsgTypeList[tsChannelMode]; /* build PTP message */ ixTimeSyncAccCodeletPTPMsgBuild (txMsgType); if (IX_SUCCESS != ixTimeSyncAccCodeletPortConfigure (portId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to configure port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } if (IX_ETH_ACC_SUCCESS != ixEthAccPortEnable (portId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to enable port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } mBufPtr = ixTimeSyncAccCodeletGlobalMBuf[portId]; if (NULL == mBufPtr) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: NULL mBuf pointer, port Id %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } /* copy PTP message data to mBuf's data buffer */ ixOsalMemCopy (IX_OSAL_MBUF_MDATA(mBufPtr), ixTimeSyncAccCodeletPtpMsgData, IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN); } /* end of for loop */ if (IX_SUCCESS != ixOsalSemaphoreInit (&ixTimeSyncAccCodeletSemId, IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to create semaphore\n", 0, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } do { /* halt PTP message transmission */ if (TRUE == ixTimeSyncAccCodeletTxHalt) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixTimeSyncAccCodeletPTPMsgTransmit: PTP message transmission was halted\n", 0, 0, 0, 0, 0, 0); return; } /* sleep and wait for interval time to elapse before transmitting next PTP message */ ixOsalSleep (IX_TIMESYNCACC_CODELET_PTP_MSG_XMIT_INTERVAL); for (portId = IX_ETH_PORT_1; portId <= IX_ETH_PORT_3; portId++) { if (IX_SUCCESS != ixOsalSemaphoreWait (&ixTimeSyncAccCodeletSemId, IX_TIMESYNCACC_CODELET_PTP_MSG_XMIT_INTERVAL)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: PTP message transmission error at port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } if (IX_ETH_ACC_SUCCESS != ixEthAccPortTxFrameSubmit (portId, ixTimeSyncAccCodeletGlobalMBuf[portId], IX_ETH_ACC_TX_DEFAULT_PRIORITY)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to transmit PTP message from port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } } /* end of for loop */ } while (TRUE); } /* end of ixTimeSyncAccCodeletPTPMsgTransmit function */
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); }