diff options
| -rw-r--r-- | include/net/sctp/structs.h | 8 | ||||
| -rw-r--r-- | net/sctp/transport.c | 44 |
2 files changed, 39 insertions, 13 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 917d425f0542..67592072a32e 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -902,7 +902,10 @@ struct sctp_transport { | |||
| 902 | * calculation completes (i.e. the DATA chunk | 902 | * calculation completes (i.e. the DATA chunk |
| 903 | * is SACK'd) clear this flag. | 903 | * is SACK'd) clear this flag. |
| 904 | */ | 904 | */ |
| 905 | int rto_pending; | 905 | __u8 rto_pending; |
| 906 | |||
| 907 | /* Flag to track the current fast recovery state */ | ||
| 908 | __u8 fast_recovery; | ||
| 906 | 909 | ||
| 907 | /* | 910 | /* |
| 908 | * These are the congestion stats. | 911 | * These are the congestion stats. |
| @@ -921,6 +924,9 @@ struct sctp_transport { | |||
| 921 | /* Data that has been sent, but not acknowledged. */ | 924 | /* Data that has been sent, but not acknowledged. */ |
| 922 | __u32 flight_size; | 925 | __u32 flight_size; |
| 923 | 926 | ||
| 927 | /* TSN marking the fast recovery exit point */ | ||
| 928 | __u32 fast_recovery_exit; | ||
| 929 | |||
| 924 | /* Destination */ | 930 | /* Destination */ |
| 925 | struct dst_entry *dst; | 931 | struct dst_entry *dst; |
| 926 | /* Source address. */ | 932 | /* Source address. */ |
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; |
