summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2011-01-07 17:50:42 +0000
committerbluhm <bluhm@openbsd.org>2011-01-07 17:50:42 +0000
commit3e816f04bbb5bf8411c3134b7593ef330bd6c5c2 (patch)
tree051f70b2a5c520ad8072475c56a1d666bb18eb0c /sys/netinet/tcp_input.c
parent- Update Test::Simple to 0.96 (diff)
downloadwireguard-openbsd-3e816f04bbb5bf8411c3134b7593ef330bd6c5c2.tar.xz
wireguard-openbsd-3e816f04bbb5bf8411c3134b7593ef330bd6c5c2.zip
Add socket option SO_SPLICE to splice together two TCP sockets.
The data received on the source socket will automatically be sent on the drain socket. This allows to write relay daemons with zero data copy. ok markus@
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 66ad114f222..9a6f406456f 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.239 2010/09/29 19:42:11 claudio Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.240 2011/01/07 17:50:42 bluhm Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -328,7 +328,9 @@ present:
pool_put(&tcpqe_pool, q);
q = nq;
} while (q != NULL && q->tcpqe_tcp->th_seq == tp->rcv_nxt);
+ tp->t_flags |= TF_BLOCKOUTPUT;
sorwakeup(so);
+ tp->t_flags &= ~TF_BLOCKOUTPUT;
return (flags);
}
@@ -368,7 +370,7 @@ tcp_input(struct mbuf *m, ...)
struct tcpcb *tp = 0;
int tiflags;
struct socket *so = NULL;
- int todrop, acked, ourfinisacked, needoutput = 0;
+ int todrop, acked, ourfinisacked;
int hdroptlen = 0;
short ostate = 0;
tcp_seq iss, *reuse = NULL;
@@ -1090,9 +1092,13 @@ after_listen:
TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur);
tcp_update_sndspace(tp);
- if (sb_notify(&so->so_snd))
+ if (sb_notify(&so->so_snd)) {
+ tp->t_flags |= TF_BLOCKOUTPUT;
sowwakeup(so);
- if (so->so_snd.sb_cc)
+ tp->t_flags &= ~TF_BLOCKOUTPUT;
+ }
+ if (so->so_snd.sb_cc ||
+ tp->t_flags & TF_NEEDOUTPUT)
(void) tcp_output(tp);
return;
}
@@ -1136,8 +1142,10 @@ after_listen:
m_adj(m, iphlen + off);
sbappendstream(&so->so_rcv, m);
}
+ tp->t_flags |= TF_BLOCKOUTPUT;
sorwakeup(so);
- if (tp->t_flags & TF_ACKNOW)
+ tp->t_flags &= ~TF_BLOCKOUTPUT;
+ if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT))
(void) tcp_output(tp);
return;
}
@@ -1773,10 +1781,10 @@ trimthenstep6:
#if defined(TCP_SACK) && defined(TCP_FACK)
/* Force call to tcp_output */
if (tp->snd_awnd < tp->snd_cwnd)
- needoutput = 1;
+ tp->t_flags |= TF_NEEDOUTPUT;
#else
tp->snd_cwnd += tp->t_maxseg;
- needoutput = 1;
+ tp->t_flags |= TF_NEEDOUTPUT;
#endif /* TCP_FACK */
} else {
/* Out of fast recovery */
@@ -1844,7 +1852,7 @@ trimthenstep6:
*/
if (th->th_ack == tp->snd_max) {
TCP_TIMER_DISARM(tp, TCPT_REXMT);
- needoutput = 1;
+ tp->t_flags |= TF_NEEDOUTPUT;
} else if (TCP_TIMER_ISARMED(tp, TCPT_PERSIST) == 0)
TCP_TIMER_ARM(tp, TCPT_REXMT, tp->t_rxtcur);
/*
@@ -1877,8 +1885,11 @@ trimthenstep6:
}
tcp_update_sndspace(tp);
- if (sb_notify(&so->so_snd))
+ if (sb_notify(&so->so_snd)) {
+ tp->t_flags |= TF_BLOCKOUTPUT;
sowwakeup(so);
+ tp->t_flags &= ~TF_BLOCKOUTPUT;
+ }
/*
* If we had a pending ICMP message that referred to data
@@ -1996,7 +2007,7 @@ step6:
tp->snd_wl2 = th->th_ack;
if (tp->snd_wnd > tp->max_sndwnd)
tp->max_sndwnd = tp->snd_wnd;
- needoutput = 1;
+ tp->t_flags |= TF_NEEDOUTPUT;
}
/*
@@ -2088,7 +2099,9 @@ dodata: /* XXX */
m_adj(m, hdroptlen);
sbappendstream(&so->so_rcv, m);
}
+ tp->t_flags |= TF_BLOCKOUTPUT;
sorwakeup(so);
+ tp->t_flags &= ~TF_BLOCKOUTPUT;
} else {
m_adj(m, hdroptlen);
tiflags = tcp_reass(tp, th, m, &tlen);
@@ -2182,9 +2195,8 @@ dodata: /* XXX */
/*
* Return any desired output.
*/
- if (needoutput || (tp->t_flags & TF_ACKNOW)) {
+ if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT))
(void) tcp_output(tp);
- }
return;
badsyn: