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 50
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
5100c1efc1SGreg Tucker
5200c1efc1SGreg Tucker #ifdef EC_ALIGNED_ADDR
5300c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
5400c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B 0
5500c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B 0 // 0 for aligned only
5600c1efc1SGreg Tucker #else
5700c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
5800c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B 32
5900c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B 32 // 0 for aligned only
6000c1efc1SGreg Tucker #endif
6100c1efc1SGreg Tucker
6200c1efc1SGreg Tucker #ifndef TEST_SEED
6300c1efc1SGreg Tucker #define TEST_SEED 11
6400c1efc1SGreg Tucker #endif
6500c1efc1SGreg Tucker
6600c1efc1SGreg Tucker typedef unsigned char u8;
6700c1efc1SGreg Tucker
68*300260a4SMarcel Cornu void
dump(unsigned char * buf,int len)69*300260a4SMarcel Cornu dump(unsigned char *buf, int len)
7000c1efc1SGreg Tucker {
7100c1efc1SGreg Tucker int i;
7200c1efc1SGreg Tucker for (i = 0; i < len;) {
7300c1efc1SGreg Tucker printf(" %2x", 0xff & buf[i++]);
7400c1efc1SGreg Tucker if (i % 32 == 0)
7500c1efc1SGreg Tucker printf("\n");
7600c1efc1SGreg Tucker }
7700c1efc1SGreg Tucker printf("\n");
7800c1efc1SGreg Tucker }
7900c1efc1SGreg Tucker
80*300260a4SMarcel Cornu void
dump_matrix(unsigned char ** s,int k,int m)81*300260a4SMarcel Cornu dump_matrix(unsigned char **s, int k, int m)
8200c1efc1SGreg Tucker {
8300c1efc1SGreg Tucker int i, j;
8400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
8500c1efc1SGreg Tucker for (j = 0; j < m; j++) {
8600c1efc1SGreg Tucker printf(" %2x", s[i][j]);
8700c1efc1SGreg Tucker }
8800c1efc1SGreg Tucker printf("\n");
8900c1efc1SGreg Tucker }
9000c1efc1SGreg Tucker printf("\n");
9100c1efc1SGreg Tucker }
9200c1efc1SGreg Tucker
93*300260a4SMarcel Cornu void
dump_u8xu8(unsigned char * s,int k,int m)94*300260a4SMarcel Cornu dump_u8xu8(unsigned char *s, int k, int m)
9500c1efc1SGreg Tucker {
9600c1efc1SGreg Tucker int i, j;
9700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
9800c1efc1SGreg Tucker for (j = 0; j < m; j++) {
9900c1efc1SGreg Tucker printf(" %2x", 0xff & s[j + (i * m)]);
10000c1efc1SGreg Tucker }
10100c1efc1SGreg Tucker printf("\n");
10200c1efc1SGreg Tucker }
10300c1efc1SGreg Tucker printf("\n");
10400c1efc1SGreg Tucker }
10500c1efc1SGreg Tucker
10600c1efc1SGreg Tucker // Generate Random errors
107*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)108*300260a4SMarcel Cornu gen_err_list(unsigned char *src_err_list, unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs,
109*300260a4SMarcel Cornu int k, int m)
11000c1efc1SGreg Tucker {
11100c1efc1SGreg Tucker int i, err;
11200c1efc1SGreg Tucker int nerrs = 0, nsrcerrs = 0;
11300c1efc1SGreg Tucker
11400c1efc1SGreg Tucker for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
11500c1efc1SGreg Tucker err = 1 & rand();
11600c1efc1SGreg Tucker src_in_err[i] = err;
11700c1efc1SGreg Tucker if (err) {
11800c1efc1SGreg Tucker src_err_list[nerrs++] = i;
11900c1efc1SGreg Tucker if (i < k) {
12000c1efc1SGreg Tucker nsrcerrs++;
12100c1efc1SGreg Tucker }
12200c1efc1SGreg Tucker }
12300c1efc1SGreg Tucker }
12400c1efc1SGreg Tucker if (nerrs == 0) { // should have at least one error
125*300260a4SMarcel Cornu while ((err = (rand() % KMAX)) >= m)
126*300260a4SMarcel Cornu ;
12700c1efc1SGreg Tucker src_err_list[nerrs++] = err;
12800c1efc1SGreg Tucker src_in_err[err] = 1;
12900c1efc1SGreg Tucker if (err < k)
13000c1efc1SGreg Tucker nsrcerrs = 1;
13100c1efc1SGreg Tucker }
13200c1efc1SGreg Tucker *pnerrs = nerrs;
13300c1efc1SGreg Tucker *pnsrcerrs = nsrcerrs;
13400c1efc1SGreg Tucker return;
13500c1efc1SGreg Tucker }
13600c1efc1SGreg Tucker
13700c1efc1SGreg Tucker #define NO_INVERT_MATRIX -2
13800c1efc1SGreg Tucker // Generate decode matrix from encode matrix
139*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)140*300260a4SMarcel Cornu gf_gen_decode_matrix(unsigned char *encode_matrix, unsigned char *decode_matrix,
141*300260a4SMarcel Cornu unsigned char *invert_matrix, unsigned int *decode_index,
142*300260a4SMarcel Cornu unsigned char *src_err_list, unsigned char *src_in_err, int nerrs,
143*300260a4SMarcel Cornu int nsrcerrs, int k, int m)
14400c1efc1SGreg Tucker {
14500c1efc1SGreg Tucker int i, j, p;
14600c1efc1SGreg Tucker int r;
14700c1efc1SGreg Tucker unsigned char *backup, *b, s;
14800c1efc1SGreg Tucker int incr = 0;
14900c1efc1SGreg Tucker
15000c1efc1SGreg Tucker b = malloc(MMAX * KMAX);
15100c1efc1SGreg Tucker backup = malloc(MMAX * KMAX);
15200c1efc1SGreg Tucker
15300c1efc1SGreg Tucker if (b == NULL || backup == NULL) {
15400c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
15500c1efc1SGreg Tucker free(b);
15600c1efc1SGreg Tucker free(backup);
15700c1efc1SGreg Tucker return -1;
15800c1efc1SGreg Tucker }
15900c1efc1SGreg Tucker // Construct matrix b by removing error rows
16000c1efc1SGreg Tucker for (i = 0, r = 0; i < k; i++, r++) {
16100c1efc1SGreg Tucker while (src_in_err[r])
16200c1efc1SGreg Tucker r++;
16300c1efc1SGreg Tucker for (j = 0; j < k; j++) {
16400c1efc1SGreg Tucker b[k * i + j] = encode_matrix[k * r + j];
16500c1efc1SGreg Tucker backup[k * i + j] = encode_matrix[k * r + j];
16600c1efc1SGreg Tucker }
16700c1efc1SGreg Tucker decode_index[i] = r;
16800c1efc1SGreg Tucker }
16900c1efc1SGreg Tucker incr = 0;
17000c1efc1SGreg Tucker while (gf_invert_matrix(b, invert_matrix, k) < 0) {
17100c1efc1SGreg Tucker if (nerrs == (m - k)) {
17200c1efc1SGreg Tucker free(b);
17300c1efc1SGreg Tucker free(backup);
17400c1efc1SGreg Tucker printf("BAD MATRIX\n");
17500c1efc1SGreg Tucker return NO_INVERT_MATRIX;
17600c1efc1SGreg Tucker }
17700c1efc1SGreg Tucker incr++;
17800c1efc1SGreg Tucker memcpy(b, backup, MMAX * KMAX);
17900c1efc1SGreg Tucker for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
18000c1efc1SGreg Tucker if (src_err_list[i] == (decode_index[k - 1] + incr)) {
18100c1efc1SGreg Tucker // skip the erased parity line
18200c1efc1SGreg Tucker incr++;
18300c1efc1SGreg Tucker continue;
18400c1efc1SGreg Tucker }
18500c1efc1SGreg Tucker }
18600c1efc1SGreg Tucker if (decode_index[k - 1] + incr >= m) {
18700c1efc1SGreg Tucker free(b);
18800c1efc1SGreg Tucker free(backup);
18900c1efc1SGreg Tucker printf("BAD MATRIX\n");
19000c1efc1SGreg Tucker return NO_INVERT_MATRIX;
19100c1efc1SGreg Tucker }
19200c1efc1SGreg Tucker decode_index[k - 1] += incr;
19300c1efc1SGreg Tucker for (j = 0; j < k; j++)
19400c1efc1SGreg Tucker b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
19500c1efc1SGreg Tucker };
19600c1efc1SGreg Tucker
19700c1efc1SGreg Tucker for (i = 0; i < nsrcerrs; i++) {
19800c1efc1SGreg Tucker for (j = 0; j < k; j++) {
19900c1efc1SGreg Tucker decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
20000c1efc1SGreg Tucker }
20100c1efc1SGreg Tucker }
20200c1efc1SGreg Tucker /* src_err_list from encode_matrix * invert of b for parity decoding */
20300c1efc1SGreg Tucker for (p = nsrcerrs; p < nerrs; p++) {
20400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
20500c1efc1SGreg Tucker s = 0;
20600c1efc1SGreg Tucker for (j = 0; j < k; j++)
20700c1efc1SGreg Tucker s ^= gf_mul(invert_matrix[j * k + i],
20800c1efc1SGreg Tucker encode_matrix[k * src_err_list[p] + j]);
20900c1efc1SGreg Tucker
21000c1efc1SGreg Tucker decode_matrix[k * p + i] = s;
21100c1efc1SGreg Tucker }
21200c1efc1SGreg Tucker }
21300c1efc1SGreg Tucker free(b);
21400c1efc1SGreg Tucker free(backup);
21500c1efc1SGreg Tucker return 0;
21600c1efc1SGreg Tucker }
21700c1efc1SGreg Tucker
218*300260a4SMarcel Cornu int
main(int argc,char * argv[])219*300260a4SMarcel Cornu main(int argc, char *argv[])
22000c1efc1SGreg Tucker {
22100c1efc1SGreg Tucker int re = 0;
22200c1efc1SGreg Tucker int i, j, p, rtest, m, k;
22300c1efc1SGreg Tucker int nerrs, nsrcerrs;
22400c1efc1SGreg Tucker void *buf;
22500c1efc1SGreg Tucker unsigned int decode_index[MMAX];
22600c1efc1SGreg Tucker unsigned char *temp_buffs[TEST_SOURCES], *buffs[TEST_SOURCES];
22700c1efc1SGreg Tucker unsigned char *encode_matrix, *decode_matrix, *invert_matrix, *g_tbls;
22800c1efc1SGreg Tucker unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
22900c1efc1SGreg Tucker unsigned char *recov[TEST_SOURCES];
23000c1efc1SGreg Tucker
23100c1efc1SGreg Tucker int rows, align, size;
23200c1efc1SGreg Tucker unsigned char *efence_buffs[TEST_SOURCES];
23300c1efc1SGreg Tucker unsigned int offset;
23400c1efc1SGreg Tucker u8 *ubuffs[TEST_SOURCES];
23500c1efc1SGreg Tucker u8 *temp_ubuffs[TEST_SOURCES];
23600c1efc1SGreg Tucker
23700c1efc1SGreg Tucker printf("erasure_code_base_test: %dx%d ", TEST_SOURCES, TEST_LEN);
23800c1efc1SGreg Tucker srand(TEST_SEED);
23900c1efc1SGreg Tucker
24000c1efc1SGreg Tucker // Allocate the arrays
24100c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
24200c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
24300c1efc1SGreg Tucker printf("alloc error: Fail");
24400c1efc1SGreg Tucker return -1;
24500c1efc1SGreg Tucker }
24600c1efc1SGreg Tucker buffs[i] = buf;
24700c1efc1SGreg Tucker }
24800c1efc1SGreg Tucker
24900c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
25000c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
25100c1efc1SGreg Tucker printf("alloc error: Fail");
25200c1efc1SGreg Tucker return -1;
25300c1efc1SGreg Tucker }
25400c1efc1SGreg Tucker temp_buffs[i] = buf;
25500c1efc1SGreg Tucker }
25600c1efc1SGreg Tucker
25700c1efc1SGreg Tucker // Test erasure code by encode and recovery
25800c1efc1SGreg Tucker
25900c1efc1SGreg Tucker encode_matrix = malloc(MMAX * KMAX);
26000c1efc1SGreg Tucker decode_matrix = malloc(MMAX * KMAX);
26100c1efc1SGreg Tucker invert_matrix = malloc(MMAX * KMAX);
26200c1efc1SGreg Tucker g_tbls = malloc(KMAX * TEST_SOURCES * 32);
263*300260a4SMarcel Cornu if (encode_matrix == NULL || decode_matrix == NULL || invert_matrix == NULL ||
264*300260a4SMarcel Cornu g_tbls == NULL) {
26500c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
26600c1efc1SGreg Tucker return -1;
26700c1efc1SGreg Tucker }
26800c1efc1SGreg Tucker // Pick a first test
26900c1efc1SGreg Tucker m = 9;
27000c1efc1SGreg Tucker k = 5;
271402bd4f7STomasz Kantecki assert((m <= MMAX) && (k <= KMAX));
27200c1efc1SGreg Tucker
27300c1efc1SGreg Tucker // Make random data
27400c1efc1SGreg Tucker for (i = 0; i < k; i++)
27500c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
27600c1efc1SGreg Tucker buffs[i][j] = rand();
27700c1efc1SGreg Tucker
27800c1efc1SGreg Tucker // Generate encode matrix encode_matrix
27900c1efc1SGreg Tucker // The matrix generated by gf_gen_rs_matrix
28000c1efc1SGreg Tucker // is not always invertable.
28100c1efc1SGreg Tucker gf_gen_rs_matrix(encode_matrix, m, k);
28200c1efc1SGreg Tucker
28300c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
284f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
28500c1efc1SGreg Tucker
28600c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
28700c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
28800c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
28900c1efc1SGreg Tucker
29000c1efc1SGreg Tucker // Choose random buffers to be in erasure
29100c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
29200c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
29300c1efc1SGreg Tucker
29400c1efc1SGreg Tucker // Generate decode matrix
295*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
296*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
29700c1efc1SGreg Tucker if (re != 0) {
29800c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
29900c1efc1SGreg Tucker return -1;
30000c1efc1SGreg Tucker }
30100c1efc1SGreg Tucker // Pack recovery array as list of valid sources
30200c1efc1SGreg Tucker // Its order must be the same as the order
30300c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
30400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
30500c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
30600c1efc1SGreg Tucker }
30700c1efc1SGreg Tucker
30800c1efc1SGreg Tucker // Recover data
309f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
31000c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
31100c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
31200c1efc1SGreg Tucker
31300c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
31400c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
31500c1efc1SGreg Tucker printf(" - erase list = ");
31600c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
31700c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
31800c1efc1SGreg Tucker printf(" - Index = ");
31900c1efc1SGreg Tucker for (p = 0; p < k; p++)
32000c1efc1SGreg Tucker printf(" %d", decode_index[p]);
32100c1efc1SGreg Tucker printf("\nencode_matrix:\n");
32200c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
32300c1efc1SGreg Tucker printf("inv b:\n");
32400c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
32500c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
32600c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
32700c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
32800c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
32900c1efc1SGreg Tucker printf("orig :");
33000c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
33100c1efc1SGreg Tucker return -1;
33200c1efc1SGreg Tucker }
33300c1efc1SGreg Tucker }
33400c1efc1SGreg Tucker
33500c1efc1SGreg Tucker // Pick a first test
33600c1efc1SGreg Tucker m = 9;
33700c1efc1SGreg Tucker k = 5;
33800c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
33900c1efc1SGreg Tucker return -1;
34000c1efc1SGreg Tucker
34100c1efc1SGreg Tucker // Make random data
34200c1efc1SGreg Tucker for (i = 0; i < k; i++)
34300c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
34400c1efc1SGreg Tucker buffs[i][j] = rand();
34500c1efc1SGreg Tucker
34600c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
34700c1efc1SGreg Tucker // is always invertable.
34800c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
34900c1efc1SGreg Tucker
35000c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
351f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
35200c1efc1SGreg Tucker
35300c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
35400c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
35500c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
35600c1efc1SGreg Tucker
35700c1efc1SGreg Tucker // Choose random buffers to be in erasure
35800c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
35900c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
36000c1efc1SGreg Tucker
36100c1efc1SGreg Tucker // Generate decode matrix
362*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
363*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
36400c1efc1SGreg Tucker if (re != 0) {
36500c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
36600c1efc1SGreg Tucker return -1;
36700c1efc1SGreg Tucker }
36800c1efc1SGreg Tucker // Pack recovery array as list of valid sources
36900c1efc1SGreg Tucker // Its order must be the same as the order
37000c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
37100c1efc1SGreg Tucker for (i = 0; i < k; i++) {
37200c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
37300c1efc1SGreg Tucker }
37400c1efc1SGreg Tucker
37500c1efc1SGreg Tucker // Recover data
376f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
37700c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
37800c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
37900c1efc1SGreg Tucker
38000c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
38100c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
38200c1efc1SGreg Tucker printf(" - erase list = ");
38300c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
38400c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
38500c1efc1SGreg Tucker printf(" - Index = ");
38600c1efc1SGreg Tucker for (p = 0; p < k; p++)
38700c1efc1SGreg Tucker printf(" %d", decode_index[p]);
38800c1efc1SGreg Tucker printf("\nencode_matrix:\n");
38900c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
39000c1efc1SGreg Tucker printf("inv b:\n");
39100c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
39200c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
39300c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
39400c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
39500c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
39600c1efc1SGreg Tucker printf("orig :");
39700c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
39800c1efc1SGreg Tucker return -1;
39900c1efc1SGreg Tucker }
40000c1efc1SGreg Tucker }
40100c1efc1SGreg Tucker
40200c1efc1SGreg Tucker // Do more random tests
40300c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
404*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
405*300260a4SMarcel Cornu ;
406*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
407*300260a4SMarcel Cornu ;
40800c1efc1SGreg Tucker
40900c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
41000c1efc1SGreg Tucker continue;
41100c1efc1SGreg Tucker
41200c1efc1SGreg Tucker // Make random data
41300c1efc1SGreg Tucker for (i = 0; i < k; i++)
41400c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
41500c1efc1SGreg Tucker buffs[i][j] = rand();
41600c1efc1SGreg Tucker
41700c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
41800c1efc1SGreg Tucker // is always invertable.
41900c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
42000c1efc1SGreg Tucker
42100c1efc1SGreg Tucker // Make parity vects
42200c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
423f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
42400c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
42500c1efc1SGreg Tucker // using g_tbls from encode matrix a
42600c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
42700c1efc1SGreg Tucker
42800c1efc1SGreg Tucker // Random errors
42900c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
43000c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
43100c1efc1SGreg Tucker
43200c1efc1SGreg Tucker // Generate decode matrix
433*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
434*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
43500c1efc1SGreg Tucker if (re != 0) {
43600c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
43700c1efc1SGreg Tucker return -1;
43800c1efc1SGreg Tucker }
43900c1efc1SGreg Tucker // Pack recovery array as list of valid sources
44000c1efc1SGreg Tucker // Its order must be the same as the order
44100c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
44200c1efc1SGreg Tucker for (i = 0; i < k; i++) {
44300c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
44400c1efc1SGreg Tucker }
44500c1efc1SGreg Tucker
44600c1efc1SGreg Tucker // Recover data
447f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
44800c1efc1SGreg Tucker ec_encode_data_base(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
44900c1efc1SGreg Tucker
45000c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
45100c1efc1SGreg Tucker
45200c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], TEST_LEN)) {
45300c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
45400c1efc1SGreg Tucker printf(" - erase list = ");
45500c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
45600c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
45700c1efc1SGreg Tucker printf(" - Index = ");
45800c1efc1SGreg Tucker for (p = 0; p < k; p++)
45900c1efc1SGreg Tucker printf(" %d", decode_index[p]);
46000c1efc1SGreg Tucker printf("\nencode_matrix:\n");
46100c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
46200c1efc1SGreg Tucker printf("inv b:\n");
46300c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
46400c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
46500c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
46600c1efc1SGreg Tucker printf("orig data:\n");
46700c1efc1SGreg Tucker dump_matrix(buffs, m, 25);
46800c1efc1SGreg Tucker printf("orig :");
46900c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
47000c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
47100c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
47200c1efc1SGreg Tucker return -1;
47300c1efc1SGreg Tucker }
47400c1efc1SGreg Tucker }
4752ca781dfSPablo de Lara #ifdef TEST_VERBOSE
47600c1efc1SGreg Tucker putchar('.');
4772ca781dfSPablo de Lara #endif
47800c1efc1SGreg Tucker }
47900c1efc1SGreg Tucker
48000c1efc1SGreg Tucker // Run tests at end of buffer for Electric Fence
48100c1efc1SGreg Tucker k = 16;
48200c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 1 : 16;
48300c1efc1SGreg Tucker if (k > KMAX)
48400c1efc1SGreg Tucker return -1;
48500c1efc1SGreg Tucker
48600c1efc1SGreg Tucker for (rows = 1; rows <= 16; rows++) {
48700c1efc1SGreg Tucker m = k + rows;
48800c1efc1SGreg Tucker if (m > MMAX)
48900c1efc1SGreg Tucker return -1;
49000c1efc1SGreg Tucker
49100c1efc1SGreg Tucker // Make random data
49200c1efc1SGreg Tucker for (i = 0; i < k; i++)
49300c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++)
49400c1efc1SGreg Tucker buffs[i][j] = rand();
49500c1efc1SGreg Tucker
49600c1efc1SGreg Tucker for (size = EFENCE_TEST_MIN_SIZE; size <= TEST_SIZE; size += align) {
49700c1efc1SGreg Tucker for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
49800c1efc1SGreg Tucker efence_buffs[i] = buffs[i] + TEST_LEN - size;
49900c1efc1SGreg Tucker }
50000c1efc1SGreg Tucker
50100c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
50200c1efc1SGreg Tucker // is always invertable.
50300c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
50400c1efc1SGreg Tucker
50500c1efc1SGreg Tucker // Make parity vects
50600c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
507f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
50800c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
50900c1efc1SGreg Tucker // using g_tbls from encode matrix a
510*300260a4SMarcel Cornu ec_encode_data_base(size, k, m - k, g_tbls, efence_buffs, &efence_buffs[k]);
51100c1efc1SGreg Tucker
51200c1efc1SGreg Tucker // Random errors
51300c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
51400c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
51500c1efc1SGreg Tucker
51600c1efc1SGreg Tucker // Generate decode matrix
517*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix,
518*300260a4SMarcel Cornu decode_index, src_err_list, src_in_err, nerrs,
519*300260a4SMarcel Cornu nsrcerrs, k, m);
52000c1efc1SGreg Tucker if (re != 0) {
52100c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
52200c1efc1SGreg Tucker return -1;
52300c1efc1SGreg Tucker }
52400c1efc1SGreg Tucker // Pack recovery array as list of valid sources
52500c1efc1SGreg Tucker // Its order must be the same as the order
52600c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
52700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
52800c1efc1SGreg Tucker recov[i] = efence_buffs[decode_index[i]];
52900c1efc1SGreg Tucker }
53000c1efc1SGreg Tucker
53100c1efc1SGreg Tucker // Recover data
532f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
53300c1efc1SGreg Tucker ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
53400c1efc1SGreg Tucker
53500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
53600c1efc1SGreg Tucker
537*300260a4SMarcel Cornu if (0 != memcmp(temp_buffs[k + i], efence_buffs[src_err_list[i]],
53800c1efc1SGreg Tucker size)) {
539*300260a4SMarcel Cornu printf("Efence: Fail error recovery (%d, %d, %d)\n", m, k,
540*300260a4SMarcel Cornu nerrs);
54100c1efc1SGreg Tucker
54200c1efc1SGreg Tucker printf("size = %d\n", size);
54300c1efc1SGreg Tucker
54400c1efc1SGreg Tucker printf("Test erase list = ");
54500c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
54600c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
54700c1efc1SGreg Tucker printf(" - Index = ");
54800c1efc1SGreg Tucker for (p = 0; p < k; p++)
54900c1efc1SGreg Tucker printf(" %d", decode_index[p]);
55000c1efc1SGreg Tucker printf("\nencode_matrix:\n");
55100c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
55200c1efc1SGreg Tucker printf("inv b:\n");
55300c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
55400c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
55500c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
55600c1efc1SGreg Tucker
55700c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
55800c1efc1SGreg Tucker dump(temp_buffs[k + i], align);
55900c1efc1SGreg Tucker printf("orig :");
56000c1efc1SGreg Tucker dump(efence_buffs[src_err_list[i]], align);
56100c1efc1SGreg Tucker return -1;
56200c1efc1SGreg Tucker }
56300c1efc1SGreg Tucker }
56400c1efc1SGreg Tucker }
56500c1efc1SGreg Tucker }
56600c1efc1SGreg Tucker
56700c1efc1SGreg Tucker // Test rand ptr alignment if available
56800c1efc1SGreg Tucker
56900c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
570*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
571*300260a4SMarcel Cornu ;
572*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
573*300260a4SMarcel Cornu ;
57400c1efc1SGreg Tucker
57500c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
57600c1efc1SGreg Tucker continue;
57700c1efc1SGreg Tucker
57800c1efc1SGreg Tucker size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
57900c1efc1SGreg Tucker
58000c1efc1SGreg Tucker offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
58100c1efc1SGreg Tucker // Add random offsets
58200c1efc1SGreg Tucker for (i = 0; i < m; i++) {
58300c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
58400c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
58500c1efc1SGreg Tucker ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
58600c1efc1SGreg Tucker temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
58700c1efc1SGreg Tucker }
58800c1efc1SGreg Tucker
58900c1efc1SGreg Tucker for (i = 0; i < k; i++)
59000c1efc1SGreg Tucker for (j = 0; j < size; j++)
59100c1efc1SGreg Tucker ubuffs[i][j] = rand();
59200c1efc1SGreg Tucker
59300c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
59400c1efc1SGreg Tucker // is always invertable.
59500c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
59600c1efc1SGreg Tucker
59700c1efc1SGreg Tucker // Make parity vects
59800c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
599f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
60000c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
60100c1efc1SGreg Tucker // using g_tbls from encode matrix a
60200c1efc1SGreg Tucker ec_encode_data_base(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
60300c1efc1SGreg Tucker
60400c1efc1SGreg Tucker // Random errors
60500c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
60600c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
60700c1efc1SGreg Tucker
60800c1efc1SGreg Tucker // Generate decode matrix
609*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
610*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
61100c1efc1SGreg Tucker if (re != 0) {
61200c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
61300c1efc1SGreg Tucker return -1;
61400c1efc1SGreg Tucker }
61500c1efc1SGreg Tucker // Pack recovery array as list of valid sources
61600c1efc1SGreg Tucker // Its order must be the same as the order
61700c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
61800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
61900c1efc1SGreg Tucker recov[i] = ubuffs[decode_index[i]];
62000c1efc1SGreg Tucker }
62100c1efc1SGreg Tucker
62200c1efc1SGreg Tucker // Recover data
623f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
62400c1efc1SGreg Tucker ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_ubuffs[k]);
62500c1efc1SGreg Tucker
62600c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
62700c1efc1SGreg Tucker
62800c1efc1SGreg Tucker if (0 != memcmp(temp_ubuffs[k + i], ubuffs[src_err_list[i]], size)) {
62900c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
63000c1efc1SGreg Tucker printf(" - erase list = ");
63100c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
63200c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
63300c1efc1SGreg Tucker printf(" - Index = ");
63400c1efc1SGreg Tucker for (p = 0; p < k; p++)
63500c1efc1SGreg Tucker printf(" %d", decode_index[p]);
63600c1efc1SGreg Tucker printf("\nencode_matrix:\n");
63700c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
63800c1efc1SGreg Tucker printf("inv b:\n");
63900c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
64000c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
64100c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
64200c1efc1SGreg Tucker printf("orig data:\n");
64300c1efc1SGreg Tucker dump_matrix(ubuffs, m, 25);
64400c1efc1SGreg Tucker printf("orig :");
64500c1efc1SGreg Tucker dump(ubuffs[src_err_list[i]], 25);
64600c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
64700c1efc1SGreg Tucker dump(temp_ubuffs[k + i], 25);
64800c1efc1SGreg Tucker return -1;
64900c1efc1SGreg Tucker }
65000c1efc1SGreg Tucker }
65100c1efc1SGreg Tucker
65200c1efc1SGreg Tucker // Confirm that padding around dests is unchanged
65300c1efc1SGreg Tucker memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
65400c1efc1SGreg Tucker
65500c1efc1SGreg Tucker for (i = 0; i < m; i++) {
65600c1efc1SGreg Tucker
65700c1efc1SGreg Tucker offset = ubuffs[i] - buffs[i];
65800c1efc1SGreg Tucker
65900c1efc1SGreg Tucker if (memcmp(buffs[i], temp_buffs[0], offset)) {
66000c1efc1SGreg Tucker printf("Fail rand ualign encode pad start\n");
66100c1efc1SGreg Tucker return -1;
66200c1efc1SGreg Tucker }
663*300260a4SMarcel Cornu if (memcmp(buffs[i] + offset + size, temp_buffs[0],
66400c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
66500c1efc1SGreg Tucker printf("Fail rand ualign encode pad end\n");
66600c1efc1SGreg Tucker return -1;
66700c1efc1SGreg Tucker }
66800c1efc1SGreg Tucker }
66900c1efc1SGreg Tucker
67000c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
67100c1efc1SGreg Tucker
67200c1efc1SGreg Tucker offset = temp_ubuffs[k + i] - temp_buffs[k + i];
67300c1efc1SGreg Tucker if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
67400c1efc1SGreg Tucker printf("Fail rand ualign decode pad start\n");
67500c1efc1SGreg Tucker return -1;
67600c1efc1SGreg Tucker }
677*300260a4SMarcel Cornu if (memcmp(temp_buffs[k + i] + offset + size, temp_buffs[0],
67800c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
67900c1efc1SGreg Tucker printf("Fail rand ualign decode pad end\n");
68000c1efc1SGreg Tucker return -1;
68100c1efc1SGreg Tucker }
68200c1efc1SGreg Tucker }
68300c1efc1SGreg Tucker
6842ca781dfSPablo de Lara #ifdef TEST_VERBOSE
68500c1efc1SGreg Tucker putchar('.');
6862ca781dfSPablo de Lara #endif
68700c1efc1SGreg Tucker }
68800c1efc1SGreg Tucker
68900c1efc1SGreg Tucker // Test size alignment
69000c1efc1SGreg Tucker
69100c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 13 : 16;
69200c1efc1SGreg Tucker
69300c1efc1SGreg Tucker for (size = TEST_LEN; size > 0; size -= align) {
694*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
695*300260a4SMarcel Cornu ;
696*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
697*300260a4SMarcel Cornu ;
69800c1efc1SGreg Tucker
69900c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
70000c1efc1SGreg Tucker continue;
70100c1efc1SGreg Tucker
70200c1efc1SGreg Tucker for (i = 0; i < k; i++)
70300c1efc1SGreg Tucker for (j = 0; j < size; j++)
70400c1efc1SGreg Tucker buffs[i][j] = rand();
70500c1efc1SGreg Tucker
70600c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
70700c1efc1SGreg Tucker // is always invertable.
70800c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
70900c1efc1SGreg Tucker
71000c1efc1SGreg Tucker // Make parity vects
71100c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
712f971f023SPablo de Lara ec_init_tables_base(k, m - k, &encode_matrix[k * k], g_tbls);
71300c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
71400c1efc1SGreg Tucker // using g_tbls from encode matrix a
71500c1efc1SGreg Tucker ec_encode_data_base(size, k, m - k, g_tbls, buffs, &buffs[k]);
71600c1efc1SGreg Tucker
71700c1efc1SGreg Tucker // Random errors
71800c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
71900c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
72000c1efc1SGreg Tucker // Generate decode matrix
721*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
722*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
72300c1efc1SGreg Tucker if (re != 0) {
72400c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
72500c1efc1SGreg Tucker return -1;
72600c1efc1SGreg Tucker }
72700c1efc1SGreg Tucker // Pack recovery array as list of valid sources
72800c1efc1SGreg Tucker // Its order must be the same as the order
72900c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
73000c1efc1SGreg Tucker for (i = 0; i < k; i++) {
73100c1efc1SGreg Tucker recov[i] = buffs[decode_index[i]];
73200c1efc1SGreg Tucker }
73300c1efc1SGreg Tucker
73400c1efc1SGreg Tucker // Recover data
735f971f023SPablo de Lara ec_init_tables_base(k, nerrs, decode_matrix, g_tbls);
73600c1efc1SGreg Tucker ec_encode_data_base(size, k, nerrs, g_tbls, recov, &temp_buffs[k]);
73700c1efc1SGreg Tucker
73800c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
73900c1efc1SGreg Tucker
74000c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], buffs[src_err_list[i]], size)) {
74100c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
74200c1efc1SGreg Tucker printf(" - erase list = ");
74300c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
74400c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
74500c1efc1SGreg Tucker printf(" - Index = ");
74600c1efc1SGreg Tucker for (p = 0; p < k; p++)
74700c1efc1SGreg Tucker printf(" %d", decode_index[p]);
74800c1efc1SGreg Tucker printf("\nencode_matrix:\n");
74900c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
75000c1efc1SGreg Tucker printf("inv b:\n");
75100c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
75200c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
75300c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
75400c1efc1SGreg Tucker printf("orig data:\n");
75500c1efc1SGreg Tucker dump_matrix(buffs, m, 25);
75600c1efc1SGreg Tucker printf("orig :");
75700c1efc1SGreg Tucker dump(buffs[src_err_list[i]], 25);
75800c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
75900c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
76000c1efc1SGreg Tucker return -1;
76100c1efc1SGreg Tucker }
76200c1efc1SGreg Tucker }
76300c1efc1SGreg Tucker }
76400c1efc1SGreg Tucker
76500c1efc1SGreg Tucker printf("done EC tests: Pass\n");
76600c1efc1SGreg Tucker return 0;
76700c1efc1SGreg Tucker }
768