aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2009-11-23 15:54:00 -0500
committerVlad Yasevich <vladislav.yasevich@hp.com>2009-11-23 15:54:00 -0500
commit46d5a808558181e03a4760d2188cc9879445738a (patch)
treea51cc59d64042f61518d25ef4ecc71924f243084
parenta5b03ad2143c5bc9ae76533e8321fe66258b4f35 (diff)
sctp: Update max.burst implementation
Current implementation of max.burst ends up limiting new data during cwnd decay period. The decay is happening becuase the connection is idle and we are allowed to fill the congestion window. The point of max.burst is to limit micro-bursts in response to large acks. This still happens, as max.burst is still applied to each transmit opportunity. It will also apply if a very large send is made (greater then allowed by burst). Tested-by: Florian Niederbacher <florian.niederbacher@student.uibk.ac.at> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
-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;