diff options
author | 2004-02-27 16:44:44 +0000 | |
---|---|---|
committer | 2004-02-27 16:44:44 +0000 | |
commit | 23d303a2c6e8191a25a6652f095608805941f706 (patch) | |
tree | e0ab317df0f084ccd4ab003eba09167dd432bac2 | |
parent | API change; counter for upcoming tcp_drain(); ok deraadt (diff) | |
download | wireguard-openbsd-23d303a2c6e8191a25a6652f095608805941f706.tar.xz wireguard-openbsd-23d303a2c6e8191a25a6652f095608805941f706.zip |
implement tcp_drain() similar to ip_drain(); ok mcbride@
-rw-r--r-- | sys/netinet/tcp_input.c | 9 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 17 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 36 |
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 */ /* |