@@ -2653,3 +2653,130 @@ void test_prvTCPSendReset( void )
26532653 TEST_ASSERT_EQUAL ( tcpTCP_FLAG_ACK | tcpTCP_FLAG_RST , pxTCPPacket -> xTCPHeader .ucTCPFlags );
26542654 TEST_ASSERT_EQUAL ( 0x50 , pxTCPPacket -> xTCPHeader .ucTCPOffset );
26552655}
2656+
2657+ /* Stub for usGenerateProtocolChecksum that computes a simple byte-sum
2658+ * "checksum" over [ETH_HEADER, uxBufferLength) and writes it to the TCP
2659+ * checksum field. A snapshot of the buffer at stub-invocation time is
2660+ * saved so the test can recompute the expected value independent of any
2661+ * post-checksum mutations the SUT performs (MAC rewrite, port flip, ...). */
2662+ static uint8_t ucChecksumStubSnapshot [ ipconfigNETWORK_MTU ];
2663+ static size_t xChecksumStubBufferLength ;
2664+
2665+ static uint16_t usGenerateProtocolChecksum_ByteSum ( uint8_t * pucEthernetBuffer ,
2666+ size_t uxBufferLength ,
2667+ BaseType_t xOutgoingPacket ,
2668+ int cmock_num_calls )
2669+ {
2670+ const size_t xChecksumOffset = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + 16U ;
2671+ uint16_t usSum = 0U ;
2672+ size_t i ;
2673+
2674+ ( void ) xOutgoingPacket ;
2675+ ( void ) cmock_num_calls ;
2676+
2677+ pucEthernetBuffer [ xChecksumOffset ] = 0U ;
2678+ pucEthernetBuffer [ xChecksumOffset + 1U ] = 0U ;
2679+
2680+ for ( i = ipSIZE_OF_ETH_HEADER ; i < uxBufferLength ; i ++ )
2681+ {
2682+ usSum = ( uint16_t ) ( usSum + pucEthernetBuffer [ i ] );
2683+ }
2684+
2685+ pucEthernetBuffer [ xChecksumOffset ] = ( uint8_t ) ( usSum >> 8 );
2686+ pucEthernetBuffer [ xChecksumOffset + 1U ] = ( uint8_t ) ( usSum & 0xFFU );
2687+
2688+ memcpy ( ucChecksumStubSnapshot , pucEthernetBuffer , uxBufferLength );
2689+ xChecksumStubBufferLength = uxBufferLength ;
2690+ return ipCORRECT_CRC ;
2691+ }
2692+
2693+ /**
2694+ * @brief Verify that prvTCPReturnPacket computes the TCP checksum over the
2695+ * outgoing packet length, not over the stale xDataLength which may
2696+ * reflect an incoming frame padded to the Ethernet minimum (60 bytes).
2697+ */
2698+ void test_prvTCPReturnPacket_ChecksumReceivesOutgoingLength ( void )
2699+ {
2700+ const uint32_t ulLen = ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 12U ; /* 52 */
2701+ const size_t xRxDataLength = ipconfigETHERNET_MINIMUM_PACKET_BYTES ; /* 60 */
2702+ const size_t xChecksumOffset = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + 16U ;
2703+ size_t i ;
2704+ uint16_t usExpectedChecksum ;
2705+ uint16_t usActualChecksum ;
2706+
2707+ pxSocket = & xSocket ;
2708+ pxNetworkBuffer = & xNetworkBuffer ;
2709+ pxNetworkBuffer -> pucEthernetBuffer = ucEthernetBuffer ;
2710+ pxNetworkBuffer -> xDataLength = xRxDataLength ;
2711+
2712+ TCPWindow_t * pxTCPWindow = & pxSocket -> u .xTCP .xTCPWindow ;
2713+ struct xNetworkEndPoint xEndPoint = { 0 };
2714+ struct xNetworkInterface xInterface ;
2715+ struct xNetworkEndPoint * pxEndPoint = & xEndPoint ;
2716+
2717+ xEndPoint .pxNetworkInterface = & xInterface ;
2718+ xEndPoint .ipv4_settings .ulIPAddress = 0xC0C0C0C0 ;
2719+ xEndPoint .pxNetworkInterface -> pfOutput = & NetworkInterfaceOutputFunction_Stub ;
2720+ NetworkInterfaceOutputFunction_Stub_Called = 0 ;
2721+ pxSocket -> pxEndPoint = & xEndPoint ;
2722+ pxNetworkBuffer -> pxEndPoint = & xEndPoint ;
2723+
2724+ pxSocket -> u .xTCP .rxStream = ( StreamBuffer_t * ) 0x12345678 ;
2725+ pxSocket -> u .xTCP .uxRxStreamSize = 1500 ;
2726+ pxSocket -> u .xTCP .bits .bLowWater = pdFALSE ;
2727+ pxSocket -> u .xTCP .bits .bRxStopped = pdFALSE ;
2728+ pxSocket -> u .xTCP .usMSS = 1000 ;
2729+ pxSocket -> u .xTCP .ucMyWinScaleFactor = 0 ;
2730+ pxSocket -> u .xTCP .bits .bSendKeepAlive = pdFALSE ;
2731+ pxSocket -> u .xTCP .xTCPWindow .ulOurSequenceNumber = 100 ;
2732+ pxTCPWindow -> xSize .ulRxWindowLength = 500 ;
2733+ pxTCPWindow -> rx .ulCurrentSequenceNumber = 50 ;
2734+
2735+ /* Populate the tail of the buffer (bytes ulLen+ETH..xRxDataLength) with a
2736+ * distinctive pattern so that including them in the sum produces a
2737+ * different result than summing only the outgoing bytes. */
2738+ for ( i = 0 ; i < sizeof ( ucEthernetBuffer ); i ++ )
2739+ {
2740+ ucEthernetBuffer [ i ] = 0U ;
2741+ }
2742+
2743+ for ( i = ulLen + ipSIZE_OF_ETH_HEADER ; i < xRxDataLength ; i ++ )
2744+ {
2745+ ucEthernetBuffer [ i ] = 0xFFU ;
2746+ }
2747+
2748+ uxIPHeaderSizePacket_IgnoreAndReturn ( ipSIZE_OF_IPv4_HEADER );
2749+ uxStreamBufferFrontSpace_ExpectAnyArgsAndReturn ( 1000 );
2750+ FreeRTOS_min_uint32_ExpectAnyArgsAndReturn ( 500 );
2751+ usGenerateChecksum_ExpectAnyArgsAndReturn ( 0x1111 );
2752+ usGenerateProtocolChecksum_Stub ( usGenerateProtocolChecksum_ByteSum );
2753+ eARPGetCacheEntry_ExpectAnyArgsAndReturn ( eResolutionCacheHit );
2754+ eARPGetCacheEntry_ReturnThruPtr_ppxEndPoint ( & pxEndPoint );
2755+
2756+ xChecksumStubBufferLength = 0U ;
2757+
2758+ prvTCPReturnPacket ( pxSocket , pxNetworkBuffer , ulLen , pdFALSE );
2759+
2760+ TEST_ASSERT_NOT_EQUAL ( 0U , xChecksumStubBufferLength );
2761+
2762+ /* Read the checksum the stub actually wrote into the packet, from the
2763+ * snapshot taken at stub invocation (before any post-checksum mutations
2764+ * by the SUT). */
2765+ usActualChecksum = ( uint16_t ) ( ( ucChecksumStubSnapshot [ xChecksumOffset ] << 8 ) |
2766+ ucChecksumStubSnapshot [ xChecksumOffset + 1U ] );
2767+
2768+ /* Recompute the expected checksum on the same snapshot, summing over the
2769+ * full outgoing packet length. With the bug the stub saw only
2770+ * xRxDataLength bytes and its sum differs from this reference. */
2771+ ucChecksumStubSnapshot [ xChecksumOffset ] = 0U ;
2772+ ucChecksumStubSnapshot [ xChecksumOffset + 1U ] = 0U ;
2773+
2774+ usExpectedChecksum = 0U ;
2775+
2776+ for ( i = ipSIZE_OF_ETH_HEADER ; i < ulLen + ipSIZE_OF_ETH_HEADER ; i ++ )
2777+ {
2778+ usExpectedChecksum = ( uint16_t ) ( usExpectedChecksum + ucChecksumStubSnapshot [ i ] );
2779+ }
2780+
2781+ TEST_ASSERT_EQUAL_HEX16 ( usExpectedChecksum , usActualChecksum );
2782+ }
0 commit comments