aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/outqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r--net/sctp/outqueue.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 582585393d35..8081476ed313 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -382,17 +382,18 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
382} 382}
383 383
384static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, 384static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
385 struct sctp_sndrcvinfo *sinfo, 385 struct sctp_sndrcvinfo *sinfo, int msg_len)
386 struct list_head *queue, int msg_len)
387{ 386{
387 struct sctp_outq *q = &asoc->outqueue;
388 struct sctp_chunk *chk, *temp; 388 struct sctp_chunk *chk, *temp;
389 389
390 list_for_each_entry_safe(chk, temp, queue, list) { 390 list_for_each_entry_safe(chk, temp, &q->out_chunk_list, list) {
391 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || 391 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
392 chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) 392 chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
393 continue; 393 continue;
394 394
395 list_del_init(&chk->list); 395 list_del_init(&chk->list);
396 q->out_qlen -= chk->skb->len;
396 asoc->sent_cnt_removable--; 397 asoc->sent_cnt_removable--;
397 asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; 398 asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
398 399
@@ -431,9 +432,7 @@ void sctp_prsctp_prune(struct sctp_association *asoc,
431 return; 432 return;
432 } 433 }
433 434
434 sctp_prsctp_prune_unsent(asoc, sinfo, 435 sctp_prsctp_prune_unsent(asoc, sinfo, msg_len);
435 &asoc->outqueue.out_chunk_list,
436 msg_len);
437} 436}
438 437
439/* Mark all the eligible packets on a transport for retransmission. */ 438/* Mark all the eligible packets on a transport for retransmission. */
@@ -507,8 +506,6 @@ void sctp_retransmit_mark(struct sctp_outq *q,
507 transport->rto_pending = 0; 506 transport->rto_pending = 0;
508 } 507 }
509 508
510 chunk->resent = 1;
511
512 /* Move the chunk to the retransmit queue. The chunks 509 /* Move the chunk to the retransmit queue. The chunks
513 * on the retransmit queue are always kept in order. 510 * on the retransmit queue are always kept in order.
514 */ 511 */
@@ -917,22 +914,28 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
917 case SCTP_CID_ECN_ECNE: 914 case SCTP_CID_ECN_ECNE:
918 case SCTP_CID_ASCONF: 915 case SCTP_CID_ASCONF:
919 case SCTP_CID_FWD_TSN: 916 case SCTP_CID_FWD_TSN:
917 case SCTP_CID_RECONF:
920 status = sctp_packet_transmit_chunk(packet, chunk, 918 status = sctp_packet_transmit_chunk(packet, chunk,
921 one_packet, gfp); 919 one_packet, gfp);
922 if (status != SCTP_XMIT_OK) { 920 if (status != SCTP_XMIT_OK) {
923 /* put the chunk back */ 921 /* put the chunk back */
924 list_add(&chunk->list, &q->control_chunk_list); 922 list_add(&chunk->list, &q->control_chunk_list);
925 } else { 923 break;
926 asoc->stats.octrlchunks++;
927 /* PR-SCTP C5) If a FORWARD TSN is sent, the
928 * sender MUST assure that at least one T3-rtx
929 * timer is running.
930 */
931 if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
932 sctp_transport_reset_t3_rtx(transport);
933 transport->last_time_sent = jiffies;
934 }
935 } 924 }
925
926 asoc->stats.octrlchunks++;
927 /* PR-SCTP C5) If a FORWARD TSN is sent, the
928 * sender MUST assure that at least one T3-rtx
929 * timer is running.
930 */
931 if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
932 sctp_transport_reset_t3_rtx(transport);
933 transport->last_time_sent = jiffies;
934 }
935
936 if (chunk == asoc->strreset_chunk)
937 sctp_transport_reset_reconf_timer(transport);
938
936 break; 939 break;
937 940
938 default: 941 default:
@@ -1018,11 +1021,12 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
1018 1021
1019 /* Finally, transmit new packets. */ 1022 /* Finally, transmit new packets. */
1020 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { 1023 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
1024 __u32 sid = ntohs(chunk->subh.data_hdr->stream);
1025
1021 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid 1026 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid
1022 * stream identifier. 1027 * stream identifier.
1023 */ 1028 */
1024 if (chunk->sinfo.sinfo_stream >= 1029 if (chunk->sinfo.sinfo_stream >= asoc->stream->outcnt) {
1025 asoc->c.sinit_num_ostreams) {
1026 1030
1027 /* Mark as failed send. */ 1031 /* Mark as failed send. */
1028 sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM); 1032 sctp_chunk_fail(chunk, SCTP_ERROR_INV_STRM);
@@ -1040,6 +1044,11 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
1040 continue; 1044 continue;
1041 } 1045 }
1042 1046
1047 if (asoc->stream->out[sid].state == SCTP_STREAM_CLOSED) {
1048 sctp_outq_head_data(q, chunk);
1049 goto sctp_flush_out;
1050 }
1051
1043 /* If there is a specified transport, use it. 1052 /* If there is a specified transport, use it.
1044 * Otherwise, we want to use the active path. 1053 * Otherwise, we want to use the active path.
1045 */ 1054 */
@@ -1050,7 +1059,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
1050 (new_transport->state == SCTP_PF))) 1059 (new_transport->state == SCTP_PF)))
1051 new_transport = asoc->peer.active_path; 1060 new_transport = asoc->peer.active_path;
1052 if (new_transport->state == SCTP_UNCONFIRMED) { 1061 if (new_transport->state == SCTP_UNCONFIRMED) {
1053 WARN_ONCE(1, "Atempt to send packet on unconfirmed path."); 1062 WARN_ONCE(1, "Attempt to send packet on unconfirmed path.");
1054 sctp_chunk_fail(chunk, 0); 1063 sctp_chunk_fail(chunk, 0);
1055 sctp_chunk_free(chunk); 1064 sctp_chunk_free(chunk);
1056 continue; 1065 continue;
@@ -1439,7 +1448,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1439 * instance). 1448 * instance).
1440 */ 1449 */
1441 if (!tchunk->tsn_gap_acked && 1450 if (!tchunk->tsn_gap_acked &&
1442 !tchunk->resent && 1451 !sctp_chunk_retransmitted(tchunk) &&
1443 tchunk->rtt_in_progress) { 1452 tchunk->rtt_in_progress) {
1444 tchunk->rtt_in_progress = 0; 1453 tchunk->rtt_in_progress = 0;
1445 rtt = jiffies - tchunk->sent_at; 1454 rtt = jiffies - tchunk->sent_at;
@@ -1643,7 +1652,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1643 1652
1644 if (forward_progress) { 1653 if (forward_progress) {
1645 if (transport->dst) 1654 if (transport->dst)
1646 dst_confirm(transport->dst); 1655 sctp_transport_dst_confirm(transport);
1647 } 1656 }
1648 } 1657 }
1649 1658