Subject: Re: udp receive buffer overflow with many small packets
To: Stuart Brooks <stuartb@cat.co.za>
From: Jonathan Stone <jonathan@dsg.stanford.edu>
List: tech-net
Date: 04/21/2005 09:37:50
In message <057501c5466d$7bc1b880$5e22a8c0@STU95>,
"Stuart Brooks" writes:

>I am experiencing udp buffer overflows when receiving large numbers of
>small udp packets. In particular, if handling is blocked, only the first
>164 get through, even though the receive buffer is sitting at 15kB (out
>of a possible 40kB).  So obviously size is not the only constraint.

Size *is* the relevant constraint here, but there are two size
constraints.  The first contraint is the actual amount of user data
queued on a socket (which is what you are looking at), which is
computed as (sb->sb_hiwat - sb->sb_cc).  The second constraint is the
one you are almost certaily hitting, namely: how much buffer space is
that queued data actually consuming? That limit is computed as
(sb->sb_mbmax - sb->sb_mbcnt)

Both limits are implemented inside the macro sbspace() in
sys/sys/socketvar.h.

Your UDP datgrams have, on average, just under 100 bytes of user data.
But each UDP datagram occupies at least one mbuf, which holds at least
256 bytes of actual kernel memory. Possibly more, after headers are
pulled up into a separate mbuf.

You can increase the sb->sb_hiwat limit (the limit on bytes of valid
user data) for UDP-socket receive buffers by increasing the sysctl
knobs

	net.inet.udp.recvspace
	net.inet6.udp6.recvspace 

(use .sendspace for send-side buffers).  But I know of no good way to
increase the limit on the number of mbuf objects, and certainly not on
a per-protocol basis.  That was one of many design flaws in the KAME
IPsec code (PF_KEY sockets also send very small messages). That flaw,
at least, has been remedied (see sbappendaddrchain(), which
deliberalety ignores sbspace() restrictions for this exact reason).

You can try bumping up the recvspace limits to a multiple (about 4x,
from the numbers above) what you really want; but I expect you will
quickly run into the sb_mbmax limit.  Last I looked, there was no
protocol-specific way to increase the sb_mbmax (buffer count) to
sb_hiwat (user-data byte count) ratio; also no sysctl knob. I think
you'll have to build a custom kernel.