tncd.dev — downloads, packages, and documentation


Linux has a packet radio problem.

When Linux 7.1 ships, the native AX.25 kernel networking stack goes away. The AF_AX25 socket family is being removed. Tools like ldsped that depend on it will stop working. PAT will lose its AX.25 transport. Xastir will go silent. Anyone running a current distribution will eventually face this, and “don’t upgrade your kernel” is not a long-term answer.

I wrote tncd to fix this before it becomes everyone’s problem.

What it does

Most packet software speaks AGWPE — a TCP-based protocol that lets applications talk to a TNC without needing kernel socket support or direct serial access. On Windows, AGWPE itself handles everything. On Linux, the kernel’s AX.25 stack has traditionally done the heavy lifting, with tools like ldsped sitting between the application and the kernel.

KISS TNCs — everything from a classic Kantronics KPC-3 (in KISS mode) to a modern Mobilinkd or BTECH UV-Pro — are dumb modems. They encode and decode packets over the air but do not implement AX.25 Layer 2. The handshake, the sequencing, the acknowledgements have always lived somewhere else. tncd moves that somewhere else into userspace.

[PAT / Xastir / Paracon]
         |
      TCP:8000  (AGWPE protocol)
         |
       [tncd]
         |
   serial / TCP  (KISS protocol)
         |
     [TNC hardware]

tncd handles the full AGWPE protocol surface — version negotiation, port enumeration, callsign registration, UI frames, raw KISS passthrough, and monitoring events — and runs a complete AX.25 v2.0 Layer 2 state machine on the KISS side: SABM/UA handshake, I-frame sequencing with a mod-8 window, RR acknowledgement, duplicate detection, T1 retransmit, flow control, and clean DISC/DM handling. Serial (including USB), TCP, and Bluetooth RFCOMM TNCs are all supported.

How it’s tested

The unit test suite covers the Layer 2 state machine and AGWPE frame handling in isolation, but the more interesting part is the end-to-end test harness.

The e2e tests spin up two Direwolf instances as software AFSK modems and cross-link their audio through PipeWire. Direwolf-A’s TX output is wired directly to Direwolf-B’s RX input and vice versa — in software, no hardware, no loopback cable. tncd connects to Direwolf-A over KISS (both TCP and serial PTY modes are tested). PAT connects to tncd over AGWPE on one side; on the other side, a second PAT instance connects to Direwolf-B’s native AGWPE port.

The test then composes a P2P Winlink message with a random binary attachment, sends it, and asserts that it arrives intact in the other mailbox — in both directions. It is about as close to on-air testing as you can get without keying up a radio.

The APRS tests work the same way: packets sent from an AGWPE client through tncd are modulated by Direwolf-A, cross-linked to Direwolf-B, demodulated, and verified in Direwolf-B’s log.

Current state

tncd is in Alpha. APRS and unproto UI frames work reliably. Short connected-mode sessions work. Where things still break is longer or more complex connected-mode transfers — notably long Winlink sessions, especially with attachments, which is exactly what the e2e tests exercise. The connected-mode tests are currently marked xfail for this reason. There is a known issue in the AX.25 state machine around N(R) tracking under heavy load, and fixing it is the immediate priority.

If your use case is APRS or short BBS sessions, tncd is likely fine today. If you are running Winlink, or doing file transfers to your local BBS, expect rough edges and please report what you see — the test harness makes it straightforward to reproduce.

Hardware confirmed working so far: BTECH UV-Pro over Bluetooth RFCOMM, Dire Wolf over TCP KISS. The compatibility list on GitHub contains the fully functional TNCs I own. There are some noticeable gaps, including anything from Kantronics. Although I’ve owned many over the years, none currently in my possession are working correctly. Please feel free to test and update the README if you have a TNC that’s working (or not).

Packages are available for Debian/Ubuntu, Fedora/RHEL, openSUSE, Arch (AUR), and NixOS. See tncd.dev for install instructions.

What’s next

The immediate work is getting the P2P e2e tests passing consistently. After that, the hardware compatibility list needs to grow — if you have a Mobilinkd, an AEA, or a Kenwood with a TNC, I would love to hear how it goes.

Longer term, KF0ACN has started a Go port of tncd. The Python implementation is maintainable and well-tested, but a single self-contained binary is a better fit for the embedded Linux and low-power gateway use cases where tncd matters most. We expect the Go port to become the primary implementation over time.

The code is at github.com/ben-kuhn/tncd and is GPL-3.0. Bug reports with tncd -vvv logs are extremely helpful.


tncd.dev — downloads, packages, and documentation