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>