Sysctl knob(s) to set TCP 'nagle' time-out?
dillon at apollo.backplane.com
Mon Jun 23 08:27:12 UTC 2008
:I'm wondering if anything exists to set this.. When you create an INET
:without the 'TCP_NODELAY' flag the network layer does 'naggling' on your
:transmitted data. Sometimes with hosts that use Delayed_ACK
:delayed_ack) it creates a dead-lock where the host will not ACK until
:another packet and the client will not send another packet until it
:gets an ACK..
:The dead-lock gets broken by a time-out, which I think is around 200ms?
:But I would like to change that time-out if possible to something
:I can't really see any sysctl knobs that have a name that suggests
:So does anyone know IF this can be tuned and if so by what?
:(And yes you could solve it by setting the TCP_NODELAY flag on the
:but not everything has programmed in options to set it and you don't
:have access to the source, besides setting a sysctl value would be much
:simpler than recompiling stuff)
There is a sysctl which adjusts the delayed-ack timing, its
called net.inet.tcp.delacktime. The default is 1/10 of a second
(100 == 100 ms = 1/10 of a second).
BUT, it shouldn't be possible for nagle to deadlock against delayed acks
unless the TCP implementation is broken somehow. A delayed ack is
simply that... the ack is delayed 100 ms in order to improve its
chances of being piggy-backed on return data. The ack is not blocked
completely, just delayed, and certain events (such as the receiving
end turning around and sending data back, which is typical for an
interactive connection)... certain events will cause the delayed ack
to be aborted and for the ack to be immediately sent with the return data.
Can it break down and cause excessive lag? Yes, it can. Interactive
games almost universally have to disable Nagle because the lag is
actually due to the data relay from client 1 -> server then relaying
the interactive event to client 2. Without an immediate interactive
response to client 1 the ack gets delayed and the next event from
client 1 hits Nagle and stops dead in the water until the first event
reaches client 2 and client 2 reacts to it (then client 2 -> server ->
(abort delayed ack and send) -> client 1 (client 1's nagle now allows
the second event to be transmitted). That isn't a deadlock, just
really poor interactive performance in that particular situation.
Delayed acks also have a safety valve. The spec says that an ack
cannot be delayed more then two packets. In a batch link when the
second (unacked) packet is received, the delayed ack is aborted and
an ack is immediately returned to the sender. This is to prevent
congestion control (which is based on acks) from getting completely
out of whack and also to prevent the TCP window from getting exhausted.
In anycase, the usual solution is to disable Nagle rather then mess
with delayed acks. What we need is a new Nagle that understands the
new reality for interactive connections... something that doesn't break
performance in the 'server in the middle' data relaying case.
More information about the freebsd-stable