@@ -172,6 +172,10 @@ void mptcp_data_ready(struct sock *sk)
if (test_and_set_bit(MPTCP_WORK_DATA_READY, &msk->flags))
return;
+ /* don't schedule if mptcp sk is (still) over limit */
+ if (atomic_read(&sk->sk_rmem_alloc) > READ_ONCE(sk->sk_rcvbuf))
+ return;
+
sock_hold(sk);
if (!schedule_work(&msk->rtx_work))
sock_put(sk);
@@ -699,7 +703,7 @@ static void __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
struct sock *sk = (struct sock *)msk;
__skb_unlink(skb, &ssk->sk_receive_queue);
- skb_orphan(skb);
+ skb_set_owner_r(skb, sk);
__skb_queue_tail(&sk->sk_receive_queue, skb);
msk->ack_seq += copy_len;
@@ -717,6 +721,7 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
struct sock *ssk;
bool more_data_avail;
struct tcp_sock *tp;
+ int rcvbuf;
ssk = mptcp_subflow_recv_lookup(msk);
if (!ssk)
@@ -726,6 +731,10 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
lock_sock(ssk);
+ rcvbuf = max(ssk->sk_rcvbuf, sk->sk_rcvbuf);
+ if (rcvbuf > sk->sk_rcvbuf)
+ sk->sk_rcvbuf = rcvbuf;
+
tp = tcp_sk(ssk);
do {
u32 map_remaining, offset;
@@ -741,6 +750,11 @@ static bool __mptcp_move_skbs(struct mptcp_sock *msk)
if (!skb)
break;
+ if (!sk_rmem_schedule(sk, skb, skb->truesize)) {
+ done = true;
+ break;
+ }
+
offset = seq - TCP_SKB_CB(skb)->seq;
fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN;
if (fin) {
v2: adjust rcvbuf outside of loop. Signed-off-by: Florian Westphal <fw@strlen.de> --- net/mptcp/protocol.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)