]> git.proxmox.com Git - ceph.git/blob - ceph/src/isa-l/erasure_code/erasure_code_update_test.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / isa-l / erasure_code / erasure_code_update_test.c
1 /**********************************************************************
2 Copyright(c) 2011-2015 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h> // for memset, memcmp
33 #include "erasure_code.h"
34 #include "types.h"
35
36 #ifndef ALIGN_SIZE
37 # define ALIGN_SIZE 16
38 #endif
39
40 //By default, test multibinary version
41 #ifndef FUNCTION_UNDER_TEST
42 # define FUNCTION_UNDER_TEST ec_encode_data_update
43 # define REF_FUNCTION ec_encode_data
44 #endif
45
46 #define TEST_LEN 8192
47 #define TEST_SIZE (TEST_LEN/2)
48
49 #ifndef TEST_SOURCES
50 # define TEST_SOURCES 127
51 #endif
52 #ifndef RANDOMS
53 # define RANDOMS 200
54 #endif
55
56 #define MMAX TEST_SOURCES
57 #define KMAX TEST_SOURCES
58
59 #ifdef EC_ALIGNED_ADDR
60 // Define power of 2 range to check ptr, len alignment
61 # define PTR_ALIGN_CHK_B 0
62 # define LEN_ALIGN_CHK_B 0 // 0 for aligned only
63 #else
64 // Define power of 2 range to check ptr, len alignment
65 # define PTR_ALIGN_CHK_B ALIGN_SIZE
66 # define LEN_ALIGN_CHK_B ALIGN_SIZE // 0 for aligned only
67 #endif
68
69 #ifndef TEST_SEED
70 #define TEST_SEED 11
71 #endif
72
73 #define str(s) #s
74 #define xstr(s) str(s)
75
76 typedef unsigned char u8;
77
78 void dump(unsigned char *buf, int len)
79 {
80 int i;
81 for (i = 0; i < len;) {
82 printf(" %2x", 0xff & buf[i++]);
83 if (i % 32 == 0)
84 printf("\n");
85 }
86 printf("\n");
87 }
88
89 void dump_matrix(unsigned char **s, int k, int m)
90 {
91 int i, j;
92 for (i = 0; i < k; i++) {
93 for (j = 0; j < m; j++) {
94 printf(" %2x", s[i][j]);
95 }
96 printf("\n");
97 }
98 printf("\n");
99 }
100
101 void dump_u8xu8(unsigned char *s, int k, int m)
102 {
103 int i, j;
104 for (i = 0; i < k; i++) {
105 for (j = 0; j < m; j++) {
106 printf(" %2x", 0xff & s[j + (i * m)]);
107 }
108 printf("\n");
109 }
110 printf("\n");
111 }
112
113 // Generate Random errors
114 static void gen_err_list(unsigned char *src_err_list,
115 unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs, int k, int m)
116 {
117 int i, err;
118 int nerrs = 0, nsrcerrs = 0;
119
120 for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
121 err = 1 & rand();
122 src_in_err[i] = err;
123 if (err) {
124 src_err_list[nerrs++] = i;
125 if (i < k) {
126 nsrcerrs++;
127 }
128 }
129 }
130 if (nerrs == 0) { // should have at least one error
131 while ((err = (rand() % KMAX)) >= m) ;
132 src_err_list[nerrs++] = err;
133 src_in_err[err] = 1;
134 if (err < k)
135 nsrcerrs = 1;
136 }
137 *pnerrs = nerrs;
138 *pnsrcerrs = nsrcerrs;
139 return;
140 }
141
142 #define NO_INVERT_MATRIX -2
143 // Generate decode matrix from encode matrix
144 static int gf_gen_decode_matrix(unsigned char *encode_matrix,
145 unsigned char *decode_matrix,
146 unsigned char *invert_matrix,
147 unsigned int *decode_index,
148 unsigned char *src_err_list,
149 unsigned char *src_in_err,
150 int nerrs, int nsrcerrs, int k, int m)
151 {
152 int i, j, p;
153 int r;
154 unsigned char *backup, *b, s;
155 int incr = 0;
156
157 b = malloc(MMAX * KMAX);
158 backup = malloc(MMAX * KMAX);
159
160 if (b == NULL || backup == NULL) {
161 printf("Test failure! Error with malloc\n");
162 free(b);
163 free(backup);
164 return -1;
165 }
166 // Construct matrix b by removing error rows
167 for (i = 0, r = 0; i < k; i++, r++) {
168 while (src_in_err[r])
169 r++;
170 for (j = 0; j < k; j++) {
171 b[k * i + j] = encode_matrix[k * r + j];
172 backup[k * i + j] = encode_matrix[k * r + j];
173 }
174 decode_index[i] = r;
175 }
176 incr = 0;
177 while (gf_invert_matrix(b, invert_matrix, k) < 0) {
178 if (nerrs == (m - k)) {
179 free(b);
180 free(backup);
181 printf("BAD MATRIX\n");
182 return NO_INVERT_MATRIX;
183 }
184 incr++;
185 memcpy(b, backup, MMAX * KMAX);
186 for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
187 if (src_err_list[i] == (decode_index[k - 1] + incr)) {
188 // skip the erased parity line
189 incr++;
190 continue;
191 }
192 }
193 if (decode_index[k - 1] + incr >= m) {
194 free(b);
195 free(backup);
196 printf("BAD MATRIX\n");
197 return NO_INVERT_MATRIX;
198 }
199 decode_index[k - 1] += incr;
200 for (j = 0; j < k; j++)
201 b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
202
203 };
204
205 for (i = 0; i < nsrcerrs; i++) {
206 for (j = 0; j < k; j++) {
207 decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
208 }
209 }
210 /* src_err_list from encode_matrix * invert of b for parity decoding */
211 for (p = nsrcerrs; p < nerrs; p++) {
212 for (i = 0; i < k; i++) {
213 s = 0;
214 for (j = 0; j < k; j++)
215 s ^= gf_mul(invert_matrix[j * k + i],
216 encode_matrix[k * src_err_list[p] + j]);
217
218 decode_matrix[k * p + i] = s;
219 }
220 }
221 free(b);
222 free(backup);
223 return 0;
224 }
225
226 int main(int argc, char *argv[])
227 {
228 int re = 0;
229 int i, j, p, rtest, m, k;
230 int nerrs, nsrcerrs;
231 void *buf;
232 unsigned int decode_index[MMAX];
233 unsigned char *temp_buffs[TEST_SOURCES], *buffs[TEST_SOURCES];
234 unsigned char *update_buffs[TEST_SOURCES];
235 unsigned char *encode_matrix, *decode_matrix, *invert_matrix, *g_tbls;
236 unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
237 unsigned char *recov[TEST_SOURCES];
238
239 int rows, align, size;
240 unsigned char *efence_buffs[TEST_SOURCES];
241 unsigned char *efence_update_buffs[TEST_SOURCES];
242 unsigned int offset;
243 u8 *ubuffs[TEST_SOURCES];
244 u8 *update_ubuffs[TEST_SOURCES];
245 u8 *temp_ubuffs[TEST_SOURCES];
246
247 printf("test " xstr(FUNCTION_UNDER_TEST) ": %dx%d ", TEST_SOURCES, TEST_LEN);
248 srand(TEST_SEED);
249
250 // Allocate the arrays
251 for (i = 0; i < TEST_SOURCES; i++) {
252 if (posix_memalign(&buf, 64, TEST_LEN)) {
253 printf("alloc error: Fail");
254 return -1;
255 }
256 buffs[i] = buf;
257 }
258
259 for (i = 0; i < TEST_SOURCES; i++) {
260 if (posix_memalign(&buf, 64, TEST_LEN)) {
261 printf("alloc error: Fail");
262 return -1;
263 }
264 temp_buffs[i] = buf;
265 memset(temp_buffs[i], 0, TEST_LEN); // initialize the destination buffer to be zero for update function
266 }
267
268 for (i = 0; i < TEST_SOURCES; i++) {
269 if (posix_memalign(&buf, 64, TEST_LEN)) {
270 printf("alloc error: Fail");
271 return -1;
272 }
273 update_buffs[i] = buf;
274 memset(update_buffs[i], 0, TEST_LEN); // initialize the destination buffer to be zero for update function
275 }
276 // Test erasure code by encode and recovery
277
278 encode_matrix = malloc(MMAX * KMAX);
279 decode_matrix = malloc(MMAX * KMAX);
280 invert_matrix = malloc(MMAX * KMAX);
281 g_tbls = malloc(KMAX * TEST_SOURCES * 32);
282 if (encode_matrix == NULL || decode_matrix == NULL
283 || invert_matrix == NULL || g_tbls == NULL) {
284 printf("Test failure! Error with malloc\n");
285 return -1;
286 }
287 // Pick a first test
288 m = 15;
289 k = 10;
290 if (m > MMAX || k > KMAX)
291 return -1;
292
293 // Make random data
294 for (i = 0; i < k; i++) {
295 for (j = 0; j < TEST_LEN; j++) {
296 buffs[i][j] = rand();
297 update_buffs[i][j] = buffs[i][j];
298 }
299 }
300
301 // Generate encode matrix encode_matrix
302 // The matrix generated by gf_gen_rs_matrix
303 // is not always invertable.
304 gf_gen_rs_matrix(encode_matrix, m, k);
305
306 // Generate g_tbls from encode matrix encode_matrix
307 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
308
309 // Perform matrix dot_prod for EC encoding
310 // using g_tbls from encode matrix encode_matrix
311 REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
312 for (i = 0; i < k; i++) {
313 FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
314 &update_buffs[k]);
315 }
316 for (i = 0; i < m - k; i++) {
317 if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
318 printf("\nupdate_buffs%d :", i);
319 dump(update_buffs[k + i], 25);
320 printf("buffs%d :", i);
321 dump(buffs[k + i], 25);
322 return -1;
323 }
324 }
325
326 // Choose random buffers to be in erasure
327 memset(src_in_err, 0, TEST_SOURCES);
328 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
329
330 // Generate decode matrix
331 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
332 invert_matrix, decode_index, src_err_list, src_in_err,
333 nerrs, nsrcerrs, k, m);
334 if (re != 0) {
335 printf("Fail to gf_gen_decode_matrix\n");
336 return -1;
337 }
338 // Pack recovery array as list of valid sources
339 // Its order must be the same as the order
340 // to generate matrix b in gf_gen_decode_matrix
341 for (i = 0; i < k; i++) {
342 recov[i] = update_buffs[decode_index[i]];
343 }
344
345 // Recover data
346 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
347 REF_FUNCTION(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
348 for (i = 0; i < nerrs; i++) {
349
350 if (0 != memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], TEST_LEN)) {
351 printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
352 printf(" - erase list = ");
353 for (j = 0; j < nerrs; j++)
354 printf(" %d", src_err_list[j]);
355 printf(" - Index = ");
356 for (p = 0; p < k; p++)
357 printf(" %d", decode_index[p]);
358 printf("\nencode_matrix:\n");
359 dump_u8xu8((u8 *) encode_matrix, m, k);
360 printf("inv b:\n");
361 dump_u8xu8((u8 *) invert_matrix, k, k);
362 printf("\ndecode_matrix:\n");
363 dump_u8xu8((u8 *) decode_matrix, m, k);
364 printf("recov %d:", src_err_list[i]);
365 dump(temp_buffs[k + i], 25);
366 printf("orig :");
367 dump(update_buffs[src_err_list[i]], 25);
368 return -1;
369 }
370 }
371 putchar('.');
372
373 // Pick a first test
374 m = 7;
375 k = 5;
376 if (m > MMAX || k > KMAX)
377 return -1;
378
379 // Zero the destination buffer for update function
380 for (i = k; i < TEST_SOURCES; i++) {
381 memset(buffs[i], 0, TEST_LEN);
382 memset(update_buffs[i], 0, TEST_LEN);
383 }
384 // Make random data
385 for (i = 0; i < k; i++) {
386 for (j = 0; j < TEST_LEN; j++) {
387 buffs[i][j] = rand();
388 update_buffs[i][j] = buffs[i][j];
389 }
390 }
391
392 // The matrix generated by gf_gen_cauchy1_matrix
393 // is always invertable.
394 gf_gen_cauchy1_matrix(encode_matrix, m, k);
395
396 // Generate g_tbls from encode matrix encode_matrix
397 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
398
399 // Perform matrix dot_prod for EC encoding
400 // using g_tbls from encode matrix encode_matrix
401 REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
402 for (i = 0; i < k; i++) {
403 FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
404 &update_buffs[k]);
405 }
406 for (i = 0; i < m - k; i++) {
407 if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
408 printf("\nupdate_buffs%d :", i);
409 dump(update_buffs[k + i], 25);
410 printf("buffs%d :", i);
411 dump(buffs[k + i], 25);
412 return -1;
413 }
414 }
415
416 // Choose random buffers to be in erasure
417 memset(src_in_err, 0, TEST_SOURCES);
418 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
419
420 // Generate decode matrix
421 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
422 invert_matrix, decode_index, src_err_list, src_in_err,
423 nerrs, nsrcerrs, k, m);
424 if (re != 0) {
425 printf("Fail to gf_gen_decode_matrix\n");
426 return -1;
427 }
428 // Pack recovery array as list of valid sources
429 // Its order must be the same as the order
430 // to generate matrix b in gf_gen_decode_matrix
431 for (i = 0; i < k; i++) {
432 recov[i] = update_buffs[decode_index[i]];
433 }
434
435 // Recover data
436 for (i = 0; i < TEST_SOURCES; i++) {
437 memset(temp_buffs[i], 0, TEST_LEN);
438 }
439 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
440 for (i = 0; i < k; i++) {
441 FUNCTION_UNDER_TEST(TEST_LEN, k, nerrs, i, g_tbls, recov[i], &temp_buffs[k]);
442 }
443 for (i = 0; i < nerrs; i++) {
444
445 if (0 != memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], TEST_LEN)) {
446 printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
447 printf(" - erase list = ");
448 for (j = 0; j < nerrs; j++)
449 printf(" %d", src_err_list[j]);
450 printf(" - Index = ");
451 for (p = 0; p < k; p++)
452 printf(" %d", decode_index[p]);
453 printf("\nencode_matrix:\n");
454 dump_u8xu8((u8 *) encode_matrix, m, k);
455 printf("inv b:\n");
456 dump_u8xu8((u8 *) invert_matrix, k, k);
457 printf("\ndecode_matrix:\n");
458 dump_u8xu8((u8 *) decode_matrix, m, k);
459 printf("recov %d:", src_err_list[i]);
460 dump(temp_buffs[k + i], 25);
461 printf("orig :");
462 dump(update_buffs[src_err_list[i]], 25);
463 return -1;
464 }
465 }
466 putchar('.');
467
468 // Do more random tests
469 for (rtest = 0; rtest < RANDOMS; rtest++) {
470 while ((m = (rand() % MMAX)) < 2) ;
471 while ((k = (rand() % KMAX)) >= m || k < 1) ;
472
473 if (m > MMAX || k > KMAX)
474 continue;
475
476 // Zero the destination buffer for update function
477 for (i = k; i < TEST_SOURCES; i++) {
478 memset(buffs[i], 0, TEST_LEN);
479 memset(update_buffs[i], 0, TEST_LEN);
480 }
481 // Make random data
482 for (i = 0; i < k; i++) {
483 for (j = 0; j < TEST_LEN; j++) {
484 buffs[i][j] = rand();
485 update_buffs[i][j] = buffs[i][j];
486 }
487 }
488
489 // The matrix generated by gf_gen_cauchy1_matrix
490 // is always invertable.
491 gf_gen_cauchy1_matrix(encode_matrix, m, k);
492
493 // Make parity vects
494 // Generate g_tbls from encode matrix a
495 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
496 // Perform matrix dot_prod for EC encoding
497 // using g_tbls from encode matrix a
498 REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
499 for (i = 0; i < k; i++) {
500 FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
501 &update_buffs[k]);
502 }
503 for (i = 0; i < m - k; i++) {
504 if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
505 printf("\nupdate_buffs%d :", i);
506 dump(update_buffs[k + i], 25);
507 printf("buffs%d :", i);
508 dump(buffs[k + i], 25);
509 return -1;
510 }
511 }
512
513 // Random errors
514 memset(src_in_err, 0, TEST_SOURCES);
515 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
516
517 // Generate decode matrix
518 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
519 invert_matrix, decode_index, src_err_list,
520 src_in_err, nerrs, nsrcerrs, k, m);
521 if (re != 0) {
522 printf("Fail to gf_gen_decode_matrix\n");
523 return -1;
524 }
525 // Pack recovery array as list of valid sources
526 // Its order must be the same as the order
527 // to generate matrix b in gf_gen_decode_matrix
528 for (i = 0; i < k; i++) {
529 recov[i] = update_buffs[decode_index[i]];
530 }
531
532 // Recover data
533 for (i = 0; i < TEST_SOURCES; i++) {
534 memset(temp_buffs[i], 0, TEST_LEN);
535 }
536 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
537 for (i = 0; i < k; i++) {
538 FUNCTION_UNDER_TEST(TEST_LEN, k, nerrs, i, g_tbls, recov[i],
539 &temp_buffs[k]);
540 }
541
542 for (i = 0; i < nerrs; i++) {
543
544 if (0 !=
545 memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]],
546 TEST_LEN)) {
547 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
548 printf(" - erase list = ");
549 for (j = 0; j < nerrs; j++)
550 printf(" %d", src_err_list[j]);
551 printf(" - Index = ");
552 for (p = 0; p < k; p++)
553 printf(" %d", decode_index[p]);
554 printf("\nencode_matrix:\n");
555 dump_u8xu8((u8 *) encode_matrix, m, k);
556 printf("inv b:\n");
557 dump_u8xu8((u8 *) invert_matrix, k, k);
558 printf("\ndecode_matrix:\n");
559 dump_u8xu8((u8 *) decode_matrix, m, k);
560 printf("orig data:\n");
561 dump_matrix(update_buffs, m, 25);
562 printf("orig :");
563 dump(update_buffs[src_err_list[i]], 25);
564 printf("recov %d:", src_err_list[i]);
565 dump(temp_buffs[k + i], 25);
566 return -1;
567 }
568 }
569 putchar('.');
570 }
571
572 // Run tests at end of buffer for Electric Fence
573 k = 16;
574 align = (LEN_ALIGN_CHK_B != 0) ? 1 : ALIGN_SIZE;
575 if (k > KMAX)
576 return -1;
577
578 for (rows = 1; rows <= 16; rows++) {
579 m = k + rows;
580 if (m > MMAX)
581 return -1;
582
583 for (i = k; i < TEST_SOURCES; i++) {
584 memset(buffs[i], 0, TEST_LEN);
585 memset(update_buffs[i], 0, TEST_LEN);
586 }
587 // Make random data
588 for (i = 0; i < k; i++) {
589 for (j = 0; j < TEST_LEN; j++) {
590 buffs[i][j] = rand();
591 update_buffs[i][j] = buffs[i][j];
592 }
593 }
594
595 for (size = 0; size <= TEST_SIZE; size += align) {
596 for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
597 efence_buffs[i] = buffs[i] + TEST_LEN - size;
598 efence_update_buffs[i] = update_buffs[i] + TEST_LEN - size;
599 }
600 // Zero the destination buffer for update function
601 for (i = k; i < m; i++) {
602 memset(efence_buffs[i], 0, size);
603 memset(efence_update_buffs[i], 0, size);
604 }
605
606 // The matrix generated by gf_gen_cauchy1_matrix
607 // is always invertable.
608 gf_gen_cauchy1_matrix(encode_matrix, m, k);
609
610 // Make parity vects
611 // Generate g_tbls from encode matrix a
612 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
613 // Perform matrix dot_prod for EC encoding
614 // using g_tbls from encode matrix a
615 REF_FUNCTION(size, k, m - k, g_tbls, efence_buffs, &efence_buffs[k]);
616 for (i = 0; i < k; i++) {
617 FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls,
618 efence_update_buffs[i],
619 &efence_update_buffs[k]);
620 }
621 for (i = 0; i < m - k; i++) {
622 if (0 !=
623 memcmp(efence_update_buffs[k + i], efence_buffs[k + i],
624 size)) {
625 printf("\nefence_update_buffs%d :", i);
626 dump(efence_update_buffs[k + i], 25);
627 printf("efence_buffs%d :", i);
628 dump(efence_buffs[k + i], 25);
629 return -1;
630 }
631 }
632
633 // Random errors
634 memset(src_in_err, 0, TEST_SOURCES);
635 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
636
637 // Generate decode matrix
638 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
639 invert_matrix, decode_index, src_err_list,
640 src_in_err, nerrs, nsrcerrs, k, m);
641 if (re != 0) {
642 printf("Fail to gf_gen_decode_matrix\n");
643 return -1;
644 }
645 // Pack recovery array as list of valid sources
646 // Its order must be the same as the order
647 // to generate matrix b in gf_gen_decode_matrix
648 for (i = 0; i < k; i++) {
649 recov[i] = efence_update_buffs[decode_index[i]];
650 }
651
652 // Recover data
653 for (i = 0; i < TEST_SOURCES; i++) {
654 memset(temp_buffs[i], 0, TEST_LEN);
655 }
656 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
657 for (i = 0; i < k; i++) {
658 FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i],
659 &temp_buffs[k]);
660 }
661
662 for (i = 0; i < nerrs; i++) {
663
664 if (0 !=
665 memcmp(temp_buffs[k + i],
666 efence_update_buffs[src_err_list[i]], size)) {
667 printf("Efence: Fail error recovery (%d, %d, %d)\n", m,
668 k, nerrs);
669
670 printf("size = %d\n", size);
671
672 printf("Test erase list = ");
673 for (j = 0; j < nerrs; j++)
674 printf(" %d", src_err_list[j]);
675 printf(" - Index = ");
676 for (p = 0; p < k; p++)
677 printf(" %d", decode_index[p]);
678 printf("\nencode_matrix:\n");
679 dump_u8xu8((u8 *) encode_matrix, m, k);
680 printf("inv b:\n");
681 dump_u8xu8((u8 *) invert_matrix, k, k);
682 printf("\ndecode_matrix:\n");
683 dump_u8xu8((u8 *) decode_matrix, m, k);
684
685 printf("recov %d:", src_err_list[i]);
686 dump(temp_buffs[k + i], align);
687 printf("orig :");
688 dump(efence_update_buffs[src_err_list[i]], align);
689 return -1;
690 }
691 }
692 }
693 putchar('.');
694
695 }
696
697 // Test rand ptr alignment if available
698
699 for (rtest = 0; rtest < RANDOMS; rtest++) {
700 while ((m = (rand() % MMAX)) < 2) ;
701 while ((k = (rand() % KMAX)) >= m || k < 1) ;
702
703 if (m > MMAX || k > KMAX)
704 continue;
705
706 size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
707
708 offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
709 // Add random offsets
710 for (i = 0; i < m; i++) {
711 memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
712 memset(update_buffs[i], 0, TEST_LEN); // zero pad to check write-over
713 memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
714 ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
715 update_ubuffs[i] =
716 update_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
717 temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
718 }
719
720 // Zero the destination buffer for update function
721 for (i = k; i < m; i++) {
722 memset(ubuffs[i], 0, size);
723 memset(update_ubuffs[i], 0, size);
724 }
725 // Make random data
726 for (i = 0; i < k; i++) {
727 for (j = 0; j < size; j++) {
728 ubuffs[i][j] = rand();
729 update_ubuffs[i][j] = ubuffs[i][j];
730 }
731 }
732
733 // The matrix generated by gf_gen_cauchy1_matrix
734 // is always invertable.
735 gf_gen_cauchy1_matrix(encode_matrix, m, k);
736
737 // Make parity vects
738 // Generate g_tbls from encode matrix a
739 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
740 // Perform matrix dot_prod for EC encoding
741 // using g_tbls from encode matrix a
742 REF_FUNCTION(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
743 for (i = 0; i < k; i++) {
744 FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls, update_ubuffs[i],
745 &update_ubuffs[k]);
746 }
747 for (i = 0; i < m - k; i++) {
748 if (0 != memcmp(update_ubuffs[k + i], ubuffs[k + i], size)) {
749 printf("\nupdate_ubuffs%d :", i);
750 dump(update_ubuffs[k + i], 25);
751 printf("ubuffs%d :", i);
752 dump(ubuffs[k + i], 25);
753 return -1;
754 }
755 }
756
757 // Random errors
758 memset(src_in_err, 0, TEST_SOURCES);
759 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
760
761 // Generate decode matrix
762 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
763 invert_matrix, decode_index, src_err_list,
764 src_in_err, nerrs, nsrcerrs, k, m);
765 if (re != 0) {
766 printf("Fail to gf_gen_decode_matrix\n");
767 return -1;
768 }
769 // Pack recovery array as list of valid sources
770 // Its order must be the same as the order
771 // to generate matrix b in gf_gen_decode_matrix
772 for (i = 0; i < k; i++) {
773 recov[i] = update_ubuffs[decode_index[i]];
774 }
775
776 // Recover data
777 for (i = 0; i < m; i++) {
778 memset(temp_ubuffs[i], 0, size);
779 }
780 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
781 for (i = 0; i < k; i++) {
782 FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i],
783 &temp_ubuffs[k]);
784 }
785
786 for (i = 0; i < nerrs; i++) {
787
788 if (0 !=
789 memcmp(temp_ubuffs[k + i], update_ubuffs[src_err_list[i]], size)) {
790 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
791 printf(" - erase list = ");
792 for (j = 0; j < nerrs; j++)
793 printf(" %d", src_err_list[j]);
794 printf(" - Index = ");
795 for (p = 0; p < k; p++)
796 printf(" %d", decode_index[p]);
797 printf("\nencode_matrix:\n");
798 dump_u8xu8((unsigned char *)encode_matrix, m, k);
799 printf("inv b:\n");
800 dump_u8xu8((unsigned char *)invert_matrix, k, k);
801 printf("\ndecode_matrix:\n");
802 dump_u8xu8((unsigned char *)decode_matrix, m, k);
803 printf("orig data:\n");
804 dump_matrix(update_ubuffs, m, 25);
805 printf("orig :");
806 dump(update_ubuffs[src_err_list[i]], 25);
807 printf("recov %d:", src_err_list[i]);
808 dump(temp_ubuffs[k + i], 25);
809 return -1;
810 }
811 }
812
813 // Confirm that padding around dests is unchanged
814 memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
815
816 for (i = 0; i < m; i++) {
817
818 offset = update_ubuffs[i] - update_buffs[i];
819
820 if (memcmp(update_buffs[i], temp_buffs[0], offset)) {
821 printf("Fail rand ualign encode pad start\n");
822 return -1;
823 }
824 if (memcmp
825 (update_buffs[i] + offset + size, temp_buffs[0],
826 PTR_ALIGN_CHK_B - offset)) {
827 printf("Fail rand ualign encode pad end\n");
828 return -1;
829 }
830 }
831
832 for (i = 0; i < nerrs; i++) {
833
834 offset = temp_ubuffs[k + i] - temp_buffs[k + i];
835 if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
836 printf("Fail rand ualign decode pad start\n");
837 return -1;
838 }
839 if (memcmp
840 (temp_buffs[k + i] + offset + size, temp_buffs[0],
841 PTR_ALIGN_CHK_B - offset)) {
842 printf("Fail rand ualign decode pad end\n");
843 return -1;
844 }
845 }
846
847 putchar('.');
848 }
849
850 // Test size alignment
851
852 align = (LEN_ALIGN_CHK_B != 0) ? 13 : ALIGN_SIZE;
853
854 for (size = TEST_LEN; size >= 0; size -= align) {
855 while ((m = (rand() % MMAX)) < 2) ;
856 while ((k = (rand() % KMAX)) >= m || k < 1) ;
857
858 if (m > MMAX || k > KMAX)
859 continue;
860
861 // Zero the destination buffer for update function
862 for (i = k; i < TEST_SOURCES; i++) {
863 memset(buffs[i], 0, size);
864 memset(update_buffs[i], 0, size);
865 }
866 // Make random data
867 for (i = 0; i < k; i++) {
868 for (j = 0; j < size; j++) {
869 buffs[i][j] = rand();
870 update_buffs[i][j] = buffs[i][j];
871 }
872 }
873
874 // The matrix generated by gf_gen_cauchy1_matrix
875 // is always invertable.
876 gf_gen_cauchy1_matrix(encode_matrix, m, k);
877
878 // Make parity vects
879 // Generate g_tbls from encode matrix a
880 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
881 // Perform matrix dot_prod for EC encoding
882 // using g_tbls from encode matrix a
883 REF_FUNCTION(size, k, m - k, g_tbls, buffs, &buffs[k]);
884 for (i = 0; i < k; i++) {
885 FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls, update_buffs[i],
886 &update_buffs[k]);
887 }
888 for (i = 0; i < m - k; i++) {
889 if (0 != memcmp(update_buffs[k + i], buffs[k + i], size)) {
890 printf("\nupdate_buffs%d (size=%d) :", i, size);
891 dump(update_buffs[k + i], 25);
892 printf("buffs%d (size=%d) :", i, size);
893 dump(buffs[k + i], 25);
894 return -1;
895 }
896 }
897
898 // Random errors
899 memset(src_in_err, 0, TEST_SOURCES);
900 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
901 // Generate decode matrix
902 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
903 invert_matrix, decode_index, src_err_list,
904 src_in_err, nerrs, nsrcerrs, k, m);
905 if (re != 0) {
906 printf("Fail to gf_gen_decode_matrix\n");
907 return -1;
908 }
909 // Pack recovery array as list of valid sources
910 // Its order must be the same as the order
911 // to generate matrix b in gf_gen_decode_matrix
912 for (i = 0; i < k; i++) {
913 recov[i] = update_buffs[decode_index[i]];
914 }
915
916 // Recover data
917 for (i = 0; i < TEST_SOURCES; i++) {
918 memset(temp_buffs[i], 0, TEST_LEN);
919 }
920 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
921 for (i = 0; i < k; i++) {
922 FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i],
923 &temp_buffs[k]);
924 }
925
926 for (i = 0; i < nerrs; i++) {
927
928 if (0 !=
929 memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], size)) {
930 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
931 printf(" - erase list = ");
932 for (j = 0; j < nerrs; j++)
933 printf(" %d", src_err_list[j]);
934 printf(" - Index = ");
935 for (p = 0; p < k; p++)
936 printf(" %d", decode_index[p]);
937 printf("\nencode_matrix:\n");
938 dump_u8xu8((unsigned char *)encode_matrix, m, k);
939 printf("inv b:\n");
940 dump_u8xu8((unsigned char *)invert_matrix, k, k);
941 printf("\ndecode_matrix:\n");
942 dump_u8xu8((unsigned char *)decode_matrix, m, k);
943 printf("orig data:\n");
944 dump_matrix(update_buffs, m, 25);
945 printf("orig :");
946 dump(update_buffs[src_err_list[i]], 25);
947 printf("recov %d:", src_err_list[i]);
948 dump(temp_buffs[k + i], 25);
949 return -1;
950 }
951 }
952 putchar('.');
953 }
954
955 printf("done EC tests: Pass\n");
956 return 0;
957 }