Mercurial > ecos
changeset 3013:286a2ab55044
* src/sys/netinet/if_ether.c: Merge fix from FreeBSD CVS r1.108.
Prevents creation of reciprocal ARP cache entries for hosts not on
local subnet.
* cdl/freebsd_net.cdl:
* include/netinet/tcp_var.c:
* src/sys/netinet/tcp_subr.c:
* src/sys/netinet/tcp_input.c: Merge fix from FreeBSD CVS. Introduces
a maximum size for the TCP reassembly queue to limit network buffer
usage associated with reassembly. Enable CYGNUM_NET_TCP_REASS_DIVISOR
and set it to configure the maximum number of buffers usable for TCP
reassembly.
| author | jlarmour |
|---|---|
| date | Tue, 22 Feb 2011 04:36:20 +0000 |
| parents | 6f3a55d82b7f |
| children | 5c7def252040 |
| files | packages/net/bsd_tcpip/current/ChangeLog packages/net/bsd_tcpip/current/cdl/freebsd_net.cdl packages/net/bsd_tcpip/current/include/netinet/tcp_var.h packages/net/bsd_tcpip/current/src/sys/netinet/if_ether.c packages/net/bsd_tcpip/current/src/sys/netinet/tcp_input.c packages/net/bsd_tcpip/current/src/sys/netinet/tcp_subr.c |
| diffstat | 6 files changed, 113 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/net/bsd_tcpip/current/ChangeLog +++ b/packages/net/bsd_tcpip/current/ChangeLog @@ -1,3 +1,17 @@ +2011-02-22 Kelvin Lawson <kelvinl@users.sf.net> + + * src/sys/netinet/if_ether.c: Merge fix from FreeBSD CVS r1.108. + Prevents creation of reciprocal ARP cache entries for hosts not on + local subnet. + * cdl/freebsd_net.cdl: + * include/netinet/tcp_var.c: + * src/sys/netinet/tcp_subr.c: + * src/sys/netinet/tcp_input.c: Merge fix from FreeBSD CVS. Introduces + a maximum size for the TCP reassembly queue to limit network buffer + usage associated with reassembly. Enable CYGNUM_NET_TCP_REASS_DIVISOR + and set it to configure the maximum number of buffers usable for TCP + reassembly. + 2010-09-18 John Dallaway <john@dallaway.org.uk> * doc/freebsd.sgml: No longer "recent".
--- a/packages/net/bsd_tcpip/current/cdl/freebsd_net.cdl +++ b/packages/net/bsd_tcpip/current/cdl/freebsd_net.cdl @@ -291,7 +291,7 @@ cdl_package CYGPKG_NET_FREEBSD_STACK { for buffers used by the networking code. The number is an upper limit, with at least enough space to get the stack initialized. Tip: setting a breakpoint at cyg_memalloc_alloc_fail() - is an especially useful tool in establishing when there is too + is an especially useful tool in establishing when there is too little memory for an application. " } @@ -320,6 +320,22 @@ cdl_package CYGPKG_NET_FREEBSD_STACK { Clusters size." } + cdl_option CYGNUM_NET_TCP_REASS_DIVISOR { + display "Max TCP reassembly queue fraction" + flavor booldata + default_value 0 + description " + Enabling this option puts a maximum limit on the number of TCP + segments which can be queued for reassembly. The value of this + option gives the maximum proportion of clusters that can be used + for TCP reassembly. The maximum number of segments is given + by the total number of clusters available divided by the value of + this option (in other words, + nmbclusters / CYGNUM_NET_TCP_REASS_DIVISOR). So for example, + setting this option to 16 will means that no more than 1/16 of + the total number of clusters will be used for TCP reassembly." + } + cdl_option CYGPKG_NET_MAXSOCKETS { display "Max number of open sockets" flavor data @@ -419,8 +435,8 @@ cdl_package CYGPKG_NET_FREEBSD_STACK { description " The default is 50, which will usually mean a delay between tests for 'stuck' devices of 500mS, that is half a second. - The overhead only applies if no network activity occurred, - so it may be acceptable to make this value very small, + The overhead only applies if no network activity occurred, + so it may be acceptable to make this value very small, where high CPU load does not matter during network idle periods, or very large if your application tries often to send packets itself."
--- a/packages/net/bsd_tcpip/current/include/netinet/tcp_var.h +++ b/packages/net/bsd_tcpip/current/include/netinet/tcp_var.h @@ -67,6 +67,8 @@ struct tseg_qent { struct mbuf *tqe_m; /* mbuf contains packet */ }; LIST_HEAD(tsegqe_head, tseg_qent); +extern int tcp_reass_maxseg; +extern int tcp_reass_qsize; #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_TSEGQ); #endif
--- a/packages/net/bsd_tcpip/current/src/sys/netinet/if_ether.c +++ b/packages/net/bsd_tcpip/current/src/sys/netinet/if_ether.c @@ -807,13 +807,25 @@ arplookup(addr, create, proxy) why = "could not allocate llinfo"; else if (rt->rt_gateway->sa_family != AF_LINK) why = "gateway route is not ours"; - - if (why && create) { - log(LOG_DEBUG, "arplookup %s failed: %s\n", - inet_ntoa(sin.sin_addr), why); - return 0; - } else if (why) { - return 0; + + if (why) { + if (create) { + log(LOG_DEBUG, "arplookup %s failed: %s\n", + inet_ntoa(sin.sin_addr), why); + /* + * If there are no references to this Layer 2 route, + * and it is a cloned route, and not static, and + * arplookup() is creating the route, then purge + * it from the routing table as it is probably bogus. + */ + if (((rt->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == + RTF_WASCLONED) && (rt->rt_refcnt == 0)) + rtrequest(RTM_DELETE, + (struct sockaddr *)rt_key(rt), + rt->rt_gateway, rt_mask(rt), + rt->rt_flags, 0); + } + return (0); } return ((struct llinfo_arp *)rt->rt_llinfo); }
--- a/packages/net/bsd_tcpip/current/src/sys/netinet/tcp_input.c +++ b/packages/net/bsd_tcpip/current/src/sys/netinet/tcp_input.c @@ -132,6 +132,26 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, drop &drop_synfin, 0, "Drop TCP packets with SYN+FIN set"); #endif +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR +SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0, + "TCP Segment Reassembly Queue"); + +int tcp_reass_maxseg = 0; +SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RD, + &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_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"); +#endif + struct inpcbhead tcb; #define tcb6 tcb /* for KAME src sync over BSD*'s */ struct inpcbinfo tcbinfo; @@ -185,6 +205,23 @@ tcp_reass(tp, th, tlenp, m) if (th == 0) 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. + */ +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + if (th->th_seq != tp->rcv_nxt && + tcp_reass_qsize + 1 >= tcp_reass_maxseg) { + tcp_reass_overflows++; + tcpstat.tcps_rcvmemdrop++; + m_freem(m); + return (0); + } +#endif + /* Allocate a new queue entry. If we can't, just drop the pkt. XXX */ MALLOC(te, struct tseg_qent *, sizeof (struct tseg_qent), M_TSEGQ, M_NOWAIT); @@ -193,6 +230,9 @@ tcp_reass(tp, th, tlenp, m) m_freem(m); return (0); } +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize++; +#endif /* * Find a segment which begins after this one does. @@ -218,6 +258,9 @@ tcp_reass(tp, th, tlenp, m) tcpstat.tcps_rcvdupbyte += *tlenp; m_freem(m); FREE(te, M_TSEGQ); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize--; +#endif /* * Try to present any queued data * at the left window edge to the user. @@ -253,6 +296,9 @@ tcp_reass(tp, th, tlenp, m) LIST_REMOVE(q, tqe_q); m_freem(q->tqe_m); FREE(q, M_TSEGQ); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize--; +#endif q = nq; } @@ -287,6 +333,9 @@ present: else sbappend(&so->so_rcv, q->tqe_m); FREE(q, M_TSEGQ); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize--; +#endif q = nq; } while (q && q->tqe_th->th_seq == tp->rcv_nxt); ND6_HINT(tp);
--- a/packages/net/bsd_tcpip/current/src/sys/netinet/tcp_subr.c +++ b/packages/net/bsd_tcpip/current/src/sys/netinet/tcp_subr.c @@ -213,6 +213,10 @@ tcp_init() &tcbinfo.porthashmask); tcbinfo.ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets, ZONE_INTERRUPT, 0); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_maxseg = nmbclusters / CYGNUM_NET_TCP_REASS_DIVISOR; +#endif + #ifdef INET6 #define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) #else /* INET6 */ @@ -732,6 +736,9 @@ tcp_close(tp) LIST_REMOVE(q, tqe_q); m_freem(q->tqe_m); FREE(q, M_TSEGQ); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize--; +#endif } inp->inp_ppcb = NULL; soisdisconnected(so); @@ -770,6 +777,9 @@ tcp_drain() LIST_REMOVE(te, tqe_q); m_freem(te->tqe_m); FREE(te, M_TSEGQ); +#ifdef CYGNUM_NET_TCP_REASS_DIVISOR + tcp_reass_qsize--; +#endif } } }
