mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
sctp: abandon the whole msg if one part of a fragmented message is abandoned
As rfc3758#section-3.1 demands:
A3) When a TSN is "abandoned", if it is part of a fragmented message,
all other TSN's within that fragmented message MUST be abandoned
at the same time.
Besides, if it couldn't handle this, the rest frags would never get
assembled in peer side.
This patch supports it by adding abandoned flag in sctp_datamsg, when
one chunk is being abandoned, set chunk->msg->abandoned as well. Next
time when checking for abandoned, go checking chunk->msg->abandoned
first.
Signed-off-by: Xin Long <[email protected]>
Acked-by: Marcelo Ricardo Leitner <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
parent
d30fc5126e
commit
e5f612969c
3 changed files with 17 additions and 5 deletions
|
|
@ -53,6 +53,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg)
|
|||
msg->send_failed = 0;
|
||||
msg->send_error = 0;
|
||||
msg->can_delay = 1;
|
||||
msg->abandoned = 0;
|
||||
msg->expires_at = 0;
|
||||
INIT_LIST_HEAD(&msg->chunks);
|
||||
}
|
||||
|
|
@ -304,6 +305,9 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
|
|||
if (!chunk->asoc->peer.prsctp_capable)
|
||||
return 0;
|
||||
|
||||
if (chunk->msg->abandoned)
|
||||
return 1;
|
||||
|
||||
if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
|
||||
time_after(jiffies, chunk->msg->expires_at)) {
|
||||
struct sctp_stream_out *streamout =
|
||||
|
|
@ -316,6 +320,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
|
|||
chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
|
||||
streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
|
||||
}
|
||||
chunk->msg->abandoned = 1;
|
||||
return 1;
|
||||
} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
|
||||
chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
|
||||
|
|
@ -324,10 +329,12 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
|
|||
|
||||
chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
|
||||
streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
|
||||
chunk->msg->abandoned = 1;
|
||||
return 1;
|
||||
} else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
|
||||
chunk->msg->expires_at &&
|
||||
time_after(jiffies, chunk->msg->expires_at)) {
|
||||
chunk->msg->abandoned = 1;
|
||||
return 1;
|
||||
}
|
||||
/* PRIO policy is processed by sendmsg, not here */
|
||||
|
|
|
|||
|
|
@ -364,10 +364,12 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
|
|||
list_for_each_entry_safe(chk, temp, queue, transmitted_list) {
|
||||
struct sctp_stream_out *streamout;
|
||||
|
||||
if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
|
||||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
|
||||
if (!chk->msg->abandoned &&
|
||||
(!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
|
||||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive))
|
||||
continue;
|
||||
|
||||
chk->msg->abandoned = 1;
|
||||
list_del_init(&chk->transmitted_list);
|
||||
sctp_insert_list(&asoc->outqueue.abandoned,
|
||||
&chk->transmitted_list);
|
||||
|
|
@ -404,10 +406,12 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
|
|||
q->sched->unsched_all(&asoc->stream);
|
||||
|
||||
list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) {
|
||||
if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
|
||||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
|
||||
if (!chk->msg->abandoned &&
|
||||
(!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
|
||||
chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive))
|
||||
continue;
|
||||
|
||||
chk->msg->abandoned = 1;
|
||||
sctp_sched_dequeue_common(q, chk);
|
||||
asoc->sent_cnt_removable--;
|
||||
asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
|
||||
|
|
|
|||
Loading…
Reference in a new issue