Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jan 2002 02:18:40 -0800
From:      Luigi Rizzo <rizzo@icir.org>
To:        Ruslan Ermilov <ru@FreeBSD.ORG>
Cc:        chkno@dork.com, freebsd-ipfw@FreeBSD.ORG
Subject:   Re: ip_dummynet.c:"*** OUCH! pipe should have been idle!"
Message-ID:  <20020115021839.A74391@iguana.icir.org>
In-Reply-To: <20020115120531.C46269@sunbay.com>
References:  <20020114141539.A70340@iguana.icir.org> <200201142246.g0EMkXC05128@chk.phattydomain.com> <20020114145849.A70496@iguana.icir.org> <20020115120531.C46269@sunbay.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Jan 15, 2002 at 12:05:31PM +0200, Ruslan Ermilov wrote:
> On Mon, Jan 14, 2002 at 02:58:49PM -0800, Luigi Rizzo wrote:
> > When the queue overflows, you get an ENOBUFS error, which natd
> > detects and handles by retransmitting the packet at a later time
> > (not a very good idea, I'd say that natd should just drop the packet
> > in this case. The "fix" might be trapping the ENOBUFS error in
> > usr/src/sbin/natd.c:FlushPacketBuffer() and returning as if the
> > transmission was successful).
> > 
> ENOBUFS may be returned by sendto(2) when no socket buffer space
> is available.  In this case, natd(8) retransmits the packet only
> after select(2) says that the socket is writable again.  Dropping
> the packet in this case would be bogus, and natd.c has fixed this
> in revision 1.2.

Sorry Ruslan, but I think you are wrong.

For udp/datagram sockets, the i[output] socket buffer has no role
other than limit the max datagram size, and it is entirely bypassed
by the sendto/write routines. So, select() sees the socket as always
writable, and natd in this case loop forever. This is why i said
retrying is broken. And it is severely broken, indeed.


Look at the sendto() manpage:

   ERRORS
	...

     [ENOBUFS]          The system was unable to allocate an internal buffer.
                        The operation may succeed when buffers become avail-
                        able.

     [ENOBUFS]          The output queue for a network interface was full.
                        This generally indicates that the interface has
                        stopped sending, but may be caused by transient con-
                        gestion.

and also at the source code for sendto().

The reason why you cannot queue in the socket buffer is that there
is no way to trigger the transmission when the device becomes available
again -- for TCP this is supported by incoming acks or timeouts, but
there is no equivalent for UDP.
Sure you could think of queueing the socket on the output device, but
apart that there is no infrastructure for that, which interface to
use depends on routing info, and then you might have multiple
ones because of multicast...

	cheers
	luigi (who discovered this during fall 2000)
----------------------------------+-----------------------------------------
 Luigi RIZZO, luigi@iet.unipi.it  . ACIRI/ICSI (on leave from Univ. di Pisa)
 http://www.iet.unipi.it/~luigi/  . 1947 Center St, Berkeley CA 94704
 Phone: (510) 666 2927
----------------------------------+-----------------------------------------

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ipfw" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020115021839.A74391>