summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2013-08-12 21:57:17 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2013-08-12 21:57:17 +0000
commitbee789b12305f3c5e594fe03c965e0786969eeb7 (patch)
tree3aa5e06c1aab733f0373558f3ea8e66cc18a011e /sys/netinet
parent260fc866468e3fb9f8f739d0c67b72fe8f1c91ac (diff)
Add the TCP socket option TCP_NOPUSH to delay sending the stream.
This is useful to aggregate data in the kernel from multiple sources like writes and socket splicing. It avoids sending small packets. From FreeBSD via David Hill; OK mikeb@ henning@
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/tcp.h3
-rw-r--r--sys/netinet/tcp_output.c7
-rw-r--r--sys/netinet/tcp_usrreq.c17
-rw-r--r--sys/netinet/tcp_var.h3
4 files changed, 24 insertions, 6 deletions
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index c4ae9533f90..ab62ec0bc34 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp.h,v 1.19 2013/06/02 23:12:23 henning Exp $ */
+/* $OpenBSD: tcp.h,v 1.20 2013/08/12 21:57:16 bluhm Exp $ */
/* $NetBSD: tcp.h,v 1.8 1995/04/17 05:32:58 cgd Exp $ */
/*
@@ -127,5 +127,6 @@ struct tcphdr {
#define TCP_MAXSEG 0x02 /* set maximum segment size */
#define TCP_MD5SIG 0x04 /* enable TCP MD5 signature option */
#define TCP_SACK_ENABLE 0x08 /* enable SACKs (if disabled by def.) */
+#define TCP_NOPUSH 0x10 /* don't push last block of write */
#endif /* _NETINET_TCP_H_ */
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index c5cd8a8eaec..9d5b469a51f 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.98 2013/06/03 16:57:06 bluhm Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.99 2013/08/12 21:57:16 bluhm Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -415,8 +415,9 @@ again:
if (len) {
if (len == txmaxseg)
goto send;
- if ((idle || tp->t_flags & TF_NODELAY) &&
- len + off >= so->so_snd.sb_cc && !soissending(so))
+ if ((idle || (tp->t_flags & TF_NODELAY)) &&
+ len + off >= so->so_snd.sb_cc && !soissending(so) &&
+ (tp->t_flags & TF_NOPUSH) == 0)
goto send;
if (tp->t_force)
goto send;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 4e108d144fe..9fd519615ab 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.113 2013/08/06 07:31:48 bluhm Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.114 2013/08/12 21:57:16 bluhm Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -532,6 +532,18 @@ tcp_ctloutput(op, so, level, optname, mp)
tp->t_flags &= ~TF_NODELAY;
break;
+ case TCP_NOPUSH:
+ if (m == NULL || m->m_len < sizeof (int))
+ error = EINVAL;
+ else if (*mtod(m, int *))
+ tp->t_flags |= TF_NOPUSH;
+ else if (tp->t_flags & TF_NOPUSH) {
+ tp->t_flags &= ~TF_NOPUSH;
+ if (TCPS_HAVEESTABLISHED(tp->t_state))
+ error = tcp_output(tp);
+ }
+ break;
+
case TCP_MAXSEG:
if (m == NULL || m->m_len < sizeof (int)) {
error = EINVAL;
@@ -605,6 +617,9 @@ tcp_ctloutput(op, so, level, optname, mp)
case TCP_NODELAY:
*mtod(m, int *) = tp->t_flags & TF_NODELAY;
break;
+ case TCP_NOPUSH:
+ *mtod(m, int *) = tp->t_flags & TF_NOPUSH;
+ break;
case TCP_MAXSEG:
*mtod(m, int *) = tp->t_maxseg;
break;
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index f3053598a58..acded92556b 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.101 2013/06/01 16:22:05 bluhm Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.102 2013/08/12 21:57:16 bluhm Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -97,6 +97,7 @@ struct tcpcb {
#define TF_PMTUD_PEND 0x00400000 /* Path MTU Discovery pending */
#define TF_NEEDOUTPUT 0x00800000 /* call tcp_output after tcp_input */
#define TF_BLOCKOUTPUT 0x01000000 /* avert tcp_output during tcp_input */
+#define TF_NOPUSH 0x02000000 /* don't push */
struct mbuf *t_template; /* skeletal packet for transmit */
struct inpcb *t_inpcb; /* back pointer to internet pcb */