erasure_code_base_test.c 22 KB

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