Commit 2398e399 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

mptcp: always include dack if possible.

Currently passive MPTCP socket can skip including the DACK
option - if the peer sends data before accept() completes.

The above happens because the msk 'can_ack' flag is set
only after the accept() call.

Such missing DACK option may cause - as per RFC spec -
unwanted fallback to TCP.

This change addresses the issue using the key material
available in the current subflow, if any, to create a suitable
dack option when msk ack seq is not yet available.

v1 -> v2:
 - adavance the generated ack after the initial MPC packet

Fixes: d22f4988 ("mptcp: process MP_CAPABLE data option")
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Reviewed-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a3aefbfe
...@@ -334,6 +334,8 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -334,6 +334,8 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
struct mptcp_sock *msk; struct mptcp_sock *msk;
unsigned int ack_size; unsigned int ack_size;
bool ret = false; bool ret = false;
bool can_ack;
u64 ack_seq;
u8 tcp_fin; u8 tcp_fin;
if (skb) { if (skb) {
...@@ -360,9 +362,22 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -360,9 +362,22 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
ret = true; ret = true;
} }
/* passive sockets msk will set the 'can_ack' after accept(), even
* if the first subflow may have the already the remote key handy
*/
can_ack = true;
opts->ext_copy.use_ack = 0; opts->ext_copy.use_ack = 0;
msk = mptcp_sk(subflow->conn); msk = mptcp_sk(subflow->conn);
if (!msk || !READ_ONCE(msk->can_ack)) { if (likely(msk && READ_ONCE(msk->can_ack))) {
ack_seq = msk->ack_seq;
} else if (subflow->can_ack) {
mptcp_crypto_key_sha(subflow->remote_key, NULL, &ack_seq);
ack_seq++;
} else {
can_ack = false;
}
if (unlikely(!can_ack)) {
*size = ALIGN(dss_size, 4); *size = ALIGN(dss_size, 4);
return ret; return ret;
} }
...@@ -375,7 +390,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, ...@@ -375,7 +390,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
dss_size += ack_size; dss_size += ack_size;
opts->ext_copy.data_ack = msk->ack_seq; opts->ext_copy.data_ack = ack_seq;
opts->ext_copy.ack64 = 1; opts->ext_copy.ack64 = 1;
opts->ext_copy.use_ack = 1; opts->ext_copy.use_ack = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment