aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/mptcp/protocol.c
diff options
context:
space:
mode:
authorChristoph Paasch <cpaasch@apple.com>2020-01-21 16:56:32 -0800
committerDavid S. Miller <davem@davemloft.net>2020-01-24 13:44:08 +0100
commitd22f4988ffecbe284e4d00e897525adbd0edd801 (patch)
treed1e7660e53298c99fa14f7cb973a5b0f04a71780 /net/mptcp/protocol.c
parentmptcp: parse and emit MP_CAPABLE option according to v1 spec (diff)
downloadwireguard-linux-d22f4988ffecbe284e4d00e897525adbd0edd801.tar.xz
wireguard-linux-d22f4988ffecbe284e4d00e897525adbd0edd801.zip
mptcp: process MP_CAPABLE data option
This patch implements the handling of MP_CAPABLE + data option, as per RFC 6824 bis / RFC 8684: MPTCP v1. On the server side we can receive the remote key after that the connection is established. We need to explicitly track the 'missing remote key' status and avoid emitting a mptcp ack until we get such info. When a late/retransmitted/OoO pkt carrying MP_CAPABLE[+data] option is received, we have to propagate the mptcp seq number info to the msk socket. To avoid ABBA locking issue, explicitly check for that in recvmsg(), where we own msk and subflow sock locks. The above also means that an established mp_capable subflow - still waiting for the remote key - can be 'downgraded' to plain TCP. Such change could potentially block a reader waiting for new data forever - as they hook to msk, while later wake-up after the downgrade will be on subflow only. The above issue is not handled here, we likely have to get rid of msk->fallback to handle that cleanly. Signed-off-by: Christoph Paasch <cpaasch@apple.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mptcp/protocol.c')
-rw-r--r--net/mptcp/protocol.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 45e482864a19..1b64dfaa5f63 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -30,7 +30,7 @@
*/
static struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk)
{
- if (!msk->subflow || mptcp_subflow_ctx(msk->subflow->sk)->fourth_ack)
+ if (!msk->subflow || READ_ONCE(msk->can_ack))
return NULL;
return msk->subflow;
@@ -651,17 +651,20 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
__mptcp_init_sock(new_mptcp_sock);
msk = mptcp_sk(new_mptcp_sock);
- msk->remote_key = subflow->remote_key;
msk->local_key = subflow->local_key;
msk->token = subflow->token;
msk->subflow = NULL;
mptcp_token_update_accept(newsk, new_mptcp_sock);
- mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
msk->write_seq = subflow->idsn + 1;
- ack_seq++;
- msk->ack_seq = ack_seq;
+ if (subflow->can_ack) {
+ msk->can_ack = true;
+ msk->remote_key = subflow->remote_key;
+ mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
+ ack_seq++;
+ msk->ack_seq = ack_seq;
+ }
newsk = new_mptcp_sock;
mptcp_copy_inaddrs(newsk, ssk);
list_add(&subflow->node, &msk->conn_list);
@@ -678,8 +681,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
* the receive path and process the pending ones
*/
lock_sock(ssk);
- subflow->map_seq = ack_seq;
- subflow->map_subflow_seq = 1;
subflow->rel_write_seq = 1;
subflow->tcp_sock = ssk;
subflow->conn = new_mptcp_sock;
@@ -795,6 +796,7 @@ void mptcp_finish_connect(struct sock *ssk)
WRITE_ONCE(msk->token, subflow->token);
WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
WRITE_ONCE(msk->ack_seq, ack_seq);
+ WRITE_ONCE(msk->can_ack, 1);
}
static void mptcp_sock_graft(struct sock *sk, struct socket *parent)