Bug 15384

Summary: e1000 needs checksum offloading blacklist entries
Product: Drivers Reporter: Björn Jacke (bjoern)
Component: NetworkAssignee: drivers_network (drivers_network)
Severity: normal CC: alan, emil.s.tantilov, jesse.brandeburg, tushar.n.dave
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 3.6 Subsystem:
Regression: No Bisected commit-id:

Description Björn Jacke 2010-02-24 16:05:58 UTC
there are e1000 network adaptors which compute and send out 0xffff tcp checksums and don't send them out as 0x0 like RFC1624 suggests. Some TCP implementations withdraw any packet that has a 0xffff checksum (MS DOS for example). There are reports about the same problem in a Solaris forum: http://www.keyongtech.com/5415896-disable-e1000-tcp-checksum-offloading

The Mac address of our adaptor is 00:02:A5:4F:9B:16. lspci -vv output:

06:01.0 Ethernet controller: Intel Corporation 82546EB Gigabit Ethernet Controller (Copper) (rev 01)
        Subsystem: Compaq Computer Corporation NC7170 Gigabit Server Adapter
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap+ 66MHz+ UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 64 (63750ns min), Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 24
        Region 0: Memory at f7fe0000 (64-bit, non-prefetchable) [size=128K]
        Region 2: Memory at f7f80000 (64-bit, non-prefetchable) [size=256K]
        Region 4: I/O ports at 4000 [size=64]
        [virtual] Expansion ROM at 50080000 [disabled] [size=256K]
        Capabilities: [dc] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [e4] PCI-X non-bridge device
                Command: DPERE- ERO+ RBC=512 OST=1
                Status: Dev=06:01.0 64bit+ 133MHz+ SCD- USC- DC=simple DMMRBC=2048 DMOST=1 DMCRS=16 RSCEM- 266MHz- 533MHz-
        Capabilities: [f0] Message Signalled Interrupts: Mask- 64bit+ Count=1/1 Enable-
                Address: 0000000000000000  Data: 0000
        Kernel driver in use: e1000
        Kernel modules: e1000

I did not check the most recent kernel but in the vanilla 2.6.33rc7 sources I didn't find any blacklist code in the e1000 code for this hw bug.

Manually disabling tx checksum offloading fixed the problem for us.
Comment 1 Björn Jacke 2010-02-25 20:59:16 UTC
https://bugzilla.redhat.com/show_bug.cgi?id=165676 shows more people with 82546EB controllers who see problems that may have the same cause. Maybe the whole 82546EB series needs to be blacklisted for checksum offloading.
Comment 2 Jesse Brandeburg 2010-03-02 07:31:48 UTC
http://download.intel.com/design/network/specupdt/82546eb.pdf is the specification update for this part, and it doesn't mention anything about a checksum computation issue.

I think I know of the patch that might need to be made to fix this issue in the kernel.
Comment 3 Björn Jacke 2010-03-03 15:32:22 UTC
06:02.0 Ethernet controller: Intel Corporation 82546GB Gigabit Ethernet Controller (rev 03)
        Subsystem: Intel Corporation PRO/1000 MT Dual Port Server Adapter
06:02.0 0200: 8086:1079 (rev 03)
        Subsystem: 8086:1179

is just another 82546GB bases card we have. It has the same checksumming bug.
Comment 4 Björn Jacke 2010-03-04 00:27:01 UTC
This Intel document about the 82543GC shows that this is a known bug: ftp://download.intel.com/design/network/specupdt/82543gc.pdf

38. Transmit TCP Checksum Incorrectly Modified if Calculated as 0x0000

If the controller calculates a transmit TCP checksum as 0x0000, it will automatically change the checksum to 0xFFFF. 
Specifications call for 0xFFFF be substituted for 0x0000 for UDP packets to distinguish UDP packets that carry no checksum. However, the modification does not apply to TCP packets.

If the receiving station is running MS-DOS and calculates a receive checksum of 0x0000, it will flag an error if the checksum contained in the packet is 0xFFFF. Other operating systems treat 0x0000 and 0xFFFF as equivalent in one’s complement math. UDP checksums are correct.

Intel modified the DOS Ethernet driver to check for a received checksum of 0xFFFF on a TCP/IP packet and change it back to 0x0000 before passing the packet to the operating system.

Intel does not plan to resolve this erratum in a future stepping of the 82543GC Gigabit Ethernet Controller.
Comment 5 Björn Jacke 2010-03-04 00:31:18 UTC
so far known to be broken are 82546EB, 82546GB and 82543GC.

Is there a more complete list of broken cards available?
Comment 6 Björn Jacke 2010-03-10 20:11:44 UTC
Jesse: can someone @Intel tell which chipsets are affected?
Comment 7 Björn Jacke 2012-05-13 11:10:40 UTC
the TCP checksum offloading of those cards are still broken. The bug should not get resolved as "obsolete" but be the tcp checksum offloading be blacklisted instead.
Comment 8 Tushar 2012-11-21 23:36:19 UTC
Here is the background info I found:

Because 0000h and FFFFh are equivalent in 1’s complement arithmetic, it will not cause problems if a checksum value of FFFFh is used instead of 0000h.

For a UDP packet, a checksum value of 0000h means that the packet does not include a checksum.  Thus, if the packet is supposed to include a checksum, and the checksum calculation happens to result in a value of 0000h, then the actual value used for the checksum field is FFFFh.

The preferred method of verifying the IP, UDP or TCP checksum is to sum the covered data (in 16-bit quantities) using 1’s complement arithmetic and comparing the result to FFFFh.  If it matches then the checksum is valid; otherwise it is invalid.  This method is described in RFC 1071 (section 1, item 3) and in RFC 1624 (section 5).

This allows the UDP checksum to be verified without the end system worrying about converting a checksum of 0000h into FFFFh.

It also allows the IP and TCP checksum calculation to use this replacement.  Because the values 0000h and FFFFh are equivalent in 1’s complement arithmetic, the sum will still be FFFFh for a valid checksum.

In order to simplify the design, our hardware always converts a checksum value of 0000h into FFFFh.  Because the RFC method accounts for this, there should be no conflict with well-written TCP/IP stacks.