Linux implementation of the KISS protocol

The "mkiss"-module is the kernel KISS protocol driver module. It interfaces a serial device (or any other character device) with the kernel AX.25 networking stack.
With this, the Linux kernel acts as a TNC.

To enable this, load the mkiss module (modprobe mkiss) and run kissattach:

/usr/sbin/kissattach /dev/ttyUSB0 ax0
/dev/ttyUSB0 is a serial device, as stated before this can also be e.g. a pseudo tty or any other character device. 'ax0' is the network-device name. is an option IP address.

In the example above, the network device 'ax0' was used. This device can be configured via /etc/ax25/axports:

ax0     FH9GOU-1        38400   236     7       AXUDP gateway
ax0 is again the network device. FH9GOU-1 is the CALL to use. 38400 is, if the device is a serial device, the baudrate used to talk to it. 236 is the maxium AX.25 packet size and 7 is the window size. "AXUDP gateway" is a descriptive comment.

The KISS protocol is fully implemented in Linux. Not only SMACK and FLEX checksums, but also the range of special commands like configuring the tx delay, enabling full duplex, etc.

The implemented KISS protocol consists of frames where a regular AX.25 packet gets a command-byte at the front and two optional CRC bytes. When calculating the CRC, only the AX.25 frame is evaluated, not the command-byte at the front.

The first byte consists of 2 nibbles:

  • A. type of CRC (back then this was a TNC port number)
  • B. command.
The CRC nibble (A, the MSN) can be:
  • 0x20: FLEXNET
  • 0x80: SMACK
The command nibble (B, LSN) can be:
  • 0x00: frame is a regular AX.25 data frame
  • 0x01: set TX delay
  • 0x02: set persistance
  • 0x03: set slot time
  • 0x04: set tx tail
  • 0x05: set full duplex mode
  • 0x06: set hardware address
  • 0x0f: kernel asked for a shutdown

SMACK is a regular CRC16 polynome:

X^16 + X^15 + X^2 + 1
FLEXNET is a bit different:

Before packets can be pushed into the kernel (and also the reverse when retrieving them from the kernel), they're encoded: some bytes are escaped.

#define FEND    0xc0
#define FESC    0xdb
#define TFEND   0xdc
#define TFESC   0xdd

void put_byte(uint8_t *const out, int *const offset, const uint8_t c) 
        if (c == FEND) 
                out[(*offset)++] = FESC; 
                out[(*offset)++] = TFEND; 
        else if (c == FESC) 
                out[(*offset)++] = FESC; 
                out[(*offset)++] = TFESC; 
                out[(*offset)++] = c; 
Bytes that contain FEND (0xc0) are replaced by FESC + TFEND, FEST by FESC + TFESC. This escaping mechanism is performed over all bytes except the first (command-)byte.