Move payload CRC to layer 2

Layer 1 only does decoding of the FEC, but the CRC check for data integrity is
done in layer 2 now.
This commit is contained in:
Thomas Kolb 2024-05-31 17:25:50 +02:00
parent 0e8e049e0a
commit f6404dd0ea
8 changed files with 74 additions and 47 deletions

View file

@ -16,7 +16,7 @@
#define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34 #define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34
#define PAYLOAD_MODULATION LIQUID_MODEM_QAM16 #define PAYLOAD_MODULATION LIQUID_MODEM_QAM16
#define HEADER_CHANNEL_CODE LIQUID_FEC_HAMMING84 #define HEADER_CHANNEL_CODE LIQUID_FEC_HAMMING128
#define HEADER_MODULATION LIQUID_MODEM_QPSK #define HEADER_MODULATION LIQUID_MODEM_QPSK
#define PAYLOAD_CRC_SCHEME LIQUID_CRC_16 #define PAYLOAD_CRC_SCHEME LIQUID_CRC_16

View file

@ -81,7 +81,6 @@ result_t packet_mod_set_data(packet_mod_ctx_t *ctx, const unsigned char *data, s
memcpy(ctx->pkt_bytes, data, length); memcpy(ctx->pkt_bytes, data, length);
ctx->length = length; ctx->length = length;
ctx->raw_data_crc = crc_generate_key(PAYLOAD_CRC_SCHEME, (unsigned char *)data, length);
ctx->raw_data_len = length; ctx->raw_data_len = length;
ctx->state = DATA_RAW; ctx->state = DATA_RAW;
@ -173,18 +172,12 @@ result_t packet_mod_add_header(packet_mod_ctx_t *ctx)
} }
// build the header. All field are transferred in network byte order (big endian). // build the header. All field are transferred in network byte order (big endian).
uint8_t header[5]; uint8_t header[2];
// set length // set length
header[0] = (ctx->raw_data_len >> 8) & 0x07; header[0] = (ctx->raw_data_len >> 8) & 0x07;
header[0] |= ctx->modcod << 3; header[0] |= ctx->modcod << 3;
header[1] = (ctx->raw_data_len >> 0) & 0xFF; header[1] = (ctx->raw_data_len >> 0) & 0xFF;
// set raw data CRC
header[2] = (ctx->raw_data_crc >> 8) & 0xFF;
header[3] = (ctx->raw_data_crc >> 0) & 0xFF;
// append an 8-bit CRC to the header
crc_append_key(LIQUID_CRC_8, header, 4);
// note: the header is coded and modulated differently than the data. // note: the header is coded and modulated differently than the data.

View file

@ -30,7 +30,6 @@ typedef struct
modem hdr_modem; modem hdr_modem;
fec hdr_fec; fec hdr_fec;
uint16_t raw_data_crc;
uint16_t raw_data_len; uint16_t raw_data_len;
uint8_t modcod; uint8_t modcod;

View file

@ -20,7 +20,7 @@
#define SYMBOL_BUFFER_SIZE 16384 #define SYMBOL_BUFFER_SIZE 16384
#define HEADER_SIZE_BYTES 5 // including CRC #define HEADER_SIZE_BYTES 2
#define FREQ_EST_L 24 #define FREQ_EST_L 24
#define AGC_BW_ACQUISITION 5e-2f #define AGC_BW_ACQUISITION 5e-2f
@ -370,18 +370,7 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
break; break;
} }
// CRC check
if(crc_check_key(LIQUID_CRC_8, header, HEADER_SIZE_BYTES) != LIQUID_OK) {
uint8_t expected_crc = crc_generate_key(LIQUID_CRC_8, header, 4);
LOG(LVL_WARN, "@%zu: Header CRC check failed! Expected: 0x%02x, received: 0x%02x",
rx->sample_index, expected_crc, header[4]);
rx->state = RX_STATE_ACQUISITION;
rx->callback(RX_EVT_HEADER_ERROR, rx, NULL, 0);
break;
}
rx->payload_len_bytes = (((uint16_t)header[0] << 8) | header[1]) & 0x07FF; rx->payload_len_bytes = (((uint16_t)header[0] << 8) | header[1]) & 0x07FF;
rx->payload_crc = ((uint16_t)header[2] << 8) | header[3];
rx->modcod = header[0] >> 3; rx->modcod = header[0] >> 3;
// check the received information // check the received information
@ -417,7 +406,6 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
LOG(LVL_DUMP, "=== DECODED HEADER @%zu ===", rx->sample_index); LOG(LVL_DUMP, "=== DECODED HEADER @%zu ===", rx->sample_index);
LOG(LVL_DUMP, "Payload length: %u symbols, %u bytes encoded, %u bytes decoded", rx->payload_len_symbols, rx->payload_len_enc_bytes, rx->payload_len_bytes); LOG(LVL_DUMP, "Payload length: %u symbols, %u bytes encoded, %u bytes decoded", rx->payload_len_symbols, rx->payload_len_enc_bytes, rx->payload_len_bytes);
LOG(LVL_DUMP, "CRC16: 0x%04x", rx->payload_crc);
LOG(LVL_DUMP, "======================"); LOG(LVL_DUMP, "======================");
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/hdr.cpx"); //dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/hdr.cpx");
@ -461,22 +449,25 @@ result_t layer1_rx_process(layer1_rx_t *rx, const float complex *samples, size_t
payload_enc, 8, sizeof(payload_enc), &nsyms)); payload_enc, 8, sizeof(payload_enc), &nsyms));
fec payload_fec = modcod_create_fec(rx->modcod); fec payload_fec = modcod_create_fec(rx->modcod);
fec_decode(payload_fec, rx->payload_len_bytes, payload_enc, payload); result_t res = fec_decode(payload_fec, rx->payload_len_bytes, payload_enc, payload);
fec_destroy(payload_fec); fec_destroy(payload_fec);
if(res != LIQUID_OK) {
LOG(LVL_WARN, "@%zu: Payload decoding failed!", rx->sample_index);
rx->state = RX_STATE_ACQUISITION;
rx->callback(RX_EVT_DECODE_FAILED, rx, NULL, 0);
break;
}
// de-whiten the data // de-whiten the data
whitening_apply_in_place(payload, rx->payload_len_bytes); whitening_apply_in_place(payload, rx->payload_len_bytes);
int valid = crc_validate_message(PAYLOAD_CRC_SCHEME, payload, rx->payload_len_bytes, rx->payload_crc); // note: CRC is included in data and checked in layer 2
payload[rx->payload_len_bytes] = '\0'; payload[rx->payload_len_bytes] = '\0';
//dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx"); //dump_array_cf(symbols_cpx, symbol_counter, 1.0f, "/tmp/payload.cpx");
if(valid) {
rx->callback(RX_EVT_PACKET_RECEIVED, rx, payload, rx->payload_len_bytes); rx->callback(RX_EVT_PACKET_RECEIVED, rx, payload, rx->payload_len_bytes);
} else {
rx->callback(RX_EVT_CHECKSUM_ERROR, rx, payload, rx->payload_len_bytes);
}
modem_destroy(rx->payload_demod); modem_destroy(rx->payload_demod);
rx->state = RX_STATE_ACQUISITION; rx->state = RX_STATE_ACQUISITION;

View file

@ -20,7 +20,7 @@ typedef enum {
RX_EVT_PACKET_RECEIVED, RX_EVT_PACKET_RECEIVED,
RX_EVT_PREAMBLE_FOUND, RX_EVT_PREAMBLE_FOUND,
RX_EVT_HEADER_ERROR, RX_EVT_HEADER_ERROR,
RX_EVT_CHECKSUM_ERROR, RX_EVT_DECODE_FAILED,
RX_EVT_PACKET_DEBUG_INFO_COMPLETE, RX_EVT_PACKET_DEBUG_INFO_COMPLETE,
} rx_evt_t; } rx_evt_t;
@ -69,7 +69,6 @@ typedef struct layer1_rx_s
// Information from the decoded header // Information from the decoded header
uint16_t payload_len_symbols; uint16_t payload_len_symbols;
uint16_t payload_len_bytes; uint16_t payload_len_bytes;
uint16_t payload_crc;
uint16_t payload_len_enc_bytes; uint16_t payload_len_enc_bytes;
modcod_t modcod; modcod_t modcod;

View file

@ -116,7 +116,7 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz
switch(evt) switch(evt)
{ {
case RX_EVT_CHECKSUM_ERROR: case RX_EVT_DECODE_FAILED:
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len); //LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
//LOG(LVL_INFO, "=== FAILED PAYLOAD ==="); //LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
//hexdump(packet_data, packet_len); //hexdump(packet_data, packet_len);
@ -138,7 +138,15 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz
block_tx_for(TX_SWITCH_BACKOFF_END_OF_PACKET_MS); block_tx_for(TX_SWITCH_BACKOFF_END_OF_PACKET_MS);
ret = write(m_tunfd, packet_data, packet_len); unsigned int data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
// FIXME: move to layer 2
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
LOG(LVL_WARN, "payload CRC check failed!");
break;
}
ret = write(m_tunfd, packet_data, data_size);
if(ret < 0) { if(ret < 0) {
LOG(LVL_ERR, "write: %s", strerror(errno)); LOG(LVL_ERR, "write: %s", strerror(errno));
} }
@ -278,6 +286,16 @@ int main(int argc, char **argv)
break; break;
} }
/* append CRC to packet */
unsigned int crc_size = crc_sizeof_key(PAYLOAD_CRC_SCHEME);
if((unsigned)ret > sizeof(packetbuf) - crc_size) {
LOG(LVL_ERR, "Packet is too large to append CRC! %i bytes.", ret);
break;
}
crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf, ret);
LOG(LVL_DEBUG, "Transmitting packet with %d bytes.", ret); LOG(LVL_DEBUG, "Transmitting packet with %d bytes.", ret);
RESULT_CHECK(layer1_tx_reset(&tx)); RESULT_CHECK(layer1_tx_reset(&tx));

View file

@ -12,6 +12,7 @@
#include "logger.h" #include "logger.h"
#include "utils.h" #include "utils.h"
#include "config.h"
#define RESULT_CHECK(stmt) { \ #define RESULT_CHECK(stmt) { \
result_t res = stmt; \ result_t res = stmt; \
@ -77,9 +78,11 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
{ {
(void)rx; (void)rx;
unsigned int data_size;
switch(evt) switch(evt)
{ {
case RX_EVT_CHECKSUM_ERROR: case RX_EVT_DECODE_FAILED:
LOG(LVL_ERR, "Received a message of %zu bytes, but decoding failed.", packet_len); LOG(LVL_ERR, "Received a message of %zu bytes, but decoding failed.", packet_len);
LOG(LVL_INFO, "=== FAILED PAYLOAD ==="); LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
hexdump(packet_data, packet_len); hexdump(packet_data, packet_len);
@ -87,10 +90,19 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
break; break;
case RX_EVT_PACKET_RECEIVED: case RX_EVT_PACKET_RECEIVED:
LOG(LVL_INFO, "A message of %zu bytes was decoded successfully.", packet_len); data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
LOG(LVL_INFO, "=== DECODED PAYLOAD (%4zu bytes) ===", packet_len); LOG(LVL_INFO, "=== DECODED PAYLOAD (%4zu bytes) ===", packet_len);
hexdump(packet_data, packet_len < 64 ? packet_len : 64); hexdump(packet_data, packet_len);
LOG(LVL_INFO, "===================================="); LOG(LVL_INFO, "====================================");
// FIXME: move to layer 2
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
LOG(LVL_WARN, "payload CRC check failed!");
break;
}
LOG(LVL_INFO, "A message of %zu bytes was decoded successfully.", packet_len);
break; break;
case RX_EVT_HEADER_ERROR: case RX_EVT_HEADER_ERROR:
@ -127,19 +139,24 @@ int main(void)
RESULT_CHECK(layer1_tx_reset(&tx)); RESULT_CHECK(layer1_tx_reset(&tx));
uint8_t packetbuf1[] = "Hello World! 1234567890"; uint8_t packetbuf1[64] = "Hello World! 1234567890";
size_t l = sizeof(packetbuf1); size_t crc_size = crc_sizeof_key(PAYLOAD_CRC_SCHEME);
size_t l = strlen((char*)packetbuf1);
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l); crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf1, l);
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf1, l)); LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l + crc_size);
uint8_t packetbuf2[] = "This is just a test message. Just writing some stuff here to create a longer packet."; RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf1, l + crc_size));
l = sizeof(packetbuf2);
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l); uint8_t packetbuf2[128] = "This is just a test message. Just writing some stuff here to create a longer packet.";
l = strlen((char*)packetbuf2);
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf2, l)); crc_append_key(PAYLOAD_CRC_SCHEME, packetbuf2, l);
LOG(LVL_INFO, "Transmitting packet with %zd bytes.", l + crc_size);
RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf2, l + crc_size));
RESULT_CHECK(layer1_tx_finalize_burst(&tx)); RESULT_CHECK(layer1_tx_finalize_burst(&tx));
@ -150,7 +167,7 @@ int main(void)
// ** Simulate channel effects ** // ** Simulate channel effects **
channel_cccf ch = channel_cccf_create(); channel_cccf ch = channel_cccf_create();
channel_cccf_add_awgn(ch, -30, 10); channel_cccf_add_awgn(ch, -30, 30);
//channel_cccf_add_carrier_offset(ch, 0.05f, 1.23f); //channel_cccf_add_carrier_offset(ch, 0.05f, 1.23f);
float complex whole_burst_ch[burst_len]; float complex whole_burst_ch[burst_len];

View file

@ -64,9 +64,11 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
(void)packet_len; (void)packet_len;
(void)rx; (void)rx;
unsigned int data_size;
switch(evt) switch(evt)
{ {
case RX_EVT_CHECKSUM_ERROR: case RX_EVT_DECODE_FAILED:
//LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len); //LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len);
//LOG(LVL_INFO, "=== FAILED PAYLOAD ==="); //LOG(LVL_INFO, "=== FAILED PAYLOAD ===");
//hexdump(packet_data, packet_len); //hexdump(packet_data, packet_len);
@ -84,6 +86,14 @@ void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t pac
//hexdump(packet_data, packet_len < 64 ? packet_len : 64); //hexdump(packet_data, packet_len < 64 ? packet_len : 64);
//LOG(LVL_INFO, "===================================="); //LOG(LVL_INFO, "====================================");
data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME);
// FIXME: move to layer 2
if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) {
LOG(LVL_WARN, "payload CRC check failed!");
break;
}
m_rx_stats.successful_decodes++; m_rx_stats.successful_decodes++;
break; break;