diff options
author | Andre Oppermann <andre@FreeBSD.org> | 2007-05-13 22:16:13 +0000 |
---|---|---|
committer | Andre Oppermann <andre@FreeBSD.org> | 2007-05-13 22:16:13 +0000 |
commit | ec9c7553527a2a9b1e6f8f455e3124a1a53c144e (patch) | |
tree | fbfc990be06928fffd46d3d8014bb2017f4a7456 /sys/netinet | |
parent | a60c1777eaff18b31a776da19867984927b1d406 (diff) | |
download | src-ec9c7553527a2a9b1e6f8f455e3124a1a53c144e.tar.gz src-ec9c7553527a2a9b1e6f8f455e3124a1a53c144e.zip |
Complete the (mechanical) move of the TCP reassembly and timewait
functions from their origininal place to their own files.
TCP Reassembly from tcp_input.c -> tcp_reass.c
TCP Timewait from tcp_subr.c -> tcp_timewait.c
Notes
Notes:
svn path=/head/; revision=169541
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_input.c | 211 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 33 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 354 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 34 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 15 |
5 files changed, 23 insertions, 624 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ad42e0335f2e..6fcbded02722 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -134,29 +134,6 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_rst, CTLFLAG_RW, &tcp_insecure_rst, 0, "Follow the old (insecure) criteria for accepting RST packets"); -SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0, - "TCP Segment Reassembly Queue"); - -static int tcp_reass_maxseg = 0; -SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN, - &tcp_reass_maxseg, 0, - "Global maximum number of TCP Segments in Reassembly Queue"); - -int tcp_reass_qsize = 0; -SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD, - &tcp_reass_qsize, 0, - "Global number of TCP Segments currently in Reassembly Queue"); - -static int tcp_reass_maxqlen = 48; -SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, maxqlen, CTLFLAG_RW, - &tcp_reass_maxqlen, 0, - "Maximum number of TCP Segments per individual Reassembly Queue"); - -static int tcp_reass_overflows = 0; -SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, - &tcp_reass_overflows, 0, - "Global number of TCP Segment Reassembly Queue Overflows"); - int tcp_do_autorcvbuf = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_RW, &tcp_do_autorcvbuf, 0, "Enable automatic receive buffer sizing"); @@ -181,8 +158,6 @@ static void tcp_dropwithreset(struct mbuf *, struct tcphdr *, struct tcpcb *, int, int); static void tcp_pulloutofband(struct socket *, struct tcphdr *, struct mbuf *, int); -static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, - struct mbuf *); static void tcp_xmit_timer(struct tcpcb *, int); static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); static int tcp_timewait(struct inpcb *, struct tcpopt *, @@ -213,192 +188,6 @@ do { \ (tp->t_flags & TF_RXWIN0SENT) == 0) && \ (tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN))) -/* Initialize TCP reassembly queue */ -static void -tcp_reass_zone_change(void *tag) -{ - - tcp_reass_maxseg = nmbclusters / 16; - uma_zone_set_max(tcp_reass_zone, tcp_reass_maxseg); -} - -uma_zone_t tcp_reass_zone; -void -tcp_reass_init(void) -{ - - tcp_reass_maxseg = nmbclusters / 16; - TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments", - &tcp_reass_maxseg); - tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - uma_zone_set_max(tcp_reass_zone, tcp_reass_maxseg); - EVENTHANDLER_REGISTER(nmbclusters_change, - tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY); -} - -static int -tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) -{ - struct tseg_qent *q; - struct tseg_qent *p = NULL; - struct tseg_qent *nq; - struct tseg_qent *te = NULL; - struct socket *so = tp->t_inpcb->inp_socket; - int flags; - - INP_LOCK_ASSERT(tp->t_inpcb); - - /* - * XXX: tcp_reass() is rather inefficient with its data structures - * and should be rewritten (see NetBSD for optimizations). While - * doing that it should move to its own file tcp_reass.c. - */ - - /* - * Call with th==NULL after become established to - * force pre-ESTABLISHED data up to user socket. - */ - if (th == NULL) - goto present; - - /* - * Limit the number of segments in the reassembly queue to prevent - * holding on to too many segments (and thus running out of mbufs). - * Make sure to let the missing segment through which caused this - * queue. Always keep one global queue entry spare to be able to - * process the missing segment. - */ - if (th->th_seq != tp->rcv_nxt && - (tcp_reass_qsize + 1 >= tcp_reass_maxseg || - tp->t_segqlen >= tcp_reass_maxqlen)) { - tcp_reass_overflows++; - tcpstat.tcps_rcvmemdrop++; - m_freem(m); - *tlenp = 0; - return (0); - } - - /* - * Allocate a new queue entry. If we can't, or hit the zone limit - * just drop the pkt. - */ - te = uma_zalloc(tcp_reass_zone, M_NOWAIT); - if (te == NULL) { - tcpstat.tcps_rcvmemdrop++; - m_freem(m); - *tlenp = 0; - return (0); - } - tp->t_segqlen++; - tcp_reass_qsize++; - - /* - * Find a segment which begins after this one does. - */ - LIST_FOREACH(q, &tp->t_segq, tqe_q) { - if (SEQ_GT(q->tqe_th->th_seq, th->th_seq)) - break; - p = q; - } - - /* - * If there is a preceding segment, it may provide some of - * our data already. If so, drop the data from the incoming - * segment. If it provides all of our data, drop us. - */ - if (p != NULL) { - int i; - /* conversion to int (in i) handles seq wraparound */ - i = p->tqe_th->th_seq + p->tqe_len - th->th_seq; - if (i > 0) { - if (i >= *tlenp) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += *tlenp; - m_freem(m); - uma_zfree(tcp_reass_zone, te); - tp->t_segqlen--; - tcp_reass_qsize--; - /* - * Try to present any queued data - * at the left window edge to the user. - * This is needed after the 3-WHS - * completes. - */ - goto present; /* ??? */ - } - m_adj(m, i); - *tlenp -= i; - th->th_seq += i; - } - } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += *tlenp; - - /* - * While we overlap succeeding segments trim them or, - * if they are completely covered, dequeue them. - */ - while (q) { - int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq; - if (i <= 0) - break; - if (i < q->tqe_len) { - q->tqe_th->th_seq += i; - q->tqe_len -= i; - m_adj(q->tqe_m, i); - break; - } - - nq = LIST_NEXT(q, tqe_q); - LIST_REMOVE(q, tqe_q); - m_freem(q->tqe_m); - uma_zfree(tcp_reass_zone, q); - tp->t_segqlen--; - tcp_reass_qsize--; - q = nq; - } - - /* Insert the new segment queue entry into place. */ - te->tqe_m = m; - te->tqe_th = th; - te->tqe_len = *tlenp; - - if (p == NULL) { - LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q); - } else { - LIST_INSERT_AFTER(p, te, tqe_q); - } - -present: - /* - * Present data to user, advancing rcv_nxt through - * completed sequence space. - */ - if (!TCPS_HAVEESTABLISHED(tp->t_state)) - return (0); - q = LIST_FIRST(&tp->t_segq); - if (!q || q->tqe_th->th_seq != tp->rcv_nxt) - return (0); - SOCKBUF_LOCK(&so->so_rcv); - do { - tp->rcv_nxt += q->tqe_len; - flags = q->tqe_th->th_flags & TH_FIN; - nq = LIST_NEXT(q, tqe_q); - LIST_REMOVE(q, tqe_q); - if (so->so_rcv.sb_state & SBS_CANTRCVMORE) - m_freem(q->tqe_m); - else - sbappendstream_locked(&so->so_rcv, q->tqe_m); - uma_zfree(tcp_reass_zone, q); - tp->t_segqlen--; - tcp_reass_qsize--; - q = nq; - } while (q && q->tqe_th->th_seq == tp->rcv_nxt); - ND6_HINT(tp); - sorwakeup_locked(so); - return (flags); -} /* * TCP input routine, follows pages 65-76 of the diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index bff1e012382d..2cb9b6902770 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -30,28 +30,20 @@ * $FreeBSD$ */ -#include "opt_ipfw.h" /* for ipfw_fwd */ #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" -#include "opt_mac.h" #include "opt_tcpdebug.h" #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> -#include <sys/proc.h> /* for proc0 declaration */ -#include <sys/protosw.h> -#include <sys/signalvar.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/systm.h> -#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ - #include <vm/uma.h> #include <net/if.h> @@ -62,12 +54,9 @@ #include <netinet/in_systm.h> #include <netinet/in_var.h> #include <netinet/ip.h> -#include <netinet/ip_icmp.h> /* required for icmp_var.h */ -#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ #include <netinet/ip_var.h> #include <netinet/ip_options.h> #include <netinet/ip6.h> -#include <netinet/icmp6.h> #include <netinet6/in6_pcb.h> #include <netinet6/ip6_var.h> #include <netinet6/nd6.h> @@ -82,21 +71,6 @@ #include <netinet/tcp_debug.h> #endif /* TCPDEBUG */ -#ifdef FAST_IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/ipsec6.h> -#endif /*FAST_IPSEC*/ - -#ifdef IPSEC -#include <netinet6/ipsec.h> -#include <netinet6/ipsec6.h> -#include <netkey/key.h> -#endif /*IPSEC*/ - -#include <machine/in_cksum.h> - -#include <security/mac/mac_framework.h> - SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0, "TCP Segment Reassembly Queue"); @@ -120,10 +94,6 @@ SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, &tcp_reass_overflows, 0, "Global number of TCP Segment Reassembly Queue Overflows"); -static int tcp_reass(struct tcpcb *, struct tcphdr *, int *, - struct mbuf *); - - /* Initialize TCP reassembly queue */ static void tcp_reass_zone_change(void *tag) @@ -134,6 +104,7 @@ tcp_reass_zone_change(void *tag) } uma_zone_t tcp_reass_zone; + void tcp_reass_init(void) { @@ -148,7 +119,7 @@ tcp_reass_init(void) tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY); } -static int +int tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) { struct tseg_qent *q; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 90c2abab8e51..8d2e8e49d555 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -162,52 +162,6 @@ static int tcp_isn_reseed_interval = 0; SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW, &tcp_isn_reseed_interval, 0, "Seconds between reseeding of ISN secret"); -static uma_zone_t tcptw_zone; -static int maxtcptw; - -static int -tcptw_auto_size(void) -{ - int halfrange; - - /* - * Max out at half the ephemeral port range so that TIME_WAIT - * sockets don't tie up too many ephemeral ports. - */ - if (ipport_lastauto > ipport_firstauto) - halfrange = (ipport_lastauto - ipport_firstauto) / 2; - else - halfrange = (ipport_firstauto - ipport_lastauto) / 2; - /* Protect against goofy port ranges smaller than 32. */ - return (imin(imax(halfrange, 32), maxsockets / 5)); -} - -static int -sysctl_maxtcptw(SYSCTL_HANDLER_ARGS) -{ - int error, new; - - if (maxtcptw == 0) - new = tcptw_auto_size(); - else - new = maxtcptw; - error = sysctl_handle_int(oidp, &new, sizeof(int), req); - if (error == 0 && req->newptr) - if (new >= 32) { - maxtcptw = new; - uma_zone_set_max(tcptw_zone, maxtcptw); - } - return (error); -} -SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW, - &maxtcptw, 0, sysctl_maxtcptw, "IU", - "Maximum number of compressed TCP TIME_WAIT entries"); - -static int nolocaltimewait = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_RW, - &nolocaltimewait, 0, - "Do not create compressed TCP TIME_WAIT entries for local connections"); - /* * TCP bandwidth limiting sysctls. Note that the default lower bound of * 1024 exists only for debugging. A good production default would be @@ -284,8 +238,7 @@ tcp_zone_change(void *tag) uma_zone_set_max(tcbinfo.ipi_zone, maxsockets); uma_zone_set_max(tcpcb_zone, maxsockets); - if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, tcptw_auto_size()); + tcp_tw_zone_change(); } static int @@ -345,14 +298,8 @@ tcp_init(void) tcpcb_zone = uma_zcreate("tcpcb", sizeof(struct tcpcb_mem), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uma_zone_set_max(tcpcb_zone, maxsockets); - tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw), - NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw); - if (maxtcptw == 0) - uma_zone_set_max(tcptw_zone, tcptw_auto_size()); - else - uma_zone_set_max(tcptw_zone, maxtcptw); tcp_timer_init(); + tcp_tw_init(); syncache_init(); tcp_hc_init(); tcp_reass_init(); @@ -1742,303 +1689,6 @@ ipsec_hdrsiz_tcp(struct tcpcb *tp) #endif /*IPSEC*/ /* - * Move a TCP connection into TIME_WAIT state. - * tcbinfo is locked. - * inp is locked, and is unlocked before returning. - */ -void -tcp_twstart(struct tcpcb *tp) -{ - struct tcptw *tw; - struct inpcb *inp = tp->t_inpcb; - int acknow; - struct socket *so; - - INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */ - INP_LOCK_ASSERT(inp); - - if (nolocaltimewait && in_localip(inp->inp_faddr)) { - tp = tcp_close(tp); - if (tp != NULL) - INP_UNLOCK(inp); - return; - } - - tw = uma_zalloc(tcptw_zone, M_NOWAIT); - if (tw == NULL) { - tw = tcp_timer_2msl_tw(1); - if (tw == NULL) { - tp = tcp_close(tp); - if (tp != NULL) - INP_UNLOCK(inp); - return; - } - } - tw->tw_inpcb = inp; - - /* - * Recover last window size sent. - */ - tw->last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale; - - /* - * Set t_recent if timestamps are used on the connection. - */ - if ((tp->t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP|TF_NOOPT)) == - (TF_REQ_TSTMP|TF_RCVD_TSTMP)) { - tw->t_recent = tp->ts_recent; - tw->ts_offset = tp->ts_offset; - } else { - tw->t_recent = 0; - tw->ts_offset = 0; - } - - tw->snd_nxt = tp->snd_nxt; - tw->rcv_nxt = tp->rcv_nxt; - tw->iss = tp->iss; - tw->irs = tp->irs; - tw->t_starttime = tp->t_starttime; - tw->tw_time = 0; - -/* XXX - * If this code will - * be used for fin-wait-2 state also, then we may need - * a ts_recent from the last segment. - */ - acknow = tp->t_flags & TF_ACKNOW; - - /* - * First, discard tcpcb state, which includes stopping its timers and - * freeing it. tcp_discardcb() used to also release the inpcb, but - * that work is now done in the caller. - * - * Note: soisdisconnected() call used to be made in tcp_discardcb(), - * and might not be needed here any longer. - */ - 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); - if (acknow) - tcp_twrespond(tw, TH_ACK); - inp->inp_ppcb = tw; - inp->inp_vflag |= INP_TIMEWAIT; - tcp_timer_2msl_reset(tw, 0); - - /* - * If the inpcb owns the sole reference to the socket, then we can - * detach and free the socket as it is not needed in time wait. - */ - if (inp->inp_vflag & INP_SOCKREF) { - KASSERT(so->so_state & SS_PROTOREF, - ("tcp_twstart: !SS_PROTOREF")); - inp->inp_vflag &= ~INP_SOCKREF; - INP_UNLOCK(inp); - ACCEPT_LOCK(); - SOCK_LOCK(so); - so->so_state &= ~SS_PROTOREF; - sofree(so); - } else - INP_UNLOCK(inp); -} - -#if 0 -/* - * The appromixate rate of ISN increase of Microsoft TCP stacks; - * the actual rate is slightly higher due to the addition of - * random positive increments. - * - * Most other new OSes use semi-randomized ISN values, so we - * do not need to worry about them. - */ -#define MS_ISN_BYTES_PER_SECOND 250000 - -/* - * Determine if the ISN we will generate has advanced beyond the last - * sequence number used by the previous connection. If so, indicate - * that it is safe to recycle this tw socket by returning 1. - */ -int -tcp_twrecycleable(struct tcptw *tw) -{ - tcp_seq new_iss = tw->iss; - tcp_seq new_irs = tw->irs; - - INP_INFO_WLOCK_ASSERT(&tcbinfo); - new_iss += (ticks - tw->t_starttime) * (ISN_BYTES_PER_SECOND / hz); - new_irs += (ticks - tw->t_starttime) * (MS_ISN_BYTES_PER_SECOND / hz); - - if (SEQ_GT(new_iss, tw->snd_nxt) && SEQ_GT(new_irs, tw->rcv_nxt)) - return (1); - else - return (0); -} -#endif - -void -tcp_twclose(struct tcptw *tw, int reuse) -{ - struct socket *so; - struct inpcb *inp; - - /* - * At this point, we are in one of two situations: - * - * (1) We have no socket, just an inpcb<->twtcp pair. We can free - * all state. - * - * (2) We have a socket -- if we own a reference, release it and - * notify the socket layer. - */ - inp = tw->tw_inpcb; - KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait")); - KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw")); - INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_stop(). */ - INP_LOCK_ASSERT(inp); - - tw->tw_inpcb = NULL; - tcp_timer_2msl_stop(tw); - inp->inp_ppcb = NULL; - in_pcbdrop(inp); - - so = inp->inp_socket; - if (so != NULL) { - /* - * If there's a socket, handle two cases: first, we own a - * strong reference, which we will now release, or we don't - * in which case another reference exists (XXXRW: think - * about this more), and we don't need to take action. - */ - if (inp->inp_vflag & INP_SOCKREF) { - inp->inp_vflag &= ~INP_SOCKREF; - INP_UNLOCK(inp); - ACCEPT_LOCK(); - SOCK_LOCK(so); - KASSERT(so->so_state & SS_PROTOREF, - ("tcp_twclose: INP_SOCKREF && !SS_PROTOREF")); - so->so_state &= ~SS_PROTOREF; - sofree(so); - } else { - /* - * If we don't own the only reference, the socket and - * inpcb need to be left around to be handled by - * tcp_usr_detach() later. - */ - INP_UNLOCK(inp); - } - } else { -#ifdef INET6 - if (inp->inp_vflag & INP_IPV6PROTO) - in6_pcbfree(inp); - else -#endif - in_pcbfree(inp); - } - tcpstat.tcps_closed++; - crfree(tw->tw_cred); - tw->tw_cred = NULL; - if (reuse) - return; - uma_zfree(tcptw_zone, tw); -} - -int -tcp_twrespond(struct tcptw *tw, int flags) -{ - struct inpcb *inp = tw->tw_inpcb; - struct tcphdr *th; - struct mbuf *m; - struct ip *ip = NULL; - u_int hdrlen, optlen; - int error; - struct tcpopt to; -#ifdef INET6 - struct ip6_hdr *ip6 = NULL; - int isipv6 = inp->inp_inc.inc_isipv6; -#endif - - INP_LOCK_ASSERT(inp); - - m = m_gethdr(M_DONTWAIT, MT_DATA); - if (m == NULL) - return (ENOBUFS); - m->m_data += max_linkhdr; - -#ifdef MAC - mac_create_mbuf_from_inpcb(inp, m); -#endif - -#ifdef INET6 - if (isipv6) { - hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); - ip6 = mtod(m, struct ip6_hdr *); - th = (struct tcphdr *)(ip6 + 1); - tcpip_fillheaders(inp, ip6, th); - } else -#endif - { - hdrlen = sizeof(struct tcpiphdr); - ip = mtod(m, struct ip *); - th = (struct tcphdr *)(ip + 1); - tcpip_fillheaders(inp, ip, th); - } - to.to_flags = 0; - - /* - * Send a timestamp and echo-reply if both our side and our peer - * have sent timestamps in our SYN's and this is not a RST. - */ - if (tw->t_recent && flags == TH_ACK) { - to.to_flags |= TOF_TS; - to.to_tsval = ticks + tw->ts_offset; - to.to_tsecr = tw->t_recent; - } - optlen = tcp_addoptions(&to, (u_char *)(th + 1)); - - m->m_len = hdrlen + optlen; - m->m_pkthdr.len = m->m_len; - - KASSERT(max_linkhdr + m->m_len <= MHLEN, ("tcptw: mbuf too small")); - - th->th_seq = htonl(tw->snd_nxt); - th->th_ack = htonl(tw->rcv_nxt); - th->th_off = (sizeof(struct tcphdr) + optlen) >> 2; - th->th_flags = flags; - th->th_win = htons(tw->last_win); - -#ifdef INET6 - if (isipv6) { - th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), - sizeof(struct tcphdr) + optlen); - ip6->ip6_hlim = in6_selecthlim(inp, NULL); - error = ip6_output(m, inp->in6p_outputopts, NULL, - (tw->tw_so_options & SO_DONTROUTE), NULL, NULL, inp); - } else -#endif - { - th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(sizeof(struct tcphdr) + optlen + IPPROTO_TCP)); - m->m_pkthdr.csum_flags = CSUM_TCP; - m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); - ip->ip_len = m->m_pkthdr.len; - if (path_mtu_discovery) - ip->ip_off |= IP_DF; - error = ip_output(m, inp->inp_options, NULL, - ((tw->tw_so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), - NULL, inp); - } - if (flags & TH_ACK) - tcpstat.tcps_sndacks++; - else - tcpstat.tcps_sndctrl++; - tcpstat.tcps_sndtotal++; - return (error); -} - -/* * TCP BANDWIDTH DELAY PRODUCT WINDOW LIMITING * * This code attempts to calculate the bandwidth-delay product as a diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index b1e22bc2ba60..c04b6fcb5777 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -30,10 +30,8 @@ * $FreeBSD$ */ -#include "opt_compat.h" #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_mac.h" #include "opt_tcpdebug.h" @@ -44,9 +42,6 @@ #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/mbuf.h> -#ifdef INET6 -#include <sys/domain.h> -#endif #include <sys/priv.h> #include <sys/proc.h> #include <sys/socket.h> @@ -91,26 +86,7 @@ #endif #include <netinet6/ip6protosw.h> -#ifdef IPSEC -#include <netinet6/ipsec.h> -#ifdef INET6 -#include <netinet6/ipsec6.h> -#endif -#include <netkey/key.h> -#endif /*IPSEC*/ - -#ifdef FAST_IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/xform.h> -#ifdef INET6 -#include <netipsec/ipsec6.h> -#endif -#include <netipsec/key.h> -#define IPSEC -#endif /*FAST_IPSEC*/ - #include <machine/in_cksum.h> -#include <sys/md5.h> #include <security/mac/mac_framework.h> @@ -151,6 +127,7 @@ sysctl_maxtcptw(SYSCTL_HANDLER_ARGS) } return (error); } + SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW, &maxtcptw, 0, sysctl_maxtcptw, "IU", "Maximum number of compressed TCP TIME_WAIT entries"); @@ -160,11 +137,8 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_RW, &nolocaltimewait, 0, "Do not create compressed TCP TIME_WAIT entries for local connections"); -/* - * TCP initialization. - */ -static void -tcp_zone_change(void *tag) +void +tcp_tw_zone_change(void) { if (maxtcptw == 0) @@ -172,7 +146,7 @@ tcp_zone_change(void *tag) } void -tcp_init(void) +tcp_tw_init(void) { tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw), diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index bb1c18d1db4d..925ee7d1ef68 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -75,6 +75,18 @@ struct tcptemp { #define tcp6cb tcpcb /* for KAME src sync over BSD*'s */ +/* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint. */ +#ifdef INET6 +#define ND6_HINT(tp) \ +do { \ + if ((tp) && (tp)->t_inpcb && \ + ((tp)->t_inpcb->inp_vflag & INP_IPV6) != 0) \ + nd6_nud_hint(NULL, NULL, 0); \ +} while (0) +#else +#define ND6_HINT(tp) +#endif + /* * Tcp control block, one per tcp; fields: * Organized for 16 byte cacheline efficiency. @@ -508,6 +520,7 @@ void tcp_drain(void); void tcp_fasttimo(void); void tcp_init(void); void tcp_fini(void *); +int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *); void tcp_reass_init(void); void tcp_input(struct mbuf *, int); u_long tcp_maxmtu(struct in_conninfo *, int *); @@ -523,6 +536,8 @@ struct tcpcb * int tcp_output(struct tcpcb *); void tcp_respond(struct tcpcb *, void *, struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int); +void tcp_tw_init(void); +void tcp_tw_zone_change(void); int tcp_twrespond(struct tcptw *, int); void tcp_setpersist(struct tcpcb *); #ifdef TCP_SIGNATURE |