Damjan Marion | 2e5921b | 2021-11-28 22:57:15 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: Apache-2.0 |
| 2 | * Copyright(c) 2021 Cisco Systems, Inc. |
| 3 | */ |
| 4 | |
| 5 | #include <vppinfra/format.h> |
| 6 | #include <vppinfra/vector/test/test.h> |
| 7 | #include <vppinfra/vector/toeplitz.h> |
| 8 | |
| 9 | /* secret key and test cases taken from: |
| 10 | * https://docs.microsoft.com/en-us/windows-hardware/drivers/network/verifying-the-rss-hash-calculation |
| 11 | */ |
| 12 | |
| 13 | typedef struct |
| 14 | { |
| 15 | u32 sip, dip; |
| 16 | u16 sport, dport; |
| 17 | } __clib_packed ip4_key_t; |
| 18 | |
| 19 | typedef struct |
| 20 | { |
| 21 | ip4_key_t key; |
| 22 | u32 hash_2t, hash_4t; |
| 23 | } ip4_test_t; |
| 24 | |
| 25 | typedef struct |
| 26 | { |
| 27 | u16 sip[8], dip[8]; |
| 28 | u16 sport, dport; |
| 29 | } __clib_packed ip6_key_t; |
| 30 | |
| 31 | typedef struct |
| 32 | { |
| 33 | ip6_key_t key; |
| 34 | u32 hash_2t, hash_4t; |
| 35 | } ip6_test_t; |
| 36 | |
| 37 | #define N_IP4_TESTS 5 |
| 38 | #define N_IP6_TESTS 3 |
| 39 | #define N_LENGTH_TESTS 240 |
| 40 | |
| 41 | #ifndef CLIB_MARCH_VARIANT |
| 42 | #define _IP4(a, b, c, d) ((d) << 24 | (c) << 16 | (b) << 8 | (a)) |
| 43 | #define _IP6(a, b, c, d, e, f, g, h) \ |
| 44 | { \ |
| 45 | (u16) ((a) << 8) | (u8) ((a) >> 8), (u16) ((b) << 8) | (u8) ((b) >> 8), \ |
| 46 | (u16) ((c) << 8) | (u8) ((c) >> 8), (u16) ((d) << 8) | (u8) ((d) >> 8), \ |
| 47 | (u16) ((e) << 8) | (u8) ((e) >> 8), (u16) ((f) << 8) | (u8) ((f) >> 8), \ |
| 48 | (u16) ((g) << 8) | (u8) ((g) >> 8), (u16) ((h) << 8) | (u8) ((h) >> 8), \ |
| 49 | } |
| 50 | #define _PORT(a) ((a) >> 8 | (((a) &0xff) << 8)) |
| 51 | |
| 52 | const ip4_test_t ip4_tests[N_IP4_TESTS] = { |
| 53 | /* ipv4 tests */ |
| 54 | { |
| 55 | .key.sip = _IP4 (66, 9, 149, 187), |
| 56 | .key.dip = _IP4 (161, 142, 100, 80), |
| 57 | .key.sport = _PORT (2794), |
| 58 | .key.dport = _PORT (1766), |
| 59 | .hash_2t = 0x323e8fc2, |
| 60 | .hash_4t = 0x51ccc178, |
| 61 | }, |
| 62 | { |
| 63 | .key.sip = _IP4 (199, 92, 111, 2), |
| 64 | .key.dip = _IP4 (65, 69, 140, 83), |
| 65 | .key.sport = _PORT (14230), |
| 66 | .key.dport = _PORT (4739), |
| 67 | .hash_2t = 0xd718262a, |
| 68 | .hash_4t = 0xc626b0ea, |
| 69 | }, |
| 70 | { |
| 71 | .key.sip = _IP4 (24, 19, 198, 95), |
| 72 | .key.dip = _IP4 (12, 22, 207, 184), |
| 73 | .key.sport = _PORT (12898), |
| 74 | .key.dport = _PORT (38024), |
| 75 | .hash_2t = 0xd2d0a5de, |
| 76 | .hash_4t = 0x5c2b394a, |
| 77 | }, |
| 78 | { |
| 79 | .key.sip = _IP4 (38, 27, 205, 30), |
| 80 | .key.dip = _IP4 (209, 142, 163, 6), |
| 81 | .key.sport = _PORT (48228), |
| 82 | .key.dport = _PORT (2217), |
| 83 | .hash_2t = 0x82989176, |
| 84 | .hash_4t = 0xafc7327f, |
| 85 | }, |
| 86 | { |
| 87 | .key.sip = _IP4 (153, 39, 163, 191), |
| 88 | .key.dip = _IP4 (202, 188, 127, 2), |
| 89 | .key.sport = _PORT (44251), |
| 90 | .key.dport = _PORT (1303), |
| 91 | .hash_2t = 0x5d1809c5, |
| 92 | .hash_4t = 0x10e828a2, |
| 93 | } |
| 94 | }; |
| 95 | |
| 96 | const ip6_test_t ip6_tests[N_IP6_TESTS] = { |
| 97 | { |
| 98 | .key.sip = _IP6 (0x3ffe, 0x2501, 0x200, 0x1fff, 0, 0, 0, 7), |
| 99 | .key.dip = _IP6 (0x3ffe, 0x2501, 0x200, 3, 0, 0, 0, 1), |
| 100 | .key.sport = _PORT (2794), |
| 101 | .key.dport = _PORT (1766), |
| 102 | .hash_2t = 0x2cc18cd5, |
| 103 | .hash_4t = 0x40207d3d, |
| 104 | }, |
| 105 | { |
| 106 | .key.sip = _IP6 (0x3ffe, 0x501, 8, 0, 0x260, 0x97ff, 0xfe40, 0xefab), |
| 107 | .key.dip = _IP6 (0xff02, 0, 0, 0, 0, 0, 0, 1), |
| 108 | .key.sport = _PORT (14230), |
| 109 | .key.dport = _PORT (4739), |
| 110 | .hash_2t = 0x0f0c461c, |
| 111 | .hash_4t = 0xdde51bbf, |
| 112 | }, |
| 113 | { |
| 114 | .key.sip = _IP6 (0x3ffe, 0x1900, 0x4545, 3, 0x200, 0xf8ff, 0xfe21, 0x67cf), |
| 115 | .key.dip = _IP6 (0xfe80, 0, 0, 0, 0x200, 0xf8ff, 0xfe21, 0x67cf), |
| 116 | .key.sport = _PORT (44251), |
| 117 | .key.dport = _PORT (38024), |
| 118 | .hash_2t = 0x4b61e985, |
| 119 | .hash_4t = 0x02d1feef, |
| 120 | } |
| 121 | }; |
| 122 | |
| 123 | const u32 length_test_hashes[N_LENGTH_TESTS] = { |
| 124 | 0x00000000, 0x00000000, 0x2b6d12ad, 0x9de4446e, 0x061f00bf, 0xad7ed8f7, |
| 125 | 0x4bc7b068, 0x231fc545, 0xdbd97a33, 0xcdab29e7, 0x2d665c0c, 0x31e28ed7, |
| 126 | 0x14e19218, 0x5aa89f0f, 0xd47de07f, 0x355ec712, 0x7e1cbfc0, 0xf84de19d, |
| 127 | 0xbcf66bd3, 0x104086c6, 0x71900b34, 0xcd2f9819, 0xeae68ebb, 0x54d63b4c, |
| 128 | 0x5f865a2c, 0x9d6ded08, 0xe00b0912, 0x3fcf07a6, 0x3bd9ca93, 0x3f4f3bbb, |
| 129 | 0xd0b82624, 0xa28a08e1, 0xa585969f, 0x0c8f4a71, 0x5dce7bdd, 0x4fcf2a6d, |
| 130 | 0x91c89ae9, 0xbef8a24d, 0x8e3d30fe, 0xc8027848, 0xc1e7e513, 0xa12bd3d9, |
| 131 | 0x46700bb4, 0xc6339dab, 0x970805ad, 0xfcb50ac8, 0xc6db4f44, 0x792e2987, |
| 132 | 0xacfb7836, 0xa25ec529, 0x957d7beb, 0x6732809a, 0x891836ed, 0xeefb83b2, |
| 133 | 0xca96b40b, 0x93fd5abd, 0x9076f922, 0x59adb4eb, 0x9705aafb, 0x282719b1, |
| 134 | 0xdda9cb8a, 0x3f499131, 0x47491130, 0x30ef0759, 0xad1cf855, 0x428aa312, |
| 135 | 0x4200240a, 0x71a72857, 0x16b30c36, 0x10cca9a3, 0x166f091e, 0x30e00560, |
| 136 | 0x8acd20ba, 0xfa633d76, 0x0fe32eb7, 0xdcc0122f, 0x20aa8ab0, 0x62b2a9af, |
| 137 | 0x7a6c80a6, 0x27e87268, 0x95b797a8, 0x25d18ccd, 0x68a7fb00, 0xc54bcdad, |
| 138 | 0x3bd0e717, 0xf0df54c9, 0x780daadf, 0x7b435605, 0x150c1e10, 0x8a892e54, |
| 139 | 0x9d27cb25, 0xe23383a5, 0x57aac408, 0x83b8abf8, 0x560f33af, 0xd5cb3307, |
| 140 | 0x79ae8edc, 0x9b127665, 0x320f18bd, 0x385d636b, 0xbd1b2dbf, 0x97679888, |
| 141 | 0x738894a4, 0xeba2afb0, 0xfa7c2d50, 0xb6741aa1, 0x28922bba, 0x7783242b, |
| 142 | 0xa694cca2, 0xa32781c0, 0x696cd670, 0xa714d72f, 0xea34d35a, 0xc5aed81e, |
| 143 | 0x0438433a, 0xc1939ab2, 0xb51c123a, 0x121426b9, 0x1add93ba, 0x50c56b6a, |
| 144 | 0x7e90902a, 0xae3abd85, 0x2f7a0088, 0xb45cf6f9, 0x80070094, 0x8bd46467, |
| 145 | 0xdfd1b762, 0x0bb25856, 0x48eefe84, 0x0989dbb9, 0xfc32472b, 0x965fec6b, |
| 146 | 0x5a256bd0, 0x6df7127a, 0x7856d0d6, 0xedc82bd3, 0x1b563b96, 0xc73eace7, |
| 147 | 0xba4c0a93, 0xdfd6dd97, 0x923c41db, 0x14926ca6, 0x22e52ab1, 0x22852a66, |
| 148 | 0x79606b9c, 0xb0f22b23, 0xb46354ba, 0x9c3cd931, 0x03a92bd6, 0x84000834, |
| 149 | 0x5425df65, 0xf4dd3fc9, 0x391cc873, 0xa560b52e, 0x828037d9, 0x31323dd5, |
| 150 | 0x5c6e3147, 0x28e21f85, 0xa431eb51, 0xf468c4a3, 0x9bea1d2e, 0x43d9109c, |
| 151 | 0x5bb9b081, 0xe0825675, 0xc9c92591, 0xd29fc812, 0x03136bc9, 0x5e005a1f, |
| 152 | 0x6d821ed8, 0x3f0bfcc4, 0x24774162, 0x893bde94, 0x6475efea, 0x6711538e, |
| 153 | 0xc4755f6d, 0x9425ebe2, 0xacf471b4, 0xb947ab0c, 0x1f78c455, 0x372b3ed7, |
| 154 | 0xb3ec24d7, 0x18c4459f, 0xa8ff3695, 0xe4aa2b85, 0x8a52ad7e, 0xe05e8177, |
| 155 | 0x7aa348ed, 0x3e4ac6aa, 0x17dcf8a5, 0x93b933b0, 0x8f7413ec, 0xc77bfe61, |
| 156 | 0xfdb72874, 0x4370f138, 0xdf3462ad, 0xc8970a59, 0xb4a9fed8, 0xa2ddc39b, |
| 157 | 0xd61db62a, 0x95c5fc1b, 0x7b22e6e0, 0x1969702c, 0x7992aebb, 0x59d7c225, |
| 158 | 0x0e16db0b, 0x9f2afc21, 0x246cf66b, 0xb3d6569d, 0x29c532d7, 0xe155747a, |
| 159 | 0xe38d7872, 0xea704969, 0xb69095b0, 0x1b198efd, 0x55daab76, 0xa2a377b6, |
| 160 | 0xb31aa2fa, 0x48b73c41, 0xf0cc501a, 0x9c9ca831, 0x1b591b99, 0xb2d8d22f, |
| 161 | 0xab4b5f69, 0x4fe00e71, 0xdf5480bd, 0x982540d7, 0x7f34ea4f, 0xd7be66e1, |
| 162 | 0x9d2ab1ba, 0x1ba62e12, 0xee3fb36c, 0xf28d7c5a, 0x756311eb, 0xc68567f2, |
| 163 | 0x7b6ea177, 0xc398d9f3 |
| 164 | }; |
| 165 | |
| 166 | #else |
| 167 | extern const ip4_test_t ip4_tests[N_IP4_TESTS]; |
| 168 | extern const ip6_test_t ip6_tests[N_IP6_TESTS]; |
| 169 | extern const u32 length_test_hashes[N_LENGTH_TESTS]; |
| 170 | #endif |
| 171 | |
| 172 | __test_funct_fn u32 |
| 173 | wrapper (clib_toeplitz_hash_key_t *k, u8 *data, u32 n_bytes) |
| 174 | { |
| 175 | return clib_toeplitz_hash (k, data, n_bytes); |
| 176 | } |
| 177 | |
Damjan Marion | 88019c4 | 2021-12-15 10:17:04 +0000 | [diff] [blame] | 178 | __test_funct_fn void |
| 179 | wrapper_x4 (clib_toeplitz_hash_key_t *k, u8 *d0, u8 *d1, u8 *d2, u8 *d3, |
| 180 | u32 *h0, u32 *h1, u32 *h2, u32 *h3, u32 n_bytes) |
| 181 | { |
| 182 | clib_toeplitz_hash_x4 (k, d0, d1, d2, d3, h0, h1, h2, h3, n_bytes); |
| 183 | } |
| 184 | |
Damjan Marion | 2e5921b | 2021-11-28 22:57:15 +0100 | [diff] [blame] | 185 | static clib_error_t * |
| 186 | test_clib_toeplitz_hash (clib_error_t *err) |
| 187 | { |
| 188 | u32 r; |
| 189 | int n_key_copies, bigkey_len, bigdata_len; |
| 190 | u8 *bigkey, *bigdata; |
| 191 | clib_toeplitz_hash_key_t *k; |
| 192 | |
| 193 | k = clib_toeplitz_hash_key_init (0, 0); |
| 194 | |
| 195 | for (int i = 0; i < N_IP4_TESTS; i++) |
| 196 | { |
| 197 | r = wrapper (k, (u8 *) &ip4_tests[i].key, 8); |
| 198 | if (ip4_tests[i].hash_2t != r) |
| 199 | return clib_error_return (err, |
| 200 | "wrong IPv4 2 tuple hash for test %u, " |
| 201 | "calculated 0x%08x expected 0x%08x", |
| 202 | i, ip4_tests[i].hash_2t, r); |
| 203 | |
| 204 | r = wrapper (k, (u8 *) &ip4_tests[i].key, 12); |
| 205 | if (ip4_tests[i].hash_4t != r) |
| 206 | return clib_error_return (err, |
| 207 | "wrong IPv4 4 tuple hash for test %u, " |
| 208 | "calculated 0x%08x expected 0x%08x", |
| 209 | i, ip4_tests[i].hash_4t, r); |
| 210 | } |
| 211 | |
| 212 | for (int i = 0; i < N_IP6_TESTS; i++) |
| 213 | { |
| 214 | r = wrapper (k, (u8 *) &ip6_tests[i].key, 32); |
| 215 | if (ip6_tests[i].hash_2t != r) |
| 216 | return clib_error_return (err, |
| 217 | "wrong IPv6 2 tuple hash for test %u, " |
| 218 | "calculated 0x%08x expected 0x%08x", |
| 219 | i, ip6_tests[i].hash_2t, r); |
| 220 | |
| 221 | r = wrapper (k, (u8 *) &ip6_tests[i].key, 36); |
| 222 | if (ip6_tests[i].hash_4t != r) |
| 223 | return clib_error_return (err, |
| 224 | "wrong IPv6 4 tuple hash for test %u, " |
| 225 | "calculated 0x%08x expected 0x%08x", |
| 226 | i, ip6_tests[i].hash_4t, r); |
| 227 | } |
| 228 | |
| 229 | n_key_copies = 6; |
| 230 | bigkey_len = k->key_length * n_key_copies; |
| 231 | bigdata_len = bigkey_len - 4; |
Damjan Marion | 88019c4 | 2021-12-15 10:17:04 +0000 | [diff] [blame] | 232 | bigkey = test_mem_alloc_and_splat (k->key_length, n_key_copies, k->data); |
| 233 | bigdata = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0); |
Damjan Marion | 2e5921b | 2021-11-28 22:57:15 +0100 | [diff] [blame] | 234 | u32 key_len = k->key_length; |
| 235 | |
Damjan Marion | 2e5921b | 2021-11-28 22:57:15 +0100 | [diff] [blame] | 236 | clib_toeplitz_hash_key_free (k); |
| 237 | k = clib_toeplitz_hash_key_init (bigkey, n_key_copies * key_len); |
| 238 | |
| 239 | for (int i = 0; i < N_LENGTH_TESTS - 4; i++) |
| 240 | { |
| 241 | r = wrapper (k, bigdata, i); |
| 242 | if (length_test_hashes[i] != r) |
| 243 | { |
| 244 | err = clib_error_return (err, |
| 245 | "wrong length test hash for length %u, " |
| 246 | "calculated 0x%08x expected 0x%08x " |
| 247 | "xor 0x%08x", |
| 248 | i, r, length_test_hashes[i], |
| 249 | r ^ length_test_hashes[i]); |
| 250 | goto done; |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | done: |
| 255 | clib_toeplitz_hash_key_free (k); |
Damjan Marion | 88019c4 | 2021-12-15 10:17:04 +0000 | [diff] [blame] | 256 | test_mem_free (bigkey); |
| 257 | test_mem_free (bigdata); |
Damjan Marion | 2e5921b | 2021-11-28 22:57:15 +0100 | [diff] [blame] | 258 | return err; |
| 259 | } |
| 260 | |
| 261 | void __test_perf_fn |
| 262 | perftest_fixed_12byte (int fd, test_perf_t *tp) |
| 263 | { |
| 264 | u32 n = tp->n_ops; |
| 265 | u8 *data = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key); |
| 266 | u8 *res = test_mem_alloc (4 * n); |
| 267 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 268 | |
| 269 | test_perf_event_enable (fd); |
| 270 | for (int i = 0; i < n; i++) |
| 271 | ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 12, 12); |
| 272 | test_perf_event_disable (fd); |
| 273 | |
| 274 | clib_toeplitz_hash_key_free (k); |
| 275 | test_mem_free (data); |
| 276 | test_mem_free (res); |
| 277 | } |
| 278 | |
| 279 | void __test_perf_fn |
| 280 | perftest_fixed_36byte (int fd, test_perf_t *tp) |
| 281 | { |
| 282 | u32 n = tp->n_ops; |
| 283 | u8 *data = test_mem_alloc_and_splat (36, n, (void *) &ip6_tests[0].key); |
| 284 | u8 *res = test_mem_alloc (4 * n); |
| 285 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 286 | |
| 287 | test_perf_event_enable (fd); |
| 288 | for (int i = 0; i < n; i++) |
| 289 | ((u32 *) res)[i] = clib_toeplitz_hash (k, data + i * 36, 36); |
| 290 | test_perf_event_disable (fd); |
| 291 | |
| 292 | clib_toeplitz_hash_key_free (k); |
| 293 | test_mem_free (data); |
| 294 | test_mem_free (res); |
| 295 | } |
| 296 | |
| 297 | void __test_perf_fn |
| 298 | perftest_variable_size (int fd, test_perf_t *tp) |
| 299 | { |
| 300 | u32 key_len, n_keys, n = tp->n_ops; |
| 301 | u8 *key, *data = test_mem_alloc (n); |
| 302 | u32 *res = test_mem_alloc (sizeof (u32)); |
| 303 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 304 | |
| 305 | k = clib_toeplitz_hash_key_init (0, 0); |
| 306 | key_len = k->key_length; |
| 307 | n_keys = ((n + 4) / k->key_length) + 1; |
| 308 | key = test_mem_alloc_and_splat (n_keys, key_len, k->data); |
| 309 | clib_toeplitz_hash_key_free (k); |
| 310 | k = clib_toeplitz_hash_key_init (key, key_len * n_keys); |
| 311 | |
| 312 | test_perf_event_enable (fd); |
| 313 | res[0] = clib_toeplitz_hash (k, data, n); |
| 314 | test_perf_event_disable (fd); |
| 315 | |
| 316 | clib_toeplitz_hash_key_free (k); |
| 317 | test_mem_free (data); |
| 318 | test_mem_free (res); |
| 319 | test_mem_free (key); |
| 320 | } |
| 321 | |
| 322 | REGISTER_TEST (clib_toeplitz_hash) = { |
| 323 | .name = "clib_toeplitz_hash", |
| 324 | .fn = test_clib_toeplitz_hash, |
| 325 | .perf_tests = PERF_TESTS ({ .name = "fixed_12", |
| 326 | .op_name = "12B Tuple", |
| 327 | .n_ops = 1024, |
| 328 | .fn = perftest_fixed_12byte }, |
| 329 | { .name = "fixed_36", |
| 330 | .op_name = "36B Tuple", |
| 331 | .n_ops = 1024, |
| 332 | .fn = perftest_fixed_36byte }, |
| 333 | { .name = "variable_size", |
| 334 | .op_name = "Byte", |
| 335 | .n_ops = 16384, |
| 336 | .fn = perftest_variable_size }), |
| 337 | }; |
Damjan Marion | 88019c4 | 2021-12-15 10:17:04 +0000 | [diff] [blame] | 338 | |
| 339 | static clib_error_t * |
| 340 | test_clib_toeplitz_hash_x4 (clib_error_t *err) |
| 341 | { |
| 342 | u32 r[4]; |
| 343 | int n_key_copies, bigkey_len, bigdata_len; |
| 344 | u8 *bigkey, *bigdata0, *bigdata1, *bigdata2, *bigdata3; |
| 345 | clib_toeplitz_hash_key_t *k; |
| 346 | |
| 347 | k = clib_toeplitz_hash_key_init (0, 0); |
| 348 | |
| 349 | wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key, |
| 350 | (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1, |
| 351 | r + 2, r + 3, 8); |
| 352 | |
| 353 | if (ip4_tests[0].hash_2t != r[0] || ip4_tests[1].hash_2t != r[1] || |
| 354 | ip4_tests[2].hash_2t != r[2] || ip4_tests[3].hash_2t != r[3]) |
| 355 | return clib_error_return (err, |
| 356 | "wrong IPv4 2 tuple x4 hash " |
| 357 | "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } " |
| 358 | "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }", |
| 359 | ip4_tests[0].hash_2t, ip4_tests[1].hash_2t, |
| 360 | ip4_tests[2].hash_2t, ip4_tests[3].hash_2t, r[0], |
| 361 | r[1], r[2], r[3]); |
| 362 | |
| 363 | wrapper_x4 (k, (u8 *) &ip4_tests[0].key, (u8 *) &ip4_tests[1].key, |
| 364 | (u8 *) &ip4_tests[2].key, (u8 *) &ip4_tests[3].key, r, r + 1, |
| 365 | r + 2, r + 3, 12); |
| 366 | |
| 367 | if (ip4_tests[0].hash_4t != r[0] || ip4_tests[1].hash_4t != r[1] || |
| 368 | ip4_tests[2].hash_4t != r[2] || ip4_tests[3].hash_4t != r[3]) |
| 369 | return clib_error_return (err, |
| 370 | "wrong IPv4 4 tuple x4 hash " |
| 371 | "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } " |
| 372 | "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }", |
| 373 | ip4_tests[0].hash_4t, ip4_tests[1].hash_4t, |
| 374 | ip4_tests[2].hash_4t, ip4_tests[3].hash_4t, r[0], |
| 375 | r[1], r[2], r[3]); |
| 376 | |
| 377 | wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key, |
| 378 | (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1, |
| 379 | r + 2, r + 3, 32); |
| 380 | |
| 381 | if (ip6_tests[0].hash_2t != r[0] || ip6_tests[1].hash_2t != r[1] || |
| 382 | ip6_tests[2].hash_2t != r[2] || ip6_tests[0].hash_2t != r[3]) |
| 383 | return clib_error_return (err, |
| 384 | "wrong IPv6 2 tuple x4 hash " |
| 385 | "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } " |
| 386 | "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }", |
| 387 | ip6_tests[0].hash_2t, ip6_tests[1].hash_2t, |
| 388 | ip6_tests[2].hash_2t, ip6_tests[0].hash_2t, r[0], |
| 389 | r[1], r[2], r[3]); |
| 390 | |
| 391 | wrapper_x4 (k, (u8 *) &ip6_tests[0].key, (u8 *) &ip6_tests[1].key, |
| 392 | (u8 *) &ip6_tests[2].key, (u8 *) &ip6_tests[0].key, r, r + 1, |
| 393 | r + 2, r + 3, 36); |
| 394 | |
| 395 | if (ip6_tests[0].hash_4t != r[0] || ip6_tests[1].hash_4t != r[1] || |
| 396 | ip6_tests[2].hash_4t != r[2] || ip6_tests[0].hash_4t != r[3]) |
| 397 | return clib_error_return (err, |
| 398 | "wrong IPv6 4 tuple x4 hash " |
| 399 | "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x } " |
| 400 | "expected { 0x%08x, 0x%08x, 0x%08x, 0x%08x }", |
| 401 | ip6_tests[0].hash_4t, ip6_tests[1].hash_4t, |
| 402 | ip6_tests[2].hash_4t, ip6_tests[0].hash_4t, r[0], |
| 403 | r[1], r[2], r[3]); |
| 404 | |
| 405 | n_key_copies = 6; |
| 406 | bigkey_len = k->key_length * n_key_copies; |
| 407 | bigdata_len = bigkey_len - 4; |
| 408 | bigkey = test_mem_alloc_and_splat (k->key_length, n_key_copies, k->data); |
| 409 | bigdata0 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0); |
| 410 | bigdata1 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0); |
| 411 | bigdata2 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0); |
| 412 | bigdata3 = test_mem_alloc_and_fill_inc_u8 (bigdata_len, 0, 0); |
| 413 | u32 key_len = k->key_length; |
| 414 | |
| 415 | clib_toeplitz_hash_key_free (k); |
| 416 | k = clib_toeplitz_hash_key_init (bigkey, n_key_copies * key_len); |
| 417 | |
| 418 | for (int i = 0; i < N_LENGTH_TESTS - 4; i++) |
| 419 | { |
| 420 | wrapper_x4 (k, bigdata0, bigdata1, bigdata2, bigdata3, r, r + 1, r + 2, |
| 421 | r + 3, i); |
| 422 | if (length_test_hashes[i] != r[0] || length_test_hashes[i] != r[1] || |
| 423 | length_test_hashes[i] != r[2] || length_test_hashes[i] != r[3]) |
| 424 | { |
| 425 | err = clib_error_return ( |
| 426 | err, |
| 427 | "wrong length test hash x4 for length %u, " |
| 428 | "calculated { 0x%08x, 0x%08x, 0x%08x, 0x%08x }, expected 0x%08x", |
| 429 | i, r[0], r[1], r[2], r[3], length_test_hashes[i]); |
| 430 | goto done; |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | done: |
| 435 | clib_toeplitz_hash_key_free (k); |
| 436 | test_mem_free (bigkey); |
| 437 | test_mem_free (bigdata0); |
| 438 | test_mem_free (bigdata1); |
| 439 | test_mem_free (bigdata2); |
| 440 | test_mem_free (bigdata3); |
| 441 | return err; |
| 442 | } |
| 443 | |
| 444 | void __test_perf_fn |
| 445 | perftest_fixed_12byte_x4 (int fd, test_perf_t *tp) |
| 446 | { |
| 447 | u32 n = tp->n_ops / 4; |
| 448 | u8 *d0 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[0].key); |
| 449 | u8 *d1 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[1].key); |
| 450 | u8 *d2 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[2].key); |
| 451 | u8 *d3 = test_mem_alloc_and_splat (12, n, (void *) &ip4_tests[3].key); |
| 452 | u32 *h0 = test_mem_alloc (4 * n); |
| 453 | u32 *h1 = test_mem_alloc (4 * n); |
| 454 | u32 *h2 = test_mem_alloc (4 * n); |
| 455 | u32 *h3 = test_mem_alloc (4 * n); |
| 456 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 457 | |
| 458 | test_perf_event_enable (fd); |
| 459 | for (int i = 0; i < n; i++) |
| 460 | clib_toeplitz_hash_x4 (k, d0 + i * 12, d1 + i * 12, d2 + i * 12, |
| 461 | d3 + i * 12, h0 + i, h1 + i, h2 + i, h3 + i, 12); |
| 462 | test_perf_event_disable (fd); |
| 463 | |
| 464 | clib_toeplitz_hash_key_free (k); |
| 465 | test_mem_free (d0); |
| 466 | test_mem_free (d1); |
| 467 | test_mem_free (d2); |
| 468 | test_mem_free (d3); |
| 469 | test_mem_free (h0); |
| 470 | test_mem_free (h1); |
| 471 | test_mem_free (h2); |
| 472 | test_mem_free (h3); |
| 473 | } |
| 474 | |
| 475 | void __test_perf_fn |
| 476 | perftest_fixed_36byte_x4 (int fd, test_perf_t *tp) |
| 477 | { |
| 478 | u32 n = tp->n_ops / 4; |
| 479 | u8 *d0 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[0].key); |
| 480 | u8 *d1 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[1].key); |
| 481 | u8 *d2 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[2].key); |
| 482 | u8 *d3 = test_mem_alloc_and_splat (36, n, (void *) &ip4_tests[3].key); |
| 483 | u32 *h0 = test_mem_alloc (4 * n); |
| 484 | u32 *h1 = test_mem_alloc (4 * n); |
| 485 | u32 *h2 = test_mem_alloc (4 * n); |
| 486 | u32 *h3 = test_mem_alloc (4 * n); |
| 487 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 488 | |
| 489 | test_perf_event_enable (fd); |
| 490 | for (int i = 0; i < n; i++) |
| 491 | clib_toeplitz_hash_x4 (k, d0 + i * 36, d1 + i * 36, d2 + i * 36, |
| 492 | d3 + i * 36, h0 + i, h1 + i, h2 + i, h3 + i, 36); |
| 493 | test_perf_event_disable (fd); |
| 494 | |
| 495 | clib_toeplitz_hash_key_free (k); |
| 496 | test_mem_free (d0); |
| 497 | test_mem_free (d1); |
| 498 | test_mem_free (d2); |
| 499 | test_mem_free (d3); |
| 500 | test_mem_free (h0); |
| 501 | test_mem_free (h1); |
| 502 | test_mem_free (h2); |
| 503 | test_mem_free (h3); |
| 504 | } |
| 505 | |
| 506 | void __test_perf_fn |
| 507 | perftest_variable_size_x4 (int fd, test_perf_t *tp) |
| 508 | { |
| 509 | u32 key_len, n_keys, n = tp->n_ops / 4; |
| 510 | u8 *key; |
| 511 | u8 *d0 = test_mem_alloc (n); |
| 512 | u8 *d1 = test_mem_alloc (n); |
| 513 | u8 *d2 = test_mem_alloc (n); |
| 514 | u8 *d3 = test_mem_alloc (n); |
| 515 | u32 *h0 = test_mem_alloc (sizeof (u32)); |
| 516 | u32 *h1 = test_mem_alloc (sizeof (u32)); |
| 517 | u32 *h2 = test_mem_alloc (sizeof (u32)); |
| 518 | u32 *h3 = test_mem_alloc (sizeof (u32)); |
| 519 | clib_toeplitz_hash_key_t *k = clib_toeplitz_hash_key_init (0, 0); |
| 520 | |
| 521 | k = clib_toeplitz_hash_key_init (0, 0); |
| 522 | key_len = k->key_length; |
| 523 | n_keys = ((n + 4) / k->key_length) + 1; |
| 524 | key = test_mem_alloc_and_splat (n_keys, key_len, k->data); |
| 525 | clib_toeplitz_hash_key_free (k); |
| 526 | k = clib_toeplitz_hash_key_init (key, key_len * n_keys); |
| 527 | |
| 528 | test_perf_event_enable (fd); |
| 529 | clib_toeplitz_hash_x4 (k, d0, d1, d2, d3, h0, h1, h2, h3, n); |
| 530 | test_perf_event_disable (fd); |
| 531 | |
| 532 | clib_toeplitz_hash_key_free (k); |
| 533 | test_mem_free (key); |
| 534 | test_mem_free (d0); |
| 535 | test_mem_free (d1); |
| 536 | test_mem_free (d2); |
| 537 | test_mem_free (d3); |
| 538 | test_mem_free (h0); |
| 539 | test_mem_free (h1); |
| 540 | test_mem_free (h2); |
| 541 | test_mem_free (h3); |
| 542 | } |
| 543 | |
| 544 | REGISTER_TEST (clib_toeplitz_hash_x4) = { |
| 545 | .name = "clib_toeplitz_hash_x4", |
| 546 | .fn = test_clib_toeplitz_hash_x4, |
| 547 | .perf_tests = PERF_TESTS ({ .name = "fixed_12", |
| 548 | .op_name = "12B Tuple", |
| 549 | .n_ops = 1024, |
| 550 | .fn = perftest_fixed_12byte_x4 }, |
| 551 | { .name = "fixed_36", |
| 552 | .op_name = "36B Tuple", |
| 553 | .n_ops = 1024, |
| 554 | .fn = perftest_fixed_36byte_x4 }, |
| 555 | { .name = "variable_size", |
| 556 | .op_name = "Byte", |
| 557 | .n_ops = 16384, |
| 558 | .fn = perftest_variable_size_x4 }), |
| 559 | }; |