aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/structs.h4
-rw-r--r--net/sctp/associola.c1
-rw-r--r--net/sctp/output.c23
-rw-r--r--net/sctp/outqueue.c15
-rw-r--r--net/sctp/transport.c38
5 files changed, 58 insertions, 23 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ac794a6823eb..bc3f8d879c5c 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -942,6 +942,8 @@ struct sctp_transport {
942 /* Data that has been sent, but not acknowledged. */ 942 /* Data that has been sent, but not acknowledged. */
943 __u32 flight_size; 943 __u32 flight_size;
944 944
945 __u32 burst_limited; /* Holds old cwnd when max.burst is applied */
946
945 /* TSN marking the fast recovery exit point */ 947 /* TSN marking the fast recovery exit point */
946 __u32 fast_recovery_exit; 948 __u32 fast_recovery_exit;
947 949
@@ -1070,6 +1072,8 @@ void sctp_transport_put(struct sctp_transport *);
1070void sctp_transport_update_rto(struct sctp_transport *, __u32); 1072void sctp_transport_update_rto(struct sctp_transport *, __u32);
1071void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32); 1073void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
1072void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t); 1074void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
1075void sctp_transport_burst_limited(struct sctp_transport *);
1076void sctp_transport_burst_reset(struct sctp_transport *);
1073unsigned long sctp_transport_timeout(struct sctp_transport *); 1077unsigned long sctp_transport_timeout(struct sctp_transport *);
1074void sctp_transport_reset(struct sctp_transport *); 1078void sctp_transport_reset(struct sctp_transport *);
1075void sctp_transport_update_pmtu(struct sctp_transport *, u32); 1079void sctp_transport_update_pmtu(struct sctp_transport *, u32);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 37e982510bea..880dae2ca87b 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -738,6 +738,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
738 738
739 peer->partial_bytes_acked = 0; 739 peer->partial_bytes_acked = 0;
740 peer->flight_size = 0; 740 peer->flight_size = 0;
741 peer->burst_limited = 0;
741 742
742 /* Set the transport's RTO.initial value */ 743 /* Set the transport's RTO.initial value */
743 peer->rto = asoc->rto_initial; 744 peer->rto = asoc->rto_initial;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 9e8e0ea844be..b210d2077e28 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -615,7 +615,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
615 sctp_xmit_t retval = SCTP_XMIT_OK; 615 sctp_xmit_t retval = SCTP_XMIT_OK;
616 size_t datasize, rwnd, inflight, flight_size; 616 size_t datasize, rwnd, inflight, flight_size;
617 struct sctp_transport *transport = packet->transport; 617 struct sctp_transport *transport = packet->transport;
618 __u32 max_burst_bytes;
619 struct sctp_association *asoc = transport->asoc; 618 struct sctp_association *asoc = transport->asoc;
620 struct sctp_outq *q = &asoc->outqueue; 619 struct sctp_outq *q = &asoc->outqueue;
621 620
@@ -648,28 +647,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
648 } 647 }
649 } 648 }
650 649
651 /* sctpimpguide-05 2.14.2
652 * D) When the time comes for the sender to
653 * transmit new DATA chunks, the protocol parameter Max.Burst MUST
654 * first be applied to limit how many new DATA chunks may be sent.
655 * The limit is applied by adjusting cwnd as follows:
656 * if ((flightsize + Max.Burst * MTU) < cwnd)
657 * cwnd = flightsize + Max.Burst * MTU
658 */
659 max_burst_bytes = asoc->max_burst * asoc->pathmtu;
660 if ((flight_size + max_burst_bytes) < transport->cwnd) {
661 transport->cwnd = flight_size + max_burst_bytes;
662 SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: "
663 "transport: %p, cwnd: %d, "
664 "ssthresh: %d, flight_size: %d, "
665 "pba: %d\n",
666 __func__, transport,
667 transport->cwnd,
668 transport->ssthresh,
669 transport->flight_size,
670 transport->partial_bytes_acked);
671 }
672
673 /* RFC 2960 6.1 Transmission of DATA Chunks 650 /* RFC 2960 6.1 Transmission of DATA Chunks
674 * 651 *
675 * B) At any given time, the sender MUST NOT transmit new data 652 * B) At any given time, the sender MUST NOT transmit new data
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 5732661c87d3..2f2377369e2b 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -931,6 +931,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
931 goto sctp_flush_out; 931 goto sctp_flush_out;
932 } 932 }
933 933
934 /* Apply Max.Burst limitation to the current transport in
935 * case it will be used for new data. We are going to
936 * rest it before we return, but we want to apply the limit
937 * to the currently queued data.
938 */
939 if (transport)
940 sctp_transport_burst_limited(transport);
941
934 /* Finally, transmit new packets. */ 942 /* Finally, transmit new packets. */
935 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { 943 while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
936 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid 944 /* RFC 2960 6.5 Every DATA chunk MUST carry a valid
@@ -976,6 +984,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
976 packet = &transport->packet; 984 packet = &transport->packet;
977 sctp_packet_config(packet, vtag, 985 sctp_packet_config(packet, vtag,
978 asoc->peer.ecn_capable); 986 asoc->peer.ecn_capable);
987 /* We've switched transports, so apply the
988 * Burst limit to the new transport.
989 */
990 sctp_transport_burst_limited(transport);
979 } 991 }
980 992
981 SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", 993 SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
@@ -1070,6 +1082,9 @@ sctp_flush_out:
1070 packet = &t->packet; 1082 packet = &t->packet;
1071 if (!sctp_packet_empty(packet)) 1083 if (!sctp_packet_empty(packet))
1072 error = sctp_packet_transmit(packet); 1084 error = sctp_packet_transmit(packet);
1085
1086 /* Clear the burst limited state, if any */
1087 sctp_transport_burst_reset(t);
1073 } 1088 }
1074 1089
1075 return error; 1090 return error;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 2df29cbdaf5a..9a6cb22d129f 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -576,6 +576,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
576 transport->cwnd, transport->ssthresh); 576 transport->cwnd, transport->ssthresh);
577} 577}
578 578
579/* Apply Max.Burst limit to the congestion window:
580 * sctpimpguide-05 2.14.2
581 * D) When the time comes for the sender to
582 * transmit new DATA chunks, the protocol parameter Max.Burst MUST
583 * first be applied to limit how many new DATA chunks may be sent.
584 * The limit is applied by adjusting cwnd as follows:
585 * if ((flightsize+ Max.Burst * MTU) < cwnd)
586 * cwnd = flightsize + Max.Burst * MTU
587 */
588
589void sctp_transport_burst_limited(struct sctp_transport *t)
590{
591 struct sctp_association *asoc = t->asoc;
592 u32 old_cwnd = t->cwnd;
593 u32 max_burst_bytes;
594
595 if (t->burst_limited)
596 return;
597
598 max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
599 if (max_burst_bytes < old_cwnd) {
600 t->cwnd = max_burst_bytes;
601 t->burst_limited = old_cwnd;
602 }
603}
604
605/* Restore the old cwnd congestion window, after the burst had it's
606 * desired effect.
607 */
608void sctp_transport_burst_reset(struct sctp_transport *t)
609{
610 if (t->burst_limited) {
611 t->cwnd = t->burst_limited;
612 t->burst_limited = 0;
613 }
614}
615
579/* What is the next timeout value for this transport? */ 616/* What is the next timeout value for this transport? */
580unsigned long sctp_transport_timeout(struct sctp_transport *t) 617unsigned long sctp_transport_timeout(struct sctp_transport *t)
581{ 618{
@@ -598,6 +635,7 @@ void sctp_transport_reset(struct sctp_transport *t)
598 * (see Section 6.2.1) 635 * (see Section 6.2.1)
599 */ 636 */
600 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); 637 t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
638 t->burst_limited = 0;
601 t->ssthresh = asoc->peer.i.a_rwnd; 639 t->ssthresh = asoc->peer.i.a_rwnd;
602 t->last_rto = t->rto = asoc->rto_initial; 640 t->last_rto = t->rto = asoc->rto_initial;
603 t->rtt = 0; 641 t->rtt = 0;