aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-06-04 15:39:11 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-04 15:39:11 -0400
commit62aeaff5ccd96462b7077046357a6d7886175a57 (patch)
tree8ea18997997a8724222c86f659b559e12bcf4a86 /net/sctp
parenta6465234814efda9ed1dccdba852953f7508e827 (diff)
sctp: Start T3-RTX timer when fast retransmitting lowest TSN
When we are trying to fast retransmit the lowest outstanding TSN, we need to restart the T3-RTX timer, so that subsequent timeouts will correctly tag all the packets necessary for retransmissions. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Tested-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/outqueue.c42
-rw-r--r--net/sctp/transport.c4
2 files changed, 33 insertions, 13 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 59edfd25a19c..5d3c441e84d3 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -208,6 +208,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
208 INIT_LIST_HEAD(&q->sacked); 208 INIT_LIST_HEAD(&q->sacked);
209 INIT_LIST_HEAD(&q->abandoned); 209 INIT_LIST_HEAD(&q->abandoned);
210 210
211 q->fast_rtx = 0;
211 q->outstanding_bytes = 0; 212 q->outstanding_bytes = 0;
212 q->empty = 1; 213 q->empty = 1;
213 q->cork = 0; 214 q->cork = 0;
@@ -500,6 +501,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
500 case SCTP_RTXR_FAST_RTX: 501 case SCTP_RTXR_FAST_RTX:
501 SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); 502 SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
502 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); 503 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
504 q->fast_rtx = 1;
503 break; 505 break;
504 case SCTP_RTXR_PMTUD: 506 case SCTP_RTXR_PMTUD:
505 SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); 507 SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
@@ -543,10 +545,13 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
543 sctp_xmit_t status; 545 sctp_xmit_t status;
544 struct sctp_chunk *chunk, *chunk1; 546 struct sctp_chunk *chunk, *chunk1;
545 struct sctp_association *asoc; 547 struct sctp_association *asoc;
548 int fast_rtx;
546 int error = 0; 549 int error = 0;
550 int timer = 0;
547 551
548 asoc = q->asoc; 552 asoc = q->asoc;
549 lqueue = &q->retransmit; 553 lqueue = &q->retransmit;
554 fast_rtx = q->fast_rtx;
550 555
551 /* RFC 2960 6.3.3 Handle T3-rtx Expiration 556 /* RFC 2960 6.3.3 Handle T3-rtx Expiration
552 * 557 *
@@ -587,13 +592,12 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
587 switch (status) { 592 switch (status) {
588 case SCTP_XMIT_PMTU_FULL: 593 case SCTP_XMIT_PMTU_FULL:
589 /* Send this packet. */ 594 /* Send this packet. */
590 if ((error = sctp_packet_transmit(pkt)) == 0) 595 error = sctp_packet_transmit(pkt);
591 *start_timer = 1;
592 596
593 /* If we are retransmitting, we should only 597 /* If we are retransmitting, we should only
594 * send a single packet. 598 * send a single packet.
595 */ 599 */
596 if (rtx_timeout) { 600 if (rtx_timeout || fast_rtx) {
597 list_add(lchunk, lqueue); 601 list_add(lchunk, lqueue);
598 lchunk = NULL; 602 lchunk = NULL;
599 } 603 }
@@ -603,8 +607,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
603 607
604 case SCTP_XMIT_RWND_FULL: 608 case SCTP_XMIT_RWND_FULL:
605 /* Send this packet. */ 609 /* Send this packet. */
606 if ((error = sctp_packet_transmit(pkt)) == 0) 610 error = sctp_packet_transmit(pkt);
607 *start_timer = 1;
608 611
609 /* Stop sending DATA as there is no more room 612 /* Stop sending DATA as there is no more room
610 * at the receiver. 613 * at the receiver.
@@ -615,8 +618,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
615 618
616 case SCTP_XMIT_NAGLE_DELAY: 619 case SCTP_XMIT_NAGLE_DELAY:
617 /* Send this packet. */ 620 /* Send this packet. */
618 if ((error = sctp_packet_transmit(pkt)) == 0) 621 error = sctp_packet_transmit(pkt);
619 *start_timer = 1;
620 622
621 /* Stop sending DATA because of nagle delay. */ 623 /* Stop sending DATA because of nagle delay. */
622 list_add(lchunk, lqueue); 624 list_add(lchunk, lqueue);
@@ -635,7 +637,14 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
635 if (chunk->fast_retransmit > 0) 637 if (chunk->fast_retransmit > 0)
636 chunk->fast_retransmit = -1; 638 chunk->fast_retransmit = -1;
637 639
638 *start_timer = 1; 640 /* Force start T3-rtx timer when fast retransmitting
641 * the earliest outstanding TSN
642 */
643 if (!timer && fast_rtx &&
644 ntohl(chunk->subh.data_hdr->tsn) ==
645 asoc->ctsn_ack_point + 1)
646 timer = 2;
647
639 q->empty = 0; 648 q->empty = 0;
640 649
641 /* Retrieve a new chunk to bundle. */ 650 /* Retrieve a new chunk to bundle. */
@@ -643,12 +652,16 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
643 break; 652 break;
644 } 653 }
645 654
655 /* Set the timer if there were no errors */
656 if (!error && !timer)
657 timer = 1;
658
646 /* If we are here due to a retransmit timeout or a fast 659 /* If we are here due to a retransmit timeout or a fast
647 * retransmit and if there are any chunks left in the retransmit 660 * retransmit and if there are any chunks left in the retransmit
648 * queue that could not fit in the PMTU sized packet, they need 661 * queue that could not fit in the PMTU sized packet, they need
649 * to be marked as ineligible for a subsequent fast retransmit. 662 * to be marked as ineligible for a subsequent fast retransmit.
650 */ 663 */
651 if (rtx_timeout && !lchunk) { 664 if (rtx_timeout && fast_rtx) {
652 list_for_each_entry(chunk1, lqueue, transmitted_list) { 665 list_for_each_entry(chunk1, lqueue, transmitted_list) {
653 if (chunk1->fast_retransmit > 0) 666 if (chunk1->fast_retransmit > 0)
654 chunk1->fast_retransmit = -1; 667 chunk1->fast_retransmit = -1;
@@ -656,6 +669,12 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
656 } 669 }
657 } 670 }
658 671
672 *start_timer = timer;
673
674 /* Clear fast retransmit hint */
675 if (fast_rtx)
676 q->fast_rtx = 0;
677
659 return error; 678 return error;
660} 679}
661 680
@@ -862,7 +881,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
862 rtx_timeout, &start_timer); 881 rtx_timeout, &start_timer);
863 882
864 if (start_timer) 883 if (start_timer)
865 sctp_transport_reset_timers(transport); 884 sctp_transport_reset_timers(transport,
885 start_timer-1);
866 886
867 /* This can happen on COOKIE-ECHO resend. Only 887 /* This can happen on COOKIE-ECHO resend. Only
868 * one chunk can get bundled with a COOKIE-ECHO. 888 * one chunk can get bundled with a COOKIE-ECHO.
@@ -977,7 +997,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
977 list_add_tail(&chunk->transmitted_list, 997 list_add_tail(&chunk->transmitted_list,
978 &transport->transmitted); 998 &transport->transmitted);
979 999
980 sctp_transport_reset_timers(transport); 1000 sctp_transport_reset_timers(transport, start_timer-1);
981 1001
982 q->empty = 0; 1002 q->empty = 0;
983 1003
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 9647fb277221..3f34f61221ec 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -191,7 +191,7 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
191/* Start T3_rtx timer if it is not already running and update the heartbeat 191/* Start T3_rtx timer if it is not already running and update the heartbeat
192 * timer. This routine is called every time a DATA chunk is sent. 192 * timer. This routine is called every time a DATA chunk is sent.
193 */ 193 */
194void sctp_transport_reset_timers(struct sctp_transport *transport) 194void sctp_transport_reset_timers(struct sctp_transport *transport, int force)
195{ 195{
196 /* RFC 2960 6.3.2 Retransmission Timer Rules 196 /* RFC 2960 6.3.2 Retransmission Timer Rules
197 * 197 *
@@ -201,7 +201,7 @@ void sctp_transport_reset_timers(struct sctp_transport *transport)
201 * address. 201 * address.
202 */ 202 */
203 203
204 if (!timer_pending(&transport->T3_rtx_timer)) 204 if (force || !timer_pending(&transport->T3_rtx_timer))
205 if (!mod_timer(&transport->T3_rtx_timer, 205 if (!mod_timer(&transport->T3_rtx_timer,
206 jiffies + transport->rto)) 206 jiffies + transport->rto))
207 sctp_transport_hold(transport); 207 sctp_transport_hold(transport);