Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!pasteur!ucbvax!BEAST.DDN.MIL!stjohns
From: stjo...@BEAST.DDN.MIL (Mike St. Johns)
Newsgroups: comp.protocols.tcp-ip
Subject: Go-Ahead Considered Harmless??
Message-ID: <8901032039.AA04944@beast.ddn.mil>
Date: 3 Jan 89 20:39:31 GMT
Sender: dae...@ucbvax.BERKELEY.EDU
Organization: The Internet
Lines: 10

Can someone refresh my memory -

When a TELNET connection is first opened, what is the state of
Go-Ahead?  Is it enabled and does it have to be negotiated away?  Or
can it just be ignored?

Has anyone experience problems with TAC114 and having lock-ups between
the TAC and a terminal?

Mike

Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!pasteur!ucbvax!GATEWAY.MITRE.ORG!
barns
From: ba...@GATEWAY.MITRE.ORG (Bill Barns)
Newsgroups: comp.protocols.tcp-ip
Subject: Re:  Go-Ahead Considered Harmless??
Message-ID: <8901041413.AA23333@gateway.mitre.org>
Date: 4 Jan 89 14:13:43 GMT
Sender: dae...@ucbvax.BERKELEY.EDU
Organization: The Internet
Lines: 110

[Warning: long discourse, but maybe worth it to protocol hackers of
a middling level of expertise.]

Mike,

Since I blundered into expounding Telnet the other day, I suppose I
might as well take a shot at this one too.  Under the original theory
of Go-Ahead, they are supposed to be used until their suppression is
negotiated (Suppress Go-Ahead Option).  GA is supposed to tell the
telnet process receiving it to do whatever is the appropriate act to
unlock the keyboard of the NVT.  It is supposed to be sent by the other
telnet end whenever it knows that keyboard input is the next thing that
needs to happen.  The definition of when they are supposed to be used
is inherently loose, so it is hard to pin a problem on any setting of
this option, unless you are actually using a 2741-like terminal that
really locks its keyboard, and a telnet implementation that can drive
such a terminal.

There was NEVER any rule that said that a telnet process should ever
actively lock the keyboard of its NVT!!  That was a feature of the IBM
2741 terminal family (and some others) which unfortunately couldn't be
turned off.  2741's aren't even supposed to be supported by TACs
nowadays - they were weird in lots of ways and the extra code to
support them ate up memory - and I don't know of a way for GA-related
nonsense (e.g., a broken host Telnet) to "legitimately" lock up a
telnet driving a normal full-duplex terminal.  Were this to occur, I
would suspect some kind of brokenness in the TAC.  I'd be inclined to
look for the brokenness elsewhere in the protocol interactions first
(or even in the hardware), but, who knows, bizarre things happen
sometimes.

The Host Requirements RFC is taking the position that Go-Ahead is
obsolete and should be treated as always suppressed, independent of the
setting of the SGA option.  I'll append the text at the end of this
message for the sake of interested parties.

One quasi-lockup I have seen with TACs in the past, not specifically
114, is really a host problem of dealing with TCP window behavior of
the TAC, which is "strange" compared to what some implementors seem to
expect.  (It does not behave like UNIX.  This seems to be a difficult
concept for some to get a handle on.)  The TAC is more likely than
'most' hosts to present zero windows, often has small windows, tends to
have window sizes that jump around, and has a (sometimes) varying
low-frequency component to its 'maximum window' offered during various
portions of the lifetime of a connection.  I think all this stems from
the TAC being a rather buffer-starved animal.  When it is heavily
loaded, the small buffers per terminal port mean small windows which
fill up with one (submaximal) packet.

I *think* that some implementations have gotten into trouble by
overreacting to the zero windows, maybe immediately going into a 2
minute zero window probe cycle.  This isn't a lockup but it's an
excessive wait for a small buffer (maybe 32 or 64 bytes) to drain.  If
the zero window probe code in the host is totally broken, then it might
actually lock up.  RFC 793 (unfortunately, in my view) seems to justify
immediately going to a 2 minute timer when a zero window occurs.  I
think I believe that one should use an exponential backoff from RTO to
2 minutes.  If the TAC sends a new ACK with updated window when the
buffer drains, the host should come off its zero window probe.  Of
course, this ACK might get lost - improbable if host and TAC are on
same subnet, more likely if a busy gateway is in between.  Failure of
the TAC to spit out this window update ACK is an imaginable contributor
to lockup or quasi-lockup.

I've spent a few minutes trying to figure out what interactions exist
between Jacobson style TCP and TACs but did not get far, so far.

Bill Barns / MITRE-Washington / ba...@gateway.mitre.org

----------

         [Host Requirements RFC Draft]

         5.4.2.2  Telnet Go-Ahead Function: RFC-854, p. 5, and RFC-858

            The Telnet Go Ahead (GA) signal is obsolete; server Telnet
            implementations should not try to support sending GA
            commands.  A server Telnet should always accept negotiation
            of the Suppress Go Ahead option (i.e., reply "WILL Suppress
            Go Ahead" to "DO Suppress Go Ahead").

            User Telnet implementations that do not explicitly negotiate
            the Suppress Go Ahead option from the server must accept,
            but may ignore, GA commands.

            DISCUSSION:
                 Half-duplex ("locked-keyboard") line-at-a-time
                 terminals for which the Go-Ahead mechanism was designed
                 have largely disappeared from the scene.  This is
                 fortunate, since it turned out to be difficult or
                 impossible to implement sending the Go-Ahead signal in
                 existing operating systems, even those systems that
                 support native half-duplex terminals.  The difficulty
                 was that the Telnet server code does not typically have
                 access to information about whether the user process is
                 blocked awaiting input from the Telnet connection,
                 i.e., it cannot reliably determine when to send a Go-
                 Ahead.

                 Telnet Server hosts do not generally implement sending
                 GA commands.  Therefore, even when the Suppress Go
                 Ahead option is not negotiated, a User Telnet should
                 not expect a Server to ever send a GA, or believe a GA
                 that it receives.

                 There is a class of half-duplex terminals that is still
                 commercially important: "data entry terminals," which
                 interact in a full-screen manner.  However, supporting
                 data entry terminals using the Telnet protocol does not
                 require the Go Ahead signal; see Section 5.4.3.2.

Path: utzoo!utgpu!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!rutgers!
ucsd!ucbvax!HELIOS.EE.LBL.GOV!van
From: v...@HELIOS.EE.LBL.GOV (Van Jacobson)
Newsgroups: comp.protocols.tcp-ip
Subject: Re: Go-Ahead Considered Harmless??
Message-ID: <8901051158.AA14205@helios.ee.lbl.gov>
Date: 5 Jan 89 11:58:38 GMT
Sender: dae...@ucbvax.BERKELEY.EDU
Organization: The Internet
Lines: 70

> I've spent a few minutes trying to figure out what interactions exist
> between Jacobson style TCP and TACs but did not get far, so far.

Bill -

The 20 line comment preceeding the relevant code in tcp_output
probably makes it hard to find (I keep telling Mike Karels that
C is self documenting -- he insists on these huge block comments
that just use up screen real estate when you're trying to read
the code :-).  Take a look at the code below the comment that
starts "TCP window updates are not reliable,...".  If the timer
setup in tcp_setpersist seems obscure, see the 30 or so lines of
comment in tcp_input that start with the line "srtt is stored as
fixed point with 3 bits ...".  (Some other code relevant to
poor, buffer-starved TACs, but not with zero windows, is
associated with the sender's estimate of the peer's receive
buffer size, max_sndwnd.  See the comment starting "Sender silly
window avoidance..." in tcp_output.)

The code does just what you thought it should -- probe with
exponential backoff from the current RTO -- and has done this in
every version of BSD since 4.1c.  There is no 2 minute timer and
never has been.  There is a 5 second minimum interprobe time
(which seems to accommodate the human response time in the usual
zero window cause on a local net -- ^S on a terminal -- and is
effectively a nop on a long haul net).  Attached is a trace of
what happens when the window goes to zero (obtained by starting
an ftp from a file on yak to a terminal window on okeeffe then
^S'ing the window).  Note the first probe goes out 5 sec after
the zero window is announced, there are 3 probes at 5 sec
spacing (it takes 2 backoffs to ramp the 1 sec rto above the
minimum interprobe time), then pure binary exponential after
that (if you don't want to compute them, the deltas between probe
sends are 5, 5, 5, 8, 16, 32 & 64 sec starting from the zero-window
ack at 00:56:14.65 and the probe at 00:56:19.48).

If your comment referred to interaction between slow-start
and/or congestion avoidance and TACs, the answer is there isn't
any.  The only 4BSD congestion algorithm that comes into play
with TACs is John Nagle's small packet avoidance algorithm
(which is essentially the computation of "idle" and the line
"if ((idle || tp->t_flags & TF_NODELAY) &&" below the comment
starting "Sender silly window avoidance..." in tcp_output) and
by all reports this is an unmitigated win.

 - Van


00:56:14.31  okeeffe.1064 > yak.ftp-data: . ack 114177 win 4096
00:56:14.31  yak.ftp-data > okeeffe.1064: . 116225:116737(512) ack 1 win 4096
00:56:14.32  yak.ftp-data > okeeffe.1064: . 116737:117249(512) ack 1 win 4096
00:56:14.32  yak.ftp-data > okeeffe.1064: . 117249:117761(512) ack 1 win 4096
00:56:14.32  yak.ftp-data > okeeffe.1064: P 117761:118273(512) ack 1 win 4096
00:56:14.45  okeeffe.1064 > yak.ftp-data: . ack 116225 win 2048
00:56:14.51  okeeffe.1064 > yak.ftp-data: . ack 117761 win 512
00:56:14.65  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:56:19.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:56:19.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:56:24.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:56:24.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:56:29.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:56:29.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:56:37.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:56:37.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:56:53.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:56:53.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:57:25.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:57:25.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0
00:58:29.48  yak.ftp-data > okeeffe.1064: . 118273:118274(1) ack 1 win 4096
00:58:29.52  okeeffe.1064 > yak.ftp-data: . ack 118273 win 0