diff --git a/src/suricata.c b/src/suricata.c index e9a377421d..4f27e43d76 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -901,6 +901,12 @@ static void PrintBuildInfo(void) #endif #if defined(__SSE2__) strlcat(features, "SSE_2 ", sizeof(features)); +#endif +#if defined(__ARM_FEATURE_SVE) + strlcat(features, "SVE ", sizeof(features)); +#endif +#if defined(__ARM_NEON) + strlcat(features, "NEON ", sizeof(features)); #endif if (strlen(features) == 0) { strlcat(features, "none", sizeof(features)); diff --git a/src/util-memcmp.c b/src/util-memcmp.c index 2fd62ce43a..f3a41d03c3 100644 --- a/src/util-memcmp.c +++ b/src/util-memcmp.c @@ -34,102 +34,134 @@ static int MemcmpTest01 (void) { - uint8_t a[] = "abcd"; - uint8_t b[] = "abcd"; + uint8_t a[] = "abcd abcd"; + uint8_t b[] = "abcd abcd"; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest02 (void) { - uint8_t a[] = "abcdabcdabcdabcd"; - uint8_t b[] = "abcdabcdabcdabcd"; + uint8_t a[] = "abcdabcdabcdabcd "; + uint8_t b[] = "abcdabcdabcdabcd "; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest03 (void) { - uint8_t a[] = "abcdabcd"; - uint8_t b[] = "abcdabcd"; + uint8_t a[] = "abcdabcd "; + uint8_t b[] = "abcdabcd "; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest04 (void) { - uint8_t a[] = "abcd"; - uint8_t b[] = "abcD"; + uint8_t a[] = "abcd "; + uint8_t b[] = "abcD "; - int r = SCMemcmp(a, b, sizeof(a)-1); - FAIL_IF(r != 1); + for (size_t x = 4; x < sizeof(a); x++) { + int r = SCMemcmp(a, b, x); + FAIL_IF(r != 1); + } PASS; } static int MemcmpTest05 (void) { - uint8_t a[] = "abcdabcdabcdabcd"; - uint8_t b[] = "abcDabcdabcdabcd"; + uint8_t a[] = "abcdabcdabcdabcd "; + uint8_t b[] = "abcDabcdabcdabcd "; + + for (size_t x = 4; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); PASS; } static int MemcmpTest06 (void) { - uint8_t a[] = "abcdabcd"; - uint8_t b[] = "abcDabcd"; + uint8_t a[] = "abcdabcd "; + uint8_t b[] = "abcDabcd "; + + for (size_t x = 4; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); PASS; } static int MemcmpTest07 (void) { - uint8_t a[] = "abcd"; - uint8_t b[] = "abcde"; + uint8_t a[] = " abcd"; + uint8_t b[] = " abcde"; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest08 (void) { - uint8_t a[] = "abcdabcdabcdabcd"; - uint8_t b[] = "abcdabcdabcdabcde"; + uint8_t a[] = " zyxvabcdabcdabcdabcd"; + uint8_t b[] = " zyxvabcdabcdabcdabcde"; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest09 (void) { - uint8_t a[] = "abcdabcd"; - uint8_t b[] = "abcdabcde"; + uint8_t a[] = " abcdabcd"; + uint8_t b[] = " abcdabcde"; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 0); PASS; } static int MemcmpTest10 (void) { - uint8_t a[] = "abcd"; - uint8_t b[] = "Zbcde"; + uint8_t a[] = "abcd "; + uint8_t b[] = "Zbcde "; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); PASS; } static int MemcmpTest11 (void) { - uint8_t a[] = "abcdabcdabcdabcd"; - uint8_t b[] = "Zbcdabcdabcdabcde"; + uint8_t a[] = "abcdabcdabcdabcd "; + uint8_t b[] = "Zbcdabcdabcdabcde "; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); + } - FAIL_IF(SCMemcmp(a, b, sizeof(a) - 1) != 1); PASS; } @@ -144,10 +176,13 @@ static int MemcmpTest12 (void) static int MemcmpTest13 (void) { - uint8_t a[] = "abcdefgh"; - uint8_t b[] = "AbCdEfGhIjK"; + uint8_t a[] = " abcdefgh"; + uint8_t b[] = " AbCdEfGhIjK"; + + for (size_t x = 1; x < sizeof(a); x++) { + FAIL_IF(SCMemcmpLowercase(a, b, sizeof(a) - 1) != 0); + } - FAIL_IF(SCMemcmpLowercase(a, b, sizeof(a) - 1) != 0); PASS; } @@ -311,25 +346,142 @@ struct MemcmpTest18Tests { const char *b; int result; } memcmp_tests18_tests[] = { - { "abcdefgh", "!bcdefgh", 1, }, - { "?bcdefgh", "!bcdefgh", 1, }, - { "!bcdefgh", "abcdefgh", 1, }, - { "!bcdefgh", "?bcdefgh", 1, }, - { "zbcdefgh", "bbcdefgh", 1, }, - - { "abcdefgh12345678", "!bcdefgh12345678", 1, }, - { "?bcdefgh12345678", "!bcdefgh12345678", 1, }, - { "!bcdefgh12345678", "abcdefgh12345678", 1, }, - { "!bcdefgh12345678", "?bcdefgh12345678", 1, }, - { "bbcdefgh12345678", "zbcdefgh12345678", 1, }, - - { "abcdefgh", "abcdefgh", 0, }, - { "abcdefgh", "Abcdefgh", 0, }, - { "abcdefgh12345678", "Abcdefgh12345678", 0, }, - - { NULL, NULL, 0 }, - - }; + { + "abcdefgh", + "!bcdefgh", + 1, + }, + { + "?bcdefgh", + "!bcdefgh", + 1, + }, + { + "!bcdefgh", + "abcdefgh", + 1, + }, + { + "!bcdefgh", + "?bcdefgh", + 1, + }, + { + "zbcdefgh", + "bbcdefgh", + 1, + }, + { + "abcdefgh ", + "!bcdefgh ", + 1, + }, + { + "?bcdefgh ", + "!bcdefgh ", + 1, + }, + { + "!bcdefgh ", + "abcdefgh ", + 1, + }, + { + "!bcdefgh ", + "?bcdefgh ", + 1, + }, + { + "zbcdefgh ", + "bbcdefgh ", + 1, + }, + + { + "abcdefgh12345678", + "!bcdefgh12345678", + 1, + }, + { + "?bcdefgh12345678", + "!bcdefgh12345678", + 1, + }, + { + "!bcdefgh12345678", + "abcdefgh12345678", + 1, + }, + { + "!bcdefgh12345678", + "?bcdefgh12345678", + 1, + }, + { + "bbcdefgh12345678", + "zbcdefgh12345678", + 1, + }, + + { + "abcdefgh", + "abcdefgh", + 0, + }, + { + "abcdefgh", + "Abcdefgh", + 0, + }, + { + "abcdefgh ", + "abcdefgh ", + 0, + }, + { + "abcdefgh ", + "Abcdefgh ", + 0, + }, + { + "abcdefgh12345678", + "Abcdefgh12345678", + 0, + }, + { + "abcdefgz12345678", + "AbcdefgZ12345678", + 0, + }, + { + "abcdefgz[@@45678aa", + "AbcdefgZ[@@45678AA", + 0, + }, + { + "abcdefgz12345678", + "abcdefgz12345678", + 0, + }, + { + "abcdefgz12345678", + "Xbcdefgz12345678", + 1, + }, + { + "abcdefgz12345678", + "abcdefgzX2345678", + 1, + }, + { + "abcdefgz12345678", + "abcdXfgz1234X678", + 1, + }, + + { NULL, NULL, 0 }, + +}; static int MemcmpTest18 (void) { diff --git a/src/util-memcmp.h b/src/util-memcmp.h index 3cd4befa85..ce98c5d1db 100644 --- a/src/util-memcmp.h +++ b/src/util-memcmp.h @@ -281,6 +281,94 @@ static inline int SCMemcmpLowercase(const void *s1, const void *s2, size_t len) return 0; } +#elif defined(__aarch64__) +#include + +#if defined(__ARM_FEATURE_SVE) +#include + +static inline int SCMemcmp(const void *s1, const void *s2, size_t len) +{ + uint64_t i = 0; + int vec_size = svcntb(); + svbool_t pg = svwhilelt_b8(i, len); + do { + svuint8_t b1 = svld1(pg, (uint8_t *)s1 + i); + svuint8_t b2 = svld1(pg, (uint8_t *)s2 + i); + svbool_t match = svcmpne(pg, b1, b2); + if (svptest_any(pg, match)) + return 1; + + i += vec_size; + pg = svwhilelt_b8(i, len); + } while (svptest_any(svptrue_b64(), pg)); + return 0; +} + +#else + +/* wrapper around memcmp to match the retvals of the SIMD implementations */ +#define SCMemcmp(a, b, c) ({ memcmp((a), (b), (c)) ? 1 : 0; }) + +#endif + +#define SCMEMCMP_BYTES 16 + +#define UPPER_LOW 0x41 /* "A" */ +#define UPPER_HIGH 0x5A /* "Z" */ +#define UPPER_DELTA 0x20 + +static inline int SCMemcmpLowercase(const void *s1, const void *s2, size_t len) +{ + size_t offset = 0; + uint8x16_t b1, mask1, mask2, delta, b3, equiv; + uint8x16_t b2, upper1, upper2; + uint64_t eqt, eqb; + + /* setup registers for upper to lower conversion */ + upper1 = vdupq_n_u8(UPPER_LOW); + upper2 = vdupq_n_u8(UPPER_HIGH); + delta = vdupq_n_u8(UPPER_DELTA); + + do { + if (likely(len - offset < SCMEMCMP_BYTES)) { + return MemcmpLowercase(s1, s2, len - offset); + } + + /* unaligned loading of the bytes to compare */ + b1 = vld1q_u8(s1); + b2 = vld1q_u8(s2); + + /* mark all chars bigger than upper1 */ + mask1 = vcgeq_u8(b2, upper1); + /* mark all chars lower than upper2 */ + mask2 = vcleq_u8(b2, upper2); + /* merge the two, leaving only those that are true in both */ + mask1 = vandq_u8(mask1, mask2); + + /* Generate only 0x20 which is the delta from a upper-case to lower-case */ + mask1 = vandq_u8(mask1, delta); + + /* add 0x20 to each upper case value */ + b3 = vaddq_u8(b2, mask1); + + /* do the actual compare */ + equiv = vceqq_u8(b1, b3); + + /* move the values to a GP */ + eqb = vgetq_lane_u64(vreinterpretq_u64_u8(equiv), 0); + eqt = vgetq_lane_u64(vreinterpretq_u64_u8(equiv), 1); + + if (!(~eqb == 0 && ~eqt == 0)) { + return 1; + } + offset += SCMEMCMP_BYTES; + s1 += SCMEMCMP_BYTES; + s2 += SCMEMCMP_BYTES; + } while (len > offset); + + return 0; +} #else /* No SIMD support, fall back to plain memcmp and a home grown lowercase one */