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 R”hner, 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, x4380, 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>