aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@redhat.com>2011-12-18 23:11:40 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-20 13:58:37 -0500
commita76c0adf60f6ca5ff3481992e4ea0383776b24d2 (patch)
tree97d0fa429a11bf6a975778728e10fd44bbfad80f
parente8303a3b2196272c3eb994d0fd1a189a958a2bdd (diff)
sctp: Do not account for sizeof(struct sk_buff) in estimated rwnd
When checking whether a DATA chunk fits into the estimated rwnd a full sizeof(struct sk_buff) is added to the needed chunk size. This quickly exhausts the available rwnd space and leads to packets being sent which are much below the PMTU limit. This can lead to much worse performance. The reason for this behaviour was to avoid putting too much memory pressure on the receiver. The concept is not completely irational because a Linux receiver does in fact clone an skb for each DATA chunk delivered. However, Linux also reserves half the available socket buffer space for data structures therefore usage of it is already accounted for. When proposing to change this the last time it was noted that this behaviour was introduced to solve a performance issue caused by rwnd overusage in combination with small DATA chunks. Trying to reproduce this I found that with the sk_buff overhead removed, the performance would improve significantly unless socket buffer limits are increased. The following numbers have been gathered using a patched iperf supporting SCTP over a live 1 Gbit ethernet network. The -l option was used to limit DATA chunk sizes. The numbers listed are based on the average of 3 test runs each. Default values have been used for sk_(r|w)mem. Chunk Size Unpatched No Overhead ------------------------------------- 4 15.2 Kbit [!] 12.2 Mbit [!] 8 35.8 Kbit [!] 26.0 Mbit [!] 16 95.5 Kbit [!] 54.4 Mbit [!] 32 106.7 Mbit 102.3 Mbit 64 189.2 Mbit 188.3 Mbit 128 331.2 Mbit 334.8 Mbit 256 537.7 Mbit 536.0 Mbit 512 766.9 Mbit 766.6 Mbit 1024 810.1 Mbit 808.6 Mbit Signed-off-by: Thomas Graf <tgraf@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/output.c8
-rw-r--r--net/sctp/outqueue.c6
2 files changed, 3 insertions, 11 deletions
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 08b3cead6503..817174eb5f41 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -697,13 +697,7 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
697 /* Keep track of how many bytes are in flight to the receiver. */ 697 /* Keep track of how many bytes are in flight to the receiver. */
698 asoc->outqueue.outstanding_bytes += datasize; 698 asoc->outqueue.outstanding_bytes += datasize;
699 699
700 /* Update our view of the receiver's rwnd. Include sk_buff overhead 700 /* Update our view of the receiver's rwnd. */
701 * while updating peer.rwnd so that it reduces the chances of a
702 * receiver running out of receive buffer space even when receive
703 * window is still open. This can happen when a sender is sending
704 * sending small messages.
705 */
706 datasize += sizeof(struct sk_buff);
707 if (datasize < rwnd) 701 if (datasize < rwnd)
708 rwnd -= datasize; 702 rwnd -= datasize;
709 else 703 else
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 14c2b06028ff..cfeb1d4a1ee6 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -411,8 +411,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
411 chunk->transport->flight_size -= 411 chunk->transport->flight_size -=
412 sctp_data_size(chunk); 412 sctp_data_size(chunk);
413 q->outstanding_bytes -= sctp_data_size(chunk); 413 q->outstanding_bytes -= sctp_data_size(chunk);
414 q->asoc->peer.rwnd += (sctp_data_size(chunk) + 414 q->asoc->peer.rwnd += sctp_data_size(chunk);
415 sizeof(struct sk_buff));
416 } 415 }
417 continue; 416 continue;
418 } 417 }
@@ -432,8 +431,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
432 * (Section 7.2.4)), add the data size of those 431 * (Section 7.2.4)), add the data size of those
433 * chunks to the rwnd. 432 * chunks to the rwnd.
434 */ 433 */
435 q->asoc->peer.rwnd += (sctp_data_size(chunk) + 434 q->asoc->peer.rwnd += sctp_data_size(chunk);
436 sizeof(struct sk_buff));
437 q->outstanding_bytes -= sctp_data_size(chunk); 435 q->outstanding_bytes -= sctp_data_size(chunk);
438 if (chunk->transport) 436 if (chunk->transport)
439 transport->flight_size -= sctp_data_size(chunk); 437 transport->flight_size -= sctp_data_size(chunk);