In amateur packet radio the AX.25 link protocol holds no notion of routing between networks: it can carry a frame between two stations within radio range, and nothing more. Everything needed to cross a network of nodes — choosing the next hop, rebuilding a path, reaching a station out of range — was built on top of AX.25 by different groups, in different years, on different assumptions. The result is that on one frequency, over the same radio link, several network protocols travel without speaking to each other. A node’s real job is not to offer a prompt: it is to terminate and translate these routing planes on a single machine.
What AX.25 does, and what it does not
AX.25 is the amateur version of X.25 at the line level, derived from LAPB. The reference specification is the one maintained by TAPR and ARRL; version 2.2 dates to 1998. It defines frames, addressing by amateur callsign, connection setup and teardown, frame numbering and retransmission. It stops at layer 2 of the OSI stack: the data link and, for the physical part, the attachment to the modem. It has no network addresses, no routing tables, no concept of an intermediate hop.
That is enough for a direct conversation between two stations within radio range. It is not enough for a network. A station a hundred kilometres away, behind two or three digital repeaters, can be reached with plain AX.25 only by manually chaining connections node by node — first-generation digipeating, fragile and slow. From here on the interesting part begins, because the network layer AX.25 lacks was added from outside, more than once.
Three incompatible network layers
Three routing schemes grew on top of the same AX.25, independent of one another.
- NET/ROM is the most widespread. It is a network layer that uses AX.25 as its link layer and introduces nodes with aliases, a table of reachable nodes and dynamic routing: each node advertises to its neighbours which stations it can reach and with what quality, and paths rebuild themselves. It started as commercial firmware for TNC controllers; in Germany its open reimplementation TheNet, and later TheNetNode, broadened its reach.
- ROSE brings the genuine X.25 packet layer onto radio, with addressing under the X.121 numbering plan. Unlike NET/ROM it does not use dynamic routing but a static switching table: each node knows, for every destination address, which neighbour to forward to. It is the packet-switched telephone-network approach applied to radio.
- FlexNet, developed by the Darmstadt group, chooses automatic routing with continuous measurement of link quality: the autorouter knows alternative paths and diverts traffic when a hop drops, and links are reversible by construction. It is the dense-mesh network born under German regulatory constraints, where every unattended node requires authorisation and point-to-point links are coordinated in advance.
Three routing models — dynamic advertisement, static X.25 switching, autorouting with a metric — over the same physical medium and the same link layer. A station that speaks only NET/ROM does not reach a ROSE station; a FlexNet network is a domain of its own. The fragmentation is not an implementation flaw: it follows from AX.25 leaving layer 3 empty, and that gap being filled three times.
Where the node gets hard
On Linux these three layers are distinct socket families in the kernel: AF_AX25, AF_NETROM, AF_ROSE. Native support grew out of the work of Alan Cox and then Jonathan Naylor (G4KLX), who added NET/ROM and ROSE to the kernel’s AX.25 stack; ROSE derives from the FPAC implementation by F6FBB in France. Each exposes a separate Berkeley socket interface: to the programmer they are three different stacks sharing only layer 2.
This is exactly the critical point for anyone writing a node. The node does not merely route within a single protocol: it has to terminate all of them and bridge between them. A user connecting in AX.25 on the access frequency must be able to ask to continue toward a NET/ROM destination, or to enter a ROSE network, or to take up a FlexNet link — and the node has to map the request onto the right routing plane, keep the state of both connections (the user’s inbound one and the network’s outbound one) and relay data between them. When the protocols use different addressing models — AX.25 callsign, NET/ROM alias, ROSE X.121 address — translation is not a detail: it is the function.
There is also the fact that AX.25 is connection-oriented and uses a limited window. Version 2.0 works modulo 8, with at most seven unacknowledged frames in flight; version 2.2 introduces modulo 128 and the negotiation of larger frame sizes. On a shared, half-duplex radio channel, with round-trip times of seconds across several hops, every connection the node carries must be handled with its own retransmission timers and its own window. A node bridging two slow connections has to absorb that asymmetry without overflowing its queues.
Design implications
The first consequence is that a node is above all a multiprotocol switch, not an interactive application. The visible part — the prompt, the list of reachable nodes, the link to a BBS or a DX cluster — is thin next to the state machine that keeps connections open and routes between the three layers. A concrete instance of this is AWZNode, the Linux node software I released from April 1998 onwards — the IZ5AWZ callsign gives the project its name — on top of LinuxNode and FlexNode, which for exactly this reason had to terminate AX.25, NET/ROM, ROSE and FlexNet and let them coexist on one station; the project, which predates noze, is described in the entry noze publishes about it: https://www.noze.it/en/open-source/awznode/.
The second consequence concerns the open nature of the code. The whole stack — kernel protocols, configuration tools, node software — is under the GNU General Public License version 2, and was distributed on the FTP archives of the time, starting from ftp.funet.fi at the University of Helsinki — the main European repository for open software — from which AWZNode was picked up into Linux distributions such as Slackware and Debian. This is not a licensing footnote: in a network where a frame crosses stations run by different people, with different implementations of the same protocol, being able to read the behaviour of each layer is the only way to find where a connection breaks. Window negotiation between AX.25 2.0 and 2.2, conversion between an X.121 address and a NET/ROM alias, the metric of a FlexNet autorouter: these are things checked against the code, not against the documentation.
Limits
Holding three network layers together on one node does not unify them. They remain three routing domains with three addressing models, and the bridge works as long as someone maintains the translation tables by hand: a ROSE destination has to be declared, a stale NET/ROM route has to be cleaned up, a FlexNet link has to be coordinated with the far end. There is no common layer 3 that turns the amateur network into a single network, and the fragmentation the node hides from the user stays just below the surface. Then there is the limit of the medium itself: a shared channel, narrow bandwidth, access times that grow with traffic. A node makes a distant station reachable; it does not make the radio network fast, and over a half-duplex link of a few thousand bits per second no network abstraction can pretend otherwise.
- https://www.ax25.net/AX25.2.2-Jul%2098-2.pdf
- https://tldp.org/HOWTO/AX25-HOWTO/
- https://web.tapr.org/meetings/DCC_1995/DCC1995-FlexNet-DK7WJ-N2IRZ.pdf
- https://ham.packet-radio.net/packet/NetRom/NetRomProtocol.pdf
- https://ftp.funet.fi/pub/ham/packet/linux/
Cover image: AWZNode project logo (noze).