summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mptcp/options.c32
-rw-r--r--net/mptcp/protocol.h1
2 files changed, 31 insertions, 2 deletions
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index b4237e50e23f..85fcc378c711 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -1001,6 +1001,31 @@ u64 __mptcp_expand_seq(u64 old_seq, u64 cur_seq)
return cur_seq;
}
+static void rwin_update(struct mptcp_sock *msk, struct sock *ssk,
+ struct sk_buff *skb)
+{
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+ struct tcp_sock *tp = tcp_sk(ssk);
+ u64 mptcp_rcv_wnd;
+
+ /* Avoid touching extra cachelines if TCP is going to accept this
+ * skb without filling the TCP-level window even with a possibly
+ * outdated mptcp-level rwin.
+ */
+ if (!skb->len || skb->len < tcp_receive_window(tp))
+ return;
+
+ mptcp_rcv_wnd = READ_ONCE(msk->rcv_wnd_sent);
+ if (!after64(mptcp_rcv_wnd, subflow->rcv_wnd_sent))
+ return;
+
+ /* Some other subflow grew the mptcp-level rwin since rcv_wup,
+ * resync.
+ */
+ tp->rcv_wnd += mptcp_rcv_wnd - subflow->rcv_wnd_sent;
+ subflow->rcv_wnd_sent = mptcp_rcv_wnd;
+}
+
static void ack_update_msk(struct mptcp_sock *msk,
struct sock *ssk,
struct mptcp_options_received *mp_opt)
@@ -1160,6 +1185,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
*/
if (mp_opt.use_ack)
ack_update_msk(msk, sk, &mp_opt);
+ rwin_update(msk, sk, skb);
/* Zero-data-length packets are dropped by the caller and not
* propagated to the MPTCP layer, so the skb extension does not
@@ -1212,7 +1238,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
static void mptcp_set_rwin(const struct tcp_sock *tp)
{
const struct sock *ssk = (const struct sock *)tp;
- const struct mptcp_subflow_context *subflow;
+ struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk;
u64 ack_seq;
@@ -1221,8 +1247,10 @@ static void mptcp_set_rwin(const struct tcp_sock *tp)
ack_seq = READ_ONCE(msk->ack_seq) + tp->rcv_wnd;
- if (after64(ack_seq, READ_ONCE(msk->rcv_wnd_sent)))
+ if (after64(ack_seq, READ_ONCE(msk->rcv_wnd_sent))) {
WRITE_ONCE(msk->rcv_wnd_sent, ack_seq);
+ subflow->rcv_wnd_sent = ack_seq;
+ }
}
static void mptcp_track_rwin(const struct tcp_sock *tp)
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index c93399d11650..3450c3cd015a 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -417,6 +417,7 @@ struct mptcp_subflow_context {
u64 remote_key;
u64 idsn;
u64 map_seq;
+ u64 rcv_wnd_sent;
u32 snd_isn;
u32 token;
u32 rel_write_seq;