diff options
-rw-r--r-- | net/sctp/sm_statefuns.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8bc279219a72..9e58144f4851 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -5293,10 +5293,18 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5293 | * seems a bit troublesome in that frag_point varies based on | 5293 | * seems a bit troublesome in that frag_point varies based on |
5294 | * PMTU. In cases, such as loopback, this might be a rather | 5294 | * PMTU. In cases, such as loopback, this might be a rather |
5295 | * large spill over. | 5295 | * large spill over. |
5296 | * NOTE: If we have a full receive buffer here, we only renege if | ||
5297 | * our receiver can still make progress without the tsn being | ||
5298 | * received. We do this because in the event that the associations | ||
5299 | * receive queue is empty we are filling a leading gap, and since | ||
5300 | * reneging moves the gap to the end of the tsn stream, we are likely | ||
5301 | * to stall again very shortly. Avoiding the renege when we fill a | ||
5302 | * leading gap is a good heuristic for avoiding such steady state | ||
5303 | * stalls. | ||
5296 | */ | 5304 | */ |
5297 | if (!asoc->rwnd || asoc->rwnd_over || | 5305 | if (!asoc->rwnd || asoc->rwnd_over || |
5298 | (datalen > asoc->rwnd + asoc->frag_point) || | 5306 | (datalen > asoc->rwnd + asoc->frag_point) || |
5299 | rcvbuf_over) { | 5307 | (rcvbuf_over && (!skb_queue_len(&sk->sk_receive_queue)))) { |
5300 | 5308 | ||
5301 | /* If this is the next TSN, consider reneging to make | 5309 | /* If this is the next TSN, consider reneging to make |
5302 | * room. Note: Playing nice with a confused sender. A | 5310 | * room. Note: Playing nice with a confused sender. A |