From owner-svn-src-stable-7@FreeBSD.ORG Sat Nov 6 15:40:34 2010 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E29071065670; Sat, 6 Nov 2010 15:40:34 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 96DE58FC08; Sat, 6 Nov 2010 15:40:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oA6FeYoc035840; Sat, 6 Nov 2010 15:40:34 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oA6FeYSL035838; Sat, 6 Nov 2010 15:40:34 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201011061540.oA6FeYSL035838@svn.freebsd.org> From: Lawrence Stewart Date: Sat, 6 Nov 2010 15:40:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214889 - stable/7/sys/netinet X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 Nov 2010 15:40:35 -0000 Author: lstewart Date: Sat Nov 6 15:40:34 2010 New Revision: 214889 URL: http://svn.freebsd.org/changeset/base/214889 Log: MFC r213912: - Switch the "net.inet.tcp.reass.cursegments" and "net.inet.tcp.reass.maxsegments" sysctl variables to be based on UMA zone stats. The value returned by the cursegments sysctl is approximate owing to the way in which uma_zone_get_cur is implemented. - Discontinue use of V_tcp_reass_qsize as a global reassembly segment count variable in the reassembly implementation. The variable was used without proper synchronisation and was duplicating accounting done by UMA already. The lack of synchronisation was particularly problematic on SMP systems terminating many TCP sessions, resulting in poor TCP performance for connections with non-zero packet loss. The base code from r213912 was modified as part of this MFC in order to work correctly on FreeBSD 7. Sponsored by: FreeBSD Foundation Reviewed by: andre, gnn, rpaulo (as part of a larger patch) Modified: stable/7/sys/netinet/tcp_reass.c Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/netinet/tcp_reass.c ============================================================================== --- stable/7/sys/netinet/tcp_reass.c Sat Nov 6 15:21:46 2010 (r214888) +++ stable/7/sys/netinet/tcp_reass.c Sat Nov 6 15:40:34 2010 (r214889) @@ -73,17 +73,20 @@ __FBSDID("$FreeBSD$"); #include #endif /* TCPDEBUG */ +static int tcp_reass_sysctl_maxseg(SYSCTL_HANDLER_ARGS); +static int tcp_reass_sysctl_qsize(SYSCTL_HANDLER_ARGS); + 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, +SYSCTL_PROC(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN, + &tcp_reass_maxseg, 0, &tcp_reass_sysctl_maxseg, "I", "Global maximum number of TCP Segments in Reassembly Queue"); static int tcp_reass_qsize = 0; -SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD, - &tcp_reass_qsize, 0, +SYSCTL_PROC(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD, + &tcp_reass_qsize, 0, &tcp_reass_sysctl_qsize, "I", "Global number of TCP Segments currently in Reassembly Queue"); static int tcp_reass_maxqlen = 48; @@ -133,7 +136,6 @@ tcp_reass_flush(struct tcpcb *tp) m_freem(qe->tqe_m); uma_zfree(tcp_reass_zone, qe); tp->t_segqlen--; - tcp_reass_qsize--; } KASSERT((tp->t_segqlen == 0), @@ -141,6 +143,20 @@ tcp_reass_flush(struct tcpcb *tp) tp, tp->t_segqlen)); } +static int +tcp_reass_sysctl_maxseg(SYSCTL_HANDLER_ARGS) +{ + tcp_reass_maxseg = uma_zone_get_max(tcp_reass_zone); + return (sysctl_handle_int(oidp, arg1, arg2, req)); +} + +static int +tcp_reass_sysctl_qsize(SYSCTL_HANDLER_ARGS) +{ + tcp_reass_qsize = uma_zone_get_cur(tcp_reass_zone); + return (sysctl_handle_int(oidp, arg1, arg2, req)); +} + int tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) { @@ -170,12 +186,10 @@ tcp_reass(struct tcpcb *tp, struct tcphd * 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. + * queue. */ if (th->th_seq != tp->rcv_nxt && - (tcp_reass_qsize + 1 >= tcp_reass_maxseg || - tp->t_segqlen >= tcp_reass_maxqlen)) { + tp->t_segqlen >= tcp_reass_maxqlen) { tcp_reass_overflows++; tcpstat.tcps_rcvmemdrop++; m_freem(m); @@ -195,7 +209,6 @@ tcp_reass(struct tcpcb *tp, struct tcphd return (0); } tp->t_segqlen++; - tcp_reass_qsize++; /* * Find a segment which begins after this one does. @@ -222,7 +235,6 @@ tcp_reass(struct tcpcb *tp, struct tcphd 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. @@ -259,7 +271,6 @@ tcp_reass(struct tcpcb *tp, struct tcphd m_freem(q->tqe_m); uma_zfree(tcp_reass_zone, q); tp->t_segqlen--; - tcp_reass_qsize--; q = nq; } @@ -296,7 +307,6 @@ present: 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);