From f6404dd0ea73d7c96069200fbff959b1a8cdba86 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Fri, 31 May 2024 17:25:50 +0200 Subject: [PATCH] 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. --- impl/src/config.h | 2 +- impl/src/layer1/packet_mod.c | 9 +------ impl/src/layer1/packet_mod.h | 1 - impl/src/layer1/rx.c | 31 +++++++++--------------- impl/src/layer1/rx.h | 3 +-- impl/src/main.c | 22 +++++++++++++++-- impl/test/layer1/test_loopback.c | 41 ++++++++++++++++++++++---------- impl/test/layer1/test_rx_file.c | 12 +++++++++- 8 files changed, 74 insertions(+), 47 deletions(-) diff --git a/impl/src/config.h b/impl/src/config.h index d72ac55..752a768 100644 --- a/impl/src/config.h +++ b/impl/src/config.h @@ -16,7 +16,7 @@ #define PAYLOAD_CHANNEL_CODE LIQUID_FEC_CONV_V27P34 #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 PAYLOAD_CRC_SCHEME LIQUID_CRC_16 diff --git a/impl/src/layer1/packet_mod.c b/impl/src/layer1/packet_mod.c index a371ce3..c916d26 100644 --- a/impl/src/layer1/packet_mod.c +++ b/impl/src/layer1/packet_mod.c @@ -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); ctx->length = length; - ctx->raw_data_crc = crc_generate_key(PAYLOAD_CRC_SCHEME, (unsigned char *)data, length); ctx->raw_data_len = length; 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). - uint8_t header[5]; + uint8_t header[2]; // set length header[0] = (ctx->raw_data_len >> 8) & 0x07; header[0] |= ctx->modcod << 3; 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. diff --git a/impl/src/layer1/packet_mod.h b/impl/src/layer1/packet_mod.h index 3720c0d..cc7457a 100644 --- a/impl/src/layer1/packet_mod.h +++ b/impl/src/layer1/packet_mod.h @@ -30,7 +30,6 @@ typedef struct modem hdr_modem; fec hdr_fec; - uint16_t raw_data_crc; uint16_t raw_data_len; uint8_t modcod; diff --git a/impl/src/layer1/rx.c b/impl/src/layer1/rx.c index 0776d78..f938bbd 100644 --- a/impl/src/layer1/rx.c +++ b/impl/src/layer1/rx.c @@ -20,7 +20,7 @@ #define SYMBOL_BUFFER_SIZE 16384 -#define HEADER_SIZE_BYTES 5 // including CRC +#define HEADER_SIZE_BYTES 2 #define FREQ_EST_L 24 #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; } - // 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_crc = ((uint16_t)header[2] << 8) | header[3]; rx->modcod = header[0] >> 3; // 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, "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, "======================"); //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)); 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); + 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 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'; //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); - } else { - rx->callback(RX_EVT_CHECKSUM_ERROR, rx, payload, rx->payload_len_bytes); - } + rx->callback(RX_EVT_PACKET_RECEIVED, rx, payload, rx->payload_len_bytes); modem_destroy(rx->payload_demod); rx->state = RX_STATE_ACQUISITION; diff --git a/impl/src/layer1/rx.h b/impl/src/layer1/rx.h index 7b315b6..44ea3d7 100644 --- a/impl/src/layer1/rx.h +++ b/impl/src/layer1/rx.h @@ -20,7 +20,7 @@ typedef enum { RX_EVT_PACKET_RECEIVED, RX_EVT_PREAMBLE_FOUND, RX_EVT_HEADER_ERROR, - RX_EVT_CHECKSUM_ERROR, + RX_EVT_DECODE_FAILED, RX_EVT_PACKET_DEBUG_INFO_COMPLETE, } rx_evt_t; @@ -69,7 +69,6 @@ typedef struct layer1_rx_s // Information from the decoded header uint16_t payload_len_symbols; uint16_t payload_len_bytes; - uint16_t payload_crc; uint16_t payload_len_enc_bytes; modcod_t modcod; diff --git a/impl/src/main.c b/impl/src/main.c index 1f6b1d4..e044966 100644 --- a/impl/src/main.c +++ b/impl/src/main.c @@ -116,7 +116,7 @@ void cb_rx(rx_evt_t evt, const struct layer1_rx_s *rx, uint8_t *packet_data, siz 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_INFO, "=== FAILED PAYLOAD ==="); //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); - 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) { LOG(LVL_ERR, "write: %s", strerror(errno)); } @@ -278,6 +286,16 @@ int main(int argc, char **argv) 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); RESULT_CHECK(layer1_tx_reset(&tx)); diff --git a/impl/test/layer1/test_loopback.c b/impl/test/layer1/test_loopback.c index 37c5cf1..72894e0 100644 --- a/impl/test/layer1/test_loopback.c +++ b/impl/test/layer1/test_loopback.c @@ -12,6 +12,7 @@ #include "logger.h" #include "utils.h" +#include "config.h" #define RESULT_CHECK(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; + unsigned int data_size; + 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_INFO, "=== FAILED PAYLOAD ==="); 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; 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); - hexdump(packet_data, packet_len < 64 ? packet_len : 64); + hexdump(packet_data, packet_len); 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; case RX_EVT_HEADER_ERROR: @@ -127,19 +139,24 @@ int main(void) RESULT_CHECK(layer1_tx_reset(&tx)); - uint8_t packetbuf1[] = "Hello World! 1234567890"; - size_t l = sizeof(packetbuf1); + uint8_t packetbuf1[64] = "Hello World! 1234567890"; + 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."; - l = sizeof(packetbuf2); + RESULT_CHECK(layer1_tx_add_packet_to_burst(&tx, packetbuf1, l + crc_size)); - 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)); @@ -150,7 +167,7 @@ int main(void) // ** Simulate channel effects ** 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); float complex whole_burst_ch[burst_len]; diff --git a/impl/test/layer1/test_rx_file.c b/impl/test/layer1/test_rx_file.c index 99ebe88..03b911c 100644 --- a/impl/test/layer1/test_rx_file.c +++ b/impl/test/layer1/test_rx_file.c @@ -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)rx; + unsigned int data_size; + 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_INFO, "=== FAILED PAYLOAD ==="); //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); //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++; break;