erasure_code_test.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /**********************************************************************
  2. Copyright(c) 2011-2015 Intel Corporation All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions
  5. are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in
  10. the documentation and/or other materials provided with the
  11. distribution.
  12. * Neither the name of Intel Corporation nor the names of its
  13. contributors may be used to endorse or promote products derived
  14. from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  18. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  19. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. **********************************************************************/
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h> // for memset, memcmp
  30. #include <assert.h>
  31. #include "erasure_code.h"
  32. #include "test.h"
  33. #define TEST_LEN 8192
  34. #define TEST_SIZE (TEST_LEN/2)
  35. #ifndef TEST_SOURCES
  36. # define TEST_SOURCES 127
  37. #endif
  38. #ifndef RANDOMS
  39. # define RANDOMS 200
  40. #endif
  41. #define MMAX TEST_SOURCES
  42. #define KMAX TEST_SOURCES
  43. #define EFENCE_TEST_MIN_SIZE 16
  44. #define EFENCE_TEST_MAX_SIZE EFENCE_TEST_MIN_SIZE + 0x100
  45. #ifdef EC_ALIGNED_ADDR
  46. // Define power of 2 range to check ptr, len alignment
  47. # define PTR_ALIGN_CHK_B 0
  48. # define LEN_ALIGN_CHK_B 0 // 0 for aligned only
  49. #else
  50. // Define power of 2 range to check ptr, len alignment
  51. # define PTR_ALIGN_CHK_B 32
  52. # define LEN_ALIGN_CHK_B 32 // 0 for aligned only
  53. #endif
  54. #ifndef TEST_SEED
  55. #define TEST_SEED 11
  56. #endif
  57. typedef unsigned char u8;
  58. void dump(unsigned char *buf, int len)
  59. {
  60. int i;
  61. for (i = 0; i < len;) {
  62. printf(" %2x", 0xff & buf[i++]);
  63. if (i % 32 == 0)
  64. printf("\n");
  65. }
  66. printf("\n");
  67. }
  68. void dump_matrix(unsigned char **s, int k, int m)
  69. {
  70. int i, j;
  71. for (i = 0; i < k; i++) {
  72. for (j = 0; j < m; j++) {
  73. printf(" %2x", s[i][j]);
  74. }
  75. printf("\n");
  76. }
  77. printf("\n");
  78. }
  79. void dump_u8xu8(unsigned char *s, int k, int m)
  80. {
  81. int i, j;
  82. for (i = 0; i < k; i++) {
  83. for (j = 0; j < m; j++) {
  84. printf(" %2x", 0xff & s[j + (i * m)]);
  85. }
  86. printf("\n");
  87. }
  88. printf("\n");
  89. }
  90. // Generate Random errors
  91. static void gen_err_list(unsigned char *src_err_list,
  92. unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs, int k, int m)
  93. {
  94. int i, err;
  95. int nerrs = 0, nsrcerrs = 0;
  96. for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
  97. err = 1 & rand();
  98. src_in_err[i] = err;
  99. if (err) {
  100. src_err_list[nerrs++] = i;
  101. if (i < k) {
  102. nsrcerrs++;
  103. }
  104. }
  105. }
  106. if (nerrs == 0) { // should have at least one error
  107. while ((err = (rand() % KMAX)) >= m) ;
  108. src_err_list[nerrs++] = err;
  109. src_in_err[err] = 1;
  110. if (err < k)
  111. nsrcerrs = 1;
  112. }
  113. *pnerrs = nerrs;
  114. *pnsrcerrs = nsrcerrs;
  115. return;
  116. }
  117. #define NO_INVERT_MATRIX -2
  118. // Generate decode matrix from encode matrix
  119. static int gf_gen_decode_matrix(unsigned char *encode_matrix,
  120. unsigned char *decode_matrix,
  121. unsigned char *invert_matrix,
  122. unsigned int *decode_index,
  123. unsigned char *src_err_list,
  124. unsigned char *src_in_err,
  125. int nerrs, int nsrcerrs, int k, int m)
  126. {
  127. int i, j, p;
  128. int r;
  129. unsigned char *backup, *b, s;
  130. int incr = 0;
  131. b = malloc(MMAX * KMAX);
  132. backup = malloc(MMAX * KMAX);
  133. if (b == NULL || backup == NULL) {
  134. printf("Test failure! Error with malloc\n");
  135. free(b);
  136. free(backup);
  137. return -1;
  138. }
  139. // Construct matrix b by removing error rows
  140. for (i = 0, r = 0; i < k; i++, r++) {
  141. while (src_in_err[r])
  142. r++;
  143. for (j = 0; j < k; j++) {
  144. b[k * i + j] = encode_matrix[k * r + j];
  145. backup[k * i + j] = encode_matrix[k * r + j];
  146. }
  147. decode_index[i] = r;
  148. }
  149. incr = 0;
  150. while (gf_invert_matrix(b, invert_matrix, k) < 0) {
  151. if (nerrs == (m - k)) {
  152. free(b);
  153. free(backup);
  154. printf("BAD MATRIX\n");
  155. return NO_INVERT_MATRIX;
  156. }
  157. incr++;
  158. memcpy(b, backup, MMAX * KMAX);
  159. for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
  160. if (src_err_list[i] == (decode_index[k - 1] + incr)) {
  161. // skip the erased parity line
  162. incr++;
  163. continue;
  164. }
  165. }
  166. if (decode_index[k - 1] + incr >= m) {
  167. free(b);
  168. free(backup);
  169. printf("BAD MATRIX\n");
  170. return NO_INVERT_MATRIX;
  171. }
  172. decode_index[k - 1] += incr;
  173. for (j = 0; j < k; j++)
  174. b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
  175. };
  176. for (i = 0; i < nsrcerrs; i++) {
  177. for (j = 0; j < k; j++) {
  178. decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
  179. }
  180. }
  181. /* src_err_list from encode_matrix * invert of b for parity decoding */
  182. for (p = nsrcerrs; p < nerrs; p++) {
  183. for (i = 0; i < k; i++) {
  184. s = 0;
  185. for (j = 0; j < k; j++)
  186. s ^= gf_mul_erasure(invert_matrix[j * k + i],
  187. encode_matrix[k * src_err_list[p] + j]);
  188. decode_matrix[k * p + i] = s;
  189. }
  190. }
  191. free(b);
  192. free(backup);
  193. return 0;
  194. }
  195. int main(int argc, char *argv[])
  196. {
  197. int re = -1;
  198. int i, j, p, rtest, m, k;
  199. int nerrs, nsrcerrs;
  200. void *buf;
  201. unsigned int decode_index[MMAX];
  202. unsigned char *temp_buffs[TEST_SOURCES] = { NULL }, *buffs[TEST_SOURCES] = { NULL };
  203. unsigned char *encode_matrix = NULL, *decode_matrix = NULL, *invert_matrix =
  204. NULL, *g_tbls = NULL;
  205. unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
  206. unsigned char *recov[TEST_SOURCES];
  207. int rows, align, size;
  208. unsigned char *efence_buffs[TEST_SOURCES];
  209. unsigned int offset;
  210. u8 *ubuffs[TEST_SOURCES];
  211. u8 *temp_ubuffs[TEST_SOURCES];
  212. printf("erasure_code_test: %dx%d ", TEST_SOURCES, TEST_LEN);
  213. srand(TEST_SEED);
  214. // Allocate the arrays
  215. for (i = 0; i < TEST_SOURCES; i++) {
  216. if (posix_memalign(&buf, 64, TEST_LEN)) {
  217. printf("alloc error: Fail");
  218. goto exit;
  219. }
  220. buffs[i] = buf;
  221. }
  222. for (i = 0; i < TEST_SOURCES; i++) {
  223. if (posix_memalign(&buf, 64, TEST_LEN)) {
  224. printf("alloc error: Fail");
  225. goto exit;
  226. }
  227. temp_buffs[i] = buf;
  228. }
  229. // Test erasure code by encode and recovery
  230. encode_matrix = malloc(MMAX * KMAX);
  231. decode_matrix = malloc(MMAX * KMAX);
  232. invert_matrix = malloc(MMAX * KMAX);
  233. g_tbls = malloc(KMAX * TEST_SOURCES * 32);
  234. if (encode_matrix == NULL || decode_matrix == NULL
  235. || invert_matrix == NULL || g_tbls == NULL) {
  236. printf("Test failure! Error with malloc\n");
  237. goto exit;
  238. }
  239. // Pick a first test
  240. m = 9;
  241. k = 5;
  242. assert((m <= MMAX) && (k <= KMAX));
  243. // Make random data
  244. for (i = 0; i < k; i++)
  245. for (j = 0; j < TEST_LEN; j++)
  246. buffs[i][j] = rand();
  247. // Generate encode matrix encode_matrix
  248. // The matrix generated by gf_gen_rs_matrix
  249. // is not always invertable.
  250. gf_gen_rs_matrix(encode_matrix, m, k);
  251. // Generate g_tbls from encode matrix encode_matrix
  252. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  253. // Perform matrix dot_prod for EC encoding
  254. // using g_tbls from encode matrix encode_matrix
  255. ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
  256. // Choose random buffers to be in erasure
  257. memset(src_in_err, 0, TEST_SOURCES);
  258. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  259. // Generate decode matrix
  260. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  261. invert_matrix, decode_index, src_err_list, src_in_err,
  262. nerrs, nsrcerrs, k, m);
  263. if (re != 0) {
  264. printf("Fail to gf_gen_decode_matrix\n");
  265. goto exit;
  266. }
  267. // Pack recovery array as list of valid sources
  268. // Its order must be the same as the order
  269. // to generate matrix b in gf_gen_decode_matrix
  270. for (i = 0; i < k; i++) {
  271. recov[i] = buffs[decode_index[i]];
  272. }
  273. // Recover data
  274. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  275. ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
  276. for (i = 0; i < nerrs; i++) {
  277. if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
  278. printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
  279. printf(" - erase list = ");
  280. for (j = 0; j < nerrs; j++)
  281. printf(" %d", src_err_list[j]);
  282. printf(" - Index = ");
  283. for (p = 0; p < k; p++)
  284. printf(" %d", decode_index[p]);
  285. printf("\nencode_matrix:\n");
  286. dump_u8xu8((u8 *) encode_matrix, m, k);
  287. printf("inv b:\n");
  288. dump_u8xu8((u8 *) invert_matrix, k, k);
  289. printf("\ndecode_matrix:\n");
  290. dump_u8xu8((u8 *) decode_matrix, m, k);
  291. printf("recov %d:", src_err_list[i]);
  292. dump(temp_buffs[k + i], 25);
  293. printf("orig :");
  294. dump(buffs[src_err_list[i]], 25);
  295. re = -1;
  296. goto exit;
  297. }
  298. }
  299. // Pick a first test
  300. m = 9;
  301. k = 5;
  302. if (m > MMAX || k > KMAX) {
  303. re = -1;
  304. goto exit;
  305. }
  306. // Make random data
  307. for (i = 0; i < k; i++)
  308. for (j = 0; j < TEST_LEN; j++)
  309. buffs[i][j] = rand();
  310. // The matrix generated by gf_gen_cauchy1_matrix
  311. // is always invertable.
  312. gf_gen_cauchy1_matrix(encode_matrix, m, k);
  313. // Generate g_tbls from encode matrix encode_matrix
  314. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  315. // Perform matrix dot_prod for EC encoding
  316. // using g_tbls from encode matrix encode_matrix
  317. ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
  318. // Choose random buffers to be in erasure
  319. memset(src_in_err, 0, TEST_SOURCES);
  320. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  321. // Generate decode matrix
  322. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  323. invert_matrix, decode_index, src_err_list, src_in_err,
  324. nerrs, nsrcerrs, k, m);
  325. if (re != 0) {
  326. printf("Fail to gf_gen_decode_matrix\n");
  327. goto exit;
  328. }
  329. // Pack recovery array as list of valid sources
  330. // Its order must be the same as the order
  331. // to generate matrix b in gf_gen_decode_matrix
  332. for (i = 0; i < k; i++) {
  333. recov[i] = buffs[decode_index[i]];
  334. }
  335. // Recover data
  336. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  337. ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
  338. for (i = 0; i < nerrs; i++) {
  339. if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
  340. printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
  341. printf(" - erase list = ");
  342. for (j = 0; j < nerrs; j++)
  343. printf(" %d", src_err_list[j]);
  344. printf(" - Index = ");
  345. for (p = 0; p < k; p++)
  346. printf(" %d", decode_index[p]);
  347. printf("\nencode_matrix:\n");
  348. dump_u8xu8((u8 *) encode_matrix, m, k);
  349. printf("inv b:\n");
  350. dump_u8xu8((u8 *) invert_matrix, k, k);
  351. printf("\ndecode_matrix:\n");
  352. dump_u8xu8((u8 *) decode_matrix, m, k);
  353. printf("recov %d:", src_err_list[i]);
  354. dump(temp_buffs[k + i], 25);
  355. printf("orig :");
  356. dump(buffs[src_err_list[i]], 25);
  357. re = -1;
  358. goto exit;
  359. }
  360. }
  361. // Do more random tests
  362. for (rtest = 0; rtest < RANDOMS; rtest++) {
  363. while ((m = (rand() % MMAX)) < 2) ;
  364. while ((k = (rand() % KMAX)) >= m || k < 1) ;
  365. if (m > MMAX || k > KMAX)
  366. continue;
  367. // Make random data
  368. for (i = 0; i < k; i++)
  369. for (j = 0; j < TEST_LEN; j++)
  370. buffs[i][j] = rand();
  371. // The matrix generated by gf_gen_cauchy1_matrix
  372. // is always invertable.
  373. gf_gen_cauchy1_matrix(encode_matrix, m, k);
  374. // Make parity vects
  375. // Generate g_tbls from encode matrix a
  376. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  377. // Perform matrix dot_prod for EC encoding
  378. // using g_tbls from encode matrix a
  379. ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
  380. // Random errors
  381. memset(src_in_err, 0, TEST_SOURCES);
  382. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  383. // Generate decode matrix
  384. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  385. invert_matrix, decode_index, src_err_list,
  386. src_in_err, nerrs, nsrcerrs, k, m);
  387. if (re != 0) {
  388. printf("Fail to gf_gen_decode_matrix\n");
  389. goto exit;
  390. }
  391. // Pack recovery array as list of valid sources
  392. // Its order must be the same as the order
  393. // to generate matrix b in gf_gen_decode_matrix
  394. for (i = 0; i < k; i++) {
  395. recov[i] = buffs[decode_index[i]];
  396. }
  397. // Recover data
  398. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  399. ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
  400. for (i = 0; i < nerrs; i++) {
  401. if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
  402. printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
  403. printf(" - erase list = ");
  404. for (j = 0; j < nerrs; j++)
  405. printf(" %d", src_err_list[j]);
  406. printf(" - Index = ");
  407. for (p = 0; p < k; p++)
  408. printf(" %d", decode_index[p]);
  409. printf("\nencode_matrix:\n");
  410. dump_u8xu8((u8 *) encode_matrix, m, k);
  411. printf("inv b:\n");
  412. dump_u8xu8((u8 *) invert_matrix, k, k);
  413. printf("\ndecode_matrix:\n");
  414. dump_u8xu8((u8 *) decode_matrix, m, k);
  415. printf("orig data:\n");
  416. dump_matrix(buffs, m, 25);
  417. printf("orig :");
  418. dump(buffs[src_err_list[i]], 25);
  419. printf("recov %d:", src_err_list[i]);
  420. dump(temp_buffs[k + i], 25);
  421. re = -1;
  422. goto exit;
  423. }
  424. }
  425. #ifdef TEST_VERBOSE
  426. putchar('.');
  427. #endif
  428. }
  429. // Run tests at end of buffer for Electric Fence
  430. k = 16;
  431. align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
  432. if (k > KMAX) {
  433. re = -1;
  434. goto exit;
  435. }
  436. for (rows = 1; rows <= 16; rows++) {
  437. m = k + rows;
  438. if (m > MMAX) {
  439. re = -1;
  440. goto exit;
  441. }
  442. // Make random data
  443. for (i = 0; i < k; i++)
  444. for (j = 0; j < TEST_LEN; j++)
  445. buffs[i][j] = rand();
  446. for (size = EFENCE_TEST_MIN_SIZE; size <= EFENCE_TEST_MAX_SIZE; size += align) {
  447. for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
  448. efence_buffs[i] = buffs[i] + TEST_LEN - size;
  449. }
  450. // The matrix generated by gf_gen_cauchy1_matrix
  451. // is always invertable.
  452. gf_gen_cauchy1_matrix(encode_matrix, m, k);
  453. // Make parity vects
  454. // Generate g_tbls from encode matrix a
  455. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  456. // Perform matrix dot_prod for EC encoding
  457. // using g_tbls from encode matrix a
  458. ec_encode_data(size, k, m - k, g_tbls, efence_buffs, &efence_buffs[k]);
  459. // Random errors
  460. memset(src_in_err, 0, TEST_SOURCES);
  461. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  462. // Generate decode matrix
  463. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  464. invert_matrix, decode_index, src_err_list,
  465. src_in_err, nerrs, nsrcerrs, k, m);
  466. if (re != 0) {
  467. printf("Fail to gf_gen_decode_matrix\n");
  468. goto exit;
  469. }
  470. // Pack recovery array as list of valid sources
  471. // Its order must be the same as the order
  472. // to generate matrix b in gf_gen_decode_matrix
  473. for (i = 0; i < k; i++) {
  474. recov[i] = efence_buffs[decode_index[i]];
  475. }
  476. // Recover data
  477. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  478. ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
  479. for (i = 0; i < nerrs; i++) {
  480. if (0 !=
  481. memcmp(temp_buffs[k + i], efence_buffs[src_err_list[i]],
  482. size)) {
  483. printf("Efence: Fail error recovery (%d, %d, %d)\n", m,
  484. k, nerrs);
  485. printf("size = %d\n", size);
  486. printf("Test erase list = ");
  487. for (j = 0; j < nerrs; j++)
  488. printf(" %d", src_err_list[j]);
  489. printf(" - Index = ");
  490. for (p = 0; p < k; p++)
  491. printf(" %d", decode_index[p]);
  492. printf("\nencode_matrix:\n");
  493. dump_u8xu8((u8 *) encode_matrix, m, k);
  494. printf("inv b:\n");
  495. dump_u8xu8((u8 *) invert_matrix, k, k);
  496. printf("\ndecode_matrix:\n");
  497. dump_u8xu8((u8 *) decode_matrix, m, k);
  498. printf("recov %d:", src_err_list[i]);
  499. dump(temp_buffs[k + i], align);
  500. printf("orig :");
  501. dump(efence_buffs[src_err_list[i]], align);
  502. re = -1;
  503. goto exit;
  504. }
  505. }
  506. }
  507. }
  508. // Test rand ptr alignment if available
  509. for (rtest = 0; rtest < RANDOMS; rtest++) {
  510. while ((m = (rand() % MMAX)) < 2) ;
  511. while ((k = (rand() % KMAX)) >= m || k < 1) ;
  512. if (m > MMAX || k > KMAX)
  513. continue;
  514. size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
  515. offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
  516. // Add random offsets
  517. for (i = 0; i < m; i++) {
  518. memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
  519. memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
  520. ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
  521. temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
  522. }
  523. for (i = 0; i < k; i++)
  524. for (j = 0; j < size; j++)
  525. ubuffs[i][j] = rand();
  526. // The matrix generated by gf_gen_cauchy1_matrix
  527. // is always invertable.
  528. gf_gen_cauchy1_matrix(encode_matrix, m, k);
  529. // Make parity vects
  530. // Generate g_tbls from encode matrix a
  531. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  532. // Perform matrix dot_prod for EC encoding
  533. // using g_tbls from encode matrix a
  534. ec_encode_data(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
  535. // Random errors
  536. memset(src_in_err, 0, TEST_SOURCES);
  537. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  538. // Generate decode matrix
  539. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  540. invert_matrix, decode_index, src_err_list,
  541. src_in_err, nerrs, nsrcerrs, k, m);
  542. if (re != 0) {
  543. printf("Fail to gf_gen_decode_matrix\n");
  544. goto exit;
  545. }
  546. // Pack recovery array as list of valid sources
  547. // Its order must be the same as the order
  548. // to generate matrix b in gf_gen_decode_matrix
  549. for (i = 0; i < k; i++) {
  550. recov[i] = ubuffs[decode_index[i]];
  551. }
  552. // Recover data
  553. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  554. ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_ubuffs[k]);
  555. for (i = 0; i < nerrs; i++) {
  556. if (0 != memcmp(temp_ubuffs[k + i], ubuffs[src_err_list[i]], size)) {
  557. printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
  558. printf(" - erase list = ");
  559. for (j = 0; j < nerrs; j++)
  560. printf(" %d", src_err_list[j]);
  561. printf(" - Index = ");
  562. for (p = 0; p < k; p++)
  563. printf(" %d", decode_index[p]);
  564. printf("\nencode_matrix:\n");
  565. dump_u8xu8((unsigned char *)encode_matrix, m, k);
  566. printf("inv b:\n");
  567. dump_u8xu8((unsigned char *)invert_matrix, k, k);
  568. printf("\ndecode_matrix:\n");
  569. dump_u8xu8((unsigned char *)decode_matrix, m, k);
  570. printf("orig data:\n");
  571. dump_matrix(ubuffs, m, 25);
  572. printf("orig :");
  573. dump(ubuffs[src_err_list[i]], 25);
  574. printf("recov %d:", src_err_list[i]);
  575. dump(temp_ubuffs[k + i], 25);
  576. re = -1;
  577. goto exit;
  578. }
  579. }
  580. // Confirm that padding around dests is unchanged
  581. memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
  582. for (i = 0; i < m; i++) {
  583. offset = ubuffs[i] - buffs[i];
  584. if (memcmp(buffs[i], temp_buffs[0], offset)) {
  585. printf("Fail rand ualign encode pad start\n");
  586. re = -1;
  587. goto exit;
  588. }
  589. if (memcmp
  590. (buffs[i] + offset + size, temp_buffs[0],
  591. PTR_ALIGN_CHK_B - offset)) {
  592. printf("Fail rand ualign encode pad end\n");
  593. re = -1;
  594. goto exit;
  595. }
  596. }
  597. for (i = 0; i < nerrs; i++) {
  598. offset = temp_ubuffs[k + i] - temp_buffs[k + i];
  599. if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
  600. printf("Fail rand ualign decode pad start\n");
  601. re = -1;
  602. goto exit;
  603. }
  604. if (memcmp
  605. (temp_buffs[k + i] + offset + size, temp_buffs[0],
  606. PTR_ALIGN_CHK_B - offset)) {
  607. printf("Fail rand ualign decode pad end\n");
  608. re = -1;
  609. goto exit;
  610. }
  611. }
  612. #ifdef TEST_VERBOSE
  613. putchar('.');
  614. #endif
  615. }
  616. // Test size alignment
  617. align = (LEN_ALIGN_CHK_B != 0) ? 13 : 16;
  618. for (size = TEST_LEN; size > 0; size -= align) {
  619. while ((m = (rand() % MMAX)) < 2) ;
  620. while ((k = (rand() % KMAX)) >= m || k < 1) ;
  621. if (m > MMAX || k > KMAX)
  622. continue;
  623. for (i = 0; i < k; i++)
  624. for (j = 0; j < size; j++)
  625. buffs[i][j] = rand();
  626. // The matrix generated by gf_gen_cauchy1_matrix
  627. // is always invertable.
  628. gf_gen_cauchy1_matrix(encode_matrix, m, k);
  629. // Make parity vects
  630. // Generate g_tbls from encode matrix a
  631. ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
  632. // Perform matrix dot_prod for EC encoding
  633. // using g_tbls from encode matrix a
  634. ec_encode_data(size, k, m - k, g_tbls, buffs, &buffs[k]);
  635. // Random errors
  636. memset(src_in_err, 0, TEST_SOURCES);
  637. gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
  638. // Generate decode matrix
  639. re = gf_gen_decode_matrix(encode_matrix, decode_matrix,
  640. invert_matrix, decode_index, src_err_list,
  641. src_in_err, nerrs, nsrcerrs, k, m);
  642. if (re != 0) {
  643. printf("Fail to gf_gen_decode_matrix\n");
  644. goto exit;
  645. }
  646. // Pack recovery array as list of valid sources
  647. // Its order must be the same as the order
  648. // to generate matrix b in gf_gen_decode_matrix
  649. for (i = 0; i < k; i++) {
  650. recov[i] = buffs[decode_index[i]];
  651. }
  652. // Recover data
  653. ec_init_tables(k, nerrs, decode_matrix, g_tbls);
  654. ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
  655. for (i = 0; i < nerrs; i++) {
  656. if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], size)) {
  657. printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
  658. printf(" - erase list = ");
  659. for (j = 0; j < nerrs; j++)
  660. printf(" %d", src_err_list[j]);
  661. printf(" - Index = ");
  662. for (p = 0; p < k; p++)
  663. printf(" %d", decode_index[p]);
  664. printf("\nencode_matrix:\n");
  665. dump_u8xu8((unsigned char *)encode_matrix, m, k);
  666. printf("inv b:\n");
  667. dump_u8xu8((unsigned char *)invert_matrix, k, k);
  668. printf("\ndecode_matrix:\n");
  669. dump_u8xu8((unsigned char *)decode_matrix, m, k);
  670. printf("orig data:\n");
  671. dump_matrix(buffs, m, 25);
  672. printf("orig :");
  673. dump(buffs[src_err_list[i]], 25);
  674. printf("recov %d:", src_err_list[i]);
  675. dump(temp_buffs[k + i], 25);
  676. re = -1;
  677. goto exit;
  678. }
  679. }
  680. }
  681. printf("done EC tests: Pass\n");
  682. re = 0;
  683. exit:
  684. for (i = 0; i < TEST_SOURCES; i++) {
  685. if (buffs[i])
  686. aligned_free(buffs[i]);
  687. if (temp_buffs[i])
  688. aligned_free(temp_buffs[i]);
  689. }
  690. free(encode_matrix);
  691. free(decode_matrix);
  692. free(invert_matrix);
  693. free(g_tbls);
  694. return re;
  695. }