diff mbox

tcp: fix wrong checksum calculation on MTU probing

Message ID 15e3bab9-f21e-9a55-a87e-e389f633f755@taghos.com.br
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Douglas Caetano dos Santos Sept. 19, 2016, 9:16 p.m. UTC
With TCP MTU probing enabled and offload TX checksumming disabled,
tcp_mtu_probe() calculated the wrong checksum when a fragment being copied
into the probe's SKB had an odd length. This was caused by the direct use
of skb_copy_and_csum_bits() to calculate the checksum, as it pads the
fragment being copied, if needed. When this fragment was not the last, a
subsequent call used the previous checksum without considering this
padding.

The effect was a stale connection in one way, as even retransmissions
wouldn't solve the problem, because the checksum was never recalculated for
the full SKB length.

Signed-off-by: Douglas Caetano dos Santos <douglascs@taghos.com.br>
---
  net/ipv4/tcp_output.c | 10 ++++++----
  1 file changed, 6 insertions(+), 4 deletions(-)

Comments

David Miller Sept. 21, 2016, 2:57 a.m. UTC | #1
This patch is whitespace damaged by your email client.

Please fix this, email the patch to yourself, and only resubmit this
when you can successfully apply the patch you emailed to yourself.

Thanks.
diff mbox

Patch

diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f53d0cc..767135e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1968,10 +1968,12 @@  static int tcp_mtu_probe(struct sock *sk)
          copy = min_t(int, skb->len, probe_size - len);
          if (nskb->ip_summed)
              skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
-        else
-            nskb->csum = skb_copy_and_csum_bits(skb, 0,
-                                skb_put(nskb, copy),
-                                copy, nskb->csum);
+        else {
+            __wsum csum = skb_copy_and_csum_bits(skb, 0,
+                                 skb_put(nskb, copy),
+                                 copy, 0);
+            nskb->csum = csum_block_add(nskb->csum, csum, len);
+        }

          if (skb->len <= copy) {
              /* We've eaten all the data from this skb.