diff --git a/[refs] b/[refs] index 748d769ed7da..5cf51c70e8ac 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d7c2c9e3977e4312d093ac092761798d4d47c9e0 +refs/heads/master: d5b9f4c083b0e3102f3101545279f623680cb3a0 diff --git a/trunk/net/sctp/sm_statefuns.c b/trunk/net/sctp/sm_statefuns.c index 8bc279219a72..9e58144f4851 100644 --- a/trunk/net/sctp/sm_statefuns.c +++ b/trunk/net/sctp/sm_statefuns.c @@ -5293,10 +5293,18 @@ static int sctp_eat_data(const struct sctp_association *asoc, * seems a bit troublesome in that frag_point varies based on * PMTU. In cases, such as loopback, this might be a rather * large spill over. + * NOTE: If we have a full receive buffer here, we only renege if + * our receiver can still make progress without the tsn being + * received. We do this because in the event that the associations + * receive queue is empty we are filling a leading gap, and since + * reneging moves the gap to the end of the tsn stream, we are likely + * to stall again very shortly. Avoiding the renege when we fill a + * leading gap is a good heuristic for avoiding such steady state + * stalls. */ if (!asoc->rwnd || asoc->rwnd_over || (datalen > asoc->rwnd + asoc->frag_point) || - rcvbuf_over) { + (rcvbuf_over && (!skb_queue_len(&sk->sk_receive_queue)))) { /* If this is the next TSN, consider reneging to make * room. Note: Playing nice with a confused sender. A