When connecting via TELNET to a running KLH10-simulated OS instance from a FreeBSD machine, I have found that the connection was being dropped after two hours. The following is what I learned about FreeBSD, and how I resolved the issue.

After an upgrade of my KLH10-hosting FreeBSD platform from FreeBSD 12-RELEASE to FreeBSD 13-RELEASE, TELNET connections began dropping after two hours of inactivity. I had not associated this with the FreeBSD upgrade, and didn't take time to diagnose the problem right away. I did determine that the disconnections did not occur when originating the TELNET connection from Linux-based machines. At that point I opted to create a relay-login account on Linux to perform the TELNET, and I would investigate later.

Today is "Later."

I've whipped out the tcpdump(8) and monitored the TELNET session.

In the output and texts below, the following hostname and operating systems are at issue:

TELNET Client host:      shell.mrynet.com running FreeBSD 13.0-RELEASE
TELNET Server host:     tops20.mrynet.com running TOPS-20 under the KLH10 PDP-10 simulator.

The actual OS hosting the KLH10 PDP-10 simulator is not at issue, since the raw packets are passed to the TOPS-20 OS and are not otherwise acted upon by the hosting OS.

The following tcpdump(8) output was captured on the KLH10 simulator host with:


# tcpdump -nnSX -i em2 host tops20.mrynet.com and port 23
(em2 is a dedicated ethernet interface name on the simulator host logically attached to the KLH10 simulator):

21:53:43.950967 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1102, win 65535, length 0
21:53:43.981740 IP tops20.mrynet.com.telnet > shell.mrynet.com.21707: Flags [P.], seq 1102:1131, ack 105, win 1356, length 29
21:53:43.982567 IP tops20.mrynet.com.telnet > shell.mrynet.com.21707: Flags [P.], seq 1131:1132, ack 105, win 1356, length 1
21:53:43.982697 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0

23:53:44.029075 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
23:54:59.029593 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
23:56:14.029869 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
23:57:29.036743 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
23:58:44.044758 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
23:59:59.058763 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
00:01:14.071775 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
00:02:29.117760 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [.], ack 1132, win 65535, length 0
00:03:44.133015 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [R.], seq 105, ack 1132, win 0, length 0
00:03:44.134285 IP tops20.mrynet.com.telnet > shell.mrynet.com.21707: Flags [.], ack 105, win 0, length 0
00:03:44.134385 IP shell.mrynet.com.21707 > tops20.mrynet.com.telnet: Flags [R], seq 2319642573, win 0, length 0

Shown in the above log section are the following activities:

21:53:43.982697 is the timestamp of the last TELNET connection transmission, this one being an ACK from the TELNET client.

23:53:44.029075 is the timestamp of the FreeBSD TELNET client-side host sending a keep-alive probe on the TELNET connection to the TOPS-20 TELNET server emulated OS. This is odd, since the TELNET protocol itself does not open the TCP connection with keep-alive (SO_KEEPALIVE) enabled, and TCP connections themselves are not required to employ such functionality. The keep-alive packet is sent by the FreeBSD TELNET client's Host, and not the TELNET client itself. It is being used as a connection keep-alive probe utilizing an ACK-flagged packet with no data payload. The TOPS-20 OS does not respond to this packet.

23:54:59.029593 \
23:56:14.029869 |
23:57:29.036743 |
23:58:44.044758 > These are additional duplicate keep-alive packets sent by the FreeBSD TELNET client host.
23:59:59.058763
00:01:14.071775 |
00:02:29.117760 /

00:03:44.133015 This packet is sent by the the FreeBSD TELNET client's host to finally shut down the TCP connection carrying the TELNET communications. It is sent as a result of the FreeBSD client host not having received responses to the keep-alive packets.

00:03:44.134285 is the response from the TOPS-20 OS dutifully complying with the connection shutdown. TOPS-20 will have notified the TELNET server of the connection being closed.

00:03:44.134385 is the final packet from the the FreeBSD TELNET client host closing the TCP connection.

While I do not know why this has suddenly become an issue when upgrading my FreeBSD systems, I have tracked down the functionality within FreeBSD that controls these keep-alive packets being sent on established TCP connections.

The four relevant FreeBSD sysctl(8) settings are in the net.inet.tcp sysctl(3) grouping. They are listed below along with their default values:
net.inet.tcp.always_keepalive: 1 (boolean)
net.inet.tcp.keepidle: 7200000 (msec)
net.inet.tcp.keep.intvl: 75000 (msec)
net.inet.tcp.keepcnt: 8 (packets)

The descriptions of these settings, from the Freebsd tcp(4) man page, are:

net.inet.tcp.always_keepalive

When set, assume that SO_KEEPALIVE is set on all TCP connections, the kernel will periodically send a packet to the remote host to verify the connection is still up.

net.inet.tcp.keepidle

         Amount of time, in milliseconds, that the connection must be idle before keep-alive probes (if enabled) are sent.

net.inet.tcp.keepintvl

         The interval, in milliseconds, between keep-alive probes sent to remote machines, when no response is received on a keep-alive probe.

net.inet.tcp.keepcnt

         Number of probes sent, with no response, before a connection is dropped.

These settings, and their default values, result in the following explanation of the packets at issue:

  1. Since net.inet.tcp.always_keepalive is enabled, FreeBSD will perform the keep-alive operation on all TCP connections being originated. In this case, the TELNET client host will perform the keep-alive process on the TELNET connection.
  2. The keep-alive probes begin at exactly 7200000 milliseconds (7200 seconds, or 120 minutes) of idle time (net.inet.tcp.keepidle) on the connection.
  3. The FreeBSD TELNET CLIENT host (shell.mrynet.com), and not the TELNET client itself, sends 8 (net.inet.tcp.keepcnt) keep-alive packets at 75000 millisecond (75 second) intervals (net.inet.tcp.keepintvl).
  4. After no response to the the 8th packet, for a total of 10 minutes of keep-alive attempts, the FreeBSD TELNET Client host closes the TCP TELNET connection.
  5. There was a total of 7800 seconds (130 minutes) of time since the TELNET connection was used until the connection was closed by the FreeBSD client host.

The TCP specification does not state that any keep-alive protocol should be employed. And it hasn't been for TELNET connections previously.

The resolution (workaround?) for this situation is to turn off the always_keepalive setting on the host running the TELNET client to connect to the TOPS-20 system instance.

I do not know if this is purely specific to FreeBSD, but I do know that it isn't occurring with the Ubuntu Linux kernel 5.4.0.

Regardless, the specific action to fix this is to run the following command on the TCP-connection-originating FreeBSD host:

# sysctl -w net.inet.tcp.always_keepalive=0

Today I discovered the cause of a long-time frustration I've had trying to modify NETSRV.MAC to add services.

I've been trying to add an RSH server listener to NETSRV.   But every time I would edit the file with VI (my Elvis V2.0 1996 port), the resulting NETSRV executable would fail to RECEIVE for all services.  Always.   ALWAYS ALWAYS ALWAYS.   Reverting back to the original untouched (ca. 2006 NETSRV.MAC from the Panda distribution) source and compiling, the resulting NETSRV.EXE would run just fine.   Changing ANYTHING and recompiling would result in the failure.

Comparing the untouched and a file created by simply saving a new copy from within the editor, there was a one-byte-off count to the file sizes.

Running the ported  UNIX diff on those files showed the following:

$diff -u ns4.mac ns4a.mac
--- ns4.mac Fri Jan 21 14:52:51 2022
+++ ns4a.mac Fri Jan 21 15:45:37 2022
@@ -1602,7 +1602,7 @@
MOVX T3,^D10 ; in decimal
NOUT% ; output local port number
JSYSF
- HRROI T2,[ASCIZ/#;PERSIST:30/] ; wait 30 seconds for synchronize
+ HRROI T2,[ASCIZ/#;PERSIST:30/] ; wait 30 seconds for synchronize
SETZ T3,
SOUT%
MOVX T1,GJ%SHT ; GTJFN% flags

No difference show.  There must be an embedded control character.   But when I load NS4.MAC into vi, the line is as-shown. 

I started to look at the binary contents of the file:

$cmp -l ns4.mac ns4a.mac | head -10
47946 26 43
47947 43 73
47948 73 120
47949 120 105
47950 105 122
47951 122 123
47952 123 111
47953 111 123
47954 123 124
47955 124 72

Aha.  There's a CTRL-V (Octal 026) in NS4.MAC that isn't in NS4A.MAC.

The other characters shown are:

43    Hash/Pound sign (#)

73    Semicolon (;)

120 105 122 123 111 123 124     Octal codes for ASCII: PERSIST

So there's an embedded CTRL-V at the beginning of the ASCIZ string in the HRROI line.

Elvis is dropping that character when loading the file for editing!

I found the offending Elvis code in io.c:

  /* maybe strip control characters */
if (beautify && nread > 0)
{
    for (i = j = 0; i < nread; i++)
    {
        if (iobuf[i] >= ' ' || iobuf[i] == '\t' || iobuf[i] == '\n' || iobuf[i] == '\f')
        {
            iobuf[j++] = iobuf[i];
        }
    }
nread = j;
}

So it is the Elvis beautify setting causing the character drop.   I never use the beautify setting.  But it is inexplicably set in my elvis.rc file.

This isn't what the beautify setting does in BSD vi or the VIM clone.

 

Regardless, removing the set beautify in my elvis.rc and I'm good now.

 

Due to a failed upgrade of Joomla (the content-management software for Retrosys), a re-installation of the software and a database restoration has occurred.  There has been no loss of public or private content.

 

========================
  September 24, 2018 UPDATE
========================

I've been sent a 3Com EtherLink II (3c503) ethernet adapter to check out with the working Mach386 distribution.

I've successfully installed the hardware and, after setting the card jumpers and reconfiguring the BIOS to accommodate this legacy ISA card, it has proven to work well.

The configuration quirks of the 3c503 and Mach386 currently allow for one of the following card configurations to be utilized:

  1. Address 0x2e0, IRQ 5, BNC Connector
  2. Address 0x2a0, IRQ 2, AUI Connector
  3. Address 0x280, IRQ 2, BNC Connector
  4. Address 0x300, IRQ 2, AUI Connector

The memory must be set for 0xDC000 or 0xD8000.  The selection will be detected automatically.

As with the WD/SMD 80x3 ethernet cards, the motherboard BIOS settings may need to be changed.   The changes required would be to reserve the IRC to Legacy ISA assignment, and to reserve the memory block to prevent it from being used for RAM addressing.

The address, IRQ and Connector settings are hardcoded, and could be changed by modifying the driver and rebuilding the kernel.