]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/isa-l/erasure_code/erasure_code_base_test.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / isa-l / erasure_code / erasure_code_base_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 #define TEST_LEN 8192
37 #define TEST_SIZE (TEST_LEN/2)
38
39 #ifndef TEST_SOURCES
40 # define TEST_SOURCES 127
41 #endif
42 #ifndef RANDOMS
43 # define RANDOMS 50
44 #endif
45
46 #define MMAX TEST_SOURCES
47 #define KMAX TEST_SOURCES
48
49 #define EFENCE_TEST_MIN_SIZE 16
50
51 #ifdef EC_ALIGNED_ADDR
52 // Define power of 2 range to check ptr, len alignment
53 # define PTR_ALIGN_CHK_B 0
54 # define LEN_ALIGN_CHK_B 0 // 0 for aligned only
55 #else
56 // Define power of 2 range to check ptr, len alignment
57 # define PTR_ALIGN_CHK_B 32
58 # define LEN_ALIGN_CHK_B 32 // 0 for aligned only
59 #endif
60
61 #ifndef TEST_SEED
62 #define TEST_SEED 11
63 #endif
64
65 typedef unsigned char u8;
66
67 void dump(unsigned char *buf, int len)
68 {
69 int i;
70 for (i = 0; i < len;) {
71 printf(" %2x", 0xff & buf[i++]);
72 if (i % 32 == 0)
73 printf("\n");
74 }
75 printf("\n");
76 }
77
78 void dump_matrix(unsigned char **s, int k, int m)
79 {
80 int i, j;
81 for (i = 0; i < k; i++) {
82 for (j = 0; j < m; j++) {
83 printf(" %2x", s[i][j]);
84 }
85 printf("\n");
86 }
87 printf("\n");
88 }
89
90 void dump_u8xu8(unsigned char *s, int k, int m)
91 {
92 int i, j;
93 for (i = 0; i < k; i++) {
94 for (j = 0; j < m; j++) {
95 printf(" %2x", 0xff & s[j + (i * m)]);
96 }
97 printf("\n");
98 }
99 printf("\n");
100 }
101
102 // Generate Random errors
103 static void gen_err_list(unsigned char *src_err_list,
104 unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs, int k, int m)
105 {
106 int i, err;
107 int nerrs = 0, nsrcerrs = 0;
108
109 for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
110 err = 1 & rand();
111 src_in_err[i] = err;
112 if (err) {
113 src_err_list[nerrs++] = i;
114 if (i < k) {
115 nsrcerrs++;
116 }
117 }
118 }
119 if (nerrs == 0) { // should have at least one error
120 while ((err = (rand() % KMAX)) >= m) ;
121 src_err_list[nerrs++] = err;
122 src_in_err[err] = 1;
123 if (err < k)
124 nsrcerrs = 1;
125 }
126 *pnerrs = nerrs;
127 *pnsrcerrs = nsrcerrs;
128 return;
129 }
130
131 #define NO_INVERT_MATRIX -2
132 // Generate decode matrix from encode matrix
133 static int gf_gen_decode_matrix(unsigned char *encode_matrix,
134 unsigned char *decode_matrix,
135 unsigned char *invert_matrix,
136 unsigned int *decode_index,
137 unsigned char *src_err_list,
138 unsigned char *src_in_err,
139 int nerrs, int nsrcerrs, int k, int m)
140 {
141 int i, j, p;
142 int r;
143 unsigned char *backup, *b, s;
144 int incr = 0;
145
146 b = malloc(MMAX * KMAX);
147 backup = malloc(MMAX * KMAX);
148
149 if (b == NULL || backup == NULL) {
150 printf("Test failure! Error with malloc\n");
151 free(b);
152 free(backup);
153 return -1;
154 }
155 // Construct matrix b by removing error rows
156 for (i = 0, r = 0; i < k; i++, r++) {
157 while (src_in_err[r])
158 r++;
159 for (j = 0; j < k; j++) {
160 b[k * i + j] = encode_matrix[k * r + j];
161 backup[k * i + j] = encode_matrix[k * r + j];
162 }
163 decode_index[i] = r;
164 }
165 incr = 0;
166 while (gf_invert_matrix(b, invert_matrix, k) < 0) {
167 if (nerrs == (m - k)) {
168 free(b);
169 free(backup);
170 printf("BAD MATRIX\n");
171 return NO_INVERT_MATRIX;
172 }
173 incr++;
174 memcpy(b, backup, MMAX * KMAX);
175 for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
176 if (src_err_list[i] == (decode_index[k - 1] + incr)) {
177 // skip the erased parity line
178 incr++;
179 continue;
180 }
181 }
182 if (decode_index[k - 1] + incr >= m) {
183 free(b);
184 free(backup);
185 printf("BAD MATRIX\n");
186 return NO_INVERT_MATRIX;
187 }
188 decode_index[k - 1] += incr;
189 for (j = 0; j < k; j++)
190 b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
191
192 };
193
194 for (i = 0; i < nsrcerrs; i++) {
195 for (j = 0; j < k; j++) {
196 decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
197 }
198 }
199 /* src_err_list from encode_matrix * invert of b for parity decoding */
200 for (p = nsrcerrs; p < nerrs; p++) {
201 for (i = 0; i < k; i++) {
202 s = 0;
203 for (j = 0; j < k; j++)
204 s ^= gf_mul(invert_matrix[j * k + i],
205 encode_matrix[k * src_err_list[p] + j]);
206
207 decode_matrix[k * p + i] = s;
208 }
209 }
210 free(b);
211 free(backup);
212 return 0;
213 }
214
215 int main(int argc, char *argv[])
216 {
217 int re = 0;
218 int i, j, p, rtest, m, k;
219 int nerrs, nsrcerrs;
220 void *buf;
221 unsigned int decode_index[MMAX];
222 unsigned char *temp_buffs[TEST_SOURCES], *buffs[TEST_SOURCES];
223 unsigned char *encode_matrix, *decode_matrix, *invert_matrix, *g_tbls;
224 unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
225 unsigned char *recov[TEST_SOURCES];
226
227 int rows, align, size;
228 unsigned char *efence_buffs[TEST_SOURCES];
229 unsigned int offset;
230 u8 *ubuffs[TEST_SOURCES];
231 u8 *temp_ubuffs[TEST_SOURCES];
232
233 printf("erasure_code_base_test: %dx%d ", TEST_SOURCES, TEST_LEN);
234 srand(TEST_SEED);
235
236 // Allocate the arrays
237 for (i = 0; i < TEST_SOURCES; i++) {
238 if (posix_memalign(&buf, 64, TEST_LEN)) {
239 printf("alloc error: Fail");
240 return -1;
241 }
242 buffs[i] = buf;
243 }
244
245 for (i = 0; i < TEST_SOURCES; i++) {
246 if (posix_memalign(&buf, 64, TEST_LEN)) {
247 printf("alloc error: Fail");
248 return -1;
249 }
250 temp_buffs[i] = buf;
251 }
252
253 // Test erasure code by encode and recovery
254
255 encode_matrix = malloc(MMAX * KMAX);
256 decode_matrix = malloc(MMAX * KMAX);
257 invert_matrix = malloc(MMAX * KMAX);
258 g_tbls = malloc(KMAX * TEST_SOURCES * 32);
259 if (encode_matrix == NULL || decode_matrix == NULL
260 || invert_matrix == NULL || g_tbls == NULL) {
261 printf("Test failure! Error with malloc\n");
262 return -1;
263 }
264 // Pick a first test
265 m = 9;
266 k = 5;
267 if (m > MMAX || k > KMAX)
268 return -1;
269
270 // Make random data
271 for (i = 0; i < k; i++)
272 for (j = 0; j < TEST_LEN; j++)
273 buffs[i][j] = rand();
274
275 // Generate encode matrix encode_matrix
276 // The matrix generated by gf_gen_rs_matrix
277 // is not always invertable.
278 gf_gen_rs_matrix(encode_matrix, m, k);
279
280 // Generate g_tbls from encode matrix encode_matrix
281 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
282
283 // Perform matrix dot_prod for EC encoding
284 // using g_tbls from encode matrix encode_matrix
285 ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
286
287 // Choose random buffers to be in erasure
288 memset(src_in_err, 0, TEST_SOURCES);
289 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
290
291 // Generate decode matrix
292 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
293 invert_matrix, decode_index, src_err_list, src_in_err,
294 nerrs, nsrcerrs, k, m);
295 if (re != 0) {
296 printf("Fail to gf_gen_decode_matrix\n");
297 return -1;
298 }
299 // Pack recovery array as list of valid sources
300 // Its order must be the same as the order
301 // to generate matrix b in gf_gen_decode_matrix
302 for (i = 0; i < k; i++) {
303 recov[i] = buffs[decode_index[i]];
304 }
305
306 // Recover data
307 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
308 ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
309 for (i = 0; i < nerrs; i++) {
310
311 if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
312 printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
313 printf(" - erase list = ");
314 for (j = 0; j < nerrs; j++)
315 printf(" %d", src_err_list[j]);
316 printf(" - Index = ");
317 for (p = 0; p < k; p++)
318 printf(" %d", decode_index[p]);
319 printf("\nencode_matrix:\n");
320 dump_u8xu8((u8 *) encode_matrix, m, k);
321 printf("inv b:\n");
322 dump_u8xu8((u8 *) invert_matrix, k, k);
323 printf("\ndecode_matrix:\n");
324 dump_u8xu8((u8 *) decode_matrix, m, k);
325 printf("recov %d:", src_err_list[i]);
326 dump(temp_buffs[k + i], 25);
327 printf("orig :");
328 dump(buffs[src_err_list[i]], 25);
329 return -1;
330 }
331 }
332
333 // Pick a first test
334 m = 9;
335 k = 5;
336 if (m > MMAX || k > KMAX)
337 return -1;
338
339 // Make random data
340 for (i = 0; i < k; i++)
341 for (j = 0; j < TEST_LEN; j++)
342 buffs[i][j] = rand();
343
344 // The matrix generated by gf_gen_cauchy1_matrix
345 // is always invertable.
346 gf_gen_cauchy1_matrix(encode_matrix, m, k);
347
348 // Generate g_tbls from encode matrix encode_matrix
349 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
350
351 // Perform matrix dot_prod for EC encoding
352 // using g_tbls from encode matrix encode_matrix
353 ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
354
355 // Choose random buffers to be in erasure
356 memset(src_in_err, 0, TEST_SOURCES);
357 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
358
359 // Generate decode matrix
360 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
361 invert_matrix, decode_index, src_err_list, src_in_err,
362 nerrs, nsrcerrs, k, m);
363 if (re != 0) {
364 printf("Fail to gf_gen_decode_matrix\n");
365 return -1;
366 }
367 // Pack recovery array as list of valid sources
368 // Its order must be the same as the order
369 // to generate matrix b in gf_gen_decode_matrix
370 for (i = 0; i < k; i++) {
371 recov[i] = buffs[decode_index[i]];
372 }
373
374 // Recover data
375 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
376 ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
377 for (i = 0; i < nerrs; i++) {
378
379 if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
380 printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
381 printf(" - erase list = ");
382 for (j = 0; j < nerrs; j++)
383 printf(" %d", src_err_list[j]);
384 printf(" - Index = ");
385 for (p = 0; p < k; p++)
386 printf(" %d", decode_index[p]);
387 printf("\nencode_matrix:\n");
388 dump_u8xu8((u8 *) encode_matrix, m, k);
389 printf("inv b:\n");
390 dump_u8xu8((u8 *) invert_matrix, k, k);
391 printf("\ndecode_matrix:\n");
392 dump_u8xu8((u8 *) decode_matrix, m, k);
393 printf("recov %d:", src_err_list[i]);
394 dump(temp_buffs[k + i], 25);
395 printf("orig :");
396 dump(buffs[src_err_list[i]], 25);
397 return -1;
398 }
399 }
400
401 // Do more random tests
402 for (rtest = 0; rtest < RANDOMS; rtest++) {
403 while ((m = (rand() % MMAX)) < 2) ;
404 while ((k = (rand() % KMAX)) >= m || k < 1) ;
405
406 if (m > MMAX || k > KMAX)
407 continue;
408
409 // Make random data
410 for (i = 0; i < k; i++)
411 for (j = 0; j < TEST_LEN; j++)
412 buffs[i][j] = rand();
413
414 // The matrix generated by gf_gen_cauchy1_matrix
415 // is always invertable.
416 gf_gen_cauchy1_matrix(encode_matrix, m, k);
417
418 // Make parity vects
419 // Generate g_tbls from encode matrix a
420 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
421 // Perform matrix dot_prod for EC encoding
422 // using g_tbls from encode matrix a
423 ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
424
425 // Random errors
426 memset(src_in_err, 0, TEST_SOURCES);
427 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
428
429 // Generate decode matrix
430 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
431 invert_matrix, decode_index, src_err_list,
432 src_in_err, nerrs, nsrcerrs, k, m);
433 if (re != 0) {
434 printf("Fail to gf_gen_decode_matrix\n");
435 return -1;
436 }
437 // Pack recovery array as list of valid sources
438 // Its order must be the same as the order
439 // to generate matrix b in gf_gen_decode_matrix
440 for (i = 0; i < k; i++) {
441 recov[i] = buffs[decode_index[i]];
442 }
443
444 // Recover data
445 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
446 ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
447
448 for (i = 0; i < nerrs; i++) {
449
450 if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
451 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
452 printf(" - erase list = ");
453 for (j = 0; j < nerrs; j++)
454 printf(" %d", src_err_list[j]);
455 printf(" - Index = ");
456 for (p = 0; p < k; p++)
457 printf(" %d", decode_index[p]);
458 printf("\nencode_matrix:\n");
459 dump_u8xu8((u8 *) encode_matrix, m, k);
460 printf("inv b:\n");
461 dump_u8xu8((u8 *) invert_matrix, k, k);
462 printf("\ndecode_matrix:\n");
463 dump_u8xu8((u8 *) decode_matrix, m, k);
464 printf("orig data:\n");
465 dump_matrix(buffs, m, 25);
466 printf("orig :");
467 dump(buffs[src_err_list[i]], 25);
468 printf("recov %d:", src_err_list[i]);
469 dump(temp_buffs[k + i], 25);
470 return -1;
471 }
472 }
473 putchar('.');
474 }
475
476 // Run tests at end of buffer for Electric Fence
477 k = 16;
478 align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
479 if (k > KMAX)
480 return -1;
481
482 for (rows = 1; rows <= 16; rows++) {
483 m = k + rows;
484 if (m > MMAX)
485 return -1;
486
487 // Make random data
488 for (i = 0; i < k; i++)
489 for (j = 0; j < TEST_LEN; j++)
490 buffs[i][j] = rand();
491
492 for (size = EFENCE_TEST_MIN_SIZE; size <= TEST_SIZE; size += align) {
493 for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
494 efence_buffs[i] = buffs[i] + TEST_LEN - size;
495 }
496
497 // The matrix generated by gf_gen_cauchy1_matrix
498 // is always invertable.
499 gf_gen_cauchy1_matrix(encode_matrix, m, k);
500
501 // Make parity vects
502 // Generate g_tbls from encode matrix a
503 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
504 // Perform matrix dot_prod for EC encoding
505 // using g_tbls from encode matrix a
506 ec_encode_data_base(size, k, m - k, g_tbls, efence_buffs,
507 &efence_buffs[k]);
508
509 // Random errors
510 memset(src_in_err, 0, TEST_SOURCES);
511 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
512
513 // Generate decode matrix
514 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
515 invert_matrix, decode_index, src_err_list,
516 src_in_err, nerrs, nsrcerrs, k, m);
517 if (re != 0) {
518 printf("Fail to gf_gen_decode_matrix\n");
519 return -1;
520 }
521 // Pack recovery array as list of valid sources
522 // Its order must be the same as the order
523 // to generate matrix b in gf_gen_decode_matrix
524 for (i = 0; i < k; i++) {
525 recov[i] = efence_buffs[decode_index[i]];
526 }
527
528 // Recover data
529 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
530 ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
531
532 for (i = 0; i < nerrs; i++) {
533
534 if (0 !=
535 memcmp(temp_buffs[k + i], efence_buffs[src_err_list[i]],
536 size)) {
537 printf("Efence: Fail error recovery (%d, %d, %d)\n", m,
538 k, nerrs);
539
540 printf("size = %d\n", size);
541
542 printf("Test erase list = ");
543 for (j = 0; j < nerrs; j++)
544 printf(" %d", src_err_list[j]);
545 printf(" - Index = ");
546 for (p = 0; p < k; p++)
547 printf(" %d", decode_index[p]);
548 printf("\nencode_matrix:\n");
549 dump_u8xu8((u8 *) encode_matrix, m, k);
550 printf("inv b:\n");
551 dump_u8xu8((u8 *) invert_matrix, k, k);
552 printf("\ndecode_matrix:\n");
553 dump_u8xu8((u8 *) decode_matrix, m, k);
554
555 printf("recov %d:", src_err_list[i]);
556 dump(temp_buffs[k + i], align);
557 printf("orig :");
558 dump(efence_buffs[src_err_list[i]], align);
559 return -1;
560 }
561 }
562 }
563
564 }
565
566 // Test rand ptr alignment if available
567
568 for (rtest = 0; rtest < RANDOMS; rtest++) {
569 while ((m = (rand() % MMAX)) < 2) ;
570 while ((k = (rand() % KMAX)) >= m || k < 1) ;
571
572 if (m > MMAX || k > KMAX)
573 continue;
574
575 size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
576
577 offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
578 // Add random offsets
579 for (i = 0; i < m; i++) {
580 memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
581 memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
582 ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
583 temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
584 }
585
586 for (i = 0; i < k; i++)
587 for (j = 0; j < size; j++)
588 ubuffs[i][j] = rand();
589
590 // The matrix generated by gf_gen_cauchy1_matrix
591 // is always invertable.
592 gf_gen_cauchy1_matrix(encode_matrix, m, k);
593
594 // Make parity vects
595 // Generate g_tbls from encode matrix a
596 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
597 // Perform matrix dot_prod for EC encoding
598 // using g_tbls from encode matrix a
599 ec_encode_data_base(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
600
601 // Random errors
602 memset(src_in_err, 0, TEST_SOURCES);
603 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
604
605 // Generate decode matrix
606 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
607 invert_matrix, decode_index, src_err_list,
608 src_in_err, nerrs, nsrcerrs, k, m);
609 if (re != 0) {
610 printf("Fail to gf_gen_decode_matrix\n");
611 return -1;
612 }
613 // Pack recovery array as list of valid sources
614 // Its order must be the same as the order
615 // to generate matrix b in gf_gen_decode_matrix
616 for (i = 0; i < k; i++) {
617 recov[i] = ubuffs[decode_index[i]];
618 }
619
620 // Recover data
621 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
622 ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_ubuffs[k]);
623
624 for (i = 0; i < nerrs; i++) {
625
626 if (0 != memcmp(temp_ubuffs[k + i], ubuffs[src_err_list[i]], size)) {
627 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
628 printf(" - erase list = ");
629 for (j = 0; j < nerrs; j++)
630 printf(" %d", src_err_list[j]);
631 printf(" - Index = ");
632 for (p = 0; p < k; p++)
633 printf(" %d", decode_index[p]);
634 printf("\nencode_matrix:\n");
635 dump_u8xu8((unsigned char *)encode_matrix, m, k);
636 printf("inv b:\n");
637 dump_u8xu8((unsigned char *)invert_matrix, k, k);
638 printf("\ndecode_matrix:\n");
639 dump_u8xu8((unsigned char *)decode_matrix, m, k);
640 printf("orig data:\n");
641 dump_matrix(ubuffs, m, 25);
642 printf("orig :");
643 dump(ubuffs[src_err_list[i]], 25);
644 printf("recov %d:", src_err_list[i]);
645 dump(temp_ubuffs[k + i], 25);
646 return -1;
647 }
648 }
649
650 // Confirm that padding around dests is unchanged
651 memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
652
653 for (i = 0; i < m; i++) {
654
655 offset = ubuffs[i] - buffs[i];
656
657 if (memcmp(buffs[i], temp_buffs[0], offset)) {
658 printf("Fail rand ualign encode pad start\n");
659 return -1;
660 }
661 if (memcmp
662 (buffs[i] + offset + size, temp_buffs[0],
663 PTR_ALIGN_CHK_B - offset)) {
664 printf("Fail rand ualign encode pad end\n");
665 return -1;
666 }
667 }
668
669 for (i = 0; i < nerrs; i++) {
670
671 offset = temp_ubuffs[k + i] - temp_buffs[k + i];
672 if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
673 printf("Fail rand ualign decode pad start\n");
674 return -1;
675 }
676 if (memcmp
677 (temp_buffs[k + i] + offset + size, temp_buffs[0],
678 PTR_ALIGN_CHK_B - offset)) {
679 printf("Fail rand ualign decode pad end\n");
680 return -1;
681 }
682 }
683
684 putchar('.');
685 }
686
687 // Test size alignment
688
689 align = (LEN_ALIGN_CHK_B != 0) ? 13 : 16;
690
691 for (size = TEST_LEN; size > 0; size -= align) {
692 while ((m = (rand() % MMAX)) < 2) ;
693 while ((k = (rand() % KMAX)) >= m || k < 1) ;
694
695 if (m > MMAX || k > KMAX)
696 continue;
697
698 for (i = 0; i < k; i++)
699 for (j = 0; j < size; j++)
700 buffs[i][j] = rand();
701
702 // The matrix generated by gf_gen_cauchy1_matrix
703 // is always invertable.
704 gf_gen_cauchy1_matrix(encode_matrix, m, k);
705
706 // Make parity vects
707 // Generate g_tbls from encode matrix a
708 ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
709 // Perform matrix dot_prod for EC encoding
710 // using g_tbls from encode matrix a
711 ec_encode_data_base(size, k, m - k, g_tbls, buffs, &buffs[k]);
712
713 // Random errors
714 memset(src_in_err, 0, TEST_SOURCES);
715 gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
716 // Generate decode matrix
717 re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
718 invert_matrix, decode_index, src_err_list,
719 src_in_err, nerrs, nsrcerrs, k, m);
720 if (re != 0) {
721 printf("Fail to gf_gen_decode_matrix\n");
722 return -1;
723 }
724 // Pack recovery array as list of valid sources
725 // Its order must be the same as the order
726 // to generate matrix b in gf_gen_decode_matrix
727 for (i = 0; i < k; i++) {
728 recov[i] = buffs[decode_index[i]];
729 }
730
731 // Recover data
732 ec_init_tables(k, nerrs, decode_matrix, g_tbls);
733 ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
734
735 for (i = 0; i < nerrs; i++) {
736
737 if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], size)) {
738 printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
739 printf(" - erase list = ");
740 for (j = 0; j < nerrs; j++)
741 printf(" %d", src_err_list[j]);
742 printf(" - Index = ");
743 for (p = 0; p < k; p++)
744 printf(" %d", decode_index[p]);
745 printf("\nencode_matrix:\n");
746 dump_u8xu8((unsigned char *)encode_matrix, m, k);
747 printf("inv b:\n");
748 dump_u8xu8((unsigned char *)invert_matrix, k, k);
749 printf("\ndecode_matrix:\n");
750 dump_u8xu8((unsigned char *)decode_matrix, m, k);
751 printf("orig data:\n");
752 dump_matrix(buffs, m, 25);
753 printf("orig :");
754 dump(buffs[src_err_list[i]], 25);
755 printf("recov %d:", src_err_list[i]);
756 dump(temp_buffs[k + i], 25);
757 return -1;
758 }
759 }
760 }
761
762 printf("done EC tests: Pass\n");
763 return 0;
764 }