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} |