Page MenuHomeFreeBSD

D14697.id40571.diff
No OneTemporary

D14697.id40571.diff

Index: head/sys/netinet/tcp_timewait.c
===================================================================
--- head/sys/netinet/tcp_timewait.c
+++ head/sys/netinet/tcp_timewait.c
@@ -172,7 +172,7 @@
&maxtcptw, 0, sysctl_maxtcptw, "IU",
"Maximum number of compressed TCP TIME_WAIT entries");
-VNET_DEFINE(int, nolocaltimewait) = 0;
+static VNET_DEFINE(int, nolocaltimewait) = 0;
#define V_nolocaltimewait VNET(nolocaltimewait)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(nolocaltimewait), 0,
@@ -225,12 +225,12 @@
void
tcp_twstart(struct tcpcb *tp)
{
- struct tcptw *tw;
+ struct tcptw twlocal, *tw;
struct inpcb *inp = tp->t_inpcb;
- int acknow;
struct socket *so;
+ bool acknow, local;
#ifdef INET6
- int isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
+ bool isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
#endif
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
@@ -241,33 +241,29 @@
"(inp->inp_flags & INP_DROPPED) != 0"));
if (V_nolocaltimewait) {
- int error = 0;
#ifdef INET6
if (isipv6)
- error = in6_localaddr(&inp->in6p_faddr);
+ local = in6_localaddr(&inp->in6p_faddr);
#endif
#if defined(INET6) && defined(INET)
else
#endif
#ifdef INET
- error = in_localip(inp->inp_faddr);
+ local = in_localip(inp->inp_faddr);
#endif
- if (error) {
- tp = tcp_close(tp);
- if (tp != NULL)
- INP_WUNLOCK(inp);
- return;
- }
- }
+ } else
+ local = false;
-
/*
* For use only by DTrace. We do not reference the state
* after this point so modifying it in place is not a problem.
*/
tcp_state_change(tp, TCPS_TIME_WAIT);
- tw = uma_zalloc(V_tcptw_zone, M_NOWAIT);
+ if (local)
+ tw = &twlocal;
+ else
+ tw = uma_zalloc(V_tcptw_zone, M_NOWAIT);
if (tw == NULL) {
/*
* Reached limit on total number of TIMEWAIT connections
@@ -286,11 +282,10 @@
}
}
/*
- * The tcptw will hold a reference on its inpcb until tcp_twclose
- * is called
+ * For !local case the tcptw will hold a reference on its inpcb
+ * until tcp_twclose is called.
*/
tw->tw_inpcb = inp;
- in_pcbref(inp); /* Reference from tw */
/*
* Recover last window size sent.
@@ -337,16 +332,19 @@
tcp_discardcb(tp);
so = inp->inp_socket;
soisdisconnected(so);
- tw->tw_cred = crhold(so->so_cred);
- SOCK_LOCK(so);
tw->tw_so_options = so->so_options;
- SOCK_UNLOCK(so);
+ inp->inp_flags |= INP_TIMEWAIT;
if (acknow)
tcp_twrespond(tw, TH_ACK);
- inp->inp_ppcb = tw;
- inp->inp_flags |= INP_TIMEWAIT;
- TCPSTATES_INC(TCPS_TIME_WAIT);
- tcp_tw_2msl_reset(tw, 0);
+ if (local)
+ in_pcbdrop(inp);
+ else {
+ in_pcbref(inp); /* Reference from tw */
+ tw->tw_cred = crhold(so->so_cred);
+ inp->inp_ppcb = tw;
+ TCPSTATES_INC(TCPS_TIME_WAIT);
+ tcp_tw_2msl_reset(tw, 0);
+ }
/*
* If the inpcb owns the sole reference to the socket, then we can
Index: head/sys/netinet/tcp_usrreq.c
===================================================================
--- head/sys/netinet/tcp_usrreq.c
+++ head/sys/netinet/tcp_usrreq.c
@@ -198,15 +198,18 @@
* XXXRW: Would it be cleaner to free the tcptw here?
*
* Astute question indeed, from twtcp perspective there are
- * three cases to consider:
+ * four cases to consider:
*
* #1 tcp_detach is called at tcptw creation time by
* tcp_twstart, then do not discard the newly created tcptw
* and leave inpcb present until timewait ends
- * #2 tcp_detach is called at timewait end (or reuse) by
+ * #2 tcp_detach is called at tcptw creation time by
+ * tcp_twstart, but connection is local and tw will be
+ * discarded immediately
+ * #3 tcp_detach is called at timewait end (or reuse) by
* tcp_twclose, then the tcptw has already been discarded
* (or reused) and inpcb is freed here
- * #3 tcp_detach is called() after timewait ends (or reuse)
+ * #4 tcp_detach is called() after timewait ends (or reuse)
* (e.g. by soclose), then tcptw has already been discarded
* (or reused) and inpcb is freed here
*

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 27, 10:25 PM (8 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16216856
Default Alt Text
D14697.id40571.diff (3 KB)

Event Timeline