Sneaky.NET

Tom’s Home page

N9LOY - Packet Radio

So, after a few years I’m getting back into Amateur Radio. I’m not so much interested in talking on the radio - but getting back to packet radio.

I thought I’d take a look around and see what the status of packet radio was these days. There’s things that I’ve always wanted to do - like building my own 2m radio with an interface to remote control it. Building my own packet TNC. Building some kind of portable packet system that I could use for field day or take to Dayton or something.

I don’t see much use for packet other then position reporting. I would REALLY like for someone to tell me I’m wrong and give me a use for it. I don’t see many services out there for packet radio.

So, for now - I’m just playing to see what I can get it to do. And, eventually I’ll get the bike setup with a packet system - at least a tracker. I’m thinking though that I may go all the way and do a portable i-gate.

Some things I’d like to get working with this..

  • digipeater
  • i-gate
  • ax.25 connections from linux
  • IP over ax.25
  • ping and telnet to a linux box over ax.25

Current status

As of right now, I have two “nodes” setup. One is based on my old Kenwood TH-D7a radio using the built-in TNC. This is pretty weak and can’t really connect to much of anything else. The second node is based on a KCP-3+ and a Kenwood TM-251 mobile radio. This one can get out pretty well.

Both are using older Raspberry Pi B’s. I didn’t really have too many problems getting them setup. The biggest issue was figuring out how to get the TNC in the HT-D7a to operate in KISS mode.

I still have some more testing to make sure things are working as I expect them to. I think they are, but I want to amek sure. So, my plan is to use the TH-D7a node to test access and reporting through the TM-251 node. I want to test both digipeating as well as two way i-gating.

I’ve connected back and forth between them. I will post more after I do my detailed testing.

How-to

ax.25 Interface configuration

Essentailly the ax25 interface is like any other interface in your linux box. You run other protocols on top of it. I haven’t dug into how IP works - for instance, how it determines what callsign (like a MAC address) is mapped to an IP address.

We have to configure the interface and then start it. You configure it thorugh the /etc/ax25/axports file. This file describes the system parameters of the interface. We will define the physical port and settings when we attach the interface.

One thing I’m not yet clear on is the reason we need the callsign here on the system level. ax25d.conf appears to use the port specified in the /etc/ax25/axports file. However, you can specify another callsign when using broadcast or ax25_call. So, maybe my testing will help figure that out.

/etc/ax25/axports
1
2
# /etc/ax25/axports
2m      N9LOY-2 9600    128     2       144.390MHz tomn@n9loy.net

This configures the interface side of things. Then we need to attach the TNC to create the interface. This is done with the commands. The first does the attach - this connects the TNC on /dev/ttyUSB0 to the “2m” port in the axports file.

The params commands set different timing parameters. After some digging I found the paramters are as follows:

  • -r - persist - The next byte is the persistence parameter, p, scaled to the range 0 - 255 as a percent. 100%=255.
  • -s - slottime - How long it waits after detecting a busy “line” before checking the percentage chance on the persistence setting.
  • -l txtail - How long do we hold up the transmitter after we send.
  • -t - txdelay - How long after bringing the transmitter up do we wait before sending data.
ManualCommands
1
2
/usr/sbin/kissattach -b -l /dev/ttyUSB0 2m
/usr/sbin/kissparms -p 2m -t 700 -s 200 -r 32 -l 100 -f n

Automated start up of the ax25 interfaces

I’ve adapted some scripts that I found out on the internet. I simplified them somewhat and got them configured to startup properly for my system. Here are my files:

This file brings up the ax25 interfaces

/etc/ax25/ax25-up
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# /etc/ax25/x25-up

# Set Sysctl values
sysctl -w kernel.panic=30          # Set the kernel to automatically reboot 30 seconds after a kernel panic
sysctl -w kernel.panic_on_oops=30  # panic if there's an oops (BUG)

# Attach KISS-device 
  /usr/sbin/kissattach /dev/ttyUSB0 2m | tail -1 > /tmp/ax25-config.tmp
  awk '/device/ { print $7 }' /tmp/ax25-config.tmp > /tmp/ax25-config-tmp
  Device=`cat /tmp/ax25-config-tmp`

# Install Parameter: Persistence=128, slot=10, TX-Delay=250
  /usr/sbin/kissparms -p 2m -r 128 -s 10 -l 20 -t 250

Stopping the interfaces is pretty easy. Just kill off the kissattach commands.

/etc/ax25/ax25-down
1
2
3
#!/bin/bash

killall -KILL kissattach > /dev/null

You can run these scripts with their full pathnames /etc/ax25/ax25-up to start and /etc/ax25/ax25-down to stop. We need an init.d script to call them on start up and shutdown.

I then used update-rc.d ax25 defaults to configure the rc.d links to auto start the interfaces. One note, the name is ax25ifs. By adding that to the Required-Start of other services (such as aprx) it will properly order the startup/shutdown scripts in /etc/rc[0-6].d.

/etc/init.d/ax25ifs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#! /bin/bash

### BEGIN INIT INFO
# Provides: ax25ifs
# Required-Start: $remote_fs $syslog $network
# Required-Stop: $remote_fs $syslog $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Ax.25 initialization
# Description: This script provides the control for the ax.25 interfaces.
#              The fine tuning is accomplished via /etc/ax25/ax25-up and /etc/ax25/ax25-down.
#
### END INIT INFO

# /etc/init.d/ax25
# /etc/rc.d/ax25
# Kernel-Parameter "ax25=yes|no" ?
  if [ "`grep -e [Aa][Xx]25=[Nn][Oo] /proc/cmdline`" != "" ] ; then
     echo -e "ax25: Aborting startup on user request (kernel boot parameter)."
     exit 1
  fi

case "$1" in
 start|-start)
   echo "/etc/init.d/ax25: Starting AX25..."
   /etc/ax25/ax25-up
   ;;

 stop|-stop)
   echo "Stopping AX25..."
   /etc/ax25/ax25-down
  ;;

  restart|-restart)
   echo "AX25 Restart"
   /etc/ax25/ax25-down
   sleep 1
   etc/ax25/ax25-up
  ;;

  status|-status)
   if [ ! -d /proc/sys/net/ax25 ] ; then
    echo "ax25 is down"
   else
    echo “ax25 is up"
   fi
  ;;

  *)
   echo "Usage: $0 {start|stop|restart|status}"
   exit 1
  ;;
esac
exit 0
# (End of Script)

axlisten Tests

Once you have the interface configured, you can start a program called axlisten to dump all the packets recieved on that interface. Here’s the command and a sample:

Sample
1
2
3
4
5
6
7
8
9
10
root@pi-amateur:/home/tomn# axlisten -p 2m
2m: fm KA8ZGE to APU25N via WB9EOC-10* W9ICE-10* WIDE2* ctl UI^ pid=F0(Text) len 79
0000  }W8FY-4>APU25N,TCPIP,KA8ZGE*:=4051.31N/08426.73WdMIDDLE POINT FD
0040   - VWEMA WXNET.
2m: fm N8WCT-1 to APN391 via WA4ZKO-15* W9ICE-10* WIDE2* ctl UI pid=F0(Text) len 31
0000  >http://www.n8wct.com/n8wct-1/.
2m: fm N614EF to APT311 via KA8ZGE* WIDE1* W9ICE-10* WIDE2* ctl UI pid=F0(Text) len 15
0000  >TinyTrak3 v1.1
2m: fm W9CYU-9 to 3Y4S7P via W9ICE-10* WIDE1* WIDE2-1 ctl UIv pid=F0(Text) len 41
0000  `rZ1l!=>/]"6g}146.700MHzformerly_kb9szf=.

beacon Tests

Now we transmit. I started an ax25listen going on the 2 meter port of one packet station and then sent a beacon from the other.

Source
1
root@raspberrypi:/home/tomn# beacon -c n9loy-5 2m "This is a test"
Reveiver
1
2
3
root@pi-amateur:/home/tomn# axlisten -p 2m
2m: fm N9LOY-5 to IDENT ctl UI^ pid=F0(Text) len 14
0000  This is a test

mheard Logging

I’m starting the mheard daemon to collect the call signs that I hear. I just went out and grabbed a generic Debian init script and edited it. I then ran update-rc.d mheard defaults and it starts automatically.

/etc/init.d/mheard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/sh
### BEGIN INIT INFO
# Provides:          mheard
# Required-Start:    $local_fs $remote_fs $network ax25ifs
# Required-Stop:     $local_fs $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: mheard daemon
# Description:       record the stations heard through the ax25 interfaces
### END INIT INFO


# Documentation available at
# http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptfunc.html
# Debian provides some extra functions though
. /lib/lsb/init-functions


DAEMON_NAME="mheardd"
DAEMON_USER="root"
DAEMON_PATH="/usr/sbin/mheardd"
DAEMON_OPTS=""
DAEMON_PWD="${PWD}"
DAEMON_DESC=$(get_lsb_header_val $0 "Short-Description")
DAEMON_PID="/var/run/${DAEMON_NAME}.pid"
DAEMON_NICE=0
DAEMON_LOG='/var/log/mheardd-prog'

[ -r "/etc/default/${DAEMON_NAME}" ] && . "/etc/default/${DAEMON_NAME}"

do_start() {
  local result

  pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
  if [ $? -eq 0 ]; then
      log_warning_msg "${DAEMON_NAME} is already started"
      result=0
  else
      log_daemon_msg "Starting ${DAEMON_DESC}" "${DAEMON_NAME}"
      touch "${DAEMON_LOG}"
      chown $DAEMON_USER "${DAEMON_LOG}"
      chmod u+rw "${DAEMON_LOG}"
      if [ -z "${DAEMON_USER}" ]; then
          start-stop-daemon --start --quiet --oknodo --background \
              --nicelevel $DAEMON_NICE \
              --chdir "${DAEMON_PWD}" \
              --pidfile "${DAEMON_PID}" --make-pidfile \
              --exec "${DAEMON_PATH}" -- $DAEMON_OPTS
          result=$?
      else
          start-stop-daemon --start --quiet --oknodo --background \
              --nicelevel $DAEMON_NICE \
              --chdir "${DAEMON_PWD}" \
              --pidfile "${DAEMON_PID}" --make-pidfile \
              --chuid "${DAEMON_USER}" \
              --exec "${DAEMON_PATH}" -- $DAEMON_OPTS
          result=$?
      fi
      log_end_msg $result
  fi
  return $result
}

do_stop() {
  local result

  pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
  if [ $? -ne 0 ]; then
      log_warning_msg "${DAEMON_NAME} is not started"
      result=0
  else
      log_daemon_msg "Stopping ${DAEMON_DESC}" "${DAEMON_NAME}"
      killproc -p "${DAEMON_PID}" "${DAEMON_PATH}"
      result=$?
      log_end_msg $result
      rm "${DAEMON_PID}"
  fi
  return $result
}

do_restart() {
  local result
  do_stop
  result=$?
  if [ $result = 0 ]; then
      do_start
      result=$?
  fi
  return $result
}

do_status() {
  local result
  status_of_proc -p "${DAEMON_PID}" "${DAEMON_PATH}" "${DAEMON_NAME}"
  result=$?
  return $result
}

do_usage() {
  echo $"Usage: $0 {start | stop | restart | status}"
  exit 1
}

case "$1" in
start)   do_start;   exit $? ;;
stop)    do_stop;    exit $? ;;
restart) do_restart; exit $? ;;
status)  do_status;  exit $? ;;
*)       do_usage;   exit  1 ;;
esac

ax25_call test

Once I got everything connected for the KCP-3 plus, I used the Raspberry Pi and TH-D7a (in KISS mode) to connect to the KPC-3. I did this through the linux command line. The KCP-3 answered in “keyboard to keyboard” mode. So, I was able to type back and forth. The connection showed up in netstat in linux as expected.

1
2
3
4
5
root@pi-amateur:/home/tomn# netstat --protocol=ax25
Active AX.25 sockets
Dest       Source     Device  State        Vr/Vs    Send-Q  Recv-Q
N9LOY-0    N9LOY-1    ax0     ESTABLISHED  003/003  0       0
root@pi-amateur:/home/tomn#

References

http://www.nq0m.com/2012/09/03/aprs-i-gatedigi-with-my-new-raspberry-pi/ http://k4gbb.us/docs/StartingAX25.html <- Config stuff http://k4gbb.us/docs/StartingAX25.html <- Startup scripts

Comments