summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2010-09-24 02:59:45 +0000
committerclaudio <claudio@openbsd.org>2010-09-24 02:59:45 +0000
commit5d991f0144114397082b21feac3eb6f0e27ea9ec (patch)
tree660ad8a782185a3fbb3780e7148421f90d8cb0e3 /sys/netinet/tcp_usrreq.c
parentdead store; found by clang (diff)
downloadwireguard-openbsd-5d991f0144114397082b21feac3eb6f0e27ea9ec.tar.xz
wireguard-openbsd-5d991f0144114397082b21feac3eb6f0e27ea9ec.zip
TCP send and recv buffer scaling.
Send buffer is scaled by not accounting unacknowledged on the wire data against the buffer limit. Receive buffer scaling is done similar to FreeBSD -- measure the delay * bandwith product and base the buffer on that. The problem is that our RTT measurment is coarse so it overshoots on low delay links. This does not matter that much since the recvbuffer is almost always empty. Add a back pressure mechanism to control the amount of memory assigned to socketbuffers that kicks in when 80% of the cluster pool is used. Increases the download speed from 300kB/s to 4.4MB/s on ftp.eu.openbsd.org. Based on work by markus@ and djm@. OK dlg@, henning@, put it in deraadt@
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 6c09f5b896d..c3676bcceaa 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.102 2010/06/07 13:08:43 claudio Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.103 2010/09/24 02:59:45 claudio Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -119,6 +119,7 @@ u_int tcp_sendspace = TCP_SENDSPACE;
#define TCP_RECVSPACE 1024*16
#endif
u_int tcp_recvspace = TCP_RECVSPACE;
+u_int tcp_autorcvbuf_inc = 16 * 1024;
int *tcpctl_vars[TCPCTL_MAXID] = TCPCTL_VARS;
@@ -313,7 +314,7 @@ tcp_usrreq(so, req, m, nam, control, p)
so->so_state |= SS_CONNECTOUT;
/* Compute window scaling to request. */
- tcp_rscale(tp, so->so_rcv.sb_hiwat);
+ tcp_rscale(tp, sb_max);
soisconnecting(so);
tcpstat.tcps_connattempt++;
@@ -652,10 +653,19 @@ tcp_attach(so)
int error;
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
- error = soreserve(so, tcp_sendspace, tcp_recvspace);
+ /* if low on memory only allow smaller then default buffers */
+ if (so->so_snd.sb_wat == 0 ||
+ sbcheckreserve(so->so_snd.sb_wat, tcp_sendspace))
+ so->so_snd.sb_wat = tcp_sendspace;
+ if (so->so_rcv.sb_wat == 0 ||
+ sbcheckreserve(so->so_rcv.sb_wat, tcp_recvspace))
+ so->so_rcv.sb_wat = tcp_recvspace;
+
+ error = soreserve(so, so->so_snd.sb_wat, so->so_rcv.sb_wat);
if (error)
return (error);
}
+
error = in_pcballoc(so, &tcbtable);
if (error)
return (error);
@@ -950,3 +960,61 @@ tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}
/* NOTREACHED */
}
+
+/*
+ * Scale the send buffer so that inflight data is not accounted against
+ * the limit. The buffer will scale with the congestion window, if the
+ * the receiver stops acking data the window will shrink and therefor
+ * the buffer size will shrink as well.
+ * In low memory situation shrink
+ */
+void
+tcp_update_sndspace(struct tcpcb *tp)
+{
+ struct socket *so = tp->t_inpcb->inp_socket;
+ int nmax;
+
+ if (sbchecklowmem())
+ /* low on memory try to get rid of some */
+ nmax = tcp_sendspace;
+ else if (so->so_snd.sb_wat != tcp_sendspace)
+ /* user requested buffer size, auto-scaling disabled */
+ nmax = so->so_snd.sb_wat;
+ else
+ /* automatic buffer scaling */
+ nmax = MIN(sb_max, so->so_snd.sb_wat + tp->snd_max -
+ tp->snd_una);
+
+ /* round to MSS boundary */
+ nmax = roundup(nmax, tp->t_maxseg);
+
+ if (nmax != so->so_snd.sb_hiwat)
+ sbreserve(&so->so_snd, nmax);
+}
+
+void
+tcp_update_rcvspace(struct tcpcb *tp)
+{
+ struct socket *so = tp->t_inpcb->inp_socket;
+ int nmax = so->so_rcv.sb_hiwat;
+
+ if (sbchecklowmem())
+ /* low on memory try to get rid of some */
+ nmax = tcp_recvspace;
+ else if (so->so_rcv.sb_wat != tcp_recvspace)
+ /* user requested buffer size, auto-scaling disabled */
+ nmax = so->so_rcv.sb_wat;
+ else {
+ /* automatic buffer scaling */
+ if (tp->rfbuf_cnt > so->so_rcv.sb_hiwat / 8 * 7)
+ nmax = MIN(sb_max, so->so_rcv.sb_hiwat +
+ tcp_autorcvbuf_inc);
+ }
+
+ if (nmax == so->so_rcv.sb_hiwat)
+ return;
+
+ /* round to MSS boundary */
+ nmax = roundup(nmax, tp->t_maxseg);
+ sbreserve(&so->so_rcv, nmax);
+}