Home | Guides | Software | Hardware | Discussions | Shop | Contact Me | Donate


2022-01-25

Ethernet and IP over Packet Radio TNCs with tncattach

If you just want the most minimal-effort setup guide on how to run ethernet and IP over packet radio TNCs, skip down to the section: "One to Many, Many to One".

The Old Ways

Running IP applications over packet radio TNCs and similar hardware has traditionally been possible, albeit in a somewhat limited form, using the Linux AX.25 kernel modules and utilities like kissattach. Recent bugs have prevented this method from working correctly in new versions of Debian (and derivatives), and there is even a discussion about removing kernel AX.25 support altogether.

While the kissattach method of IP networking over packet radio traditionally worked relatively well, it also has the drawback of having to encapsulate everything in AX.25 frames, and thus not supporting standard ethernet, while incurring overhead that is entirely unnecessary for IP networking.

A Cleaner Solution

With all that in mind, I found it was probably time to offer an alternative, so I wrote tncattach. It's a small program that replaces the functionality from kissattach, and doesn't require any special kernel modules.

With tncattach you can attach any KISS-compatible TNC as a fully ethernet-compatible network interface in Linux. It also supports more "lightweight" tunnel interfaces, for point-to-point links (where you don't need the overhead of ethernet). And it of course fully supports both RNode and OpenModem.

After writing tncattach, I optimised the buffering and queues in the device firmwares, so be sure to update your RNode to at least version 1.16, and your OpenModem to version 1.05 or above for the best results.

Creating an interface with tncattach

To create an interface with tncattach, you will first need to download the program to your system. Please read the download and install instructions here.

For the sake of this tutorial, we will go through creating two different setups, first a point-to-point link between two devices, and next a point-to-multipoint setup that can support many individual devices communicating on the same channel.

The tncattach program offers a range of options to be given on the command line, and I'd suggest you read about them by entering the command:

tncattach --help

I won't go over them all here, but I will explain the importance of some of them as we move through the tutorial.

It's also worth noting, that if you are using tncattach with RNodes, you should put them into TNC mode with the rnodeconf program before running tncattach, as tncattach will not configure radio parameters, but expects the hardware to be ready to receive and transmit when it attaches.

Point-to-Point Links

For tncattach to create an interface, it needs to know at minimum what serial port the TNC is connected to, and what the baud-rate of the port is. For the rest of this tutorial, I will assume that a TNC is connected to each system, and available on serial port /dev/ttyUSB0, using a baud-rate of 115200. A minimal command for achieving this could look like:

sudo tncattach /dev/ttyUSB0 115200

Which will create and bring up a point-to-point interface on our system:

$ ifconfig

tnc0: flags=337<UP,POINTOPOINT,RUNNING,PROMISC>  mtu 329
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Great! We actually have a usable, although unconfigured interface. In most cases, we probably want to specify a few options, though. Let's enable the built-in IPv6 filter, so we don't spam the channel with router solicitations and similar, and also tell tncattach that we will manually bring up the interface after creation, which is useful when making point-to-point links.

The default MTU of 329 bytes should work on almost all TNCs, but in most cases it can be increased. Let's assume the connected TNC is an OpenModem, which supports an MTU of 576 bytes. We need to subtract any framing overhead from that, since that is the raw packet MTU of the device. For tncattach point-to-point interface the framing overhead is 4 bytes. For ethernet interfaces it is usually 18 bytes, but can be as high as 22, if you want to support VLAN tagging. So as a rule of thumb, subtract 4 bytes for point-to-point links and 22 bytes for ethernet links from the TNCs MTU. Aplpying this, we get an mtu of 572 bytes for OpenModem.

As a last consideration, we'll tell tncattach to daemonize it's process after creating the interface, so it will run in the background as a system process. This is achieved with the -d switch.

We can now put the above considerations together into the following command:

sudo tncattach /dev/ttyUSB0 115200 -d --noipv6 --noup --mtu 572

This will create the interface tnc0 as a point-to-point interface, but it will not yet be active. We'll configure the point-to-point link with 10.0.0.1 being the local IP address, and 10.0.0.2 being the remote address, and bring the interface up:

sudo ifconfig tnc0 10.0.0.1 pointopoint 10.0.0.2

The interface is now up and running, and ready to communicate with the remote end:

$ ifconfig

tnc0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 496
        inet 10.0.0.1  netmask 255.255.255.255  destination 10.0.0.2
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

On the remote system, the configuration commands would be similar, with only the order of IP-addresses changed:

sudo tncattach /dev/ttyUSB0 115200 -d --noipv6 --noup --mtu 572<br />sudo ifconfig tnc0 10.0.0.2 pointopoint 10.0.0.1

In the next example, we'll setup a network that can support many devices communicating with each other on the same channel, using ethernet, which is suprisingly much simpler than point-to-point links.

One to Many, Many to One

Let's assume that we have 10 TNC devices, all connected to the same radio channel, and we want everyone to be able to talk to everyone else. Setting up point-to-point links between everyone will get tedious very fast, so let's use something else: Ethernet.

Setting up ethernet devices with tncattach is a surprisingly simple one-liner. Assuming we are still using OpenModems, and considering the MTU calculations from above, we can bring up an interface and configure it with the following command:

sudo tncattach /dev/ttyUSB0 115200 -d -e --noipv6 --mtu 554 --ipv4 10.91.0.1/24

The interface will now be created, have an IPv4 address configured and brought up. In this case we use the -e switch to specify we want a full ethernet device, not just a point-to-point link. We also use the --ipv4 switch to specify what IPv4 address the interface should be assigned. Please that you must supply addresses complete with a subnet mask in CIDR notation for the --ipv4 switch (hence the /24 at the end).

The interface is now up and running, and ready for use:

$ ifconfig

tnc0: flags=611&lt;UP,BROADCAST,NOTRAILERS,RUNNING,ALLMULTI&gt;  mtu 554
        inet 10.91.0.1  netmask 255.255.255.0  broadcast 10.91.0.255
        ether 62:2a:60:89:a2:3a  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Repeat the same command on any other hosts, replacing the IP address with a unique address in the same subnet for every system, and every system can now talk to everyone else.

Since this is ethernet, you could easily set up a DHCP server on one system, and have that assign IP-addresses, instead of manually specifying them on each system. Or do anything you would normally be able to, really.

Notes on MTU

The MTU that is set with tncattach is the MTU for the kernel networking interface. That is, it is the MTU for the interface you see when you type for example ifconfig tnc0. The MTU value set here tells the kernel how many bytes of payload data can be squeezed into a single physical-layer packet.

This value should not be set to the direct physical layer MTU of the TNC device! For example, even though OpenModem supports an MTU of 576 bytes, and RNode supports an MTU of 500 bytes, you need to take into account the overhead of any link-layer protocol that is transported with tncattach.

In practical terms, this means that if you just want to use point-to-point IP links with tncattach, the overhead will be 4 bytes. For full ethernet, the overhead will usually be 18 bytes, but if you also need to support 802.11q VLAN tags, it will be 22 bytes. You need to subtract this overhead from the device MTU and pass that value to tncattach.

For OpenModem, correct MTU values to use with tncattach would be 572, 558 and 554 respectively, for point-to-point IP links, Ethernet and Ethernet with VLAN tags.

For RNode, correct MTU values to use with tncattach would be 496, 482 and 478 respectively, for point-to-point IP links, Ethernet and Ethernet with VLAN tags.