#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 ) | |
{ | |
xApplicationGetRandomNumber( &( ulNextFaultCallCount ) ); | |
ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE; | |
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE ) | |
{ | |
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE; | |
} | |
ulCallCount = 0; | |
xApplicationGetRandomNumber( &( ulFault ) ); | |
ulFault = ulFault % 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; | |
} | |
/*-----------------------------------------------------------*/ |