Deleted Added
full compact
tcp_timewait.c (178285) tcp_timewait.c (181803)
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/netinet/tcp_timewait.c 178285 2008-04-17 21:38:18Z rwatson $");
33__FBSDID("$FreeBSD: head/sys/netinet/tcp_timewait.c 181803 2008-08-17 23:27:27Z bz $");
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37#include "opt_mac.h"
38#include "opt_tcpdebug.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/callout.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45#include <sys/malloc.h>
46#include <sys/mbuf.h>
47#include <sys/priv.h>
48#include <sys/proc.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/protosw.h>
52#include <sys/random.h>
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37#include "opt_mac.h"
38#include "opt_tcpdebug.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/callout.h>
43#include <sys/kernel.h>
44#include <sys/sysctl.h>
45#include <sys/malloc.h>
46#include <sys/mbuf.h>
47#include <sys/priv.h>
48#include <sys/proc.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/protosw.h>
52#include <sys/random.h>
53#include <sys/vimage.h>
53
54#include <vm/uma.h>
55
56#include <net/route.h>
57#include <net/if.h>
58
59#include <netinet/in.h>
60#include <netinet/in_systm.h>

--- 49 unchanged lines hidden (view full) ---

110tcptw_auto_size(void)
111{
112 int halfrange;
113
114 /*
115 * Max out at half the ephemeral port range so that TIME_WAIT
116 * sockets don't tie up too many ephemeral ports.
117 */
54
55#include <vm/uma.h>
56
57#include <net/route.h>
58#include <net/if.h>
59
60#include <netinet/in.h>
61#include <netinet/in_systm.h>

--- 49 unchanged lines hidden (view full) ---

111tcptw_auto_size(void)
112{
113 int halfrange;
114
115 /*
116 * Max out at half the ephemeral port range so that TIME_WAIT
117 * sockets don't tie up too many ephemeral ports.
118 */
118 if (ipport_lastauto > ipport_firstauto)
119 halfrange = (ipport_lastauto - ipport_firstauto) / 2;
119 if (V_ipport_lastauto > V_ipport_firstauto)
120 halfrange = (V_ipport_lastauto - V_ipport_firstauto) / 2;
120 else
121 else
121 halfrange = (ipport_firstauto - ipport_lastauto) / 2;
122 halfrange = (V_ipport_firstauto - V_ipport_lastauto) / 2;
122 /* Protect against goofy port ranges smaller than 32. */
123 return (imin(imax(halfrange, 32), maxsockets / 5));
124}
125
126static int
127sysctl_maxtcptw(SYSCTL_HANDLER_ARGS)
128{
129 int error, new;

--- 34 unchanged lines hidden (view full) ---

164
165 tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw),
166 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
167 TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw);
168 if (maxtcptw == 0)
169 uma_zone_set_max(tcptw_zone, tcptw_auto_size());
170 else
171 uma_zone_set_max(tcptw_zone, maxtcptw);
123 /* Protect against goofy port ranges smaller than 32. */
124 return (imin(imax(halfrange, 32), maxsockets / 5));
125}
126
127static int
128sysctl_maxtcptw(SYSCTL_HANDLER_ARGS)
129{
130 int error, new;

--- 34 unchanged lines hidden (view full) ---

165
166 tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw),
167 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
168 TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw);
169 if (maxtcptw == 0)
170 uma_zone_set_max(tcptw_zone, tcptw_auto_size());
171 else
172 uma_zone_set_max(tcptw_zone, maxtcptw);
172 TAILQ_INIT(&twq_2msl);
173 TAILQ_INIT(&V_twq_2msl);
173}
174
175/*
176 * Move a TCP connection into TIME_WAIT state.
177 * tcbinfo is locked.
178 * inp is locked, and is unlocked before returning.
179 */
180void
181tcp_twstart(struct tcpcb *tp)
182{
183 struct tcptw *tw;
184 struct inpcb *inp = tp->t_inpcb;
185 int acknow;
186 struct socket *so;
187
174}
175
176/*
177 * Move a TCP connection into TIME_WAIT state.
178 * tcbinfo is locked.
179 * inp is locked, and is unlocked before returning.
180 */
181void
182tcp_twstart(struct tcpcb *tp)
183{
184 struct tcptw *tw;
185 struct inpcb *inp = tp->t_inpcb;
186 int acknow;
187 struct socket *so;
188
188 INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_tw_2msl_reset(). */
189 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* tcp_tw_2msl_reset(). */
189 INP_WLOCK_ASSERT(inp);
190
190 INP_WLOCK_ASSERT(inp);
191
191 if (nolocaltimewait && in_localip(inp->inp_faddr)) {
192 if (V_nolocaltimewait && in_localip(inp->inp_faddr)) {
192 tp = tcp_close(tp);
193 if (tp != NULL)
194 INP_WUNLOCK(inp);
195 return;
196 }
197
198 tw = uma_zalloc(tcptw_zone, M_NOWAIT);
199 if (tw == NULL) {

--- 93 unchanged lines hidden (view full) ---

293 * that it is safe to recycle this tw socket by returning 1.
294 */
295int
296tcp_twrecycleable(struct tcptw *tw)
297{
298 tcp_seq new_iss = tw->iss;
299 tcp_seq new_irs = tw->irs;
300
193 tp = tcp_close(tp);
194 if (tp != NULL)
195 INP_WUNLOCK(inp);
196 return;
197 }
198
199 tw = uma_zalloc(tcptw_zone, M_NOWAIT);
200 if (tw == NULL) {

--- 93 unchanged lines hidden (view full) ---

294 * that it is safe to recycle this tw socket by returning 1.
295 */
296int
297tcp_twrecycleable(struct tcptw *tw)
298{
299 tcp_seq new_iss = tw->iss;
300 tcp_seq new_irs = tw->irs;
301
301 INP_INFO_WLOCK_ASSERT(&tcbinfo);
302 INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
302 new_iss += (ticks - tw->t_starttime) * (ISN_BYTES_PER_SECOND / hz);
303 new_irs += (ticks - tw->t_starttime) * (MS_ISN_BYTES_PER_SECOND / hz);
304
305 if (SEQ_GT(new_iss, tw->snd_nxt) && SEQ_GT(new_irs, tw->rcv_nxt))
306 return (1);
307 else
308 return (0);
309}

--- 12 unchanged lines hidden (view full) ---

322 tcp_seq seq;
323#ifdef INET6
324 int isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
325#else
326 const int isipv6 = 0;
327#endif
328
329 /* tcbinfo lock required for tcp_twclose(), tcp_tw_2msl_reset(). */
303 new_iss += (ticks - tw->t_starttime) * (ISN_BYTES_PER_SECOND / hz);
304 new_irs += (ticks - tw->t_starttime) * (MS_ISN_BYTES_PER_SECOND / hz);
305
306 if (SEQ_GT(new_iss, tw->snd_nxt) && SEQ_GT(new_irs, tw->rcv_nxt))
307 return (1);
308 else
309 return (0);
310}

--- 12 unchanged lines hidden (view full) ---

323 tcp_seq seq;
324#ifdef INET6
325 int isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0;
326#else
327 const int isipv6 = 0;
328#endif
329
330 /* tcbinfo lock required for tcp_twclose(), tcp_tw_2msl_reset(). */
330 INP_INFO_WLOCK_ASSERT(&tcbinfo);
331 INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
331 INP_WLOCK_ASSERT(inp);
332
333 /*
334 * XXXRW: Time wait state for inpcb has been recycled, but inpcb is
335 * still present. This is undesirable, but temporarily necessary
336 * until we work out how to handle inpcb's who's timewait state has
337 * been removed.
338 */

--- 124 unchanged lines hidden (view full) ---

463 * all state.
464 *
465 * (2) We have a socket -- if we own a reference, release it and
466 * notify the socket layer.
467 */
468 inp = tw->tw_inpcb;
469 KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
470 KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw"));
332 INP_WLOCK_ASSERT(inp);
333
334 /*
335 * XXXRW: Time wait state for inpcb has been recycled, but inpcb is
336 * still present. This is undesirable, but temporarily necessary
337 * until we work out how to handle inpcb's who's timewait state has
338 * been removed.
339 */

--- 124 unchanged lines hidden (view full) ---

464 * all state.
465 *
466 * (2) We have a socket -- if we own a reference, release it and
467 * notify the socket layer.
468 */
469 inp = tw->tw_inpcb;
470 KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
471 KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw"));
471 INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_tw_2msl_stop(). */
472 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* tcp_tw_2msl_stop(). */
472 INP_WLOCK_ASSERT(inp);
473
474 tw->tw_inpcb = NULL;
475 tcp_tw_2msl_stop(tw);
476 inp->inp_ppcb = NULL;
477 in_pcbdrop(inp);
478
479 so = inp->inp_socket;

--- 24 unchanged lines hidden (view full) ---

504 } else {
505#ifdef INET6
506 if (inp->inp_vflag & INP_IPV6PROTO)
507 in6_pcbfree(inp);
508 else
509#endif
510 in_pcbfree(inp);
511 }
473 INP_WLOCK_ASSERT(inp);
474
475 tw->tw_inpcb = NULL;
476 tcp_tw_2msl_stop(tw);
477 inp->inp_ppcb = NULL;
478 in_pcbdrop(inp);
479
480 so = inp->inp_socket;

--- 24 unchanged lines hidden (view full) ---

505 } else {
506#ifdef INET6
507 if (inp->inp_vflag & INP_IPV6PROTO)
508 in6_pcbfree(inp);
509 else
510#endif
511 in_pcbfree(inp);
512 }
512 tcpstat.tcps_closed++;
513 V_tcpstat.tcps_closed++;
513 crfree(tw->tw_cred);
514 tw->tw_cred = NULL;
515 if (reuse)
516 return;
517 uma_zfree(tcptw_zone, tw);
518}
519
520int

--- 70 unchanged lines hidden (view full) ---

591 } else
592#endif
593 {
594 th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
595 htons(sizeof(struct tcphdr) + optlen + IPPROTO_TCP));
596 m->m_pkthdr.csum_flags = CSUM_TCP;
597 m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
598 ip->ip_len = m->m_pkthdr.len;
514 crfree(tw->tw_cred);
515 tw->tw_cred = NULL;
516 if (reuse)
517 return;
518 uma_zfree(tcptw_zone, tw);
519}
520
521int

--- 70 unchanged lines hidden (view full) ---

592 } else
593#endif
594 {
595 th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
596 htons(sizeof(struct tcphdr) + optlen + IPPROTO_TCP));
597 m->m_pkthdr.csum_flags = CSUM_TCP;
598 m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
599 ip->ip_len = m->m_pkthdr.len;
599 if (path_mtu_discovery)
600 if (V_path_mtu_discovery)
600 ip->ip_off |= IP_DF;
601 error = ip_output(m, inp->inp_options, NULL,
602 ((tw->tw_so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0),
603 NULL, inp);
604 }
605 if (flags & TH_ACK)
601 ip->ip_off |= IP_DF;
602 error = ip_output(m, inp->inp_options, NULL,
603 ((tw->tw_so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0),
604 NULL, inp);
605 }
606 if (flags & TH_ACK)
606 tcpstat.tcps_sndacks++;
607 V_tcpstat.tcps_sndacks++;
607 else
608 else
608 tcpstat.tcps_sndctrl++;
609 tcpstat.tcps_sndtotal++;
609 V_tcpstat.tcps_sndctrl++;
610 V_tcpstat.tcps_sndtotal++;
610 return (error);
611}
612
613static void
614tcp_tw_2msl_reset(struct tcptw *tw, int rearm)
615{
616
611 return (error);
612}
613
614static void
615tcp_tw_2msl_reset(struct tcptw *tw, int rearm)
616{
617
617 INP_INFO_WLOCK_ASSERT(&tcbinfo);
618 INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
618 INP_WLOCK_ASSERT(tw->tw_inpcb);
619 if (rearm)
619 INP_WLOCK_ASSERT(tw->tw_inpcb);
620 if (rearm)
620 TAILQ_REMOVE(&twq_2msl, tw, tw_2msl);
621 TAILQ_REMOVE(&V_twq_2msl, tw, tw_2msl);
621 tw->tw_time = ticks + 2 * tcp_msl;
622 tw->tw_time = ticks + 2 * tcp_msl;
622 TAILQ_INSERT_TAIL(&twq_2msl, tw, tw_2msl);
623 TAILQ_INSERT_TAIL(&V_twq_2msl, tw, tw_2msl);
623}
624
625static void
626tcp_tw_2msl_stop(struct tcptw *tw)
627{
628
624}
625
626static void
627tcp_tw_2msl_stop(struct tcptw *tw)
628{
629
629 INP_INFO_WLOCK_ASSERT(&tcbinfo);
630 TAILQ_REMOVE(&twq_2msl, tw, tw_2msl);
630 INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
631 TAILQ_REMOVE(&V_twq_2msl, tw, tw_2msl);
631}
632
633struct tcptw *
634tcp_tw_2msl_scan(int reuse)
635{
636 struct tcptw *tw;
637
632}
633
634struct tcptw *
635tcp_tw_2msl_scan(int reuse)
636{
637 struct tcptw *tw;
638
638 INP_INFO_WLOCK_ASSERT(&tcbinfo);
639 INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
639 for (;;) {
640 for (;;) {
640 tw = TAILQ_FIRST(&twq_2msl);
641 tw = TAILQ_FIRST(&V_twq_2msl);
641 if (tw == NULL || (!reuse && tw->tw_time > ticks))
642 break;
643 INP_WLOCK(tw->tw_inpcb);
644 tcp_twclose(tw, reuse);
645 if (reuse)
646 return (tw);
647 }
648 return (NULL);
649}
642 if (tw == NULL || (!reuse && tw->tw_time > ticks))
643 break;
644 INP_WLOCK(tw->tw_inpcb);
645 tcp_twclose(tw, reuse);
646 if (reuse)
647 return (tw);
648 }
649 return (NULL);
650}