Skip to content

Commit

Permalink
sctp: Correctly implement Fast Recovery cwnd manipulations.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed Jun 4, 2008
1 parent 159c6be commit a646523
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 13 deletions.
8 changes: 7 additions & 1 deletion include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,10 @@ struct sctp_transport {
* calculation completes (i.e. the DATA chunk
* is SACK'd) clear this flag.
*/
int rto_pending;
__u8 rto_pending;

/* Flag to track the current fast recovery state */
__u8 fast_recovery;

/*
* These are the congestion stats.
Expand All @@ -921,6 +924,9 @@ struct sctp_transport {
/* Data that has been sent, but not acknowledged. */
__u32 flight_size;

/* TSN marking the fast recovery exit point */
__u32 fast_recovery_exit;

/* Destination */
struct dst_entry *dst;
/* Source address. */
Expand Down
44 changes: 32 additions & 12 deletions net/sctp/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->rttvar = 0;
peer->srtt = 0;
peer->rto_pending = 0;
peer->fast_recovery = 0;

peer->last_time_heard = jiffies;
peer->last_time_used = jiffies;
Expand Down Expand Up @@ -403,11 +404,16 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
cwnd = transport->cwnd;
flight_size = transport->flight_size;

/* See if we need to exit Fast Recovery first */
if (transport->fast_recovery &&
TSN_lte(transport->fast_recovery_exit, sack_ctsn))
transport->fast_recovery = 0;

/* The appropriate cwnd increase algorithm is performed if, and only
* if the cumulative TSN has advanced and the congestion window is
* if the cumulative TSN whould advanced and the congestion window is
* being fully utilized.
*/
if ((transport->asoc->ctsn_ack_point >= sack_ctsn) ||
if (TSN_lte(sack_ctsn, transport->asoc->ctsn_ack_point) ||
(flight_size < cwnd))
return;

Expand All @@ -416,17 +422,23 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
pmtu = transport->asoc->pathmtu;

if (cwnd <= ssthresh) {
/* RFC 2960 7.2.1, sctpimpguide-05 2.14.2 When cwnd is less
* than or equal to ssthresh an SCTP endpoint MUST use the
* slow start algorithm to increase cwnd only if the current
* congestion window is being fully utilized and an incoming
* SACK advances the Cumulative TSN Ack Point. Only when these
* two conditions are met can the cwnd be increased otherwise
* the cwnd MUST not be increased. If these conditions are met
* then cwnd MUST be increased by at most the lesser of
* 1) the total size of the previously outstanding DATA
* chunk(s) acknowledged, and 2) the destination's path MTU.
/* RFC 4960 7.2.1
* o When cwnd is less than or equal to ssthresh, an SCTP
* endpoint MUST use the slow-start algorithm to increase
* cwnd only if the current congestion window is being fully
* utilized, an incoming SACK advances the Cumulative TSN
* Ack Point, and the data sender is not in Fast Recovery.
* Only when these three conditions are met can the cwnd be
* increased; otherwise, the cwnd MUST not be increased.
* If these conditions are met, then cwnd MUST be increased
* by, at most, the lesser of 1) the total size of the
* previously outstanding DATA chunk(s) acknowledged, and
* 2) the destination's path MTU. This upper bound protects
* against the ACK-Splitting attack outlined in [SAVAGE99].
*/
if (transport->fast_recovery)
return;

if (bytes_acked > pmtu)
cwnd += pmtu;
else
Expand Down Expand Up @@ -502,6 +514,13 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
* cwnd = ssthresh
* partial_bytes_acked = 0
*/
if (transport->fast_recovery)
return;

/* Mark Fast recovery */
transport->fast_recovery = 1;
transport->fast_recovery_exit = transport->asoc->next_tsn - 1;

transport->ssthresh = max(transport->cwnd/2,
4*transport->asoc->pathmtu);
transport->cwnd = transport->ssthresh;
Expand Down Expand Up @@ -586,6 +605,7 @@ void sctp_transport_reset(struct sctp_transport *t)
t->flight_size = 0;
t->error_count = 0;
t->rto_pending = 0;
t->fast_recovery = 0;

/* Initialize the state information for SFR-CACC */
t->cacc.changeover_active = 0;
Expand Down

0 comments on commit a646523

Please sign in to comment.