diff options
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r-- | sys/netinet/tcp_input.c | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ad42e03..6fcbded 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 |