So that we keep per subflow unacked sequence number consistent; since we update only per socket data, no additional locking is required. Subflow and msk unacked seq are updated at different stages to keep the locking schema simple. Signed-off-by: Paolo Abeni --- rfc v1 -> rfc v2: - initialize subflow snd_una on subflow connect()/accept() --- net/mptcp/options.c | 31 +++++++++++++++++++++++++------ net/mptcp/protocol.c | 2 ++ net/mptcp/protocol.h | 1 + 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 0e7abcea5bae..e0895834ff82 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -524,6 +524,21 @@ bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, return false; } +static u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit) +{ + u32 old_ack32, cur_ack32; + + if (use_64bit) + return cur_ack; + + old_ack32 = (u32)old_ack; + cur_ack32 = (u32)cur_ack; + cur_ack = (old_ack & GENMASK_ULL(63, 32)) + cur_ack32; + if (unlikely(before(cur_ack32, old_ack32))) + return cur_ack + (1LL<<32); + return cur_ack; +} + void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, struct tcp_options_received *opt_rx) { @@ -537,6 +552,16 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, if (!mp_opt->dss) return; + /* we can't wait for recvmsg() to update the ack_seq, otherwise + * monodirectional flows will stuck + */ + if (mp_opt->use_ack) { + struct subflow_context *subflow = subflow_ctx(sk); + + subflow->snd_una = expand_ack(subflow->snd_una, + mp_opt->data_ack, mp_opt->ack64); + } + mpext = skb_ext_add(skb, SKB_EXT_MPTCP); if (!mpext) return; @@ -553,12 +578,6 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb, mpext->use_checksum = mp_opt->use_checksum; } - if (mp_opt->use_ack) { - mpext->data_ack = mp_opt->data_ack; - mpext->use_ack = 1; - mpext->ack64 = mp_opt->ack64; - } - mpext->data_fin = mp_opt->data_fin; if (msk) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 5b7ddbe64e4b..65f7cc4712ef 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -674,6 +674,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, subflow->map_subflow_seq = 1; subflow->rel_write_seq = 1; subflow->tcp_sock = new_sock; + subflow->snd_una = msk->write_seq; newsk = new_mptcp_sock; subflow->conn = new_mptcp_sock; list_add(&subflow->node, &msk->conn_list); @@ -809,6 +810,7 @@ void mptcp_finish_connect(struct sock *sk, int mp_capable) subflow->map_seq = ack_seq; subflow->map_subflow_seq = 1; subflow->rel_write_seq = 1; + subflow->snd_una = msk->write_seq; list_add(&subflow->node, &msk->conn_list); msk->subflow = NULL; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 9f261ee31917..e37fd4bcd904 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -165,6 +165,7 @@ struct subflow_context { u32 token; u32 rel_write_seq; u64 idsn; + u64 snd_una; u64 map_seq; u32 map_subflow_seq; u32 ssn_offset; -- 2.21.0