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