mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 13:31:58 -04:00
174 lines
4.5 KiB
C
174 lines
4.5 KiB
C
#define xBUFFER_CACHE_SIZE 10
|
|
#define xMAX_FAULT_INJECTION_RATE 15
|
|
#define xMIN_FAULT_INJECTION_RATE 3
|
|
#define xNUM_FAULT_TYPES 1
|
|
|
|
static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
|
|
|
|
#define xFAULT_LOG_SIZE 2048
|
|
uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
|
|
uint32_t ulFaultLogIndex = 0;
|
|
|
|
static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
|
|
{
|
|
BaseType_t x, xReturn = pdFALSE;
|
|
|
|
for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
|
|
{
|
|
if( xNetworkBufferCache[ x ] == NULL )
|
|
{
|
|
xNetworkBufferCache[ x ] = pxNetworkBufferIn;
|
|
xReturn = pdTRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
|
|
{
|
|
BaseType_t x;
|
|
NetworkBufferDescriptor_t *pxReturn = NULL;
|
|
|
|
for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
|
|
{
|
|
if( xNetworkBufferCache[ x ] != NULL )
|
|
{
|
|
pxReturn = xNetworkBufferCache[ x ];
|
|
xNetworkBufferCache[ x ] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pxReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
|
|
{
|
|
NetworkBufferDescriptor_t *pxReturn;
|
|
|
|
/* Obtain a new descriptor. */
|
|
pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
|
|
|
|
if( pxReturn != NULL )
|
|
{
|
|
/* Copy in the packet data. */
|
|
pxReturn->xDataLength = pxOriginalPacket->xDataLength;
|
|
memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
|
|
}
|
|
|
|
return pxReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
|
|
{
|
|
static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
|
|
NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
|
|
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
|
|
uint32_t ulFault;
|
|
|
|
return pxNetworkBufferIn;
|
|
|
|
ulCallCount++;
|
|
|
|
if( ulCallCount > ulNextFaultCallCount )
|
|
{
|
|
ulNextFaultCallCount = ipconfigRAND32() % xMAX_FAULT_INJECTION_RATE;
|
|
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
|
|
{
|
|
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
|
|
}
|
|
|
|
ulCallCount = 0;
|
|
|
|
ulFault = ipconfigRAND32() % xNUM_FAULT_TYPES;
|
|
|
|
if( ulFaultLogIndex < xFAULT_LOG_SIZE )
|
|
{
|
|
ulInjectedFault[ ulFaultLogIndex ] = ulFault;
|
|
ulFaultLogIndex++;
|
|
}
|
|
|
|
switch( ulFault )
|
|
{
|
|
case 0:
|
|
/* Just drop the packet. */
|
|
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
|
pxReturn = NULL;
|
|
break;
|
|
|
|
case 1:
|
|
/* Store the packet in the cache for later. */
|
|
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
|
|
{
|
|
/* The packet may get sent later, it is not being sent
|
|
now. */
|
|
pxReturn = NULL;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
/* Send a cached packet. */
|
|
pxReturn = prvGetCachedPacket();
|
|
if( pxReturn != NULL )
|
|
{
|
|
/* A cached packet was obtained so drop the original
|
|
packet. */
|
|
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
|
}
|
|
else
|
|
{
|
|
/* Could not obtain a packet from the cache so just return
|
|
the packet that was passed in. */
|
|
pxReturn = pxNetworkBufferIn;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
|
|
/* Send a duplicate of the packet right away. */
|
|
pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
|
|
|
|
/* Send the original packet to the stack. */
|
|
xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
|
|
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
|
{
|
|
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
|
|
/* Send both a cached packet and the current packet. */
|
|
xRxEvent.pvData = ( void * ) prvGetCachedPacket();
|
|
if( xRxEvent.pvData != NULL )
|
|
{
|
|
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
|
|
{
|
|
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
/* Store the packet in the cache for later. */
|
|
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
|
|
{
|
|
/* The packet may get sent later, it is not being sent
|
|
now. */
|
|
pxReturn = NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pxReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|