diff options
Diffstat (limited to 'net/sctp/transport.c')
-rw-r--r-- | net/sctp/transport.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 37a1184d789f..165d54e07fcd 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -48,6 +48,7 @@ | |||
48 | * be incorporated into the next SCTP release. | 48 | * be incorporated into the next SCTP release. |
49 | */ | 49 | */ |
50 | 50 | ||
51 | #include <linux/slab.h> | ||
51 | #include <linux/types.h> | 52 | #include <linux/types.h> |
52 | #include <linux/random.h> | 53 | #include <linux/random.h> |
53 | #include <net/sctp/sctp.h> | 54 | #include <net/sctp/sctp.h> |
@@ -83,7 +84,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
83 | peer->fast_recovery = 0; | 84 | peer->fast_recovery = 0; |
84 | 85 | ||
85 | peer->last_time_heard = jiffies; | 86 | peer->last_time_heard = jiffies; |
86 | peer->last_time_used = jiffies; | ||
87 | peer->last_time_ecne_reduced = jiffies; | 87 | peer->last_time_ecne_reduced = jiffies; |
88 | 88 | ||
89 | peer->init_sent_count = 0; | 89 | peer->init_sent_count = 0; |
@@ -108,6 +108,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
108 | (unsigned long)peer); | 108 | (unsigned long)peer); |
109 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, | 109 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, |
110 | (unsigned long)peer); | 110 | (unsigned long)peer); |
111 | setup_timer(&peer->proto_unreach_timer, | ||
112 | sctp_generate_proto_unreach_event, (unsigned long)peer); | ||
111 | 113 | ||
112 | /* Initialize the 64-bit random nonce sent with heartbeat. */ | 114 | /* Initialize the 64-bit random nonce sent with heartbeat. */ |
113 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); | 115 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); |
@@ -171,6 +173,10 @@ void sctp_transport_free(struct sctp_transport *transport) | |||
171 | del_timer(&transport->T3_rtx_timer)) | 173 | del_timer(&transport->T3_rtx_timer)) |
172 | sctp_transport_put(transport); | 174 | sctp_transport_put(transport); |
173 | 175 | ||
176 | /* Delete the ICMP proto unreachable timer if it's active. */ | ||
177 | if (timer_pending(&transport->proto_unreach_timer) && | ||
178 | del_timer(&transport->proto_unreach_timer)) | ||
179 | sctp_association_put(transport->asoc); | ||
174 | 180 | ||
175 | sctp_transport_put(transport); | 181 | sctp_transport_put(transport); |
176 | } | 182 | } |
@@ -564,10 +570,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
564 | * to be done every RTO interval, we do it every hearbeat | 570 | * to be done every RTO interval, we do it every hearbeat |
565 | * interval. | 571 | * interval. |
566 | */ | 572 | */ |
567 | if (time_after(jiffies, transport->last_time_used + | 573 | transport->cwnd = max(transport->cwnd/2, |
568 | transport->rto)) | 574 | 4*transport->asoc->pathmtu); |
569 | transport->cwnd = max(transport->cwnd/2, | ||
570 | 4*transport->asoc->pathmtu); | ||
571 | break; | 575 | break; |
572 | } | 576 | } |
573 | 577 | ||
@@ -578,6 +582,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
578 | transport->cwnd, transport->ssthresh); | 582 | transport->cwnd, transport->ssthresh); |
579 | } | 583 | } |
580 | 584 | ||
585 | /* Apply Max.Burst limit to the congestion window: | ||
586 | * sctpimpguide-05 2.14.2 | ||
587 | * D) When the time comes for the sender to | ||
588 | * transmit new DATA chunks, the protocol parameter Max.Burst MUST | ||
589 | * first be applied to limit how many new DATA chunks may be sent. | ||
590 | * The limit is applied by adjusting cwnd as follows: | ||
591 | * if ((flightsize+ Max.Burst * MTU) < cwnd) | ||
592 | * cwnd = flightsize + Max.Burst * MTU | ||
593 | */ | ||
594 | |||
595 | void sctp_transport_burst_limited(struct sctp_transport *t) | ||
596 | { | ||
597 | struct sctp_association *asoc = t->asoc; | ||
598 | u32 old_cwnd = t->cwnd; | ||
599 | u32 max_burst_bytes; | ||
600 | |||
601 | if (t->burst_limited) | ||
602 | return; | ||
603 | |||
604 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); | ||
605 | if (max_burst_bytes < old_cwnd) { | ||
606 | t->cwnd = max_burst_bytes; | ||
607 | t->burst_limited = old_cwnd; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | /* Restore the old cwnd congestion window, after the burst had it's | ||
612 | * desired effect. | ||
613 | */ | ||
614 | void sctp_transport_burst_reset(struct sctp_transport *t) | ||
615 | { | ||
616 | if (t->burst_limited) { | ||
617 | t->cwnd = t->burst_limited; | ||
618 | t->burst_limited = 0; | ||
619 | } | ||
620 | } | ||
621 | |||
581 | /* What is the next timeout value for this transport? */ | 622 | /* What is the next timeout value for this transport? */ |
582 | unsigned long sctp_transport_timeout(struct sctp_transport *t) | 623 | unsigned long sctp_transport_timeout(struct sctp_transport *t) |
583 | { | 624 | { |
@@ -600,6 +641,7 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
600 | * (see Section 6.2.1) | 641 | * (see Section 6.2.1) |
601 | */ | 642 | */ |
602 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); | 643 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); |
644 | t->burst_limited = 0; | ||
603 | t->ssthresh = asoc->peer.i.a_rwnd; | 645 | t->ssthresh = asoc->peer.i.a_rwnd; |
604 | t->rto = asoc->rto_initial; | 646 | t->rto = asoc->rto_initial; |
605 | t->rtt = 0; | 647 | t->rtt = 0; |