aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips/checksum.h
diff options
context:
space:
mode:
authorDave Johnson <djohnson+linux-mips@sw.starentnetworks.com>2007-04-18 10:39:41 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-04-20 09:58:37 -0400
commit1d464c26b5625215c4b35fb336c8f3c57d248c2e (patch)
tree88316e8149c4125dbdb55ff90a4e8d45a024940b /include/asm-mips/checksum.h
parentba755f8ec80fdbf2b5212622eabf7355464c6327 (diff)
[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>
Diffstat (limited to 'include/asm-mips/checksum.h')
-rw-r--r--include/asm-mips/checksum.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index 20a81e1548f..290485ac540 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -166,7 +166,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr,
166#else 166#else
167 "r" (proto + len), 167 "r" (proto + len),
168#endif 168#endif
169 "r" (sum)); 169 "r" ((__force unsigned long)sum));
170 170
171 return sum; 171 return sum;
172} 172}