aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/transport.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-06-04 15:38:43 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-04 15:38:43 -0400
commita6465234814efda9ed1dccdba852953f7508e827 (patch)
treed2aa1f6c5776b0bd85a1ae9652ab47b18a4ba744 /net/sctp/transport.c
parent159c6bea37c54dfae44409467e0f17600722d541 (diff)
sctp: Correctly implement Fast Recovery cwnd manipulations.
Correctly keep track of Fast Recovery state and do not reduce congestion window multiple times during sucht state. 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/transport.c')
-rw-r--r--net/sctp/transport.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 62082e7b7972..9647fb277221 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -79,6 +79,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
79 peer->rttvar = 0; 79 peer->rttvar = 0;
80 peer->srtt = 0; 80 peer->srtt = 0;
81 peer->rto_pending = 0; 81 peer->rto_pending = 0;
82 peer->fast_recovery = 0;
82 83
83 peer->last_time_heard = jiffies; 84 peer->last_time_heard = jiffies;
84 peer->last_time_used = jiffies; 85 peer->last_time_used = jiffies;
@@ -403,11 +404,16 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
403 cwnd = transport->cwnd; 404 cwnd = transport->cwnd;
404 flight_size = transport->flight_size; 405 flight_size = transport->flight_size;
405 406
407 /* See if we need to exit Fast Recovery first */
408 if (transport->fast_recovery &&
409 TSN_lte(transport->fast_recovery_exit, sack_ctsn))
410 transport->fast_recovery = 0;
411
406 /* The appropriate cwnd increase algorithm is performed if, and only 412 /* The appropriate cwnd increase algorithm is performed if, and only
407 * if the cumulative TSN has advanced and the congestion window is 413 * if the cumulative TSN whould advanced and the congestion window is
408 * being fully utilized. 414 * being fully utilized.
409 */ 415 */
410 if ((transport->asoc->ctsn_ack_point >= sack_ctsn) || 416 if (TSN_lte(sack_ctsn, transport->asoc->ctsn_ack_point) ||
411 (flight_size < cwnd)) 417 (flight_size < cwnd))
412 return; 418 return;
413 419
@@ -416,17 +422,23 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
416 pmtu = transport->asoc->pathmtu; 422 pmtu = transport->asoc->pathmtu;
417 423
418 if (cwnd <= ssthresh) { 424 if (cwnd <= ssthresh) {
419 /* RFC 2960 7.2.1, sctpimpguide-05 2.14.2 When cwnd is less 425 /* RFC 4960 7.2.1
420 * than or equal to ssthresh an SCTP endpoint MUST use the 426 * o When cwnd is less than or equal to ssthresh, an SCTP
421 * slow start algorithm to increase cwnd only if the current 427 * endpoint MUST use the slow-start algorithm to increase
422 * congestion window is being fully utilized and an incoming 428 * cwnd only if the current congestion window is being fully
423 * SACK advances the Cumulative TSN Ack Point. Only when these 429 * utilized, an incoming SACK advances the Cumulative TSN
424 * two conditions are met can the cwnd be increased otherwise 430 * Ack Point, and the data sender is not in Fast Recovery.
425 * the cwnd MUST not be increased. If these conditions are met 431 * Only when these three conditions are met can the cwnd be
426 * then cwnd MUST be increased by at most the lesser of 432 * increased; otherwise, the cwnd MUST not be increased.
427 * 1) the total size of the previously outstanding DATA 433 * If these conditions are met, then cwnd MUST be increased
428 * chunk(s) acknowledged, and 2) the destination's path MTU. 434 * by, at most, the lesser of 1) the total size of the
435 * previously outstanding DATA chunk(s) acknowledged, and
436 * 2) the destination's path MTU. This upper bound protects
437 * against the ACK-Splitting attack outlined in [SAVAGE99].
429 */ 438 */
439 if (transport->fast_recovery)
440 return;
441
430 if (bytes_acked > pmtu) 442 if (bytes_acked > pmtu)
431 cwnd += pmtu; 443 cwnd += pmtu;
432 else 444 else
@@ -502,6 +514,13 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
502 * cwnd = ssthresh 514 * cwnd = ssthresh
503 * partial_bytes_acked = 0 515 * partial_bytes_acked = 0
504 */ 516 */
517 if (transport->fast_recovery)
518 return;
519
520 /* Mark Fast recovery */
521 transport->fast_recovery = 1;
522 transport->fast_recovery_exit = transport->asoc->next_tsn - 1;
523
505 transport->ssthresh = max(transport->cwnd/2, 524 transport->ssthresh = max(transport->cwnd/2,
506 4*transport->asoc->pathmtu); 525 4*transport->asoc->pathmtu);
507 transport->cwnd = transport->ssthresh; 526 transport->cwnd = transport->ssthresh;
@@ -586,6 +605,7 @@ void sctp_transport_reset(struct sctp_transport *t)
586 t->flight_size = 0; 605 t->flight_size = 0;
587 t->error_count = 0; 606 t->error_count = 0;
588 t->rto_pending = 0; 607 t->rto_pending = 0;
608 t->fast_recovery = 0;
589 609
590 /* Initialize the state information for SFR-CACC */ 610 /* Initialize the state information for SFR-CACC */
591 t->cacc.changeover_active = 0; 611 t->cacc.changeover_active = 0;