la5nta / wl2k-go

A Winlink framework for Go.
https://getpat.io
MIT License
50 stars 20 forks source link

transport: Native KISS+AX.25 support #56

Open martinhpedersen opened 4 years ago

martinhpedersen commented 4 years ago

Several discussions regarding this topic has been started. I'm opening this issue for future discussions regarding:

KISS refers to a protocol to transfer raw bytes (as they should be transmitted on air) to a modem. KISS is usually used to encapsulate AX.25 packets in order to send it to a packet modem (hardware KISS TNC, DireWolf etc).

It merely serves to encapsulate the protocol frames in a way that can successfully pass over a serial link to the TNC.

AX.25 is a data link layer protocol, responsible for establishing link-layer connections, transferring data between nodes, detecting errors and handle re-transmission of lost packets. AX.25 is an ARQ protocol.

In order to support KISS-only TNCs (like DireWolf, TNC-X, Kenwood TH-D74 etc) natively in Go, we will first need a full AX.25 implementation for the link-layer stuff.

KISS should be trivial to implement, but writing a decent AX.25 implementation is a more challenging task.

Some open source implementations exists, but only a few of them have been used and tested extensively.

Non-exhaustive list of implementations with (more or less) open source code:

All of these implementations have their strength and weaknesses which should be identified before considering which could be the basis for an eventual port to Go.

More info on this topic:

Related issues:

cminyard commented 2 years ago

I realized I commented in a closed issue. So here it is again...

I have just finished implementing an AX25 library in C. It's part of the gensio library at https://github.com/cminyard/gensio and it's portable to Windows, MacOS, and Linux. It has C++ and Python bindings at the moment. I assume Go wouldn't be very hard.

I would really like to avoid having to deal with the Linux kernel AX25 stack. I don't know Go, though. I could learn it if you are interested.

The gensio library can do a lot of other things that might be useful, too.

Obviously it hasn't been around that long, but I'm planning to keep working on it. I have my own uses for it.

cminyard commented 2 years ago

Just FYI, I have added Go language support to the gensio library.

cminyard commented 2 years ago

I now have native AX.25 support working in pat. To use this, do the following:

git clone https://github.com/cminyard/wl2k-go.git
cd wl2k-go
git checkout gensio-work
cd ..
git clone https://github.com/cminyard/pat.git
cd pat
git checkout gensio-work
./make.bash libax25
./make.bash gensio
./make.bash

This adds a new connection type named "gax25" that works much like ax25, except it doesn't require the kernel's ax25. There is a new pat configuration entry for it.

This is based on the gensio library, and the connection below the ax25 layer is specified with a gensio string specifier. The default one is:

kiss,tcp,localhost,8001

which will connect to port 8001 and run kiss on top of that and ax25 on top of that. To connection to a kiss tnc:

kiss,serialdev,/dev/ttyS0,9600n81

Many other transports are available, like UDP, SCTP, unix sockets, ptys, stdio to another program, and connections to remote serial ports with serial port control (RFC2217). It can do encryption and authentication, too. For instance, I've tested by setting up a UDP repeater and run it on a local network without a radio. Handy for testing, especially automated.

I'm hoping this is interesting to the maintainers. It's a lot easier than using the kernel stack. It's going to be rough on the edges at this point, but it does seem to work ok for connecting into the winlink network and for P2P communication.

cminyard commented 2 years ago

Oh, I forgot, you need a bleeding-edge version of swig, the master branch at https://github.com/swig/swig so you'll need to check that out and install it so it's first in the PATH.

I've found quite a few issues with swig and Go, and there are still a few pending that I have workarounds for.

Also note that gensio works on Windows, so it would be possible to have native AX.25 support on WIndows with this.

cminyard commented 2 years ago

Well, sorry, the swig people haven't pulled in some patches I sent yet. You will need to get swig from https://github.com/cminyard/swig and use the add-goin-newline, branch. It's a pain, yes. But swig will generate go code that won't compile without those patches.

xylo04 commented 2 years ago

Still, this is exciting! I can't wait to try it out!

cminyard commented 2 years ago

I was able to get it to work under Windows. gensio is compiled with mingw64. There were a few little fixes, but nothing big, and it's all checked into the master branch of gensio.

martinhpedersen commented 2 years ago

Very exciting indeed πŸ™‚ πŸ‘ Looks like gensio and Go's net package solves much of the same things, by providing a common abstraction over networked I/O. Could be a very good fit πŸ‘

I have some concerns regarding taking in such a large non-Go dependency though. It complicates the build process, especially when it comes to cross compilation to other platforms. That's one of the reasons why a native AX.25 implementation would be such a nice addition to the project. Currently, we can provide everything but AX25 natively. Meaning you can build a full-blown Pat binary for your Android phone as simply as GOOS=android GOARCH=arm64 go build, without the AX.25 support.

But since we're already using cgo to link against libax25 on Linux, I guess we could consider replacing it with this to support even more platforms. The way I ended up implementing support for Linux's AX.25 stack was to use a specific opt-in build tag libax25 in combination with the OS specific build tags. It ensures that both wl2k-go and Pat can be compiled as pure Go programs, making it highly portable. We have also emphasized on not linking against shared libraries, to make the binaries as portable and self-contained as possible. I guess it should be possible to statically link against gensio the same way? πŸ€”

Another approach could be to wrap gensio in a small app much like libhamlib's rigctld. Then gensio would be like any another modem for Pat πŸ™‚ The benefit of this approach is of course that you could add multiplexing support so multiple apps could share the same AX.25 device.

cminyard commented 1 year ago

On Sun, Mar 27, 2022 at 06:29:02AM -0700, Martin Hebnes Pedersen wrote:

Very exciting indeed πŸ™‚ πŸ‘ Looks like gensio and Go's net package solves much of the same things, by providing a common abstraction over networked I/O. Could be a very good fit πŸ‘

Sort of. I wrote gensio because I needed a common abstraction for serial, network, pty, stdio, telnet, ssl, etc. for ser2net. So it's a lot more than just network. It was part of ser2net, and then I split it off because it seemed rather useful all by itself. It was easy to make a Go Net abstraction on top of gensio, and that made it easy to fit under Pat.

I have some concerns regarding taking in such a large non-Go dependency though. It complicates the build process, especially when it comes to cross compilation to other platforms. That's one of the reasons why a native AX.25 implementation would be such a nice addition to the project. Currently, we can provide everything but AX25 natively. Meaning you can build a full-blown Pat binary for your Android phone as simply as GOOS=android GOARCH=arm64 go build, without the AX.25 support.

Indeed, that is always a concern. I had my own reasons for doing AX.25 in gensio, but the lack of built-in AX.25 in Pat has been annoying to me, and the Linux AX.25 stack leaves something to be desired for this purpose. The nice design of Pat made it quite easy to add, so I did it.

But since we're already using cgo to link against libax25 on Linux, I guess we could consider replacing it with this to support even more platforms. The way I ended up implementing support for Linux's AX.25 stack was to use a specific opt-in build tag libax25 in combination with the OS specific build tags. It ensures that both wl2k-go and Pat can be compiled as pure Go programs, making it highly portable. We have also emphasized on not linking against shared libraries, to make the binaries as portable and self-contained as possible. I guess it should be possible to statically link against gensio the same way? πŸ€”

You can certainly link statically against gensio; the instructions I give do that. I couldn't make static linking work on Windows, but I don't know much about Windows. DLLs work fine, and I'm sure static linking could be made to work.

Gensio is known to work on Linux, Windows, MacOS, and BSD. With a little work it should be portable to most anything. So platform support shouldn't be an issue.

A Go AX.25 stack would be better, I agree, but someone has to write it. You could go with this now and if that ever came along later you could switch. I have done lots of protocol design and implementation in the past, and it's not easy, unfortunately.

Another approach could be to wrap gensio in a small app much like libhamlib's rigctld. Then gensio would be like any another modem for Pat πŸ™‚ The benefit of this approach is of course that you could add multiplexing support so multiple apps could share the same AX.25 device.

You could. It might be better to go with AGW in that case, since it's already available on common platforms. I don't know about Android, though. I looked at AGW, and from a protocol engineer's point of view the design is a little, umm, odd. But it should be usable. Wrapping gensio would be easy, too.

I work with a ham club that is using Pat and Winlink for emergency communications, and my goal was to make it as simple as possible. Using the Linux stack has too many steps to get wrong. The disadvantage of wrapping gensio is there's one more step to make it work, and I'd like to avoid that.

-corey - AE5KM