This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, master has been updated via 719ac4509920bad7d5c8d563426d21f2a0c9e80e (commit) via b1eadcb681dbe7a3d7db4d3ddb18528ebd15211b (commit) via ac851856893867331ab9f692a135a40677daa351 (commit) from 492390a79f20c7aaaf16f232fbd5ecf0d9b700e7 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 719ac4509920bad7d5c8d563426d21f2a0c9e80e Author: Petri Savolainen petri.savolainen@linaro.org Date: Mon Jun 11 14:57:51 2018 +0300
validation: hash: add generic CRC test cases
Added test cases for odp_hash_crc_gen64(). Test cases are defined for 32, 24 and 16 bit CRCs. Tests include various polynoms, init, output XOR and reflection values. Test data is "123456789" for most of the test cases, since that is used commonly as the CRC "check" data.
Used CRC names, parameters and check values are listed e.g. here: http://reveng.sourceforge.net/crc-catalogue
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/hash/hash.c b/test/validation/api/hash/hash.c index d3b01548..4edcb08a 100644 --- a/test/validation/api/hash/hash.c +++ b/test/validation/api/hash/hash.c @@ -9,6 +9,10 @@ #include <odp_api.h> #include <odp_cunit_common.h>
+/* Commonly used CRC check string */ +#define CHECK_STR "123456789" +#define CHECK_LEN 9 + #define CRC32C_INIT 0xffffffff #define CRC32C_XOR 0xffffffff #define CRC32_INIT 0xffffffff @@ -84,8 +88,7 @@ static const uint8_t test_data_11[] = "abcdefg";
static const uint8_t test_data_12[] = "The five boxing wizards jump quickly.";
-/* String of the common "check" value. */ -static const uint8_t test_data_13[] = "123456789"; +static const uint8_t test_data_13[] = CHECK_STR;
static const hash_test_vector_t crc32c_test_vector[] = { { .data = test_data_0, @@ -237,9 +240,421 @@ static void hash_test_crc32(void) } }
+/* + * Test various commonly used 32 bit CRCs. Used CRC names, parameters and + * check values can be found e.g. here: + * http://reveng.sourceforge.net/crc-catalogue + */ +static void hash_test_crc32_generic(void) +{ + uint64_t result_u64; + uint32_t result_u32, result; + int i, num; + odp_hash_crc_param_t crc_param; + + memset(&crc_param, 0, sizeof(odp_hash_crc_param_t)); + crc_param.width = 32; + crc_param.xor_out = 0; + + /* CRC-32 */ + crc_param.poly = 0x04c11db7; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + num = sizeof(crc32_test_vector) / sizeof(hash_test_vector_t); + + for (i = 0; i < num; i++) { + if (odp_hash_crc_gen64(crc32_test_vector[i].data, + crc32_test_vector[i].len, + CRC32_INIT, + &crc_param, &result_u64)) { + printf("CRC-32 not supported\n."); + break; + } + + result_u32 = CRC32_XOR ^ result_u64; + CU_ASSERT(result_u32 == crc32_test_vector[i].result.u32); + } + + /* CRC-32C */ + crc_param.poly = 0x1edc6f41; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + num = sizeof(crc32c_test_vector) / sizeof(hash_test_vector_t); + + for (i = 0; i < num; i++) { + if (odp_hash_crc_gen64(crc32c_test_vector[i].data, + crc32c_test_vector[i].len, + CRC32C_INIT, + &crc_param, &result_u64)) { + printf("CRC-32C not supported\n."); + break; + } + + result_u32 = CRC32C_XOR ^ result_u64; + CU_ASSERT(result_u32 == crc32c_test_vector[i].result.u32); + } + + /* CRC-32/AUTOSAR */ + crc_param.poly = 0xf4acfb13; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0x1697d06a; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0xffffffff ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/AUTOSAR not supported\n."); + } + + /* CRC-32/BZIP2 */ + crc_param.poly = 0x04c11db7; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xfc891918; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0xffffffff ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/BZIP2 not supported\n."); + } + + /* CRC-32D */ + crc_param.poly = 0xa833982b; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0x87315576; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0xffffffff ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32D not supported\n."); + } + + /* CRC-32/MPEG-2 */ + crc_param.poly = 0x04c11db7; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x0376e6e7; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/MPEG-2 not supported\n."); + } + + /* CRC-32/POSIX */ + crc_param.poly = 0x04c11db7; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x765e7680; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = 0xffffffff ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/POSIX not supported\n."); + } + + /* CRC-32/POSIX - with XOR parameter used */ + crc_param.xor_out = 0xffffffff; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/POSIX (with XOR) not supported\n."); + } + + crc_param.xor_out = 0; + + /* CRC-32Q */ + crc_param.poly = 0x814141ab; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x3010bf7f; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32Q not supported\n."); + } + + /* CRC-32/JAMCRC */ + crc_param.poly = 0x04c11db7; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0x340bc6d9; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/JAMCRC not supported\n."); + } + + /* CRC-32/XFER */ + crc_param.poly = 0x000000af; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xbd0be338; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-32/XFER not supported\n."); + } +} + +static void hash_test_crc24_generic(void) +{ + uint64_t result_u64; + uint32_t result_u32, result; + odp_hash_crc_param_t crc_param; + + memset(&crc_param, 0, sizeof(odp_hash_crc_param_t)); + crc_param.width = 24; + crc_param.xor_out = 0; + + /* CRC-24 */ + crc_param.poly = 0x864cfb; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x21cf02; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xb704ce, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24 not supported\n."); + } + + /* CRC-24/FLEXRAY-A */ + crc_param.poly = 0x5d6dcb; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x7979bd; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xfedcba, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/FLEXRAY-A not supported\n."); + } + + /* CRC-24/FLEXRAY-B */ + result = 0x1f23b8; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xabcdef, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/FLEXRAY-B not supported\n."); + } + + /* CRC-24/INTERLAKEN */ + crc_param.poly = 0x328b63; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xb4f3e6; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffffff, + &crc_param, &result_u64) == 0) { + result_u32 = 0xffffff ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/INTERLAKEN not supported\n."); + } + + /* CRC-24/LTE-A */ + crc_param.poly = 0x864cfb; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xcde703; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/LTE-A not supported\n."); + } + + /* CRC-24/LTE-B */ + crc_param.poly = 0x800063; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x23ef52; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/LTE-B not supported\n."); + } + + /* CRC-24/BLE */ + crc_param.poly = 0x00065b; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0xc25a56; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x555555, + &crc_param, &result_u64) == 0) { + result_u32 = 0x0 ^ result_u64; + CU_ASSERT(result_u32 == result); + } else { + printf("CRC-24/BLE not supported\n."); + } +} + +static void hash_test_crc16_generic(void) +{ + uint64_t result_u64; + uint16_t result_u16, result; + odp_hash_crc_param_t crc_param; + + memset(&crc_param, 0, sizeof(odp_hash_crc_param_t)); + crc_param.width = 16; + crc_param.xor_out = 0; + + /* CRC-16/ARC */ + crc_param.poly = 0x8005; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0xbb3d; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u16 = 0x0 ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/ARC not supported\n."); + } + + /* CRC-16/UMTS */ + crc_param.poly = 0x8005; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xfee8; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u16 = 0x0 ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/UMTS not supported\n."); + } + + /* CRC-16/CDMA2000 */ + crc_param.poly = 0xc867; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0x4c06; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffff, + &crc_param, &result_u64) == 0) { + result_u16 = 0x0 ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/CDMA2000 not supported\n."); + } + + /* CRC-16/GENIBUS */ + crc_param.poly = 0x1021; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xd64e; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffff, + &crc_param, &result_u64) == 0) { + result_u16 = 0xffff ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/GENIBUS not supported\n."); + } + + /* CRC-16/T10-DIF */ + crc_param.poly = 0x8bb7; + crc_param.reflect_in = 0; + crc_param.reflect_out = 0; + result = 0xd0db; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u16 = 0x0 ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/T10-DIF not supported\n."); + } + + /* CRC-16/USB */ + crc_param.poly = 0x8005; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0xb4c8; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffff, + &crc_param, &result_u64) == 0) { + result_u16 = 0xffff ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/USB not supported\n."); + } + + /* CRC-16/CCITT */ + crc_param.poly = 0x1021; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0x2189; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0x0, + &crc_param, &result_u64) == 0) { + result_u16 = 0x0 ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/CCITT not supported\n."); + } + + /* CRC-16/X-25 */ + crc_param.poly = 0x1021; + crc_param.reflect_in = 1; + crc_param.reflect_out = 1; + result = 0x906e; + + if (odp_hash_crc_gen64(CHECK_STR, CHECK_LEN, 0xffff, + &crc_param, &result_u64) == 0) { + result_u16 = 0xffff ^ result_u64; + CU_ASSERT(result_u16 == result); + } else { + printf("CRC-16/X25 not supported\n."); + } +} + odp_testinfo_t hash_suite[] = { ODP_TEST_INFO(hash_test_crc32c), ODP_TEST_INFO(hash_test_crc32), + ODP_TEST_INFO(hash_test_crc32_generic), + ODP_TEST_INFO(hash_test_crc24_generic), + ODP_TEST_INFO(hash_test_crc16_generic), ODP_TEST_INFO_NULL, };
commit b1eadcb681dbe7a3d7db4d3ddb18528ebd15211b Author: Petri Savolainen petri.savolainen@linaro.org Date: Mon Jun 11 15:41:18 2018 +0300
validation: hash: change result to 32 bit word
Set results as 32 bit words. Also polynom is represented as 32 bit word in cpu endian. Majority of references list CRC values in this form (as an exception RFC 7143 lists those in big endian).
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/hash/hash.c b/test/validation/api/hash/hash.c index 080201af..d3b01548 100644 --- a/test/validation/api/hash/hash.c +++ b/test/validation/api/hash/hash.c @@ -90,118 +90,118 @@ static const uint8_t test_data_13[] = "123456789"; static const hash_test_vector_t crc32c_test_vector[] = { { .data = test_data_0, .len = sizeof(test_data_0), - .result.u8 = {0xaa, 0x36, 0x91, 0x8a} + .result.u32 = 0x8a9136aa }, { .data = test_data_1, .len = sizeof(test_data_1), - .result.u8 = {0x43, 0xab, 0xa8, 0x62} + .result.u32 = 0x62a8ab43 }, { .data = test_data_2, .len = sizeof(test_data_2), - .result.u8 = {0x4e, 0x79, 0xdd, 0x46} + .result.u32 = 0x46dd794e }, { .data = test_data_3, .len = sizeof(test_data_3), - .result.u8 = {0x5c, 0xdb, 0x3f, 0x11} + .result.u32 = 0x113fdb5c }, { .data = test_data_4, .len = sizeof(test_data_4), - .result.u8 = {0x56, 0x3a, 0x96, 0xd9} + .result.u32 = 0xd9963a56 }, { .data = test_data_5, .len = sizeof(test_data_5) - 1, - .result.u8 = {0x31, 0x0a, 0xc8, 0x92} + .result.u32 = 0x92c80a31 }, { .data = test_data_6, .len = sizeof(test_data_6) - 1, - .result.u8 = {0xb7, 0x21, 0x94, 0x0a} + .result.u32 = 0x0a9421b7 }, { .data = test_data_7, .len = sizeof(test_data_7) - 1, - .result.u8 = {0xb3, 0x97, 0x00, 0x19} + .result.u32 = 0x190097b3 }, { .data = test_data_8, .len = sizeof(test_data_8) - 1, - .result.u8 = {0x30, 0x43, 0xd0, 0xc1} + .result.u32 = 0xc1d04330 }, { .data = test_data_9, .len = sizeof(test_data_9) - 1, - .result.u8 = {0x36, 0x29, 0xa2, 0xe2} + .result.u32 = 0xe2a22936 }, { .data = test_data_10, .len = sizeof(test_data_10) - 1, - .result.u8 = {0xb7, 0x3f, 0x4b, 0x36} + .result.u32 = 0x364b3fb7 }, { .data = test_data_11, .len = sizeof(test_data_11) - 1, - .result.u8 = {0x41, 0xf4, 0x27, 0xe6} + .result.u32 = 0xe627f441 }, { .data = test_data_12, .len = sizeof(test_data_12) - 1, - .result.u8 = {0x9a, 0x05, 0xd3, 0xde} + .result.u32 = 0xded3059a }, { .data = test_data_13, .len = sizeof(test_data_13) - 1, - .result.u8 = {0x83, 0x92, 0x06, 0xe3} + .result.u32 = 0xe3069283 } };
static const hash_test_vector_t crc32_test_vector[] = { { .data = test_data_0, .len = sizeof(test_data_0), - .result.u8 = {0xad, 0x55, 0x0a, 0x19} + .result.u32 = 0x190a55ad }, { .data = test_data_1, .len = sizeof(test_data_1), - .result.u8 = {0x0b, 0xab, 0x6c, 0xff} + .result.u32 = 0xff6cab0b }, { .data = test_data_2, .len = sizeof(test_data_2), - .result.u8 = {0x8a, 0x7e, 0x26, 0x91} + .result.u32 = 0x91267e8a }, { .data = test_data_3, .len = sizeof(test_data_3), - .result.u8 = {0x72, 0xef, 0xb0, 0x9a} + .result.u32 = 0x9ab0ef72 }, { .data = test_data_4, .len = sizeof(test_data_4), - .result.u8 = {0x12, 0x74, 0xe1, 0x51} + .result.u32 = 0x51e17412 }, { .data = test_data_5, .len = sizeof(test_data_5) - 1, - .result.u8 = {0x11, 0xcd, 0x82, 0xed} + .result.u32 = 0xed82cd11 }, { .data = test_data_6, .len = sizeof(test_data_6) - 1, - .result.u8 = {0x50, 0x2a, 0xef, 0xae} + .result.u32 = 0xaeef2a50 }, { .data = test_data_7, .len = sizeof(test_data_7) - 1, - .result.u8 = {0xe9, 0x25, 0x90, 0x51} + .result.u32 = 0x519025e9 }, { .data = test_data_8, .len = sizeof(test_data_8) - 1, - .result.u8 = {0x43, 0xbe, 0xb7, 0xe8} + .result.u32 = 0xe8b7be43 }, { .data = test_data_9, .len = sizeof(test_data_9) - 1, - .result.u8 = {0x6d, 0x48, 0x83, 0x9e} + .result.u32 = 0x9e83486d }, { .data = test_data_10, .len = sizeof(test_data_10) - 1, - .result.u8 = {0xc2, 0x41, 0x24, 0x35} + .result.u32 = 0x352441c2 }, { .data = test_data_11, .len = sizeof(test_data_11) - 1, - .result.u8 = {0xa6, 0x6a, 0x2a, 0x31} + .result.u32 = 0x312a6aa6 }, { .data = test_data_12, .len = sizeof(test_data_12) - 1, - .result.u8 = {0xcd, 0x2a, 0x91, 0xde} + .result.u32 = 0xde912acd }, { .data = test_data_13, .len = sizeof(test_data_13) - 1, - .result.u8 = {0x26, 0x39, 0xf4, 0xcb} + .result.u32 = 0xcbf43926 } };
commit ac851856893867331ab9f692a135a40677daa351 Author: Petri Savolainen petri.savolainen@linaro.org Date: Mon Jun 11 14:41:54 2018 +0300
linux-gen: hash: generic crc implementation
Added implementation of odp_hash_crc_gen64(). CRC widths of 32, 24 and 16 bits are supported. Only symmetric reflection setting (in/out: false/false or true/true) is supported.
Currently, 24 bit width with reflection does not work and is marked as not supported.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 1e617cc3..4d2ea9c4 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -163,6 +163,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_fdserver.c \ odp_hash_crc32.c \ odp_hash_crc32c.c \ + odp_hash_crc_gen.c \ odp_impl.c \ odp_init.c \ odp_ipsec.c \ diff --git a/platform/linux-generic/include/odp_init_internal.h b/platform/linux-generic/include/odp_init_internal.h index 3619d777..f585ceff 100644 --- a/platform/linux-generic/include/odp_init_internal.h +++ b/platform/linux-generic/include/odp_init_internal.h @@ -83,6 +83,8 @@ int _odp_ipsec_events_term_global(void);
int _odp_cpu_cycles_init_global(void);
+int _odp_hash_init_global(void); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_hash_crc_gen.c b/platform/linux-generic/odp_hash_crc_gen.c new file mode 100644 index 00000000..1ea6d8cd --- /dev/null +++ b/platform/linux-generic/odp_hash_crc_gen.c @@ -0,0 +1,222 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <string.h> + +#include <odp/api/hash.h> +#include <odp/api/hints.h> +#include <odp/api/rwlock.h> + +#include <odp_debug_internal.h> +#include <odp_init_internal.h> + +typedef struct crc_table_t { + uint32_t crc[256]; + uint32_t width; + uint32_t poly; + int reflect; + odp_rwlock_t rwlock; + +} crc_table_t; + +static crc_table_t crc_table; + +int _odp_hash_init_global(void) +{ + memset(&crc_table, 0, sizeof(crc_table_t)); + + odp_rwlock_init(&crc_table.rwlock); + + return 0; +} + +/* Reflect bits in a byte */ +static inline uint8_t reflect_u8(uint8_t byte) +{ + uint8_t u8[8]; + + u8[0] = (byte & (0x1 << 7)) >> 7; + u8[1] = (byte & (0x1 << 6)) >> 5; + u8[2] = (byte & (0x1 << 5)) >> 3; + u8[3] = (byte & (0x1 << 4)) >> 1; + + u8[4] = (byte & (0x1 << 3)) << 1; + u8[5] = (byte & (0x1 << 2)) << 3; + u8[6] = (byte & (0x1 << 1)) << 5; + u8[7] = (byte & 0x1) << 7; + + return u8[0] | u8[1] | u8[2] | u8[3] | u8[4] | u8[5] | u8[6] | u8[7]; +} + +/* Reflect 32 bits */ +static inline uint32_t reflect_u32(uint32_t u32) +{ + uint8_t u8[4]; + + u8[0] = reflect_u8((u32 & 0xff000000) >> 24); + u8[1] = reflect_u8((u32 & 0x00ff0000) >> 16); + u8[2] = reflect_u8((u32 & 0x0000ff00) >> 8); + u8[3] = reflect_u8(u32 & 0xff); + + return (u8[3] << 24) | (u8[2] << 16) | (u8[1] << 8) | u8[0]; +} + +/* Reflect 24 bits */ +static inline uint32_t reflect_u24(uint32_t u32) +{ + uint8_t u8[4]; + + u8[0] = reflect_u8((u32 & 0xff0000) >> 16); + u8[1] = reflect_u8((u32 & 0x00ff00) >> 8); + u8[2] = reflect_u8(u32 & 0xff); + + return (u8[2] << 16) | (u8[1] << 8) | u8[0]; +} + +/* Reflect 16 bits */ +static inline uint32_t reflect_u16(uint32_t u32) +{ + uint8_t u8[4]; + + u8[0] = reflect_u8((u32 & 0xff00) >> 8); + u8[1] = reflect_u8(u32 & 0xff); + + return (u8[1] << 8) | u8[0]; +} + +/* Generate table for a 32/24/16 bit CRCs. + * + * Based on an example in RFC 1952. + */ +static inline void crc_table_gen(uint32_t poly, int reflect, int width) +{ + uint32_t i, crc, bit, shift, msb, mask; + + crc_table.width = width; + crc_table.poly = poly; + crc_table.reflect = reflect; + + shift = width - 8; + mask = 0xffffffff >> (32 - width); + msb = 0x1 << (width - 1); + + if (reflect) { + if (width == 32) + poly = reflect_u32(poly); + else if (width == 24) + poly = reflect_u24(poly); + else + poly = reflect_u16(poly); + } + + for (i = 0; i < 256; i++) { + if (reflect) { + crc = i; + + for (bit = 0; bit < 8; bit++) { + if (crc & 0x1) + crc = poly ^ (crc >> 1); + else + crc = crc >> 1; + } + } else { + crc = i << shift; + + for (bit = 0; bit < 8; bit++) { + if (crc & msb) + crc = poly ^ (crc << 1); + else + crc = crc << 1; + } + } + + crc_table.crc[i] = crc & mask; + } +} + +static inline uint32_t crc_calc(const uint8_t *data, uint32_t data_len, + uint32_t init_val, int reflect, int width) +{ + uint32_t i, crc, shift; + uint8_t byte; + uint32_t mask; + + shift = width - 8; + mask = 0xffffffff >> (32 - width); + + crc = init_val; + + for (i = 0; i < data_len; i++) { + byte = data[i]; + + if (reflect) { + crc = crc_table.crc[(crc ^ byte) & 0xff] ^ (crc >> 8); + } else { + crc = crc_table.crc[(crc >> shift) ^ byte] ^ (crc << 8); + crc = crc & mask; + } + } + + return crc; +} + +int odp_hash_crc_gen64(const void *data_ptr, uint32_t data_len, + uint64_t init_val, odp_hash_crc_param_t *crc_param, + uint64_t *crc_out) +{ + uint32_t crc; + int update_table; + uint32_t poly = crc_param->poly; + uint32_t width = crc_param->width; + int reflect = crc_param->reflect_in; + + if (odp_unlikely(crc_param->reflect_in != crc_param->reflect_out)) { + ODP_ERR("Odd reflection setting not supported.\n"); + return -1; + } + + if (odp_unlikely(width != 32 && width != 24 && width != 16)) { + ODP_ERR("CRC width %" PRIu32 " bits not supported.\n", width); + return -1; + } + + /* TODO: fix implementation of 24 bit CRC with reflection */ + if (odp_unlikely(width == 24 && reflect)) { + ODP_ERR("24 bit CRC with reflection not supported.\n"); + return -1; + } + + odp_rwlock_read_lock(&crc_table.rwlock); + + update_table = (crc_table.width != width) || + (crc_table.poly != poly) || + (crc_table.reflect != reflect); + + /* Generate CRC table if not yet generated. */ + if (odp_unlikely(update_table)) { + odp_rwlock_read_unlock(&crc_table.rwlock); + odp_rwlock_write_lock(&crc_table.rwlock); + + crc_table_gen(poly, reflect, width); + } + + crc = crc_calc(data_ptr, data_len, init_val, reflect, width); + + if (odp_unlikely(update_table)) + odp_rwlock_write_unlock(&crc_table.rwlock); + else + odp_rwlock_read_unlock(&crc_table.rwlock); + + if (crc_param->xor_out) + crc = crc ^ (uint32_t)crc_param->xor_out; + + *crc_out = crc; + + return 0; +} diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index b2b75f12..61f99e4d 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -22,6 +22,7 @@ enum init_stage { LIBCONFIG_INIT, CPUMASK_INIT, CPU_CYCLES_INIT, + HASH_INIT, TIME_INIT, SYSINFO_INIT, ISHM_INIT, @@ -174,6 +175,8 @@ static int term_global(enum init_stage stage) } /* Fall through */
+ case HASH_INIT: + /* Fall through */ case CPU_CYCLES_INIT: /* Fall through */ case CPUMASK_INIT: @@ -233,6 +236,12 @@ int odp_init_global(odp_instance_t *instance, } stage = CPU_CYCLES_INIT;
+ if (_odp_hash_init_global()) { + ODP_ERR("ODP hash init failed.\n"); + goto init_failed; + } + stage = HASH_INIT; + if (odp_time_init_global()) { ODP_ERR("ODP time init failed.\n"); goto init_failed;
-----------------------------------------------------------------------
Summary of changes: platform/linux-generic/Makefile.am | 1 + platform/linux-generic/include/odp_init_internal.h | 2 + platform/linux-generic/odp_hash_crc_gen.c | 222 ++++++++++ platform/linux-generic/odp_init.c | 9 + test/validation/api/hash/hash.c | 475 +++++++++++++++++++-- 5 files changed, 679 insertions(+), 30 deletions(-) create mode 100644 platform/linux-generic/odp_hash_crc_gen.c
hooks/post-receive