Keil Logo

MAC driver bug with new IP fragmentation ?

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Author
Philippe Jalabert
Posted
2-Oct-2017 16:49 GMT
Toolset
ARM
New! MAC driver bug with new IP fragmentation ?

Hello,

I integrated the very last sources of the Ethernet stack to a project and I think that MAC driver file "EMAC_stm32f4xx.c" is now not compatible with IP fragmentation.
When a UDP fragmented frame is sent, the UDP checksum is calculated by the stack because the offload calculation applies only on one Ethernet frame. But is such a case, UDP checksum calculation offload must be deactived to avoid a bad UDP checksum put in the last fragmented frame by hardware.
I modified the file as follow in order to not crush the UDP checksum previously calculated by the software :

static int32_t SendFrame (const uint8_t *frame, uint32_t len, uint32_t flags) { uint8_t *dst = Emac.frame_end; uint32_t ctrl; uint16_t fragOfs, prot; // Added to fix bug
...
fragOfs = (((uint16_t)frame[20]) << 8) | frame[21]; // Added to fix bug
prot = (((uint16_t)frame[12]) << 8) | frame[13]; // Added to fix bug

...
#if (EMAC_CHECKSUM_OFFLOAD != 0)
// Original code :
// if (Emac.tx_cks_offload) { ctrl |= DMA_TX_CIC; }
// Correction in case of fragmented frame : if ((prot == 0x0800) && ((fragOfs & (IP4_MF_FLAG | IP4_FRAG_MASK)) != 0) { // fragmented frame, only IP checksum is calculated if (Emac.tx_cks_offload) { ctrl |= DMA_TX_CIC & 0x00400000U; } }

Author
very complicated >bold pre> tag
Posted
2-Oct-2017 19:44 GMT
Toolset
ARM
New! RE: MAC driver bug with new IP fragmentation ?

PLZ DO PROPERLY. YOUR POST IS A MESS.

Author
Franc Urbanc
Posted
3-Oct-2017 07:54 GMT
Toolset
ARM
New! RE: MAC driver bug with new IP fragmentation ?

UDP checksum is not modified for fragmented IP frames.

RM0090 - Reference manual for STM32F4xx (DocID018909 Rev 15), page 1145

Transmit Checksum Offload:

b) Fragmented IP frames (IPv4 or IPv6), IP frames with security features (such as an
authentication header or encapsulated security payload), and IPv6 frames with
routing headers are bypassed and not processed by the checksum.
Author
Philippe Jalabert
Posted
4-Oct-2017 15:08 GMT
Toolset
ARM
New! RE: MAC driver bug with new IP fragmentation ?

I've read that document and know that STM32F4 should not calculate the offload UDP checksum on fragmented frames . But it seems that there is a bug in STM32F407IG.
The MAC driver code modified as below allows to obtain a right UDP checksum in such frames.
See below the difference in second and last fragmented frame (payload size = 2000) where UDP checksum area is crushed by offload UDP checksum :

Wireshark result with EMAC driver NOT modified (ECHO response) :

<prep>
Frame 25: 562 bytes on wire (4496 bits), 562 bytes captured (4496 bits) on interface 0
Ethernet II, Src: Faiveley_a2:45:5f (00:1b:79:a2:45:5f), Dst: Trendnet_da:2c:db (00:14:d1:da:2c:db)
Internet Protocol Version 4, Src: 192.168.33.1, Dst: 192.168.33.2 0100 .... = Version: 4 .... 0101 = Header Length: 20 bytes (5) Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) 0000 00.. = Differentiated Services Codepoint: Default (0) .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) Total Length: 548 Identification: 0x0000 (0) Flags: 0x00 0... .... = Reserved bit: Not set .0.. .... = Don't fragment: Not set ..0. .... = More fragments: Not set Fragment offset: 1480 Time to live: 128 Protocol: UDP (17) Header checksum: 0x74bc [correct] [Header checksum status: Good] [Calculated Checksum: 0x74bc] Source: 192.168.33.1 Destination: 192.168.33.2 [Source GeoIP: Unknown] [Destination GeoIP: Unknown] [2 IPv4 Fragments (2008 bytes): #24(1480), #25(528)] [Frame: 24, payload: 0-1479 (1480 bytes)] [Frame: 25, payload: 1480-2007 (528 bytes)] [Fragment count: 2] [Reassembled IPv4 length: 2008] [Reassembled IPv4 data: 0007baea07d8eea5000102030405060708090a0b0c0d0e0f...]
User Datagram Protocol, Src Port: echo (7), Dst Port: 47850 (47850) Source Port: echo (7) Destination Port: 47850 (47850) Length: 2008
Checksum: 0xeea5 incorrect, should be 0xb20b (maybe caused by "UDP checksum offload"?) [Expert Info (Error/Checksum): Bad checksum [should be 0xb20b]] [Bad checksum [should be 0xb20b]] [Severity level: Error] [Group: Checksum] [Calculated Checksum: 0xb20b] [Checksum Status: Bad] [Stream index: 3]
Echo Echo data: 000102030405060708090a0b0c0d0e0f1011121314151617...

Frame (562 bytes):
0000 00 14 d1 da 2c db 00 1b 79 a2 45 5f 08 00 45 00 ....,...y.E_..E.
0010 02 24 00 00 00 b9 80 11 74 bc c0 a8 21 01 c0 a8 .$......t...!...
0020 21 02 c0 c1 c2 c3 c4 c5 42 8c c8 c9 ca cb cc cd !.......B.......
0030 ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd ................
</prep>

Wireshark result with EMAC driver modified :

<prep>
Frame 14: 562 bytes on wire (4496 bits), 562 bytes captured (4496 bits) on interface 0
Ethernet II, Src: Faiveley_a2:45:5f (00:1b:79:a2:45:5f), Dst: Trendnet_da:2c:db (00:14:d1:da:2c:db)
Internet Protocol Version 4, Src: 192.168.33.1, Dst: 192.168.33.2 0100 .... = Version: 4 .... 0101 = Header Length: 20 bytes (5) Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) 0000 00.. = Differentiated Services Codepoint: Default (0) .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0) Total Length: 548 Identification: 0x0000 (0) Flags: 0x00 0... .... = Reserved bit: Not set .0.. .... = Don't fragment: Not set ..0. .... = More fragments: Not set Fragment offset: 1480 Time to live: 128 Protocol: UDP (17) Header checksum: 0x74bc [correct] [Header checksum status: Good] [Calculated Checksum: 0x74bc] Source: 192.168.33.1 Destination: 192.168.33.2 [Source GeoIP: Unknown] [Destination GeoIP: Unknown] [2 IPv4 Fragments (2008 bytes): #13(1480), #14(528)] [Frame: 13, payload: 0-1479 (1480 bytes)] [Frame: 14, payload: 1480-2007 (528 bytes)] [Fragment count: 2] [Reassembled IPv4 length: 2008] [Reassembled IPv4 data: 0007baea07d82dd0000102030405060708090a0b0c0d0e0f...]
User Datagram Protocol, Src Port: echo (7), Dst Port: 47850 (47850) Source Port: echo (7) Destination Port: 47850 (47850) Length: 2008
Checksum: 0x2dd0 [correct] [Calculated Checksum: 0x2dd0] [Checksum Status: Good] [Stream index: 1]
Echo Echo data: 000102030405060708090a0b0c0d0e0f1011121314151617...

Frame (562 bytes):
0000 00 14 d1 da 2c db 00 1b 79 a2 45 5f 08 00 45 00 ....,...y.E_..E.
0010 02 24 00 00 00 b9 80 11 74 bc c0 a8 21 01 c0 a8 .$......t...!...
0020 21 02 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd !...............
0030 ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd ................
</prep>

UDP checksum calculated in "net_udp_send" function when frame is fragmented (size > UDP MTU) is OK (verified using a breakpoint) but replaced in the frame on wire by the wrong offload checksum.

There must be another bug in checksum calculation, this time for IP header checksum :
I use a Bombardier software tool that test the biggest fragmented frame acceptable by a software. The tool sends an ECHO request (RFC862), increasing the size of the UDP payload in each new request. In only ONE case, when payload size is 2958 (up to about 8000), the IP header offload checksum is bad !
I turned around this suppose hardware bug as follow :

//   if (Emac.tx_cks_offload) { ctrl |= DMA_TX_CIC; }   // Original code
// Bug fixed on IP header checksum
   if ((prot == 0x0800) && ((fragOfs & (IP4_MF_FLAG | IP4_FRAG_MASK)) != 0))
   {
      // Fragmented frame detected
      // STM32 bug turnaround on IP header checksum calculation
      if (tx_desc[Emac.tx_index].Size == 40)
        {
           // A frame is always minimum 60 bytes long by hardware (IEEE standard)
           tx_desc[Emac.tx_index].Size = 42;
           ((__packed uint16_t *)dst)[0] = 0;   // Bytes added set to 0
        }
   }

Remark 1: the STM32 sets the frame size the 60 when requested < 60 (IEEE standard, see RM0090) therefore modification has no effect on frame size on wire.
Remark 2: not all 40 bytes length frames have a bad IP header checksum.

Author
Franc Urbanc
Posted
5-Oct-2017 14:05 GMT
Toolset
ARM
New! RE: MAC driver bug with new IP fragmentation ?

Yes you're right. The problem exists also in fragmented ICMP checksum calculation. We will correct the drivers.

Next Thread | Thread List | Previous Thread Start a Thread | Settings

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.