# HG changeset patch # Parent 2309467e4992cab3f95d518ff8e557372b4099b2 diff -r 2309467e4992 sys/netinet/tcp_reass.c --- a/sys/netinet/tcp_reass.c Sat Sep 25 01:10:30 2010 +1000 +++ b/sys/netinet/tcp_reass.c Sat Sep 25 01:40:07 2010 +1000 @@ -92,12 +92,6 @@ &VNET_NAME(tcp_reass_qsize), 0, &tcp_reass_sysctl_qsize, "I", "Global number of TCP Segments currently in Reassembly Queue"); -static VNET_DEFINE(int, tcp_reass_maxqlen) = 48; -#define V_tcp_reass_maxqlen VNET(tcp_reass_maxqlen) -SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxqlen, CTLFLAG_RW, - &VNET_NAME(tcp_reass_maxqlen), 0, - "Maximum number of TCP Segments per individual Reassembly Queue"); - static VNET_DEFINE(int, tcp_reass_overflows) = 0; #define V_tcp_reass_overflows VNET(tcp_reass_overflows) SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, @@ -197,13 +191,18 @@ 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. + * Limit the number of segments that can be queued to reduce the + * potential for mbuf exhaustion. For best performance, we want to be + * able to queue a full window's worth of segments. The size of the + * socket receive buffer determines our advertised window and grows + * automatically when socket buffer autotuning is enabled. Use it as the + * basis for our queue limit. + * Always let the missing segment through which caused this queue. + * NB: Access to the socket buffer is left intentionally unlocked as we + * can tolerate stale information here. */ if (th->th_seq != tp->rcv_nxt && - tp->t_segqlen >= V_tcp_reass_maxqlen) { + tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) { V_tcp_reass_overflows++; TCPSTAT_INC(tcps_rcvmemdrop); m_freem(m); @@ -211,6 +210,17 @@ return (0); } + long rxsbspace = sbspace(&so->so_rcv); + if (tp->t_segqlen >= (rxsbspace / tp->t_maxseg) + 1) { + //if (tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) { + printf("tp: %p, t_segqlen: %d, sbspace(so_rcv): %ld, " + "so_rcv->sb_hiwat: %d, rcv_wnd: %ld, excess: %ld\n", tp, + tp->t_segqlen, rxsbspace / tp->t_maxseg, + so->so_rcv.sb_hiwat/tp->t_maxseg, + tp->rcv_wnd/tp->t_maxseg, tp->t_segqlen - ((rxsbspace / + tp->t_maxseg) + 1)); + } + /* * Allocate a new queue entry. If we can't, or hit the zone limit * just drop the pkt.