summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2017-11-25 14:18:36 +0100
committerDavid S. Miller <davem@davemloft.net>2017-12-01 21:06:24 +0100
commit779edd7348878a7376c0e3d0f96485c30b5f1b7d (patch)
tree9b1c645495f76394384e82ea30edb6ed29a55937
parentsctp: abandon the whole msg if one part of a fragmented message is abandoned (diff)
downloadlinux-779edd7348878a7376c0e3d0f96485c30b5f1b7d.tar.xz
linux-779edd7348878a7376c0e3d0f96485c30b5f1b7d.zip
sctp: do not abandon the other frags in unsent outq if one msg has outstanding frags
Now for the abandoned chunks in unsent outq, it would just free the chunks. Because no tsn is assigned to them yet, there's no need to send fwd tsn to peer, unlike for the abandoned chunks in sent outq. The problem is when parts of the msg have been sent and the other frags are still in unsent outq, if they are abandoned/dropped, the peer would never get this msg reassembled. So these frags in unsent outq can't be dropped if this msg already has outstanding frags. This patch does the check in sctp_chunk_abandoned and sctp_prsctp_prune_unsent. Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/chunk.c4
-rw-r--r--net/sctp/outqueue.c3
2 files changed, 6 insertions, 1 deletions
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 9213805b558d..7f8baa48e7c2 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -308,6 +308,10 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
if (chunk->msg->abandoned)
return 1;
+ if (!chunk->has_tsn &&
+ !(chunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG))
+ return 0;
+
if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
time_after(jiffies, chunk->msg->expires_at)) {
struct sctp_stream_out *streamout =
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 4ab164b5aad0..7d67feeeffc1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -407,7 +407,8 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) {
if (!chk->msg->abandoned &&
- (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
+ (!(chk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG) ||
+ !SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive))
continue;