Хабрахабр

Надежность контрольной суммы CRC16

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <time.h> #define PACKET_LEN (7)
#define NUM_OF_CYCLES (100000) static unsigned char reverse_table[16] =
{ 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF
}; uint8_t reverse_bits(uint8_t byte)
{ // Reverse the top and bottom nibble then swap them. return (reverse_table[byte & 0b1111] << 4) | reverse_table[byte >> 4];
} uint16_t reverse_word(uint16_t word)
{ return ((reverse_bits(word & 0xFF) << 8) | reverse_bits(word >> 8));
} uint16_t crc16_common(uint8_t *data, uint8_t len, uint16_t poly, uint16_t init, uint16_t doXor, bool refIn, bool refOut)
} if (refOut) crc = reverse_word(crc); return (crc ^ doXor);
} uint16_t crc16_ccitt(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x1021, 0xFFFF, 0x0000, false, false);
} uint16_t crc16_bypass(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x8005, 0x0000, 0x0000, false, false);
} uint16_t crc16_xmodem(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x1021, 0x0000, 0x0000, false, false);
} uint16_t crc16_teledisk(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0xA097, 0x0000, 0x0000, false, false);
} uint16_t crc16_augccitt(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x1021, 0x1d0f, 0x0000, false, false);
} uint16_t crc16_cdma2000(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0xc867, 0xffff, 0x0000, false, false);
} uint16_t crc16_dds110(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x8005, 0x800d, 0x0000, false, false);
} uint16_t crc16_dect(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x0589, 0x0000, 0x0000, false, false);
} uint16_t crc16_en13757(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x3d65, 0x0000, 0xffff, false, false);
} uint16_t crc16_t10dif(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x8bb7, 0x0000, 0x0000, false, false);
} uint16_t crc16_cms(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x8005, 0xFFFF, 0x0000, false, false);
} uint16_t crc16_modbus(uint8_t *data, uint8_t len)
{ return crc16_common(data, len, 0x8005, 0xFFFF, 0x0000, true, true);
} bool compare_buf(uint8_t *buf1, uint8_t *buf2)
{ uint8_t x; for (x = 0; x < PACKET_LEN; x++) { if (buf1[x] != buf2[x]) return true; } return false;
} bool method_shuffle(uint8_t *buf)
{ uint8_t i, j; uint16_t rnd; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); for (i = 0; i < PACKET_LEN; i++) { for (j = 0; j < 10; j++) { rnd = (uint16_t)rand(); if (rnd % 7 == 0) buf[i] ^= (1 << (rnd % 8)); } } return compare_buf(buf, copy);
} bool method_bitshift(uint8_t *buf)
{ uint8_t x, i, j; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); x = (uint8_t)(rand() % PACKET_LEN) + 1; for (j = 0; j < x; j++) { i = (uint8_t)(rand() % PACKET_LEN); if (buf[i] == 0) buf[i] = 0x01; else buf[i] <<= 1; } return compare_buf(buf, copy);
} bool method_packetroll(uint8_t *buf)
{ uint8_t x, i, j; uint8_t temp; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); x = (uint8_t)(rand() % (PACKET_LEN - 1)) + 1; for (j = 0; j < x; j++) { temp = buf[0]; for (i = 0; i < PACKET_LEN - 1; i++) buf[i] = buf[i + 1]; buf[PACKET_LEN - 1] = temp; } return compare_buf(buf, copy);
} bool method_shiftright(uint8_t *buf)
{ uint8_t i; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); for (i = 0; i < PACKET_LEN - 1; i++) buf[i + 1] = buf[i]; buf[0] = 0xff; return compare_buf(buf, copy);
} bool method_shiftleft(uint8_t *buf)
{ uint8_t i; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); for (i = 0; i < PACKET_LEN - 1; i++) buf[i] = buf[i + 1]; buf[PACKET_LEN - 1] = 0xff; return compare_buf(buf, copy);
} bool method_zero(uint8_t *buf)
{ uint8_t x, i, j; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); x = (uint8_t)(rand() % PACKET_LEN) + 1; for (j = 0; j < x; j++) { i = (uint8_t)(rand() % PACKET_LEN); if (buf[i] != 0x00) buf[i] = 0x00; else buf[i] = 0xFF; } return compare_buf(buf, copy);
} bool method_one(uint8_t *buf)
{ uint8_t x, i, j; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); x = (uint8_t)(rand() % PACKET_LEN) + 1; for (j = 0; j < x; j++) { i = (uint8_t)(rand() % PACKET_LEN); if (buf[i] != 0xFF) buf[i] = 0xFF; else buf[i] = 0x00; } return compare_buf(buf, copy);
} bool method_injection(uint8_t *buf)
{ uint8_t x, i; uint8_t copy[PACKET_LEN]; memcpy(copy, buf, PACKET_LEN); x = (uint8_t)(rand() % PACKET_LEN); for (i = PACKET_LEN - 1; i > x; i--) { buf[i] = buf[i - 1]; } buf[x] = (uint8_t)rand(); return compare_buf(buf, copy);
} bool method_single(uint8_t *buf)
{ uint8_t x; x = (uint8_t)(rand() % (PACKET_LEN * 8)); buf[(uint8_t)(x / 8)] ^= (1 << (x % 8)); return true;
} typedef struct
{ uint16_t crc1; uint16_t crc2; uint32_t errors; uint16_t (*fn)(uint8_t *data, uint8_t len); char name[32];
} tCRC; typedef struct
{ bool (*fn)(uint8_t *buf); char name[32];
} tMethod; static tMethod methods[] =
{ {method_shuffle, "Shuffle"}, {method_bitshift, "Bit shift"}, {method_packetroll, "Roll packet"}, {method_shiftright, "Right shift"}, {method_shiftleft, "Left shift"}, {method_zero, "Fill zeros"}, {method_one, "Fill ones"}, {method_injection, "Byte injection"}, {method_single, "Single bit"}
}; static tCRC crcs[] =
{ {0, 0, 0, crc16_cms, "CMS"}, {0, 0, 0, crc16_ccitt, "CCITT"}, {0, 0, 0, crc16_augccitt, "AUG-CCITT"}, {0, 0, 0, crc16_bypass, "BYPASS"}, {0, 0, 0, crc16_cdma2000, "CDMA2000"}, {0, 0, 0, crc16_dds110, "DDS-110"}, {0, 0, 0, crc16_dect, "DECT-X"}, {0, 0, 0, crc16_en13757, "EN-13757"}, {0, 0, 0, crc16_modbus, "Modbus"}, {0, 0, 0, crc16_t10dif, "T10-DIF"}, {0, 0, 0, crc16_teledisk, "TELEDISK"}, {0, 0, 0, crc16_xmodem, "XMODEM"}
}; int main(int argc, char * argv[])
{ uint32_t num_of_cycle; uint32_t num_of_sums; uint8_t packet[PACKET_LEN]; uint8_t i; uint8_t m; //uint8_t buf[8] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; srand(time(NULL)); printf("------------------------- CRC16 comparison -------------------------\n"); num_of_sums = sizeof(crcs) / sizeof(tCRC); for (m = 0; m < sizeof(methods) / sizeof(tMethod); m++) { printf("\r%s:\n", methods[m].name); for (i = 0; i < num_of_sums; i++) { crcs[i].errors = 0; } for (num_of_cycle = 0; num_of_cycle < NUM_OF_CYCLES; num_of_cycle++) { for (i = 0; i < PACKET_LEN; i++) packet[i] = (uint8_t)rand(); for (i = 0; i < num_of_sums; i++) crcs[i].crc1 = crcs[i].fn(packet, PACKET_LEN); if (!methods[m].fn(packet)) continue; for (i = 0; i < num_of_sums; i++) { crcs[i].crc2 = crcs[i].fn(packet, PACKET_LEN); if (crcs[i].crc1 == crcs[i].crc2) crcs[i].errors++; } if (num_of_cycle % 1000 == 0) printf("\r%.2f%%", (float)num_of_cycle / NUM_OF_CYCLES * 100); } for (i = 0; i < num_of_sums; i++) printf("\r %20s: %10d\n", crcs[i].name, crcs[i].errors); } return 0;
}

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть