| #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; |
| } |
| /*-----------------------------------------------------------*/ |