Hello,
It appears that the following problem once reported for Sparc64
affects MIPS/64 as well:
original report: http://www.spinics.net/lists/sparclinux/msg00173.html
resolution: http://www.spinics.net/lists/sparclinux/msg00179.html
The net result is that when TCP fragments unacked segments due to PMTU
discovery, the shortened segment can have a bad TCP csum. I'm testing
on Linux-2.6.26 (FWIW, on a Cavium CN3010). My repro is fairly
simple: MIPS/64 client behind a Linux router, where the Linux router
has an outbound MTU of 1492. When the client attempts to send
segments of size 1460 (1500), the router sends back an ICMP
unreachable/PMTU and the client resends the first portion of the
segment reduced to 1452 (1492), and the segments *often* (but not
always) have a bad TCP csum. Note that you can't have hardware
checksums enabled or the bug is masked.
I've experimented with the following change:
--- /home/bp/tmp/csum_partial.S.orig 2008-09-16 12:01:00.000000000 -0700
+++ arch/mips/lib/csum_partial.S 2008-09-16 11:51:44.000000000 -0700
@@ -281,6 +281,23 @@
.set reorder
/* Add the passed partial csum. */
ADDC(sum, a2)
+
+ /* fold checksum again to clear the high bits before returning */
+ .set push
+ .set noat
+#ifdef USE_DOUBLE
+ dsll32 v1, sum, 0
+ daddu sum, v1
+ sltu v1, sum, v1
+ dsra32 sum, sum, 0
+ addu sum, v1
+#endif
+ sll v1, sum, 16
+ addu sum, v1
+ sltu v1, sum, v1
+ srl sum, sum, 16
+ addu sum, v1
+
jr ra
.set noreorder
END(csum_partial)
and it seems to fix the problem for me. Can you comment?
Thanks,
--
-bp