erasure_code_update_test.c 28 KB

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