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);
    }
}
Example #6
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);
}