Merge branch 'sctp-prsctp-chunk-fixes'
Xin Long says: ==================== sctp: a couple of fixes for chunks abandoned in prsctp Now when abandoning chunks in prsctp, it doesn't consider for frags in one msg, which would cause peer can never receive the whole frags for one msg to get them reassembled, these pieces of this msg will stay in the reasm queue forever and block the following chunks' receiving. This patchset is to fix them in patch 2 and 3, and also fix another issue for prsctp in patch 1. ==================== Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
b484d8a53e
|
@ -503,7 +503,8 @@ struct sctp_datamsg {
|
|||
/* Did the messenge fail to send? */
|
||||
int send_error;
|
||||
u8 send_failed:1,
|
||||
can_delay; /* should this message be Nagle delayed */
|
||||
can_delay:1, /* should this message be Nagle delayed */
|
||||
abandoned:1; /* should this message be abandoned */
|
||||
};
|
||||
|
||||
struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
|
||||
|
|
|
@ -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,13 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
|
|||
if (!chunk->asoc->peer.prsctp_capable)
|
||||
return 0;
|
||||
|
||||
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 =
|
||||
|
@ -316,6 +324,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 +333,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);
|
||||
|
@ -377,7 +379,8 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
|
|||
asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
|
||||
streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
|
||||
|
||||
if (!chk->tsn_gap_acked) {
|
||||
if (queue != &asoc->outqueue.retransmit &&
|
||||
!chk->tsn_gap_acked) {
|
||||
if (chk->transport)
|
||||
chk->transport->flight_size -=
|
||||
sctp_data_size(chk);
|
||||
|
@ -403,10 +406,13 @@ 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 &&
|
||||
(!(chk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG) ||
|
||||
!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)]++;
|
||||
|
@ -1434,7 +1440,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
|
|||
/* If this chunk has not been acked, stop
|
||||
* considering it as 'outstanding'.
|
||||
*/
|
||||
if (!tchunk->tsn_gap_acked) {
|
||||
if (transmitted_queue != &q->retransmit &&
|
||||
!tchunk->tsn_gap_acked) {
|
||||
if (tchunk->transport)
|
||||
tchunk->transport->flight_size -=
|
||||
sctp_data_size(tchunk);
|
||||
|
|
Загрузка…
Ссылка в новой задаче