SMACK - Protocol Description
----------------------------
Version 1.0, Dated 27.02.92
by Jan Schiefer, DL5UE and Dieter Deyke, DK5SG/N0PRA
1. Introduction
The end of 1990 was the first time that the Stuttgart Packet-Radio-Amateurs
thought about the factual certainty of Data Security between TNC and
WAMPES(*)- Node Computer. Already with other Packet-Node Systems Data losses
had appeared, we considered which sort and in what manner a compatible
development of the KISS-Protocols with a Checksum could be considered
possible. From the Result of this consideration came the name SMACK
(Stuttgart Modified Amateur radio CRC-KISS. This Document should explain
the difference between SMACK and KISS and make possible the implementation
of other Systems.
2. What is KISS?
KISS had been recommended by Phil Khan KA9Q [1]. Because his TCP/IP-Software
it needed a Protocol, that enabled a simple entry to Packet-Radio below
the AX.25-Protocol level. KISS offers a layer 2a-Entry. Assignments of the
TNC are basically, only the Access Control of the Frequency (Channel-Busy-
Recognition, P-Persistence-Action) and the conversion of the synchronous
HDLC-Data on the PR-Channel into the asynchronous Format of the RS232-Port.
The KISS-Protocol regulates the demarcation of individual Packets with
Delimiters, the eventual handling n the Data Stream of the appearing
Delimiter and defines a simple Command structure for the installation of
TNC-Parameters. Also, it has met the provision, to be able to operate TNCs
with more Packet-Channels.
3. Modification of the KISS-Protocol
The Host Computer communicates with KISS in the Form of Packets. The
beginning of such a Packet will be recognised through the FEND. Then
follows the so called Command Byte. It issues, whether it is handling Data-
or a Command Packet and what Command is meant. With one exception (Reset-
Command = 255) all Commands employ only the lower 4 Bits of this Command
Byte. This means, that the upper 4 Bits with Multi-Channel-TNCs can issue
the Channel. So 16 Channels can be given Parameters individually.
Because we do not know either 16- or 8-Channel-TNCs, we have used a purpose
other than originally intended, the topmost Bit of this Command Byte. If
it is set, it handles itself with the doubtful Packet as a Data Packet with
CRC (only with Data Packets are to found a Checksum calculation instead!).
With such Packets, the Checksum will be attached at the End of the Frame,
and the lower value Byte first. Both of the following illustrations show the
layout of a Data Packet once with and once without Checksum.
+------+------+------+------+-----+------+------+
| FEND | 0x00 | DATA | DATA | ... | DATA | FEND |
+------+------+------+------+-----+------+------+
KISS-Frame without Checksum
+------+------+------+------+-----+------+---------+----------+------+
| FEND | 0x80 | DATA | DATA | ... | DATA | CRC LOW | CRC HIGH | FEND |
+------+------+------+------+-----+------+---------+----------+------+
Smack-Frame with Checksum
It should be once again reiterated here, that only Data Packets will be
CRC-secured. With that it will be prevented, that a Command can be sent to
the TNC, when themselves Host and TNC with CRC/not CRC are in disagreement.
4. Switching from KISS onto SMACK
A SMACK-TNC works after switching into the KISS-Modus, therefore generates
no Checksum. As soon as the first Packet is received with CRC, it switches
its Send Routines likewise to CRC. This Operation condition can be
abandoned only through a Reset. The Host behaves analogously. If however a
KISS-TNC is connected, so CRC-Frames from the Host by reason of their
unknown Command Byte will be discarded and working continued.
This Method has the advantage, that both KISS- as also SMACK-TNCs can be
operated alternately to a Host; without that, a reconfiguration is
necessary. That should be illustrated by a Display of both cases.
---------------------------------------------------------------------------
Case 1: KISS-TNC
Host TNC
- Sends an individual Packet with
CRC, then switches its Sender
on Normal-KISS again.
- Receives a frame which for
it is an unknown Command-
byte 0x80 and abandons it.
- Dispatches KISS-Data without
Checksum.
- Dispatches KISS-Data without
Checksum.
---------------------------------------------------------------------------
Fall 2: SMACK-TNC
Host TNC
- Sends an individual Packet with
CRC, then switches its Sender
onto Normal-KISS again.
- Receives a Frame with CRC-
Recognition, switches its
Sender on CRC.
- Dispatches KISS-Data without
Checksum.
- TNC sends the first Frame
with CRC.
- Receives a Frame with CRC-
Recognition, switches its
Sender on CRC.
- Dispatches SMACK-Data with
Checksum.
- Dispatches SMACK-Data with
Checksum.
---------------------------------------------------------------------------
Dependent upon Send condition (CRC/not CRC) the received Frames will always
be handled as follows:
Receiver Frame | Action
-------------------------------+------------------------
No CRC | Frame progressed further
With CRC, Correct Checksum | Frame progressed further
With CRC, False Checksum | Frame abandoned
This Protocol sets in advance, that a KISS-Implementation abandons its
unknown Frame. This will be promoted in the KISS-Specification [1].
4. CRC-Calculation and Implementation Tips
This is not the correct place, to explain the Theory of the cyclical
Redundancy-check CRC. Reference should be made to the work of Michael
Rhner, DC4OX [2]. This extract depicts only important Details for an
implementation.
As Check Polynomial the CRC16-Polynomial will be used. This has the form
16 15 2
X + X + X + 1
The CRC-Generator will be pre-set with 0. The calculation of the CRC will be
of the CRC over all Data Bytes inclusive of the Command Byte 0x80.
As is well known in the KISS-Protocol the demarcation of the Frame will be
performed with the FEND-Character (0xc0). In the case where this Character
occurs in the Data Stream, it will be handled otherwise. This occurrence
will be named SLIP-Encoding.
The CRC must be calculated, before the SLIP-Encoding takes place, and will
be checked, after the SLIP-Decoding has taken place. Instead it gives more
Grounds:
- The CRC Bytes could contain FESC, TFEND, FEND etc.
- The SLIP En/Decoder will be used in most Host-Implementations (e.g.
WAMPES) also dependent upon KISS, in order to make the Connection to the
Unix-Kernel as an example. Additionally, it is admitted that in this case
CRC-Checking would be desirable, but will not be understood by the other
side.
The CRCs logically belong therefore, to the KISS Layer.
Instead the Calculation is to be found as follows:
- CRC-Generator pre-set with 0.
- All Data Bytes one behind the other added into the Algorithm, including
both CRC-Bytes.
- At the End a 0 must stand again in the CRC-Generator. If the value is not
0, so a Transfer Error has occurred and the Frame must be discarded.
Different Algorithms for the CRC-Generator will be described in [2].
Here is a simple table of a controlled Algorithm issued in the C
Programming-Language, which the CRC of a Buffers (buf) calculates the
Length n
/*---------------------------------------------------------------------------*/
static int calc_crc(char *buf, int n)
{
static int crc_table[] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0xcc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
int crc;
crc = 0;
while (--n >= 0)
crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *buf++) & 0xff];
return crc;
}
/*---------------------------------------------------------------------------*/
Saving of the Table requires 512 Bytes. If the EPROM in the TNC should
be too full for the saving of this Table, so it can be constructed as
follows for the Runtime:
/*---------------------------------------------------------------------------*/
unsigned short Table[256];
const int Rest[8] = { 0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801,
0xF001, 0xA001 };
main()
{
int i, j;
unsigned short value;
for (i = 0; i < 256; i++) {
value = 0;
for (j = 0; j < 8; j++)
if (i & (1 << j))
value ^= Rest[j];
Table[i] = value;
}
}
/*---------------------------------------------------------------------------*/
If this Algorithm is to be coded in Assembler, so it requires distinctly
less space than the Saving of the Table itself.
The Theory is to be found again in [2].
5. Implementation
Previously this Protocol has been implemented in the following Systems:
- WAMPES
- SMACK, Version 1.3. This Software has been developed further by Jan
Schiefer, DL5UE, from TNC2-KISS-Implementation written by K3MC. It will
be installed especially in the TNCs of the WAMPES-NODES DB0ID (Digipeater
Stuttgart) and DB0SAO (Mailbox Stuttgart) there it contains also,
individual WAMPES-specific adaptations. - In the KISS of the NORD><LINK-
Firmware, from TheFirmware Version 2.4 - For the TCP/IP-Software NOS it
gives from Thommy Osterried, DL9SAU, a 'a rundown', of the NOS developed
from the SMACK-capabilities.
7. Outlook
A desirable Implementation of this Protocol would be especially, a Packet-
Driver from the 'Packet driver specification' [3]. With it would be given an
uninhibited possibility for all existing NET- and NOS-Versions without
alteration of the Source Codes. But also every other Packet-Radio-Software,
that installs the KISS-TNCs could profit from the Error Protection of the
CRC.
This Protocol Description has a preliminary Character. The Authors
(dl5ue@db0sao, dk5sg@db0sao) are thankful for Improvement recommendations,
Advice on Error or other Comments.
(*) WAMPES = Wrttemberg Amateurraadio Multi-Protocol-Experimental-Software.
A software packet under UNIX, that implements multiple Protocols from
AX.25-, TCP/IP and NET/ROM-Protocol Families and, will be installed
mainly in the Stuttgart Area, as Net Nodes. Compare [4].
Literature
[1] Karn, Phil, KA9Q; Proposed "Raw" TNC Functional Spec, 6.8.1986;
published in the USENET-News;
[2] Rhner, Michael, DC4OX; Was ist CRC?; distributed in the Packet-Radio
Mailbox-Net, May 1988
[3] FTP Software, Inc.; PC/TCP Version 1.09 Packet Driver Specification;
Wakefield, MA 1989
[4] Schiefer, Jan, DL5UE; WAMPES - Weiterentwicklung; Vortrags-Skriptum
des 5. berregionalen Packet-Radio-Treffens; Frankfurt 1989;
Translation by G0KIU
Ritorna a Software Radioamatoriale by
IW3FQG