100c1efc1SGreg Tucker /**********************************************************************
200c1efc1SGreg Tucker Copyright(c) 2011-2015 Intel Corporation All rights reserved.
300c1efc1SGreg Tucker
400c1efc1SGreg Tucker Redistribution and use in source and binary forms, with or without
500c1efc1SGreg Tucker modification, are permitted provided that the following conditions
600c1efc1SGreg Tucker are met:
700c1efc1SGreg Tucker * Redistributions of source code must retain the above copyright
800c1efc1SGreg Tucker notice, this list of conditions and the following disclaimer.
900c1efc1SGreg Tucker * Redistributions in binary form must reproduce the above copyright
1000c1efc1SGreg Tucker notice, this list of conditions and the following disclaimer in
1100c1efc1SGreg Tucker the documentation and/or other materials provided with the
1200c1efc1SGreg Tucker distribution.
1300c1efc1SGreg Tucker * Neither the name of Intel Corporation nor the names of its
1400c1efc1SGreg Tucker contributors may be used to endorse or promote products derived
1500c1efc1SGreg Tucker from this software without specific prior written permission.
1600c1efc1SGreg Tucker
1700c1efc1SGreg Tucker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1800c1efc1SGreg Tucker "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1900c1efc1SGreg Tucker LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2000c1efc1SGreg Tucker A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2100c1efc1SGreg Tucker OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2200c1efc1SGreg Tucker SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2300c1efc1SGreg Tucker LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2400c1efc1SGreg Tucker DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2500c1efc1SGreg Tucker THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2600c1efc1SGreg Tucker (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2700c1efc1SGreg Tucker OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2800c1efc1SGreg Tucker **********************************************************************/
2900c1efc1SGreg Tucker
3000c1efc1SGreg Tucker #include <stdio.h>
3100c1efc1SGreg Tucker #include <stdlib.h>
3200c1efc1SGreg Tucker #include <string.h> // for memset, memcmp
33402bd4f7STomasz Kantecki #include <assert.h>
3400c1efc1SGreg Tucker #include "erasure_code.h"
35112dd72cSGreg Tucker #include "test.h"
3600c1efc1SGreg Tucker
3700c1efc1SGreg Tucker #define TEST_LEN 8192
3800c1efc1SGreg Tucker #define TEST_SIZE (TEST_LEN / 2)
3900c1efc1SGreg Tucker
4000c1efc1SGreg Tucker #ifndef TEST_SOURCES
4100c1efc1SGreg Tucker #define TEST_SOURCES 127
4200c1efc1SGreg Tucker #endif
4300c1efc1SGreg Tucker #ifndef RANDOMS
4400c1efc1SGreg Tucker #define RANDOMS 200
4500c1efc1SGreg Tucker #endif
4600c1efc1SGreg Tucker
4700c1efc1SGreg Tucker #define MMAX TEST_SOURCES
4800c1efc1SGreg Tucker #define KMAX TEST_SOURCES
4900c1efc1SGreg Tucker
5000c1efc1SGreg Tucker #define EFENCE_TEST_MIN_SIZE 16
514f2d148aSRoy Oursler #define EFENCE_TEST_MAX_SIZE EFENCE_TEST_MIN_SIZE + 0x100
5200c1efc1SGreg Tucker
5300c1efc1SGreg Tucker #ifdef EC_ALIGNED_ADDR
5400c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
5500c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B 0
5600c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B 0 // 0 for aligned only
5700c1efc1SGreg Tucker #else
5800c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
5900c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B 32
6000c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B 32 // 0 for aligned only
6100c1efc1SGreg Tucker #endif
6200c1efc1SGreg Tucker
6300c1efc1SGreg Tucker #ifndef TEST_SEED
6400c1efc1SGreg Tucker #define TEST_SEED 11
6500c1efc1SGreg Tucker #endif
6600c1efc1SGreg Tucker
6700c1efc1SGreg Tucker typedef unsigned char u8;
6800c1efc1SGreg Tucker
69*300260a4SMarcel Cornu void
dump(unsigned char * buf,int len)70*300260a4SMarcel Cornu dump(unsigned char *buf, int len)
7100c1efc1SGreg Tucker {
7200c1efc1SGreg Tucker int i;
7300c1efc1SGreg Tucker for (i = 0; i < len;) {
7400c1efc1SGreg Tucker printf(" %2x", 0xff & buf[i++]);
7500c1efc1SGreg Tucker if (i % 32 == 0)
7600c1efc1SGreg Tucker printf("\n");
7700c1efc1SGreg Tucker }
7800c1efc1SGreg Tucker printf("\n");
7900c1efc1SGreg Tucker }
8000c1efc1SGreg Tucker
81*300260a4SMarcel Cornu void
dump_matrix(unsigned char ** s,int k,int m)82*300260a4SMarcel Cornu dump_matrix(unsigned char **s, int k, int m)
8300c1efc1SGreg Tucker {
8400c1efc1SGreg Tucker int i, j;
8500c1efc1SGreg Tucker for (i = 0; i < k; i++) {
8600c1efc1SGreg Tucker for (j = 0; j < m; j++) {
8700c1efc1SGreg Tucker printf(" %2x", s[i][j]);
8800c1efc1SGreg Tucker }
8900c1efc1SGreg Tucker printf("\n");
9000c1efc1SGreg Tucker }
9100c1efc1SGreg Tucker printf("\n");
9200c1efc1SGreg Tucker }
9300c1efc1SGreg Tucker
94*300260a4SMarcel Cornu void
dump_u8xu8(unsigned char * s,int k,int m)95*300260a4SMarcel Cornu dump_u8xu8(unsigned char *s, int k, int m)
9600c1efc1SGreg Tucker {
9700c1efc1SGreg Tucker int i, j;
9800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
9900c1efc1SGreg Tucker for (j = 0; j < m; j++) {
10000c1efc1SGreg Tucker printf(" %2x", 0xff & s[j + (i * m)]);
10100c1efc1SGreg Tucker }
10200c1efc1SGreg Tucker printf("\n");
10300c1efc1SGreg Tucker }
10400c1efc1SGreg Tucker printf("\n");
10500c1efc1SGreg Tucker }
10600c1efc1SGreg Tucker
10700c1efc1SGreg Tucker // Generate Random errors
108*300260a4SMarcel Cornu static void
gen_err_list(unsigned char * src_err_list,unsigned char * src_in_err,int * pnerrs,int * pnsrcerrs,int k,int m)109*300260a4SMarcel Cornu gen_err_list(unsigned char *src_err_list, unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs,
110*300260a4SMarcel Cornu int k, int m)
11100c1efc1SGreg Tucker {
11200c1efc1SGreg Tucker int i, err;
11300c1efc1SGreg Tucker int nerrs = 0, nsrcerrs = 0;
11400c1efc1SGreg Tucker
11500c1efc1SGreg Tucker for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
11600c1efc1SGreg Tucker err = 1 & rand();
11700c1efc1SGreg Tucker src_in_err[i] = err;
11800c1efc1SGreg Tucker if (err) {
11900c1efc1SGreg Tucker src_err_list[nerrs++] = i;
12000c1efc1SGreg Tucker if (i < k) {
12100c1efc1SGreg Tucker nsrcerrs++;
12200c1efc1SGreg Tucker }
12300c1efc1SGreg Tucker }
12400c1efc1SGreg Tucker }
12500c1efc1SGreg Tucker if (nerrs == 0) { // should have at least one error
126*300260a4SMarcel Cornu while ((err = (rand() % KMAX)) >= m)
127*300260a4SMarcel Cornu ;
12800c1efc1SGreg Tucker src_err_list[nerrs++] = err;
12900c1efc1SGreg Tucker src_in_err[err] = 1;
13000c1efc1SGreg Tucker if (err < k)
13100c1efc1SGreg Tucker nsrcerrs = 1;
13200c1efc1SGreg Tucker }
13300c1efc1SGreg Tucker *pnerrs = nerrs;
13400c1efc1SGreg Tucker *pnsrcerrs = nsrcerrs;
13500c1efc1SGreg Tucker return;
13600c1efc1SGreg Tucker }
13700c1efc1SGreg Tucker
13800c1efc1SGreg Tucker #define NO_INVERT_MATRIX -2
13900c1efc1SGreg Tucker // Generate decode matrix from encode matrix
140*300260a4SMarcel Cornu static int
gf_gen_decode_matrix(unsigned char * encode_matrix,unsigned char * decode_matrix,unsigned char * invert_matrix,unsigned int * decode_index,unsigned char * src_err_list,unsigned char * src_in_err,int nerrs,int nsrcerrs,int k,int m)141*300260a4SMarcel Cornu gf_gen_decode_matrix(unsigned char *encode_matrix, unsigned char *decode_matrix,
142*300260a4SMarcel Cornu unsigned char *invert_matrix, unsigned int *decode_index,
143*300260a4SMarcel Cornu unsigned char *src_err_list, unsigned char *src_in_err, int nerrs,
144*300260a4SMarcel Cornu int nsrcerrs, int k, int m)
14500c1efc1SGreg Tucker {
14600c1efc1SGreg Tucker int i, j, p;
14700c1efc1SGreg Tucker int r;
14800c1efc1SGreg Tucker unsigned char *backup, *b, s;
14900c1efc1SGreg Tucker int incr = 0;
15000c1efc1SGreg Tucker
15100c1efc1SGreg Tucker b = malloc(MMAX * KMAX);
15200c1efc1SGreg Tucker backup = malloc(MMAX * KMAX);
15300c1efc1SGreg Tucker
15400c1efc1SGreg Tucker if (b == NULL || backup == NULL) {
15500c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
15600c1efc1SGreg Tucker free(b);
15700c1efc1SGreg Tucker free(backup);
15800c1efc1SGreg Tucker return -1;
15900c1efc1SGreg Tucker }
16000c1efc1SGreg Tucker // Construct matrix b by removing error rows
16100c1efc1SGreg Tucker for (i = 0, r = 0; i < k; i++, r++) {
16200c1efc1SGreg Tucker while (src_in_err[r])
16300c1efc1SGreg Tucker r++;
16400c1efc1SGreg Tucker for (j = 0; j < k; j++) {
16500c1efc1SGreg Tucker b[k * i + j] = encode_matrix[k * r + j];
16600c1efc1SGreg Tucker backup[k * i + j] = encode_matrix[k * r + j];
16700c1efc1SGreg Tucker }
16800c1efc1SGreg Tucker decode_index[i] = r;
16900c1efc1SGreg Tucker }
17000c1efc1SGreg Tucker incr = 0;
17100c1efc1SGreg Tucker while (gf_invert_matrix(b, invert_matrix, k) < 0) {
17200c1efc1SGreg Tucker if (nerrs == (m - k)) {
17300c1efc1SGreg Tucker free(b);
17400c1efc1SGreg Tucker free(backup);
17500c1efc1SGreg Tucker printf("BAD MATRIX\n");
17600c1efc1SGreg Tucker return NO_INVERT_MATRIX;
17700c1efc1SGreg Tucker }
17800c1efc1SGreg Tucker incr++;
17900c1efc1SGreg Tucker memcpy(b, backup, MMAX * KMAX);
18000c1efc1SGreg Tucker for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
18100c1efc1SGreg Tucker if (src_err_list[i] == (decode_index[k - 1] + incr)) {
18200c1efc1SGreg Tucker // skip the erased parity line
18300c1efc1SGreg Tucker incr++;
18400c1efc1SGreg Tucker continue;
18500c1efc1SGreg Tucker }
18600c1efc1SGreg Tucker }
18700c1efc1SGreg Tucker if (decode_index[k - 1] + incr >= m) {
18800c1efc1SGreg Tucker free(b);
18900c1efc1SGreg Tucker free(backup);
19000c1efc1SGreg Tucker printf("BAD MATRIX\n");
19100c1efc1SGreg Tucker return NO_INVERT_MATRIX;
19200c1efc1SGreg Tucker }
19300c1efc1SGreg Tucker decode_index[k - 1] += incr;
19400c1efc1SGreg Tucker for (j = 0; j < k; j++)
19500c1efc1SGreg Tucker b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
19600c1efc1SGreg Tucker };
19700c1efc1SGreg Tucker
19800c1efc1SGreg Tucker for (i = 0; i < nsrcerrs; i++) {
19900c1efc1SGreg Tucker for (j = 0; j < k; j++) {
20000c1efc1SGreg Tucker decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
20100c1efc1SGreg Tucker }
20200c1efc1SGreg Tucker }
20300c1efc1SGreg Tucker /* src_err_list from encode_matrix * invert of b for parity decoding */
20400c1efc1SGreg Tucker for (p = nsrcerrs; p < nerrs; p++) {
20500c1efc1SGreg Tucker for (i = 0; i < k; i++) {
20600c1efc1SGreg Tucker s = 0;
20700c1efc1SGreg Tucker for (j = 0; j < k; j++)
20800c1efc1SGreg Tucker s ^= gf_mul(invert_matrix[j * k + i],
20900c1efc1SGreg Tucker encode_matrix[k * src_err_list[p] + j]);
21000c1efc1SGreg Tucker
21100c1efc1SGreg Tucker decode_matrix[k * p + i] = s;
21200c1efc1SGreg Tucker }
21300c1efc1SGreg Tucker }
21400c1efc1SGreg Tucker free(b);
21500c1efc1SGreg Tucker free(backup);
21600c1efc1SGreg Tucker return 0;
21700c1efc1SGreg Tucker }
21800c1efc1SGreg Tucker
219*300260a4SMarcel Cornu int
main(int argc,char * argv[])220*300260a4SMarcel Cornu main(int argc, char *argv[])
22100c1efc1SGreg Tucker {
222a3e26043SPablo de Lara int re = -1;
22300c1efc1SGreg Tucker int i, j, p, rtest, m, k;
22400c1efc1SGreg Tucker int nerrs, nsrcerrs;
22500c1efc1SGreg Tucker void *buf;
22600c1efc1SGreg Tucker unsigned int decode_index[MMAX];
227a3e26043SPablo de Lara unsigned char *temp_buffs[TEST_SOURCES] = { NULL }, *buffs[TEST_SOURCES] = { NULL };
228*300260a4SMarcel Cornu unsigned char *encode_matrix = NULL, *decode_matrix = NULL, *invert_matrix = NULL,
229*300260a4SMarcel Cornu *g_tbls = NULL;
23000c1efc1SGreg Tucker unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
23100c1efc1SGreg Tucker unsigned char *recov[TEST_SOURCES];
23200c1efc1SGreg Tucker
23300c1efc1SGreg Tucker int rows, align, size;
23400c1efc1SGreg Tucker unsigned char *efence_buffs[TEST_SOURCES];
23500c1efc1SGreg Tucker unsigned int offset;
23600c1efc1SGreg Tucker u8 *ubuffs[TEST_SOURCES];
23700c1efc1SGreg Tucker u8 *temp_ubuffs[TEST_SOURCES];
23800c1efc1SGreg Tucker
23900c1efc1SGreg Tucker printf("erasure_code_test: %dx%d ", TEST_SOURCES, TEST_LEN);
24000c1efc1SGreg Tucker srand(TEST_SEED);
24100c1efc1SGreg Tucker
24200c1efc1SGreg Tucker // Allocate the arrays
24300c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
24400c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
24500c1efc1SGreg Tucker printf("alloc error: Fail");
246a3e26043SPablo de Lara goto exit;
24700c1efc1SGreg Tucker }
24800c1efc1SGreg Tucker buffs[i] = buf;
24900c1efc1SGreg Tucker }
25000c1efc1SGreg Tucker
25100c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
25200c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
25300c1efc1SGreg Tucker printf("alloc error: Fail");
254a3e26043SPablo de Lara goto exit;
25500c1efc1SGreg Tucker }
25600c1efc1SGreg Tucker temp_buffs[i] = buf;
25700c1efc1SGreg Tucker }
25800c1efc1SGreg Tucker
25900c1efc1SGreg Tucker // Test erasure code by encode and recovery
26000c1efc1SGreg Tucker
26100c1efc1SGreg Tucker encode_matrix = malloc(MMAX * KMAX);
26200c1efc1SGreg Tucker decode_matrix = malloc(MMAX * KMAX);
26300c1efc1SGreg Tucker invert_matrix = malloc(MMAX * KMAX);
26400c1efc1SGreg Tucker g_tbls = malloc(KMAX * TEST_SOURCES * 32);
265*300260a4SMarcel Cornu if (encode_matrix == NULL || decode_matrix == NULL || invert_matrix == NULL ||
266*300260a4SMarcel Cornu g_tbls == NULL) {
26700c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
268a3e26043SPablo de Lara goto exit;
26900c1efc1SGreg Tucker }
27000c1efc1SGreg Tucker // Pick a first test
27100c1efc1SGreg Tucker m = 9;
27200c1efc1SGreg Tucker k = 5;
273402bd4f7STomasz Kantecki assert((m <= MMAX) && (k <= KMAX));
27400c1efc1SGreg Tucker
27500c1efc1SGreg Tucker // Make random data
27600c1efc1SGreg Tucker for (i = 0; i < k; i++)
27700c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
27800c1efc1SGreg Tucker buffs[i][j] = rand();
27900c1efc1SGreg Tucker
28000c1efc1SGreg Tucker // Generate encode matrix encode_matrix
28100c1efc1SGreg Tucker // The matrix generated by gf_gen_rs_matrix
28200c1efc1SGreg Tucker // is not always invertable.
28300c1efc1SGreg Tucker gf_gen_rs_matrix(encode_matrix, m, k);
28400c1efc1SGreg Tucker
28500c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
28600c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
28700c1efc1SGreg Tucker
28800c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
28900c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
29000c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
29100c1efc1SGreg Tucker
29200c1efc1SGreg Tucker // Choose random buffers to be in erasure
29300c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
29400c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
29500c1efc1SGreg Tucker
29600c1efc1SGreg Tucker // Generate decode matrix
297*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
298*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
29900c1efc1SGreg Tucker if (re != 0) {
30000c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
301a3e26043SPablo de Lara goto exit;
30200c1efc1SGreg Tucker }
30300c1efc1SGreg Tucker // Pack recovery array as list of valid sources
30400c1efc1SGreg Tucker // Its order must be the same as the order
30500c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
30600c1efc1SGreg Tucker for (i = 0; i < k; i++) {
30700c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
30800c1efc1SGreg Tucker }
30900c1efc1SGreg Tucker
31000c1efc1SGreg Tucker // Recover data
31100c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
31200c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
31300c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
31400c1efc1SGreg Tucker
31500c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
31600c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
31700c1efc1SGreg Tucker printf(" - erase list = ");
31800c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
31900c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
32000c1efc1SGreg Tucker printf(" - Index = ");
32100c1efc1SGreg Tucker for (p = 0; p < k; p++)
32200c1efc1SGreg Tucker printf(" %d", decode_index[p]);
32300c1efc1SGreg Tucker printf("\nencode_matrix:\n");
32400c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
32500c1efc1SGreg Tucker printf("inv b:\n");
32600c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
32700c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
32800c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
32900c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
33000c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
33100c1efc1SGreg Tucker printf("orig :");
33200c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
333a3e26043SPablo de Lara re = -1;
334a3e26043SPablo de Lara goto exit;
33500c1efc1SGreg Tucker }
33600c1efc1SGreg Tucker }
33700c1efc1SGreg Tucker
33800c1efc1SGreg Tucker // Pick a first test
33900c1efc1SGreg Tucker m = 9;
34000c1efc1SGreg Tucker k = 5;
341a3e26043SPablo de Lara if (m > MMAX || k > KMAX) {
342a3e26043SPablo de Lara re = -1;
343a3e26043SPablo de Lara goto exit;
344a3e26043SPablo de Lara }
34500c1efc1SGreg Tucker
34600c1efc1SGreg Tucker // Make random data
34700c1efc1SGreg Tucker for (i = 0; i < k; i++)
34800c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
34900c1efc1SGreg Tucker buffs[i][j] = rand();
35000c1efc1SGreg Tucker
35100c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
35200c1efc1SGreg Tucker // is always invertable.
35300c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
35400c1efc1SGreg Tucker
35500c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
35600c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
35700c1efc1SGreg Tucker
35800c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
35900c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
36000c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
36100c1efc1SGreg Tucker
36200c1efc1SGreg Tucker // Choose random buffers to be in erasure
36300c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
36400c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
36500c1efc1SGreg Tucker
36600c1efc1SGreg Tucker // Generate decode matrix
367*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
368*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
36900c1efc1SGreg Tucker if (re != 0) {
37000c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
371a3e26043SPablo de Lara goto exit;
37200c1efc1SGreg Tucker }
37300c1efc1SGreg Tucker // Pack recovery array as list of valid sources
37400c1efc1SGreg Tucker // Its order must be the same as the order
37500c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
37600c1efc1SGreg Tucker for (i = 0; i < k; i++) {
37700c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
37800c1efc1SGreg Tucker }
37900c1efc1SGreg Tucker
38000c1efc1SGreg Tucker // Recover data
38100c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
38200c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
38300c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
38400c1efc1SGreg Tucker
38500c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
38600c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
38700c1efc1SGreg Tucker printf(" - erase list = ");
38800c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
38900c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
39000c1efc1SGreg Tucker printf(" - Index = ");
39100c1efc1SGreg Tucker for (p = 0; p < k; p++)
39200c1efc1SGreg Tucker printf(" %d", decode_index[p]);
39300c1efc1SGreg Tucker printf("\nencode_matrix:\n");
39400c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
39500c1efc1SGreg Tucker printf("inv b:\n");
39600c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
39700c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
39800c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
39900c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
40000c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
40100c1efc1SGreg Tucker printf("orig :");
40200c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
403a3e26043SPablo de Lara re = -1;
404a3e26043SPablo de Lara goto exit;
40500c1efc1SGreg Tucker }
40600c1efc1SGreg Tucker }
40700c1efc1SGreg Tucker
40800c1efc1SGreg Tucker // Do more random tests
40900c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
410*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
411*300260a4SMarcel Cornu ;
412*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
413*300260a4SMarcel Cornu ;
41400c1efc1SGreg Tucker
41500c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
41600c1efc1SGreg Tucker continue;
41700c1efc1SGreg Tucker
41800c1efc1SGreg Tucker // Make random data
41900c1efc1SGreg Tucker for (i = 0; i < k; i++)
42000c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
42100c1efc1SGreg Tucker buffs[i][j] = rand();
42200c1efc1SGreg Tucker
42300c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
42400c1efc1SGreg Tucker // is always invertable.
42500c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
42600c1efc1SGreg Tucker
42700c1efc1SGreg Tucker // Make parity vects
42800c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
42900c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
43000c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
43100c1efc1SGreg Tucker // using g_tbls from encode matrix a
43200c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
43300c1efc1SGreg Tucker
43400c1efc1SGreg Tucker // Random errors
43500c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
43600c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
43700c1efc1SGreg Tucker
43800c1efc1SGreg Tucker // Generate decode matrix
439*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
440*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
44100c1efc1SGreg Tucker if (re != 0) {
44200c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
443a3e26043SPablo de Lara goto exit;
44400c1efc1SGreg Tucker }
44500c1efc1SGreg Tucker // Pack recovery array as list of valid sources
44600c1efc1SGreg Tucker // Its order must be the same as the order
44700c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
44800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
44900c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
45000c1efc1SGreg Tucker }
45100c1efc1SGreg Tucker
45200c1efc1SGreg Tucker // Recover data
45300c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
45400c1efc1SGreg Tucker ec_encode_data(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
45500c1efc1SGreg Tucker
45600c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
45700c1efc1SGreg Tucker
45800c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
45900c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
46000c1efc1SGreg Tucker printf(" - erase list = ");
46100c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
46200c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
46300c1efc1SGreg Tucker printf(" - Index = ");
46400c1efc1SGreg Tucker for (p = 0; p < k; p++)
46500c1efc1SGreg Tucker printf(" %d", decode_index[p]);
46600c1efc1SGreg Tucker printf("\nencode_matrix:\n");
46700c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
46800c1efc1SGreg Tucker printf("inv b:\n");
46900c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
47000c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
47100c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
47200c1efc1SGreg Tucker printf("orig data:\n");
47300c1efc1SGreg Tucker dump_matrix(buffs, m, 25);
47400c1efc1SGreg Tucker printf("orig :");
47500c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
47600c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
47700c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
478a3e26043SPablo de Lara re = -1;
479a3e26043SPablo de Lara goto exit;
48000c1efc1SGreg Tucker }
48100c1efc1SGreg Tucker }
4822ca781dfSPablo de Lara #ifdef TEST_VERBOSE
48300c1efc1SGreg Tucker putchar('.');
4842ca781dfSPablo de Lara #endif
48500c1efc1SGreg Tucker }
48600c1efc1SGreg Tucker
48700c1efc1SGreg Tucker // Run tests at end of buffer for Electric Fence
48800c1efc1SGreg Tucker k = 16;
48900c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
490a3e26043SPablo de Lara if (k > KMAX) {
491a3e26043SPablo de Lara re = -1;
492a3e26043SPablo de Lara goto exit;
493a3e26043SPablo de Lara }
49400c1efc1SGreg Tucker
49500c1efc1SGreg Tucker for (rows = 1; rows <= 16; rows++) {
49600c1efc1SGreg Tucker m = k + rows;
497a3e26043SPablo de Lara if (m > MMAX) {
498a3e26043SPablo de Lara re = -1;
499a3e26043SPablo de Lara goto exit;
500a3e26043SPablo de Lara }
50100c1efc1SGreg Tucker
50200c1efc1SGreg Tucker // Make random data
50300c1efc1SGreg Tucker for (i = 0; i < k; i++)
50400c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
50500c1efc1SGreg Tucker buffs[i][j] = rand();
50600c1efc1SGreg Tucker
5074f2d148aSRoy Oursler for (size = EFENCE_TEST_MIN_SIZE; size <= EFENCE_TEST_MAX_SIZE; size += align) {
50800c1efc1SGreg Tucker for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
50900c1efc1SGreg Tucker efence_buffs[i] = buffs[i] + TEST_LEN - size;
51000c1efc1SGreg Tucker }
51100c1efc1SGreg Tucker
51200c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
51300c1efc1SGreg Tucker // is always invertable.
51400c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
51500c1efc1SGreg Tucker
51600c1efc1SGreg Tucker // Make parity vects
51700c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
51800c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
51900c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
52000c1efc1SGreg Tucker // using g_tbls from encode matrix a
52100c1efc1SGreg Tucker ec_encode_data(size, k, m - k, g_tbls, efence_buffs, &efence_buffs[k]);
52200c1efc1SGreg Tucker
52300c1efc1SGreg Tucker // Random errors
52400c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
52500c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
52600c1efc1SGreg Tucker
52700c1efc1SGreg Tucker // Generate decode matrix
528*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix,
529*300260a4SMarcel Cornu decode_index, src_err_list, src_in_err, nerrs,
530*300260a4SMarcel Cornu nsrcerrs, k, m);
53100c1efc1SGreg Tucker if (re != 0) {
53200c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
533a3e26043SPablo de Lara goto exit;
53400c1efc1SGreg Tucker }
53500c1efc1SGreg Tucker // Pack recovery array as list of valid sources
53600c1efc1SGreg Tucker // Its order must be the same as the order
53700c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
53800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
53900c1efc1SGreg Tucker recov[i] = efence_buffs[decode_index[i]];
54000c1efc1SGreg Tucker }
54100c1efc1SGreg Tucker
54200c1efc1SGreg Tucker // Recover data
54300c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
54400c1efc1SGreg Tucker ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
54500c1efc1SGreg Tucker
54600c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
54700c1efc1SGreg Tucker
548*300260a4SMarcel Cornu if (0 != memcmp(temp_buffs[k + i], efence_buffs[src_err_list[i]],
54900c1efc1SGreg Tucker size)) {
550*300260a4SMarcel Cornu printf("Efence: Fail error recovery (%d, %d, %d)\n", m, k,
551*300260a4SMarcel Cornu nerrs);
55200c1efc1SGreg Tucker
55300c1efc1SGreg Tucker printf("size = %d\n", size);
55400c1efc1SGreg Tucker
55500c1efc1SGreg Tucker printf("Test erase list = ");
55600c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
55700c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
55800c1efc1SGreg Tucker printf(" - Index = ");
55900c1efc1SGreg Tucker for (p = 0; p < k; p++)
56000c1efc1SGreg Tucker printf(" %d", decode_index[p]);
56100c1efc1SGreg Tucker printf("\nencode_matrix:\n");
56200c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
56300c1efc1SGreg Tucker printf("inv b:\n");
56400c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
56500c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
56600c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
56700c1efc1SGreg Tucker
56800c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
56900c1efc1SGreg Tucker dump(temp_buffs[k + i], align);
57000c1efc1SGreg Tucker printf("orig :");
57100c1efc1SGreg Tucker dump(efence_buffs[src_err_list[i]], align);
572a3e26043SPablo de Lara re = -1;
573a3e26043SPablo de Lara goto exit;
57400c1efc1SGreg Tucker }
57500c1efc1SGreg Tucker }
57600c1efc1SGreg Tucker }
57700c1efc1SGreg Tucker }
57800c1efc1SGreg Tucker
57900c1efc1SGreg Tucker // Test rand ptr alignment if available
58000c1efc1SGreg Tucker
58100c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
582*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
583*300260a4SMarcel Cornu ;
584*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
585*300260a4SMarcel Cornu ;
58600c1efc1SGreg Tucker
58700c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
58800c1efc1SGreg Tucker continue;
58900c1efc1SGreg Tucker
59000c1efc1SGreg Tucker size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
59100c1efc1SGreg Tucker
59200c1efc1SGreg Tucker offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
59300c1efc1SGreg Tucker // Add random offsets
59400c1efc1SGreg Tucker for (i = 0; i < m; i++) {
59500c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
59600c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
59700c1efc1SGreg Tucker ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
59800c1efc1SGreg Tucker temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
59900c1efc1SGreg Tucker }
60000c1efc1SGreg Tucker
60100c1efc1SGreg Tucker for (i = 0; i < k; i++)
60200c1efc1SGreg Tucker for (j = 0; j < size; j++)
60300c1efc1SGreg Tucker ubuffs[i][j] = rand();
60400c1efc1SGreg Tucker
60500c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
60600c1efc1SGreg Tucker // is always invertable.
60700c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
60800c1efc1SGreg Tucker
60900c1efc1SGreg Tucker // Make parity vects
61000c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
61100c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
61200c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
61300c1efc1SGreg Tucker // using g_tbls from encode matrix a
61400c1efc1SGreg Tucker ec_encode_data(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
61500c1efc1SGreg Tucker
61600c1efc1SGreg Tucker // Random errors
61700c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
61800c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
61900c1efc1SGreg Tucker
62000c1efc1SGreg Tucker // Generate decode matrix
621*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
622*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
62300c1efc1SGreg Tucker if (re != 0) {
62400c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
625a3e26043SPablo de Lara goto exit;
62600c1efc1SGreg Tucker }
62700c1efc1SGreg Tucker // Pack recovery array as list of valid sources
62800c1efc1SGreg Tucker // Its order must be the same as the order
62900c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
63000c1efc1SGreg Tucker for (i = 0; i < k; i++) {
63100c1efc1SGreg Tucker recov[i] = ubuffs[decode_index[i]];
63200c1efc1SGreg Tucker }
63300c1efc1SGreg Tucker
63400c1efc1SGreg Tucker // Recover data
63500c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
63600c1efc1SGreg Tucker ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_ubuffs[k]);
63700c1efc1SGreg Tucker
63800c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
63900c1efc1SGreg Tucker
64000c1efc1SGreg Tucker if (0 != memcmp(temp_ubuffs[k + i], ubuffs[src_err_list[i]], size)) {
64100c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
64200c1efc1SGreg Tucker printf(" - erase list = ");
64300c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
64400c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
64500c1efc1SGreg Tucker printf(" - Index = ");
64600c1efc1SGreg Tucker for (p = 0; p < k; p++)
64700c1efc1SGreg Tucker printf(" %d", decode_index[p]);
64800c1efc1SGreg Tucker printf("\nencode_matrix:\n");
64900c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
65000c1efc1SGreg Tucker printf("inv b:\n");
65100c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
65200c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
65300c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
65400c1efc1SGreg Tucker printf("orig data:\n");
65500c1efc1SGreg Tucker dump_matrix(ubuffs, m, 25);
65600c1efc1SGreg Tucker printf("orig :");
65700c1efc1SGreg Tucker dump(ubuffs[src_err_list[i]], 25);
65800c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
65900c1efc1SGreg Tucker dump(temp_ubuffs[k + i], 25);
660a3e26043SPablo de Lara re = -1;
661a3e26043SPablo de Lara goto exit;
66200c1efc1SGreg Tucker }
66300c1efc1SGreg Tucker }
66400c1efc1SGreg Tucker
66500c1efc1SGreg Tucker // Confirm that padding around dests is unchanged
66600c1efc1SGreg Tucker memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
66700c1efc1SGreg Tucker
66800c1efc1SGreg Tucker for (i = 0; i < m; i++) {
66900c1efc1SGreg Tucker
67000c1efc1SGreg Tucker offset = ubuffs[i] - buffs[i];
67100c1efc1SGreg Tucker
67200c1efc1SGreg Tucker if (memcmp(buffs[i], temp_buffs[0], offset)) {
67300c1efc1SGreg Tucker printf("Fail rand ualign encode pad start\n");
674a3e26043SPablo de Lara re = -1;
675a3e26043SPablo de Lara goto exit;
67600c1efc1SGreg Tucker }
677*300260a4SMarcel Cornu if (memcmp(buffs[i] + offset + size, temp_buffs[0],
67800c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
67900c1efc1SGreg Tucker printf("Fail rand ualign encode pad end\n");
680a3e26043SPablo de Lara re = -1;
681a3e26043SPablo de Lara goto exit;
68200c1efc1SGreg Tucker }
68300c1efc1SGreg Tucker }
68400c1efc1SGreg Tucker
68500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
68600c1efc1SGreg Tucker
68700c1efc1SGreg Tucker offset = temp_ubuffs[k + i] - temp_buffs[k + i];
68800c1efc1SGreg Tucker if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
68900c1efc1SGreg Tucker printf("Fail rand ualign decode pad start\n");
690a3e26043SPablo de Lara re = -1;
691a3e26043SPablo de Lara goto exit;
69200c1efc1SGreg Tucker }
693*300260a4SMarcel Cornu if (memcmp(temp_buffs[k + i] + offset + size, temp_buffs[0],
69400c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
69500c1efc1SGreg Tucker printf("Fail rand ualign decode pad end\n");
696a3e26043SPablo de Lara re = -1;
697a3e26043SPablo de Lara goto exit;
69800c1efc1SGreg Tucker }
69900c1efc1SGreg Tucker }
70000c1efc1SGreg Tucker
7012ca781dfSPablo de Lara #ifdef TEST_VERBOSE
70200c1efc1SGreg Tucker putchar('.');
7032ca781dfSPablo de Lara #endif
70400c1efc1SGreg Tucker }
70500c1efc1SGreg Tucker
70600c1efc1SGreg Tucker // Test size alignment
70700c1efc1SGreg Tucker
70800c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 13 : 16;
70900c1efc1SGreg Tucker
71000c1efc1SGreg Tucker for (size = TEST_LEN; size > 0; size -= align) {
711*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
712*300260a4SMarcel Cornu ;
713*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
714*300260a4SMarcel Cornu ;
71500c1efc1SGreg Tucker
71600c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
71700c1efc1SGreg Tucker continue;
71800c1efc1SGreg Tucker
71900c1efc1SGreg Tucker for (i = 0; i < k; i++)
72000c1efc1SGreg Tucker for (j = 0; j < size; j++)
72100c1efc1SGreg Tucker buffs[i][j] = rand();
72200c1efc1SGreg Tucker
72300c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
72400c1efc1SGreg Tucker // is always invertable.
72500c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
72600c1efc1SGreg Tucker
72700c1efc1SGreg Tucker // Make parity vects
72800c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
72900c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
73000c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
73100c1efc1SGreg Tucker // using g_tbls from encode matrix a
73200c1efc1SGreg Tucker ec_encode_data(size, k, m - k, g_tbls, buffs, &buffs[k]);
73300c1efc1SGreg Tucker
73400c1efc1SGreg Tucker // Random errors
73500c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
73600c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
73700c1efc1SGreg Tucker // Generate decode matrix
738*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
739*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
74000c1efc1SGreg Tucker if (re != 0) {
74100c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
742a3e26043SPablo de Lara goto exit;
74300c1efc1SGreg Tucker }
74400c1efc1SGreg Tucker // Pack recovery array as list of valid sources
74500c1efc1SGreg Tucker // Its order must be the same as the order
74600c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
74700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
74800c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
74900c1efc1SGreg Tucker }
75000c1efc1SGreg Tucker
75100c1efc1SGreg Tucker // Recover data
75200c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
75300c1efc1SGreg Tucker ec_encode_data(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
75400c1efc1SGreg Tucker
75500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
75600c1efc1SGreg Tucker
75700c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], size)) {
75800c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
75900c1efc1SGreg Tucker printf(" - erase list = ");
76000c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
76100c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
76200c1efc1SGreg Tucker printf(" - Index = ");
76300c1efc1SGreg Tucker for (p = 0; p < k; p++)
76400c1efc1SGreg Tucker printf(" %d", decode_index[p]);
76500c1efc1SGreg Tucker printf("\nencode_matrix:\n");
76600c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
76700c1efc1SGreg Tucker printf("inv b:\n");
76800c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
76900c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
77000c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
77100c1efc1SGreg Tucker printf("orig data:\n");
77200c1efc1SGreg Tucker dump_matrix(buffs, m, 25);
77300c1efc1SGreg Tucker printf("orig :");
77400c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
77500c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
77600c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
777a3e26043SPablo de Lara re = -1;
778a3e26043SPablo de Lara goto exit;
77900c1efc1SGreg Tucker }
78000c1efc1SGreg Tucker }
78100c1efc1SGreg Tucker }
78200c1efc1SGreg Tucker
78300c1efc1SGreg Tucker printf("done EC tests: Pass\n");
784a3e26043SPablo de Lara re = 0;
785a3e26043SPablo de Lara
786a3e26043SPablo de Lara exit:
787a3e26043SPablo de Lara for (i = 0; i < TEST_SOURCES; i++) {
788a3e26043SPablo de Lara if (buffs[i])
789a3e26043SPablo de Lara aligned_free(buffs[i]);
790a3e26043SPablo de Lara if (temp_buffs[i])
791a3e26043SPablo de Lara aligned_free(temp_buffs[i]);
792a3e26043SPablo de Lara }
793a3e26043SPablo de Lara free(encode_matrix);
794a3e26043SPablo de Lara free(decode_matrix);
795a3e26043SPablo de Lara free(invert_matrix);
796a3e26043SPablo de Lara free(g_tbls);
797a3e26043SPablo de Lara
798a3e26043SPablo de Lara return re;
79900c1efc1SGreg Tucker }
800