@@ -519,6 +519,9 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
*/
ext->data_fin = 1;
ext->data_len++;
+
+ /* the pseudo header has changed, update the csum accordingly */
+ csum_replace2(&ext->csum, htons(ext->data_len - 1), htons(ext->data_len));
}
}
@@ -1279,23 +1279,16 @@ static bool mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk)
return __mptcp_alloc_tx_skb(sk, ssk, sk->sk_allocation);
}
-static __sum16 mptcp_generate_data_checksum(struct sk_buff *skb)
+/* note: this always recompute the csum on the whole skb, even
+ * if we just appended a single frag. More status info needed
+ */
+static void mptcp_update_data_checksum(struct sk_buff *skb, int added)
{
- struct csum_pseudo_header header;
- struct mptcp_ext *mpext;
- __wsum csum;
-
- mpext = mptcp_get_ext(skb);
-
- header.data_seq = mpext->data_seq;
- header.subflow_seq = mpext->subflow_seq;
- header.data_len = mpext->data_len;
- header.csum = 0;
+ struct mptcp_ext *mpext = mptcp_get_ext(skb);
+ __wsum csum = csum_unfold(mpext->csum);
+ int offset = skb->len - added;
- csum = skb_checksum(skb, 0, skb->len, 0);
- csum = csum_partial(&header, sizeof(header), csum);
-
- return csum_fold(csum);
+ mpext->csum = csum_fold(csum_block_add(csum, skb_checksum(skb, offset, added, 0), offset));
}
static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
@@ -1392,12 +1385,14 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
if (zero_window_probe) {
mptcp_subflow_ctx(ssk)->rel_write_seq += ret;
mpext->frozen = 1;
- ret = 0;
+ if (READ_ONCE(msk->csum_enabled))
+ mptcp_update_data_checksum(tail, ret);
tcp_push_pending_frames(ssk);
+ return 0;
}
out:
if (READ_ONCE(msk->csum_enabled))
- mpext->csum = mptcp_generate_data_checksum(tail);
+ mptcp_update_data_checksum(tail, ret);
mptcp_subflow_ctx(ssk)->rel_write_seq += ret;
return ret;
}
@@ -336,9 +336,9 @@ static inline struct mptcp_data_frag *mptcp_rtx_head(const struct sock *sk)
}
struct csum_pseudo_header {
- u64 data_seq;
- u32 subflow_seq;
- u16 data_len;
+ __be64 data_seq;
+ __be32 subflow_seq;
+ __be16 data_len;
__sum16 csum;
};
We must generate the csum for zero window probe, too. Do the csum update incrementally, to avoid multiple csum computation when the data is appended to existing skb. Note that in a later patch we will skip unneeded csum related operation. Changes not included here to keep the delta small. Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- v4 -> v5: - build the csum incrementally - pseudo hdr fields are in NBO/BE - must use len in NBO when updating the csum for data fin --- net/mptcp/options.c | 3 +++ net/mptcp/protocol.c | 29 ++++++++++++----------------- net/mptcp/protocol.h | 6 +++--- 3 files changed, 18 insertions(+), 20 deletions(-)