Dave Johnson 1d464c26b5 [MIPS] Fix wrong checksum for split TCP packets on 64-bit MIPS
I've traced down an off-by-one TCP checksum calculation error under
the following conditions:

1) The TCP code needs to split a full-sized packet due to a reduced
   MSS (typically due to the addition of TCP options mid-stream like
   SACK).
   _AND_
2) The checksum of the 2nd fragment is larger than the checksum of the
   original packet.  After subtraction this results in a checksum for
   the 1st fragment with bits 16..31 set to 1. (this is ok)
   _AND_
3) The checksum of the 1st fragment's TCP header plus the previously
   32bit checksum of the 1st fragment DOES NOT cause a 32bit overflow
   when added together.  This results in a checksum of the TCP header
   plus TCP data that still has the upper 16 bits as 1's.
   _THEN_
4) The TCP+data checksum is added to the checksum of the pseudo IP
   header with csum_tcpudp_nofold() incorrectly (the bug).
    
The problem is the checksum of the TCP+data is passed to
csum_tcpudp_nofold() as an 32bit unsigned value, however the assembly
code acts on it as if it is a 64bit unsigned value.

This causes an incorrect 32->64bit extension if the sum has bit 31
set.  The resulting checksum is off by one.
    
This problems is data and TCP header dependent due to #2 and #3
above so it doesn't occur on every TCP packet split.
    
Signed-off-by: Dave Johnson <djohnson+linux-mips@sw.starentnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2007-04-20 14:58:37 +01:00
..
2006-10-04 18:06:15 +01:00
2006-10-03 23:01:26 +02:00
2007-02-18 21:31:35 +00:00
2006-11-01 17:46:09 +00:00
2007-03-17 01:03:29 +00:00
2005-09-07 16:57:21 -07:00
2007-03-17 01:03:29 +00:00
2005-10-29 19:30:34 +01:00
2007-04-20 14:58:37 +01:00
2006-10-31 20:13:23 +00:00
2007-03-08 01:10:30 +00:00
2005-11-07 18:05:40 +00:00
2007-03-24 17:01:49 +00:00
2006-07-13 21:26:08 +01:00
2007-02-18 21:31:34 +00:00
2007-02-06 16:53:09 +00:00
2006-11-30 01:14:44 +00:00
2007-02-06 16:53:13 +00:00
2007-02-18 21:31:34 +00:00
2006-06-19 17:39:19 +01:00
2006-04-19 04:14:22 +02:00
2007-03-24 17:01:49 +00:00
2007-02-18 21:31:35 +00:00
2007-02-26 23:06:06 +00:00
2006-06-29 16:58:06 -07:00
2006-06-06 00:15:20 +01:00
2007-03-17 01:03:29 +00:00
2007-03-07 00:07:17 +00:00