-
Notifications
You must be signed in to change notification settings - Fork 0
TLVC Networking Guide
TLVC inherited a relatively complete and reliable networking platform from ELKS: A reliable TCP/IP network stack and drivers to support the 10Mbps Ethernet and serial network connections (SLIP) networks. Since the fork, ktcp
– the TCP/IP protocol engine – and the underlying drivers have been enhanced with stability and speed improvements and some bug fixes.
At the application level, TLVC supports the telnet
-protocol (inbound and outbound) for interactive access, the ftp
-protocol (inbound and outbound) for file transfers and http
via the TLVC httpd
server. The ftp/ftpd
client/server pair have been written from scratch for ELKS/TLVC and include special functionality to accommodate a QEMU setting (see below).
In addition to this document, there are many details to be found in the man
-pages, like man ktcp
or man ne
- the latter for info about the NE1k/NE2k Ethernet drivers.
TLVC supports several different ISA-based Ethernet interfaces and a solid TCP/IP implementation via the ktcp
user space process. The quality and diversity of this support is improving constantly. Until (approximately) 2020 the urlget
program was the key to move files into TLVC. Today, the ftp
user application and the ftpd
server deamon - which implement most basic ftp
commands, represent the most convenient file transfer mechanism, enabling interactive file transfers and the use of visual file managers like FileZilla with TLVC.
You should verify that the ethernet interface was actually configured correctly during boot by looking at the console boot messages which should show one or more of these lines (depending on your configuration):
eth: ne0 at 0x380, irq 9, (ne1k) MAC 00:1f:11:02:60:2d, flags 0x80
eth: wd0 at 0x320, irq 11, ram 0xcc00, (wd8013) MAC 00:00:C0:BC:8F:4B, flags 0x80
eth: 3c0 at 0x300, irq 15, (3c509) MAC 00:a0:24:67:7f:b1 (HWconf: 330/9), flags 0x80
Use the ps
command to check that the network is up and running (look for the ktcp
-process and the telnetd
and ftpd
daemons):
# ps
PID GRP TTY USER STAT CSEG DSEG HEAP FREE SIZE COMMAND
1 0 root S 3240 33ef 3072 2012 12864 /bin/init 4
22 22 1 root S 3564 36ff 0 1966 13136 /bin/getty /dev/tty1
23 23 S0 root S 3cca 71d3 1164 8860 66688 -/bin/sh
24 24 S1 root S 3cca 76e0 1164 8788 66688 -/bin/sh
11 11 root S 513b 63b2 3072 32690 75696 ktcp -b -p wd0 10.0.2.15 10.0.2.2 255.255.255.0
15 15 root S 5591 4c2e 0 1996 15376 telnetd
18 18 root S 5c26 5719 0 11406 32992 ftpd
27 23 S0 root R 4e67 5f9f 1024 1188 13568 ps
#
If it's not, run the net start
command, and check for errors in the output:
# net start
Starting networking on wd0
ktcp -b -p wd0 10.0.2.15 10.0.2.2 255.255.255.0
ktcp: ip 10.0.2.15, gateway 10.0.2.2, netmask 255.255.255.0
ktcp: /dev/wd0 mac 00.00.c0.bc.8f.4b mtu 1500
Starting daemons 'telnetd' 'ftpd -d'
#
net start
and the corresponding net stop
commands are automatically run at startup if net=xxx
is included in the TLVC config-file /bootopts
, ´xxx´being one of ne0, wd0, 3c0
. The same configfile includes other options that define the network configuration. For more information, check out the chapter on Boot options in the main wiki. Here is a sample working /bootopts
file:
## boot options max size 511 bytes
console=ttyS0,38400 debug net=ne0 3 # serial console, multiuser, networking
#TZ=MDT7 # timezone
#QEMU=1 # ftpd on QEMU
HOSTNAME=tlvc1 # set network IP from /etc/hosts
LOCALIP=10.0.2.16 # This machine's IP address
GATEWAY=10.0.2.2
ne0=9,0x380,,0x80
#wd0=11,0x320,0xCC00,0x80
#3c0=15,0x300,,0x80
netbufs=2,1
chs0=980,4,17
#comirq=,,7,10
#init=/bin/init 3 n # multiuser serial no /etc/rc.d/rc.sys
#init=/bin/sh # singleuser shell
#console=ttyS0,19200 # serial console
#root=hda1 ro # root hd partition 1, read-only
Which daemons to start automatically is configured in the /etc/net.cfg
file. The examples in the file are reasonably self-explanatory. Note that the httpd
daemon has to be enabled manually.
The system allows for many ways to tune the network - low level and application level. Many but not all these tuneables are available via the bootopts
file as exemplified above. Some of them, like the NIC (network card) configuration, may be obvious, others require more of an explanation. Keep in mind that the NICs have their own man
-pages with plenty low level details.
Here's a list of important network configuration considerations and non-obvious options:
- In order to keep the kernel as small as possible, use
menuconfig
to enable/disable just the interface(s) you need. - The NICs are auto-configuring, which means that the system looks for them at boot-time and configures those found. Activation occurs later.
- The installed NICs must be configured to use the IO address specified in
bootopts
files, or - if there is nobootopts
line for the NIC, the setting in theports.h
header file. And exception from this rule is the 3Com 3C503 NIC (el0
), which allows the IO address frombootopts
to override the preprogrammed address. - Only one NIC may be active at any time. You can switch between them at run-time using the
net stop
andnet start
commands. E.g. to switch from the currently active interface (say,ne0
) to thewd
-interface, use the commandnet stop; net start wd0
. And then, if you'd like to switch back,net stop; net start ne0
. - If the
net=
option is found in thebootopts
file - likenet=ne0
- the system will run thenet ne0
command at startup time and configure the network according to the settings in the/etc/net.cfg
file. Otherwise the net must be started manually. - Some times, in particular when looking for boot problems, it is convenient to just turn off a NIC without going through the hassle of building a new kernel. The IO address part of the configuration line in
bootopts
may be set to zero to achieve this, as inne0=9,0x0,,0x80
. When booting, the kernel will report the interface as 'disabled'. - Use the
QEMU=1
directive if running on QEMU and intending to useftp
. - The
netbufs=
directive instructs the kernel to allocate the specified number of receive and transmit buffers (respectively) for the NIC. See the next paragraph for details about this. - The IRQ line for NICs is not allocated at boot time but rather when the network is started. This allows all (currently 3) network interfaces to share the same IRQ. This means that the kernel's boot message about a NIC found (as in
eth: ne0 at 0x320, irq 2, (ne1k) MAC 00:1f:11:02:60:2d, flags 0x80, bufs 2r/0t
), doesn't mean the NIC will work, but that a NIC of this type was found at the given address (the proof of the pudding being the reported MAC address). The IRQ has not been assigned at this time, and thus not tested. - Be aware that the 3Com
el0
NIC may not give up its IRQ line when shut down. There isn't much to do about this. These interfaces were not made to do this at all, it's not part of any specification. The fact that it works on some of them is a strike of luck, not by design.
The Ethernet NIC drivers were created to not use buffers, but rather transfer data directory from user/process space to/from the buffers on the NIC cards. This works well, but limits performance in many situations. Thus the ability to use buffers was added. At the time of writing, the ne2k
driver is the only one supporting this, but the other interfaces will be added to the club in 2024.
The addition of 'dynamic' network buffering opened up a number of options which were too tempting to not take advantage of. These are sweet in the netbuf.h
file in the arch/i86/drivers/net` directory. The following excerpt from that file explains the basics:
/* Buffer configuration for TLVC Ethernet NICs
*
* There are 3 buffer strategies:
* - No buffers: The driver is moving data directly to/from the requester
* (via far mem move).
* - Static buffers: The number of send and receive buffers specified in the
* NET_OBUFCNT and NET_IBUFCNT defines are allocated statically at
* compile time. The BUFCNT numbers may be 0, in which case the driver
* will run as if NO_BUFS was set (except the extra code is compiled in).
* - Heap allocation: Buffer space is allocated from the kernel heap, which
* is slightly different from static allocation in that memory is
* allocated only if the network is running. Memory consumption will be
* slightly higher because of the headers in the heap allocation.
*
* When HEAP allocation is used, the # of buffers may be set in /bootopts via
* the 'netbufs=' directive. 'netbufs=2,1' means 2 receive buffers, 1 transmit
* buffer. The kernel will not do sanity checking on the netbufs= numbers,
* it's entirely possible to make the system unbuutable by requesting too many
* buffers. 2,1 or 2,2 are reasonable choices for regular usage. Again, zero is
* a valid selection and will turn off buffers entirely.
* When using heap allocation, a header strucure per buffer is also
* allocated from the heap, 6 bytes per buffer.
*
* AGAIN: zero buffers is always a valid choice - which complicates the driver
* somewhat but makes benchmarking much more convenient.
*/
The default setting is to use heap allocation, which is the most flexible since it allows you to turn off buffering and reclaim all the memory without recompiling the kernel.
How many buffers should be allocated? On TLVC, RAM is a scarce resource - as is performance. netbufs=
is a very convenient tool to balance the two - and not the least, to experiment. Remember though that the bootopts
file and thus the netbufs=
setting is read at boot time only. Changes need a reboot.
In general, a 2,1 setting (2 receive buffers, 1 transmit buffer - each buffer can contain a complete Ethernet packet, 1536 bytes) is good. Experiment with 0,0 to see if buffering is contributing at all, your mileage will vary wildly depending on the speed of the machine. The slower the machine, the more valuable the receive buffers, and the less valuable the transmit buffers. On a PC/XT, 3,0 is good. On a 386 @25MHz or higher, 2,1 or 2,2 is good (at the time of writing , the jury is still out on the value of more than one transmit buffer given the internal architecture of the kernel).
More considerations about speed, buffers and balance in the section about ktcp
below.
TBD
TBD - For now take a look at the man-pages for the available drivers, wd
, ne
, 3c
. Remember that these man
-pages are available from your development directory on the host, by using the eman
command.
TBD
- Add net buffer support to all drivers
- Add UDP support
Serial communications
Transferring limited size ascii files can be done with reasonable reliability via serial lines and terminal emulation. Using cat > filename
on TLVC and then pasting text into the terminal is reasonably efficient. If this fails marginally (losing a few bytes here and there), turn off echo in order to reduce the interrupt load on the system:
stty raw; cat > filename; stty -raw
or use the sercat
command:
sercat > filename
Terminate such transfers with ^D (EOF).
To check whether the transfer was error free, use the sum
command at both ends, after ensuring that the byte count is exactly the same (ls -l
). Note that it takes only an extra newline or CR at the end of the file to make the sum
command useless.
Even binary files may be transferred this way by first converting them to ascii. Use the hexdump
command on Linux:
hexdump -e '"%06.6_ax:" 8/1 " %02x" " " 8/1 " %02x" " " ' -e '16/1 "%_p" "\n"' "$@"
to create the ascii file, then transfer it and use hd -r
on TLVC to convert it back.
A far more efficient (and traditional!) way is using uuencode
and uudecode
. Instead of turning 16 bytes into 69 which hd
does, uuencode
converts 2 bytes into 3 ascii characters. The commands are part of the uucp
package. The (simplified) syntax is
uuencode newname < inputfile > outputfile
where newname
is the filename to be used when the file is decoded and recreated. Even the filemode (protection codes) is stored in the encoded file and will be restored during decoding – if possible. To decode, simply give the command
uudecode < inputfile
and the original file (and filename + modes) will be recreated. There are many options to override the defaults, check the man-pages for details.
Transferring text or uuencoded binary files from TLVC via serial is usually easy (and reliable) since most systems will have no problems keeping up with the speed of the TLVC system.
Mechanisms to make serial transfers binary and fully reliable - Kermit, X/Y/Z-modem etc. - are forthcoming.
The interactive ftp
client works like most ftp-clients for Linux, Unix and other OSes. Please refer to Linux ftp
-man pages for general info. The following paragraphs discuss the exceptions to the 'standard'.
Command line options
The ftp
-client recognizes the following command line options:
-u - username
-p - password
-P - Start in PASV (passive) mode. This is the default.
-A - Start in PORT (active) mode
-i - Disable multifile prompting.
-q - Qemu mode, normally set automatically via the environment-variable QEMU, see below.
-v - Verbose mode, equivalent to debug = 1, which is now the default.
-d - Debug on. The default debug level is 1, repeat -d to increase the level top max 4.
Thus a typical command line for ftp
may be
# ftp -u user 10.0.2.2 5050
or simply
# ftp
The former will connect to the given host or address and prompt for username and password, like this:
# ftp -u myusername 10.0.2.2 21
Connected to 10.0.2.2.
220 raspi2b FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.17) ready.
Name (10.0.2.2:myusername):
Password:
530 Login incorrect.
Login failed: 530 Login incorrect.
ftp>
The port number is optional, default is 21.
If ftp
is invoked without arguments, the open
command establishes the connection:
ftp> open 10.0.2.2
Connected to 10.0.2.2.
220 raspi2b FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.17) ready.
Name (10.0.2.2:ftp): username
Password:
230-
230- The programs included with the Debian GNU/Linux system are free software;
230- the exact distribution terms for each program are described in the
230- individual files in /usr/share/doc/*/copyright.
230-
230- Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
230- permitted by applicable law.
230 User helge logged in.
Remote system is Unix/Linux, using binary mode
ftp>
The commands currently supported by TLVC ftp
are:
ftp> help
directory: List remote directory
ls: List remote directory
get: Fetch remote file
mget: Fetch multiple remote files
put: Send file to remote
mput: Send multiple files to remote
cd: Change (remote) working directory
pwd: Show (remote) working directory
bin: Set file transfer type to BINARY
ascii: Set file transer type to ASCII
quit: Quit program
type: Show file transfer type.
prompt: Toggle interactive multifile transfers
debug: Set debug level 0-4 or 'off'.
bye: Leave program
!: Invoke shell to execute local command.
?: Alias for help.
help: Print this.
close: Close connection.
open: Open new connection, log in.
mkdir: Create remote directory.
delete: Delete remote file.
verbose: Toggle debug off or 1, default 1.
status: Show status, modes etc.
lcd: Change local working directory
glob: Toggle globbing
passive: Toggle passive/active mode
ftp>
Commands may be abbreviated to 3 characters.
Note the difference between bye
and close
: The former exits the program, the latter just closes the connection, and ftp
is ready for a new open
command. ^C will terminate the program.
ftp in QEMU
ftp
(and the TLVC ftp server) take special measures to work seamlessly within QEMU. The qemu.sh
script that comes with TLVC includes mapping necessary for the ftpd
server to support passive connections:
# Simultaneous telnet, http and ftp forwarding
FWD="\
hostfwd=tcp:127.0.0.1:8080-10.0.2.15:80,\
hostfwd=tcp:127.0.0.1:2323-10.0.2.15:23,\
hostfwd=tcp::8020-:20,\
hostfwd=tcp::8021-:21,\
hostfwd=tcp::8041-:49821,\
hostfwd=tcp::8042-:49822,\
hostfwd=tcp::8043-:49823,\
hostfwd=tcp::8044-:49824,\
hostfwd=tcp::8045-:49825,\
hostfwd=tcp::8046-:49826,\
hostfwd=tcp::8047-:49827,\
hostfwd=tcp::8048-:49828,\
hostfwd=tcp::8049-:49829"
With this setup, the command to connect to TLVC from the QEMU host is ftp -P 8021 localhost
.
Make sure QEMU=1
is enabled in either /bootopts
or /etc/profile
. The only limitation is that outbound ftp
(from TLVC) requires passive mode (the default). Currently, when in QEMU-mode, the ftp
-server will turn debug on, which means extra output to the console. This will eventually go away.
The FTP server (aka ´ftp daemon´) is normally started automatically with the net start
command. It will accept connections on the standard ftp port and supports both passive and port (active) modes. It requires the external user to log in, but neither checks the username or the password at this time, so you can use whatever default comes up or just empty lines.
The server implements most of the regular ftp
commands and will tell you if a command is not implemented. In most cases it will detect if the remote client is Linux or Unix, and set binary (image) mode automatically. The SITE command is supported and enables (among other things) a file transfer delay to be specified, which enables file transfers between TLVC systems to run reasonably smooth. In most cases, such delays (on client and server sides) are set automatically because the programs recognize the TLVC platform as a special case.
Likewise, the server will check for the QEMU environment variable and make adjustments accordingly (see above).
MORE ABOUT SPECIAL SERVER COMMANDS <<<<
Before TLVC had fulle native client and server ftp
support, other means were used to get data back and forth. Not as flexible and interactive as ftp
but useful - and in some cases still the easiest.
urlget
is a very flexible tool for transferring files to or from TLVC, and particularly well suited for inclusion into scripts. Four programs in one – urlget
, httpget
, ftpget
and ftpput
, supporting 3 different URLs and 3 protocols: HTTP, FTP and pure TCP (useful with netcat
) - all requiring a server to talk to at the other end. Not a problem - if such a server is not already running, a python one-liner is normally all it takes to start your own. Which frequently turns out to be preferable even when such server is already running – because you get access to you own home directory. More about that below.
A summary of the command syntax:
urlget http://host:port/filepath
urlget http://username:passwd@host:port/filepath
urlget ftp://host/filepath
urlget ftp://username:passwd@host[:port]/filepath
urlget tcp://host:port/filepath
httpget [-h] [-d] [-p] host filepath
ftpget [-v] host[:port] filepath [username [passwd]]
ftpput [-v] host[:port] filepath [username [passwd]]
For all variants, the authentication can be omitted if acceptable to the server. If included, note that the username and password are sent in plaintext over the network. Also, port
may be omitted in most cases, in which case the default port is used - 80 for http, 21 for ftp. For tcp
, the port must be included as there is no standard.
For ftpget
, if the filepath ends with a slash, a directory listing is delivered. The -v
option extends the file listing to long format (ls -l
). For http
, the -h
option will include HTTP-headers in the output, -d
will discard the contents, which is meaningful only with the -h
option (display headers only), and the -p
option will post
(send) data instead of fetching it. The data in this case is whatever follows a '?' in the filepath. This option is currently not very meaningful.
ftpput
will create new directories as needed and if permitted. ftpput 10.0.2.2 /tmp/bin/sh name passed
will create the tmp
and bin
directories (relative to the current directory) if they don't exist
The tcp-url sends the file name, but there is no standard way of handling such request at the other end, see below for a suggestion on how to use this variant. This chapter also discusses ways to set up your Linux or MacOS host to communicate with TLVC.
If running QEMU, use the default qemu.sh script and make sure this line is 'uncommented': NET="-netdev user,id=mynet,$FWD -device ne2k_isa,irq=12,netdev=mynet"
urlget with http, httpget
- Start a web server on the host, like a simple python http-server:
- If you have python V3, run
python3 -m http.server 8000 --bind 127.0.0.1
. If your version is 2 (check by runningpython -V
or resort to v3 explicitly if it exists, likepython3
):python -m SimpleHTTPServer
. If running Windows, the commands may be a little different, Google it to find out. - This will make the current directory available for file transfers.
- If you have python V3, run
I you want something more 'durable', install and run lighttpd
(see below). If using the default install- and config-files, the files to transfer would be placed in a subdirectory of /var/www/html
- such as /var/www/html/tlvc
. In this case you don't need to specify the port number (8000 above), or just add '80' (default) for the record. Make sure to create the tlvc
subdirectory and set the access bits. This installation requires root access.
- Put the file(s) you need to transfer into that directory (or a subdirectory).
- Run
- [python3/python]
urlget http://10.0.2.2:8000/filename > local_filename
orurlget http://10.0.2.2:8000/dir1/dir2/filename > local_filename
- [lighttpd, other servers]
urlget http://10.0.2.2/tlvc/filename > local_filename
- [python3/python]
urlget with ftp, ftpget
If an ftp
server is already running, you're OK. Check the server config-files to determine if anonymous access is available, and what directory such access is limited to. If you will be using authentication (username and password), ensure your user is allowed incoming ftp access.
FTP:
If no ftp
-server is running, apython
-based server is the easy way out, just like the http-example above. pyftpdlib
must be installed, google it if directions are needed. Run python3 -m pyftpdlib -p port -u someusername -P somepasswd
(see the online docs for details). Any name and password will do, not limited to your local username/passwd, but they must match when making a connection. Anonymous authentication is supposed to work, but does not. The default port number is 2121. Also, be aware that this ftp-server does not support wildcards.
Assuming an FTP server running and your user is an allowed ftp-user, you can ftp files into TLVC like this:
urlget ftp://user:passwd@host:port/filename > localfile
for example
urlget ftp://testuser:[email protected]:21/testfile > localfile
The port number (in this case :21
) is optional. 21 is the default and may be omitted. If the ftp server supports (allows) anonymous ftp, the username and password may be omitted. In that case the public (anonymous) ftp directory is where the file (testfile
) will be looked for. Otherwise, if you provide your username and password (they are being sent over the network in clear text!), your home directory is the root directory for ftp
. If test file
ends with a slash /
, then it is assumed to be a directory, and the slash means 'list this directory'. Example:
urlget ftp://user:[email protected]/
which will list the users home directory.
Similarly the syntax for ftpget
is
ftpget [-v] host[:port] filepath [user [passwd]] > localfile
The -v (verbose) option is meaningful only when listing directories (filepath has a trailing '/').
TCP:
In many ways the simplest of all variants is 'raw tcp': All you need is netcat
(nc) on the server, which exists on most Unix and Linux systems.
On the host, start nc
so that it waits for connections and then transfers a file:
nc -l 2323 < tlvcout.txt
2323 is a randomly selected port number (> 1024), which you need when making the connection from TLVC:
urlget tcp://host:2323 > localfile
The port number is mandatory since there is no default. Notice that nc
doesn't know when to terminate the connection, so you have to abort it with ^c.
ftpget and httpget
urlget
may be linked to different names which will affect its behaviour. If you use ftpget
it will use the ftp-protocol and the syntax is like this:
ftpget host[:port] filepath [user [passwd]] > localfile
for example
ftpget 10.0.2.2 filename username userpw > file
Like before, username and password may be omitted if anonymous ftp is supported by the server. And again, if the filename ends with a slash, the name is assumed to be a directory and its content will be displayed. If the command line option -v is used, the directory listing is verbose (like ls -l).
httpget
follows the same rules, with syntax as specified above:
httpget [-h] [-d] [-p] host[:port] filepath > localfile
As mentioned above, files may be transferred out of an TLVC system either using ftp (ftpput
) or the local http-server. The latter is non-trivial at first, easy when all is set up.
- Place the file/files to transfer in the
/var/www
directory on TLVC. - [QEMU]Use curl or wget to fetch the files: [qemu]
curl http://localhost:8080/filename > filename
. - [Physical machine]
curl http://10.0.2.15/filename > somename
In order to access files not in the httpd-directory, symbolic links are useful. For example, if you want to transfer the entire hard disk: cd /var/www; ln -s /dev/hda myfile
, then use curl from the other end to fetch myfile
. Be warned, this is going to take some time. As of this writing the transfer speed is about 27k bytes per second on a physical system (386/20, NE2K interface).
Using ftpget
is simpler, in particular if a ftp-server is already running on the destination machine. The syntax is documented above and is identical to the ftpget
variant.
Tiny Linux for Vintage Computers