AX.25 Connected Mode Convergence Layer Howto for the DTN2 Reference Implementation.
General Description.
AX.25 is a link layer protocol for packet radio networking over HF, VHF and UHF links and is used primarily by radio amateurs. AX.25 connected mode is connection oriented and provides a reliable, in-order transfer using a sequence of data-frames.
The AX.25 Connected Mode Convergence Layer (AX25CM-CL) is a convergence layer implementation for AF_AX25 SOCK_SEQPACKET sockets on Linux platforms. See wikipedia.org and tapr.org for information on the AX.25 protocol itself or try man 4 ax25 on Linux.
This convergence layer is described in:
Ronan, Walsh and Long, Experiments with Delay and Disruption Tolerant Networking in AX.25 and D-Star Networks, ARRL/TAPR 28th Annual Digital Communications Conference, 25-27 September 2009, Chicago.
The AX25CM-CL transports RFC-5050 bundles directly over AX.25 operating as a Layer-2 protocol, in a similar fashion to the Bluetooth-CL. It has been undergoing occasional testing with KISS mode TNCs and via AX.25 in IP encapsulation (using ax25ip).
Software Description
The AX.25-CL code in DTN2/servlib/conv_layers is based on (forked from) the existing TCP-CL implementation, but derives from the new SeqPacketConvergenceLayer class instead of the StreamConvergenceLayer in order to allow for modification of the TCP-CL Protocol for use in the amateur environment. Currently, the TCP-CL Protocol is extended only to include a 32-bit CRC appended to each TCP-CL Protocol segment, in order to ensure that corruption of KISS frames can be detected, as well as providing additional means to detect implementation induced protocol errors.
The TCP-CL and the AX25CM-CL share commonality provided by the ConnectionConvergenceLayer base class. Supporting classes providing the interface to AF_AX25 SOCK_SEQPACKET and AF_AX25 SOCK_DGRAM sockets are provided as an extension to the oasys library in oasys/ax25. A simple test-harness is provided in oasys/test for the underlying sockets abstraction.
Support for AF_AX25 SOCK_DGRAM sockets in future subclasses of the oasis class AX25Client should facilitate further development, such as the use of Disconnected Mode (UI frames) to convey discovery data or perhaps an implementation of LTP for AX.25 links.
The code has been in intermittent development since January 2007, when it started as a fork of the TCP-CL and oasys support classes.
Status.
The AX25CM-CL should probably be regarded as alpha quality. I'd recommend supervised use on shared channels, at least until you are familiar with the traffic load generated by your DTN.
Features.
The AX25CM-CL currently allows for the use of point-to-point links between two peers or with a single non-DTN digipeater in the path, for an ax25cm link. Reactive fragmentation works.
There is no announcement/discovery mechanism implemented yet. Links must be manually configured and initiated.
Routing using the static router or the Delay Tolerant Link State Router works fine, although adjustment of the default dtlsr_lsa interval and dtlsr_lsa_lifetime throughout your DTN is advised in order to avoid LSAs clogging up your AX.25 link.
Known Bugs and TODOs.
Bug: Stuck Sockets
There is currently a bug that requires a restart of the dtnd to get broken AX.25 links going again, seemingly due to a connected socket stuck in the LISTENING state at the listening end. Sometimes killing kissattach is required.
This seems to be related to contact closure by the listener. I've been wondering about proper use of the SO_LINGER socket option and the viability of calling shutdown on the socket. The problem might be a 'simple' resource leak.
Bug: Receiving runt segments
It seems that sometimes partial segments are read from the socket, effectively causing a protocol error.
TODO: Minimise segment ack traffic
Currently, the AX25CM-CL produces a flurry of (TCP-CL Protocol) segment acks (one for each segment/frame) and sends them as distinct frames. A more conservative acking mechanism would be prudent, by cramming more than one into a frame and/or adopting a selective ack mechanism. The first should in theory already happen, but it doesn't in practice, perhaps due to the way polling works in dtnd.
Update: Support for a link option - ack_window, defining the number of data segments to be aggregated before issuing a cumulative ack segment, is still undergoing testing, but is working well.
TODO: Discovery mechanism
The lowest level AX.25 socket code in oasys/ax25 should support UI frames as AF_AX25 SOCK_DGRAM as is, but there is nothing above that level to make use of the facility, yet.
Hardware requirements
In order to use AX.25 links in your DTN you will need access to one of the following:
- a pair of (or more) DTN nodes, running Linux, suitably equipped with TNCs and radios, or
- a DTN node running Linux, with a TNC and a loopback cable, or
- a pair of (or more) DTN nodes, running Linux, passing AX.25 over IP, or
- something else equally useful that I haven't thought of.
A SignaLink USB with an FT-817 and a netbook running Linux works well with soundmodem as a TNC.
Getting the code.
The code for the AX25CM-CL is available in the oasys and DTN2 Mercurial repositories at sourceforge, but is not included in the latest releases (oasys-1.4.0 and dtn-2.7.0).
Building the code
The two main mercurial repositories provide the oasis and DTN2 source (see Code). Assuming you have a functional AX.25 system running on your Linux build machine (see the AX.25 Howto), and have all the appropriate development headers, then the build process should be identical and painless, and the usual configure;make;make install should handle the rest (with your specific additional configure options where necessary.
When configuring oasys, you should see:
checking whether ax25 support should be enabled... try
checking netax25/ax25.h usability... yes
checking netax25/ax25.h presence... yes
checking for netax25/ax25.h... yes
checking netax25/axlib.h usability... yes
checking netax25/axlib.h presence... yes
checking for netax25/axlib.h... yes
checking for netax25/axconfig.h... yes
checking for library containing ax25_config_load_ports... -lax25
checking whether ax25 support was found... yes
and -lax25 in the EXTLIB_LDFLAGS in the last line of configure output.
When configuring DTN2, you should see -lax25 in the EXTLIB_LDFLAGS in the last line of configure output.
If that happened when you configured and your builds of oasys and DTN2 worked, you should be good to go and ready to configure your dtnd to use an AX.25 link.
Editing your dtn.conf files.
Currently we've only ever tried a single connection (direct or via a single digipeater), between a link initiator and a listener. In the following examples, G0HWW-9 is the link initiator and G0HWW-8 is the listener.
The dtnd.conf for the listener node (here using G0HWW-8)
For the dtnd running on the listener node, add the listening interface:
interface add axif0 ax25cm local_call=G0HWW-8 axport=pk232
Substitute your "callsign-ssid" for "G0HWW-8" and the appropriate port from your /etc/ax25/axports file for "pk232".
Presently, we're adopting a control-freak approach to link configuration which requires the listener to have an a priori OPPORTUNISTIC link configured for each inbound ONDEMAND link from a link initiator.
link add opaxl0 G0HWW-8:G0HWW-9:pk232 OPPORTUNISTIC ax25cm remote_eid=dtn://hostb.dtn local_call=G0HWW-8 remote_call=G0HWW-9 axport=pk232 min_retry_interval=30 keepalive_interval=240 segment_length=220 data_timeout=300000 sendbuf_len=512 recvbuf_len=512 idle_close_time=300 hexdump=true
This link is known as "opaxl0". The next hop shown here identifies the local callsign of the listening port, the remote callsign and the local axport for the link in the form LOCAL_CALL:REMOTE_CALL:AXPORT. The REMOTE_CALL in the next hop must match the next hop used in the specification of the ONDEMAND link defined at the initiator node, although the use of a digipeater in the initiator's next hop specification is opaque. The inbound link is specified as OPPORTUNISTIC. The convergence layer is ax25cm. The EID of the remote dtnd is specified, as are the local call, the remote call and the local axport. Other options are provided as for the TCP-CL. If these options are used, they should be matched at the other end of the link.
The dtn.conf for the link initiator (here using G0HWW-9)
The link imitator has a single link added for the link itself:
link add axl0 G0HWW-8:pk232 ONDEMAND ax25cm remote_eid=dtn://hosta.dtn local_call=G0HWW-9 remote_call=G0HWW-8 axport=pk232 min_retry_interval=30 keepalive_interval=240 segment_length=220 data_timeout=300000 sendbuf_len=512 recvbuf_len=512 idle_close_time=300 hexdump=true
This link is known as "axl0". The link initiator uses a next hop of the form REMOTE_CALL:AXPORT. A single non-DTN digipeater node may be used with a next hop of the form REMOTE_CALL,DIGI_CALL:AXPORT. Other options are used as previously described.
Opening the link.
Once your dtn.conf files have been set correctly, you can run the dtnd program on your nodes then attempt to bring up the ONDEMAND link from the initiator node. It helps to have shell access to both nodes.
At the link initiator, use "link open axl0" (or equivalent with your link name of choice). It seems that the first SABM frame sent never gets a response, but the 2nd should get a UA frame response and establish the connection, at which point, contact headers will be exchanged.
If you are using the DTLSR router, then bundle traffic should start flowing. If you are using the static router then you should manually add routes appropriately, either directly into the running dtnd or in the dtn.conf file.
The final word.
This is experimental code and may produce unexpected results. Feel free to play with link parameters and hack hard-coded values in the oasys/ax25 code.
That's all for now, except to say thanks to John Ronan, EI7IG for his help and experimentation, without which we would not have got this far.
Please let me know if you find issues with code. Questions should probably be posted to the DTN Users mailing list.
Darren Long, G0HWW
mail to: g0hww _at_ mac _dot_ com