summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkus <markus@openbsd.org>2004-02-27 16:44:44 +0000
committermarkus <markus@openbsd.org>2004-02-27 16:44:44 +0000
commit23d303a2c6e8191a25a6652f095608805941f706 (patch)
treee0ab317df0f084ccd4ab003eba09167dd432bac2
parentAPI change; counter for upcoming tcp_drain(); ok deraadt (diff)
downloadwireguard-openbsd-23d303a2c6e8191a25a6652f095608805941f706.tar.xz
wireguard-openbsd-23d303a2c6e8191a25a6652f095608805941f706.zip
implement tcp_drain() similar to ip_drain(); ok mcbride@
-rw-r--r--sys/netinet/tcp_input.c9
-rw-r--r--sys/netinet/tcp_subr.c17
-rw-r--r--sys/netinet/tcp_var.h36
3 files changed, 55 insertions, 7 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index f97c74cf018..2da98f80342 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.155 2004/02/11 20:12:33 markus Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.156 2004/02/27 16:44:44 markus Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -1221,8 +1221,10 @@ after_listen:
tp->snd_scale = tp->requested_s_scale;
tp->rcv_scale = tp->request_r_scale;
}
+ tcp_reass_lock(tp);
(void) tcp_reass(tp, (struct tcphdr *)0,
(struct mbuf *)0, &tlen);
+ tcp_reass_unlock(tp);
/*
* if we didn't have to retransmit the SYN,
* use its rtt as our initial srtt & rtt var.
@@ -1475,8 +1477,10 @@ trimthenstep6:
tp->snd_scale = tp->requested_s_scale;
tp->rcv_scale = tp->request_r_scale;
}
+ tcp_reass_lock(tp);
(void) tcp_reass(tp, (struct tcphdr *)0, (struct mbuf *)0,
&tlen);
+ tcp_reass_unlock(tp);
tp->snd_wl1 = th->th_seq - 1;
/* fall into ... */
@@ -1979,8 +1983,10 @@ dodata: /* XXX */
*/
if ((tlen || (tiflags & TH_FIN)) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ tcp_reass_lock(tp);
if (th->th_seq == tp->rcv_nxt && tp->segq.lh_first == NULL &&
tp->t_state == TCPS_ESTABLISHED) {
+ tcp_reass_unlock(tp);
TCP_SETUP_ACK(tp, tiflags);
tp->rcv_nxt += tlen;
tiflags = th->th_flags & TH_FIN;
@@ -1997,6 +2003,7 @@ dodata: /* XXX */
} else {
m_adj(m, hdroptlen);
tiflags = tcp_reass(tp, th, m, &tlen);
+ tcp_reass_unlock(tp);
tp->t_flags |= TF_ACKNOW;
}
#ifdef TCP_SACK
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 662ccc2cc7f..b920816bad5 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.75 2004/01/31 19:40:10 markus Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.76 2004/02/27 16:44:45 markus Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -681,7 +681,9 @@ tcp_close(struct tcpcb *tp)
#endif /* RTV_RTT */
/* free the reassembly queue, if any */
+ tcp_reass_lock(tp);
tcp_freeq(tp);
+ tcp_reass_unlock(tp);
tcp_canceltimers(tp);
TCP_CLEAR_DELACK(tp);
@@ -724,7 +726,20 @@ tcp_freeq(struct tcpcb *tp)
void
tcp_drain()
{
+ struct inpcb *inp;
+
+ /* called at splimp() */
+ CIRCLEQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) {
+ struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
+ if (tp != NULL) {
+ if (tcp_reass_lock_try(tp) == 0)
+ continue;
+ if (tcp_freeq(tp))
+ tcpstat.tcps_conndrained++;
+ tcp_reass_unlock(tp);
+ }
+ }
}
/*
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 2a9dc5d7dbb..1347bafc8a9 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.59 2004/02/27 16:28:24 markus Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.60 2004/02/27 16:44:45 markus Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -82,7 +82,7 @@ struct tcpcb {
#define TF_SEND_CWR 0x00020000 /* send CWR in next seg */
#define TF_DISABLE_ECN 0x00040000 /* disable ECN for this connection */
#endif
-#define TF_DEAD 0x00080000 /* dead and to-be-released */
+#define TF_REASSLOCK 0x00080000 /* reassembling or draining */
struct mbuf *t_template; /* skeletal packet for transmit */
struct inpcb *t_inpcb; /* back pointer to internet pcb */
@@ -209,7 +209,6 @@ do { \
timeout_del(&(tp)->t_delack_to); \
} \
} while (/*CONSTCOND*/0)
-#endif /* _KERNEL */
/*
* Handy way of passing around TCP option info.
@@ -221,8 +220,6 @@ struct tcp_opt_info {
u_int16_t maxseg;
};
-#ifdef _KERNEL
-
/*
* Data for the TCP compressed state engine.
*/
@@ -284,6 +281,35 @@ struct syn_cache_head {
TAILQ_HEAD(, syn_cache) sch_bucket; /* bucket entries */
u_short sch_length; /* # entries in bucket */
};
+
+static __inline int tcp_reass_lock_try(struct tcpcb *);
+static __inline void tcp_reass_unlock(struct tcpcb *);
+#define tcp_reass_lock(tp) tcp_reass_lock_try(tp)
+
+static __inline int
+tcp_reass_lock_try(struct tcpcb *tp)
+{
+ int s;
+
+ s = splimp();
+ if (tp->t_flags & TF_REASSLOCK) {
+ splx(s);
+ return (0);
+ }
+ tp->t_flags |= TF_REASSLOCK;
+ splx(s);
+ return (1);
+}
+
+static __inline void
+tcp_reass_unlock(struct tcpcb *tp)
+{
+ int s;
+
+ s = splimp();
+ tp->t_flags &= ~TF_REASSLOCK;
+ splx(s);
+}
#endif /* _KERNEL */
/*