Subject: Re: sendto() and ENOBUFS question..
To: None <tech-net@netbsd.org>
From: None <sudog@sudog.com>
List: tech-net
Date: 05/14/2002 19:36:16
> Just a thought: do you know that you are getting ENOBUFS from the
> driver? Most computers today can generate output way faster than the
> devices can manage, so it's possible that you are getting the failure
> from actually taking up all the mbufs in the system. What does 'netstat
> -m' show? Don't forget that there really isn't any backpressure in this
> case, either from UDP or from the driver (AFAIK).
>
> Does the socket layer even check with sowriteable() in the case of UDP?
> Last I looked, data on datagram sockets went straight to the protocol
> layer, bypassing all (socket) buffering completely.
>
> Regards,
>
> Justin
I've got a gut feeling that the ENOBUFS is coming from here:
netinet/udp_usrreq.c:882
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
if (m == 0) {
error = ENOBUFS;
goto release;
}
So, the question is, does select() or poll() make a check to ensure
that ENOBUFS won't show up when udp_output() is called? Or should it?
If not, how would I, in userland, cleanly wait until I can do another
udp_output safely without ENOBUFS showing up?
Uh oh.. It seems I am doomed to run a guessing heuristic on when I
think sendto() will succeed or fail.. I just checked in the nfs
drivers to see how they handle it.. when I saw this:
nfs/nfs_socket.c:450:
if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
/*
* We're too fast for the network/driver,
* and UDP isn't flowcontrolled.
* We need to resend. This is not fatal,
* just try again.
*
* Could be smarter here by doing some sort
* of a backoff, but this is rare.
*/
Doh!
Any pointers? I'd hate to have to write something unreliable to patch
the kernel with.
Thanks for your patience.
-Marc Tooley