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 #ifndef ALIGN_SIZE
3800c1efc1SGreg Tucker #define ALIGN_SIZE 16
3900c1efc1SGreg Tucker #endif
4000c1efc1SGreg Tucker
4100c1efc1SGreg Tucker // By default, test multibinary version
4200c1efc1SGreg Tucker #ifndef FUNCTION_UNDER_TEST
4300c1efc1SGreg Tucker #define FUNCTION_UNDER_TEST ec_encode_data_update
4400c1efc1SGreg Tucker #define REF_FUNCTION ec_encode_data
4500c1efc1SGreg Tucker #endif
4600c1efc1SGreg Tucker
4700c1efc1SGreg Tucker #define TEST_LEN 8192
4800c1efc1SGreg Tucker #define TEST_SIZE (TEST_LEN / 2)
4900c1efc1SGreg Tucker
5000c1efc1SGreg Tucker #ifndef TEST_SOURCES
5100c1efc1SGreg Tucker #define TEST_SOURCES 127
5200c1efc1SGreg Tucker #endif
5300c1efc1SGreg Tucker #ifndef RANDOMS
5400c1efc1SGreg Tucker #define RANDOMS 200
5500c1efc1SGreg Tucker #endif
5600c1efc1SGreg Tucker
5700c1efc1SGreg Tucker #define MMAX TEST_SOURCES
5800c1efc1SGreg Tucker #define KMAX TEST_SOURCES
5900c1efc1SGreg Tucker
604f2d148aSRoy Oursler #define EFENCE_TEST_MAX_SIZE 0x100
614f2d148aSRoy Oursler
6200c1efc1SGreg Tucker #ifdef EC_ALIGNED_ADDR
6300c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
6400c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B 0
6500c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B 0 // 0 for aligned only
6600c1efc1SGreg Tucker #else
6700c1efc1SGreg Tucker // Define power of 2 range to check ptr, len alignment
6800c1efc1SGreg Tucker #define PTR_ALIGN_CHK_B ALIGN_SIZE
6900c1efc1SGreg Tucker #define LEN_ALIGN_CHK_B ALIGN_SIZE // 0 for aligned only
7000c1efc1SGreg Tucker #endif
7100c1efc1SGreg Tucker
7200c1efc1SGreg Tucker #ifndef TEST_SEED
7300c1efc1SGreg Tucker #define TEST_SEED 11
7400c1efc1SGreg Tucker #endif
7500c1efc1SGreg Tucker
7600c1efc1SGreg Tucker #define str(s) #s
7700c1efc1SGreg Tucker #define xstr(s) str(s)
7800c1efc1SGreg Tucker
7900c1efc1SGreg Tucker typedef unsigned char u8;
8000c1efc1SGreg Tucker
81*300260a4SMarcel Cornu void
dump(unsigned char * buf,int len)82*300260a4SMarcel Cornu dump(unsigned char *buf, int len)
8300c1efc1SGreg Tucker {
8400c1efc1SGreg Tucker int i;
8500c1efc1SGreg Tucker for (i = 0; i < len;) {
8600c1efc1SGreg Tucker printf(" %2x", 0xff & buf[i++]);
8700c1efc1SGreg Tucker if (i % 32 == 0)
8800c1efc1SGreg Tucker printf("\n");
8900c1efc1SGreg Tucker }
9000c1efc1SGreg Tucker printf("\n");
9100c1efc1SGreg Tucker }
9200c1efc1SGreg Tucker
93*300260a4SMarcel Cornu void
dump_matrix(unsigned char ** s,int k,int m)94*300260a4SMarcel Cornu dump_matrix(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", s[i][j]);
10000c1efc1SGreg Tucker }
10100c1efc1SGreg Tucker printf("\n");
10200c1efc1SGreg Tucker }
10300c1efc1SGreg Tucker printf("\n");
10400c1efc1SGreg Tucker }
10500c1efc1SGreg Tucker
106*300260a4SMarcel Cornu void
dump_u8xu8(unsigned char * s,int k,int m)107*300260a4SMarcel Cornu dump_u8xu8(unsigned char *s, int k, int m)
10800c1efc1SGreg Tucker {
10900c1efc1SGreg Tucker int i, j;
11000c1efc1SGreg Tucker for (i = 0; i < k; i++) {
11100c1efc1SGreg Tucker for (j = 0; j < m; j++) {
11200c1efc1SGreg Tucker printf(" %2x", 0xff & s[j + (i * m)]);
11300c1efc1SGreg Tucker }
11400c1efc1SGreg Tucker printf("\n");
11500c1efc1SGreg Tucker }
11600c1efc1SGreg Tucker printf("\n");
11700c1efc1SGreg Tucker }
11800c1efc1SGreg Tucker
11900c1efc1SGreg Tucker // Generate Random errors
120*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)121*300260a4SMarcel Cornu gen_err_list(unsigned char *src_err_list, unsigned char *src_in_err, int *pnerrs, int *pnsrcerrs,
122*300260a4SMarcel Cornu int k, int m)
12300c1efc1SGreg Tucker {
12400c1efc1SGreg Tucker int i, err;
12500c1efc1SGreg Tucker int nerrs = 0, nsrcerrs = 0;
12600c1efc1SGreg Tucker
12700c1efc1SGreg Tucker for (i = 0, nerrs = 0, nsrcerrs = 0; i < m && nerrs < m - k; i++) {
12800c1efc1SGreg Tucker err = 1 & rand();
12900c1efc1SGreg Tucker src_in_err[i] = err;
13000c1efc1SGreg Tucker if (err) {
13100c1efc1SGreg Tucker src_err_list[nerrs++] = i;
13200c1efc1SGreg Tucker if (i < k) {
13300c1efc1SGreg Tucker nsrcerrs++;
13400c1efc1SGreg Tucker }
13500c1efc1SGreg Tucker }
13600c1efc1SGreg Tucker }
13700c1efc1SGreg Tucker if (nerrs == 0) { // should have at least one error
138*300260a4SMarcel Cornu while ((err = (rand() % KMAX)) >= m)
139*300260a4SMarcel Cornu ;
14000c1efc1SGreg Tucker src_err_list[nerrs++] = err;
14100c1efc1SGreg Tucker src_in_err[err] = 1;
14200c1efc1SGreg Tucker if (err < k)
14300c1efc1SGreg Tucker nsrcerrs = 1;
14400c1efc1SGreg Tucker }
14500c1efc1SGreg Tucker *pnerrs = nerrs;
14600c1efc1SGreg Tucker *pnsrcerrs = nsrcerrs;
14700c1efc1SGreg Tucker return;
14800c1efc1SGreg Tucker }
14900c1efc1SGreg Tucker
15000c1efc1SGreg Tucker #define NO_INVERT_MATRIX -2
15100c1efc1SGreg Tucker // Generate decode matrix from encode matrix
152*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)153*300260a4SMarcel Cornu gf_gen_decode_matrix(unsigned char *encode_matrix, unsigned char *decode_matrix,
154*300260a4SMarcel Cornu unsigned char *invert_matrix, unsigned int *decode_index,
155*300260a4SMarcel Cornu unsigned char *src_err_list, unsigned char *src_in_err, int nerrs,
156*300260a4SMarcel Cornu int nsrcerrs, int k, int m)
15700c1efc1SGreg Tucker {
15800c1efc1SGreg Tucker int i, j, p;
15900c1efc1SGreg Tucker int r;
16000c1efc1SGreg Tucker unsigned char *backup, *b, s;
16100c1efc1SGreg Tucker int incr = 0;
16200c1efc1SGreg Tucker
16300c1efc1SGreg Tucker b = malloc(MMAX * KMAX);
16400c1efc1SGreg Tucker backup = malloc(MMAX * KMAX);
16500c1efc1SGreg Tucker
16600c1efc1SGreg Tucker if (b == NULL || backup == NULL) {
16700c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
16800c1efc1SGreg Tucker free(b);
16900c1efc1SGreg Tucker free(backup);
17000c1efc1SGreg Tucker return -1;
17100c1efc1SGreg Tucker }
17200c1efc1SGreg Tucker // Construct matrix b by removing error rows
17300c1efc1SGreg Tucker for (i = 0, r = 0; i < k; i++, r++) {
17400c1efc1SGreg Tucker while (src_in_err[r])
17500c1efc1SGreg Tucker r++;
17600c1efc1SGreg Tucker for (j = 0; j < k; j++) {
17700c1efc1SGreg Tucker b[k * i + j] = encode_matrix[k * r + j];
17800c1efc1SGreg Tucker backup[k * i + j] = encode_matrix[k * r + j];
17900c1efc1SGreg Tucker }
18000c1efc1SGreg Tucker decode_index[i] = r;
18100c1efc1SGreg Tucker }
18200c1efc1SGreg Tucker incr = 0;
18300c1efc1SGreg Tucker while (gf_invert_matrix(b, invert_matrix, k) < 0) {
18400c1efc1SGreg Tucker if (nerrs == (m - k)) {
18500c1efc1SGreg Tucker free(b);
18600c1efc1SGreg Tucker free(backup);
18700c1efc1SGreg Tucker printf("BAD MATRIX\n");
18800c1efc1SGreg Tucker return NO_INVERT_MATRIX;
18900c1efc1SGreg Tucker }
19000c1efc1SGreg Tucker incr++;
19100c1efc1SGreg Tucker memcpy(b, backup, MMAX * KMAX);
19200c1efc1SGreg Tucker for (i = nsrcerrs; i < nerrs - nsrcerrs; i++) {
19300c1efc1SGreg Tucker if (src_err_list[i] == (decode_index[k - 1] + incr)) {
19400c1efc1SGreg Tucker // skip the erased parity line
19500c1efc1SGreg Tucker incr++;
19600c1efc1SGreg Tucker continue;
19700c1efc1SGreg Tucker }
19800c1efc1SGreg Tucker }
19900c1efc1SGreg Tucker if (decode_index[k - 1] + incr >= m) {
20000c1efc1SGreg Tucker free(b);
20100c1efc1SGreg Tucker free(backup);
20200c1efc1SGreg Tucker printf("BAD MATRIX\n");
20300c1efc1SGreg Tucker return NO_INVERT_MATRIX;
20400c1efc1SGreg Tucker }
20500c1efc1SGreg Tucker decode_index[k - 1] += incr;
20600c1efc1SGreg Tucker for (j = 0; j < k; j++)
20700c1efc1SGreg Tucker b[k * (k - 1) + j] = encode_matrix[k * decode_index[k - 1] + j];
20800c1efc1SGreg Tucker };
20900c1efc1SGreg Tucker
21000c1efc1SGreg Tucker for (i = 0; i < nsrcerrs; i++) {
21100c1efc1SGreg Tucker for (j = 0; j < k; j++) {
21200c1efc1SGreg Tucker decode_matrix[k * i + j] = invert_matrix[k * src_err_list[i] + j];
21300c1efc1SGreg Tucker }
21400c1efc1SGreg Tucker }
21500c1efc1SGreg Tucker /* src_err_list from encode_matrix * invert of b for parity decoding */
21600c1efc1SGreg Tucker for (p = nsrcerrs; p < nerrs; p++) {
21700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
21800c1efc1SGreg Tucker s = 0;
21900c1efc1SGreg Tucker for (j = 0; j < k; j++)
22000c1efc1SGreg Tucker s ^= gf_mul(invert_matrix[j * k + i],
22100c1efc1SGreg Tucker encode_matrix[k * src_err_list[p] + j]);
22200c1efc1SGreg Tucker
22300c1efc1SGreg Tucker decode_matrix[k * p + i] = s;
22400c1efc1SGreg Tucker }
22500c1efc1SGreg Tucker }
22600c1efc1SGreg Tucker free(b);
22700c1efc1SGreg Tucker free(backup);
22800c1efc1SGreg Tucker return 0;
22900c1efc1SGreg Tucker }
23000c1efc1SGreg Tucker
231*300260a4SMarcel Cornu int
main(int argc,char * argv[])232*300260a4SMarcel Cornu main(int argc, char *argv[])
23300c1efc1SGreg Tucker {
234a3e26043SPablo de Lara int re = -1;
23500c1efc1SGreg Tucker int i, j, p, rtest, m, k;
23600c1efc1SGreg Tucker int nerrs, nsrcerrs;
23700c1efc1SGreg Tucker void *buf;
23800c1efc1SGreg Tucker unsigned int decode_index[MMAX];
239a3e26043SPablo de Lara unsigned char *temp_buffs[TEST_SOURCES] = { NULL }, *buffs[TEST_SOURCES] = { NULL };
240a3e26043SPablo de Lara unsigned char *update_buffs[TEST_SOURCES] = { NULL };
241*300260a4SMarcel Cornu unsigned char *encode_matrix = NULL, *decode_matrix = NULL, *invert_matrix = NULL,
242*300260a4SMarcel Cornu *g_tbls = NULL;
24300c1efc1SGreg Tucker unsigned char src_in_err[TEST_SOURCES], src_err_list[TEST_SOURCES];
24400c1efc1SGreg Tucker unsigned char *recov[TEST_SOURCES];
24500c1efc1SGreg Tucker
24600c1efc1SGreg Tucker int rows, align, size;
24700c1efc1SGreg Tucker unsigned char *efence_buffs[TEST_SOURCES];
24800c1efc1SGreg Tucker unsigned char *efence_update_buffs[TEST_SOURCES];
24900c1efc1SGreg Tucker unsigned int offset;
25000c1efc1SGreg Tucker u8 *ubuffs[TEST_SOURCES];
25100c1efc1SGreg Tucker u8 *update_ubuffs[TEST_SOURCES];
25200c1efc1SGreg Tucker u8 *temp_ubuffs[TEST_SOURCES];
25300c1efc1SGreg Tucker
25400c1efc1SGreg Tucker printf("test " xstr(FUNCTION_UNDER_TEST) ": %dx%d ", TEST_SOURCES, TEST_LEN);
25500c1efc1SGreg Tucker srand(TEST_SEED);
25600c1efc1SGreg Tucker
25700c1efc1SGreg Tucker // Allocate the arrays
25800c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
25900c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
26000c1efc1SGreg Tucker printf("alloc error: Fail");
261a3e26043SPablo de Lara goto exit;
26200c1efc1SGreg Tucker }
26300c1efc1SGreg Tucker buffs[i] = buf;
26400c1efc1SGreg Tucker }
26500c1efc1SGreg Tucker
26600c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
26700c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
26800c1efc1SGreg Tucker printf("alloc error: Fail");
269a3e26043SPablo de Lara goto exit;
27000c1efc1SGreg Tucker }
27100c1efc1SGreg Tucker temp_buffs[i] = buf;
272*300260a4SMarcel Cornu memset(temp_buffs[i], 0, TEST_LEN); // initialize the destination buffer to be zero
273*300260a4SMarcel Cornu // for update function
27400c1efc1SGreg Tucker }
27500c1efc1SGreg Tucker
27600c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
27700c1efc1SGreg Tucker if (posix_memalign(&buf, 64, TEST_LEN)) {
27800c1efc1SGreg Tucker printf("alloc error: Fail");
279a3e26043SPablo de Lara goto exit;
28000c1efc1SGreg Tucker }
28100c1efc1SGreg Tucker update_buffs[i] = buf;
282*300260a4SMarcel Cornu memset(update_buffs[i], 0, TEST_LEN); // initialize the destination buffer to be
283*300260a4SMarcel Cornu // zero for update function
28400c1efc1SGreg Tucker }
28500c1efc1SGreg Tucker // Test erasure code by encode and recovery
28600c1efc1SGreg Tucker
28700c1efc1SGreg Tucker encode_matrix = malloc(MMAX * KMAX);
28800c1efc1SGreg Tucker decode_matrix = malloc(MMAX * KMAX);
28900c1efc1SGreg Tucker invert_matrix = malloc(MMAX * KMAX);
29000c1efc1SGreg Tucker g_tbls = malloc(KMAX * TEST_SOURCES * 32);
291*300260a4SMarcel Cornu if (encode_matrix == NULL || decode_matrix == NULL || invert_matrix == NULL ||
292*300260a4SMarcel Cornu g_tbls == NULL) {
29300c1efc1SGreg Tucker printf("Test failure! Error with malloc\n");
294a3e26043SPablo de Lara goto exit;
29500c1efc1SGreg Tucker }
29600c1efc1SGreg Tucker // Pick a first test
29782a6ac65SRoy Oursler m = 14;
29800c1efc1SGreg Tucker k = 10;
299402bd4f7STomasz Kantecki assert(!(m > MMAX || k > KMAX));
30000c1efc1SGreg Tucker
30100c1efc1SGreg Tucker // Make random data
30200c1efc1SGreg Tucker for (i = 0; i < k; i++) {
30300c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++) {
30400c1efc1SGreg Tucker buffs[i][j] = rand();
30500c1efc1SGreg Tucker update_buffs[i][j] = buffs[i][j];
30600c1efc1SGreg Tucker }
30700c1efc1SGreg Tucker }
30800c1efc1SGreg Tucker
30900c1efc1SGreg Tucker // Generate encode matrix encode_matrix
31000c1efc1SGreg Tucker // The matrix generated by gf_gen_rs_matrix
31100c1efc1SGreg Tucker // is not always invertable.
31200c1efc1SGreg Tucker gf_gen_rs_matrix(encode_matrix, m, k);
31300c1efc1SGreg Tucker
31400c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
31500c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
31600c1efc1SGreg Tucker
31700c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
31800c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
31900c1efc1SGreg Tucker REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
32000c1efc1SGreg Tucker for (i = 0; i < k; i++) {
32100c1efc1SGreg Tucker FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
32200c1efc1SGreg Tucker &update_buffs[k]);
32300c1efc1SGreg Tucker }
32400c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
32500c1efc1SGreg Tucker if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
32600c1efc1SGreg Tucker printf("\nupdate_buffs%d :", i);
32700c1efc1SGreg Tucker dump(update_buffs[k + i], 25);
32800c1efc1SGreg Tucker printf("buffs%d :", i);
32900c1efc1SGreg Tucker dump(buffs[k + i], 25);
330a3e26043SPablo de Lara goto exit;
33100c1efc1SGreg Tucker }
33200c1efc1SGreg Tucker }
33300c1efc1SGreg Tucker
33400c1efc1SGreg Tucker // Choose random buffers to be in erasure
33500c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
33600c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
33700c1efc1SGreg Tucker
33800c1efc1SGreg Tucker // Generate decode matrix
339*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
340*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
34100c1efc1SGreg Tucker if (re != 0) {
34200c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
343a3e26043SPablo de Lara goto exit;
34400c1efc1SGreg Tucker }
34500c1efc1SGreg Tucker // Pack recovery array as list of valid sources
34600c1efc1SGreg Tucker // Its order must be the same as the order
34700c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
34800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
34900c1efc1SGreg Tucker recov[i] = update_buffs[decode_index[i]];
35000c1efc1SGreg Tucker }
35100c1efc1SGreg Tucker
35200c1efc1SGreg Tucker // Recover data
35300c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
35400c1efc1SGreg Tucker REF_FUNCTION(TEST_LEN, k, nerrs, g_tbls, recov, &temp_buffs[k]);
35500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
35600c1efc1SGreg Tucker
35700c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], TEST_LEN)) {
35800c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
35900c1efc1SGreg Tucker printf(" - erase list = ");
36000c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
36100c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
36200c1efc1SGreg Tucker printf(" - Index = ");
36300c1efc1SGreg Tucker for (p = 0; p < k; p++)
36400c1efc1SGreg Tucker printf(" %d", decode_index[p]);
36500c1efc1SGreg Tucker printf("\nencode_matrix:\n");
36600c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
36700c1efc1SGreg Tucker printf("inv b:\n");
36800c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
36900c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
37000c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
37100c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
37200c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
37300c1efc1SGreg Tucker printf("orig :");
37400c1efc1SGreg Tucker dump(update_buffs[src_err_list[i]], 25);
375a3e26043SPablo de Lara re = -1;
376a3e26043SPablo de Lara goto exit;
37700c1efc1SGreg Tucker }
37800c1efc1SGreg Tucker }
3792ca781dfSPablo de Lara #ifdef TEST_VERBOSE
38000c1efc1SGreg Tucker putchar('.');
3812ca781dfSPablo de Lara #endif
38200c1efc1SGreg Tucker
38300c1efc1SGreg Tucker // Pick a first test
38400c1efc1SGreg Tucker m = 7;
38500c1efc1SGreg Tucker k = 5;
386a3e26043SPablo de Lara if (m > MMAX || k > KMAX) {
387a3e26043SPablo de Lara re = -1;
388a3e26043SPablo de Lara goto exit;
389a3e26043SPablo de Lara }
39000c1efc1SGreg Tucker
39100c1efc1SGreg Tucker // Zero the destination buffer for update function
39200c1efc1SGreg Tucker for (i = k; i < TEST_SOURCES; i++) {
39300c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN);
39400c1efc1SGreg Tucker memset(update_buffs[i], 0, TEST_LEN);
39500c1efc1SGreg Tucker }
39600c1efc1SGreg Tucker // Make random data
39700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
39800c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++) {
39900c1efc1SGreg Tucker buffs[i][j] = rand();
40000c1efc1SGreg Tucker update_buffs[i][j] = buffs[i][j];
40100c1efc1SGreg Tucker }
40200c1efc1SGreg Tucker }
40300c1efc1SGreg Tucker
40400c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
40500c1efc1SGreg Tucker // is always invertable.
40600c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
40700c1efc1SGreg Tucker
40800c1efc1SGreg Tucker // Generate g_tbls from encode matrix encode_matrix
40900c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
41000c1efc1SGreg Tucker
41100c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
41200c1efc1SGreg Tucker // using g_tbls from encode matrix encode_matrix
41300c1efc1SGreg Tucker REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
41400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
41500c1efc1SGreg Tucker FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
41600c1efc1SGreg Tucker &update_buffs[k]);
41700c1efc1SGreg Tucker }
41800c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
41900c1efc1SGreg Tucker if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
42000c1efc1SGreg Tucker printf("\nupdate_buffs%d :", i);
42100c1efc1SGreg Tucker dump(update_buffs[k + i], 25);
42200c1efc1SGreg Tucker printf("buffs%d :", i);
42300c1efc1SGreg Tucker dump(buffs[k + i], 25);
424a3e26043SPablo de Lara re = -1;
425a3e26043SPablo de Lara goto exit;
42600c1efc1SGreg Tucker }
42700c1efc1SGreg Tucker }
42800c1efc1SGreg Tucker
42900c1efc1SGreg Tucker // Choose random buffers to be in erasure
43000c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
43100c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
43200c1efc1SGreg Tucker
43300c1efc1SGreg Tucker // Generate decode matrix
434*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
435*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
43600c1efc1SGreg Tucker if (re != 0) {
43700c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
438a3e26043SPablo de Lara goto exit;
43900c1efc1SGreg Tucker }
44000c1efc1SGreg Tucker // Pack recovery array as list of valid sources
44100c1efc1SGreg Tucker // Its order must be the same as the order
44200c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
44300c1efc1SGreg Tucker for (i = 0; i < k; i++) {
44400c1efc1SGreg Tucker recov[i] = update_buffs[decode_index[i]];
44500c1efc1SGreg Tucker }
44600c1efc1SGreg Tucker
44700c1efc1SGreg Tucker // Recover data
44800c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
44900c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN);
45000c1efc1SGreg Tucker }
45100c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
45200c1efc1SGreg Tucker for (i = 0; i < k; i++) {
45300c1efc1SGreg Tucker FUNCTION_UNDER_TEST(TEST_LEN, k, nerrs, i, g_tbls, recov[i], &temp_buffs[k]);
45400c1efc1SGreg Tucker }
45500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
45600c1efc1SGreg Tucker
45700c1efc1SGreg Tucker if (0 != memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], TEST_LEN)) {
45800c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d)\n", m, k, nerrs);
45900c1efc1SGreg Tucker printf(" - erase list = ");
46000c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
46100c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
46200c1efc1SGreg Tucker printf(" - Index = ");
46300c1efc1SGreg Tucker for (p = 0; p < k; p++)
46400c1efc1SGreg Tucker printf(" %d", decode_index[p]);
46500c1efc1SGreg Tucker printf("\nencode_matrix:\n");
46600c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
46700c1efc1SGreg Tucker printf("inv b:\n");
46800c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
46900c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
47000c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
47100c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
47200c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
47300c1efc1SGreg Tucker printf("orig :");
47400c1efc1SGreg Tucker dump(update_buffs[src_err_list[i]], 25);
475a3e26043SPablo de Lara re = -1;
476a3e26043SPablo de Lara goto exit;
47700c1efc1SGreg Tucker }
47800c1efc1SGreg Tucker }
4792ca781dfSPablo de Lara #ifdef TEST_VERBOSE
48000c1efc1SGreg Tucker putchar('.');
4812ca781dfSPablo de Lara #endif
48200c1efc1SGreg Tucker
48300c1efc1SGreg Tucker // Do more random tests
48400c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
485*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
486*300260a4SMarcel Cornu ;
487*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
488*300260a4SMarcel Cornu ;
48900c1efc1SGreg Tucker
49000c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
49100c1efc1SGreg Tucker continue;
49200c1efc1SGreg Tucker
49300c1efc1SGreg Tucker // Zero the destination buffer for update function
49400c1efc1SGreg Tucker for (i = k; i < TEST_SOURCES; i++) {
49500c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN);
49600c1efc1SGreg Tucker memset(update_buffs[i], 0, TEST_LEN);
49700c1efc1SGreg Tucker }
49800c1efc1SGreg Tucker // Make random data
49900c1efc1SGreg Tucker for (i = 0; i < k; i++) {
50000c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++) {
50100c1efc1SGreg Tucker buffs[i][j] = rand();
50200c1efc1SGreg Tucker update_buffs[i][j] = buffs[i][j];
50300c1efc1SGreg Tucker }
50400c1efc1SGreg Tucker }
50500c1efc1SGreg Tucker
50600c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
50700c1efc1SGreg Tucker // is always invertable.
50800c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
50900c1efc1SGreg Tucker
51000c1efc1SGreg Tucker // Make parity vects
51100c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
51200c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
51300c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
51400c1efc1SGreg Tucker // using g_tbls from encode matrix a
51500c1efc1SGreg Tucker REF_FUNCTION(TEST_LEN, k, m - k, g_tbls, buffs, &buffs[k]);
51600c1efc1SGreg Tucker for (i = 0; i < k; i++) {
51700c1efc1SGreg Tucker FUNCTION_UNDER_TEST(TEST_LEN, k, m - k, i, g_tbls, update_buffs[i],
51800c1efc1SGreg Tucker &update_buffs[k]);
51900c1efc1SGreg Tucker }
52000c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
52100c1efc1SGreg Tucker if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN)) {
52200c1efc1SGreg Tucker printf("\nupdate_buffs%d :", i);
52300c1efc1SGreg Tucker dump(update_buffs[k + i], 25);
52400c1efc1SGreg Tucker printf("buffs%d :", i);
52500c1efc1SGreg Tucker dump(buffs[k + i], 25);
526a3e26043SPablo de Lara re = -1;
527a3e26043SPablo de Lara goto exit;
52800c1efc1SGreg Tucker }
52900c1efc1SGreg Tucker }
53000c1efc1SGreg Tucker
53100c1efc1SGreg Tucker // Random errors
53200c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
53300c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
53400c1efc1SGreg Tucker
53500c1efc1SGreg Tucker // Generate decode matrix
536*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
537*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
53800c1efc1SGreg Tucker if (re != 0) {
53900c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
540a3e26043SPablo de Lara goto exit;
54100c1efc1SGreg Tucker }
54200c1efc1SGreg Tucker // Pack recovery array as list of valid sources
54300c1efc1SGreg Tucker // Its order must be the same as the order
54400c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
54500c1efc1SGreg Tucker for (i = 0; i < k; i++) {
54600c1efc1SGreg Tucker recov[i] = update_buffs[decode_index[i]];
54700c1efc1SGreg Tucker }
54800c1efc1SGreg Tucker
54900c1efc1SGreg Tucker // Recover data
55000c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
55100c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN);
55200c1efc1SGreg Tucker }
55300c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
55400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
55500c1efc1SGreg Tucker FUNCTION_UNDER_TEST(TEST_LEN, k, nerrs, i, g_tbls, recov[i],
55600c1efc1SGreg Tucker &temp_buffs[k]);
55700c1efc1SGreg Tucker }
55800c1efc1SGreg Tucker
55900c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
56000c1efc1SGreg Tucker
56100c1efc1SGreg Tucker if (0 !=
562*300260a4SMarcel Cornu memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], TEST_LEN)) {
56300c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
56400c1efc1SGreg Tucker printf(" - erase list = ");
56500c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
56600c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
56700c1efc1SGreg Tucker printf(" - Index = ");
56800c1efc1SGreg Tucker for (p = 0; p < k; p++)
56900c1efc1SGreg Tucker printf(" %d", decode_index[p]);
57000c1efc1SGreg Tucker printf("\nencode_matrix:\n");
57100c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
57200c1efc1SGreg Tucker printf("inv b:\n");
57300c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
57400c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
57500c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
57600c1efc1SGreg Tucker printf("orig data:\n");
57700c1efc1SGreg Tucker dump_matrix(update_buffs, m, 25);
57800c1efc1SGreg Tucker printf("orig :");
57900c1efc1SGreg Tucker dump(update_buffs[src_err_list[i]], 25);
58000c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
58100c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
582a3e26043SPablo de Lara re = -1;
583a3e26043SPablo de Lara goto exit;
58400c1efc1SGreg Tucker }
58500c1efc1SGreg Tucker }
5862ca781dfSPablo de Lara #ifdef TEST_VERBOSE
58700c1efc1SGreg Tucker putchar('.');
5882ca781dfSPablo de Lara #endif
58900c1efc1SGreg Tucker }
59000c1efc1SGreg Tucker
59100c1efc1SGreg Tucker // Run tests at end of buffer for Electric Fence
59200c1efc1SGreg Tucker k = 16;
59300c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 1 : ALIGN_SIZE;
594a3e26043SPablo de Lara if (k > KMAX) {
595a3e26043SPablo de Lara re = -1;
596a3e26043SPablo de Lara goto exit;
597a3e26043SPablo de Lara }
59800c1efc1SGreg Tucker
59900c1efc1SGreg Tucker for (rows = 1; rows <= 16; rows++) {
60000c1efc1SGreg Tucker m = k + rows;
601a3e26043SPablo de Lara if (m > MMAX) {
602a3e26043SPablo de Lara re = -1;
603a3e26043SPablo de Lara goto exit;
604a3e26043SPablo de Lara }
60500c1efc1SGreg Tucker
60600c1efc1SGreg Tucker for (i = k; i < TEST_SOURCES; i++) {
60700c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN);
60800c1efc1SGreg Tucker memset(update_buffs[i], 0, TEST_LEN);
60900c1efc1SGreg Tucker }
61000c1efc1SGreg Tucker // Make random data
61100c1efc1SGreg Tucker for (i = 0; i < k; i++) {
61200c1efc1SGreg Tucker for (j = 0; j < TEST_LEN; j++) {
61300c1efc1SGreg Tucker buffs[i][j] = rand();
61400c1efc1SGreg Tucker update_buffs[i][j] = buffs[i][j];
61500c1efc1SGreg Tucker }
61600c1efc1SGreg Tucker }
61700c1efc1SGreg Tucker
6184f2d148aSRoy Oursler for (size = 0; size <= EFENCE_TEST_MAX_SIZE; size += align) {
61900c1efc1SGreg Tucker for (i = 0; i < m; i++) { // Line up TEST_SIZE from end
62000c1efc1SGreg Tucker efence_buffs[i] = buffs[i] + TEST_LEN - size;
62100c1efc1SGreg Tucker efence_update_buffs[i] = update_buffs[i] + TEST_LEN - size;
62200c1efc1SGreg Tucker }
62300c1efc1SGreg Tucker // Zero the destination buffer for update function
62400c1efc1SGreg Tucker for (i = k; i < m; i++) {
62500c1efc1SGreg Tucker memset(efence_buffs[i], 0, size);
62600c1efc1SGreg Tucker memset(efence_update_buffs[i], 0, size);
62700c1efc1SGreg Tucker }
62800c1efc1SGreg Tucker
62900c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
63000c1efc1SGreg Tucker // is always invertable.
63100c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
63200c1efc1SGreg Tucker
63300c1efc1SGreg Tucker // Make parity vects
63400c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
63500c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
63600c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
63700c1efc1SGreg Tucker // using g_tbls from encode matrix a
63800c1efc1SGreg Tucker REF_FUNCTION(size, k, m - k, g_tbls, efence_buffs, &efence_buffs[k]);
63900c1efc1SGreg Tucker for (i = 0; i < k; i++) {
64000c1efc1SGreg Tucker FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls,
64100c1efc1SGreg Tucker efence_update_buffs[i],
64200c1efc1SGreg Tucker &efence_update_buffs[k]);
64300c1efc1SGreg Tucker }
64400c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
64500c1efc1SGreg Tucker if (0 !=
646*300260a4SMarcel Cornu memcmp(efence_update_buffs[k + i], efence_buffs[k + i], size)) {
64700c1efc1SGreg Tucker printf("\nefence_update_buffs%d :", i);
64800c1efc1SGreg Tucker dump(efence_update_buffs[k + i], 25);
64900c1efc1SGreg Tucker printf("efence_buffs%d :", i);
65000c1efc1SGreg Tucker dump(efence_buffs[k + i], 25);
651a3e26043SPablo de Lara re = -1;
652a3e26043SPablo de Lara goto exit;
65300c1efc1SGreg Tucker }
65400c1efc1SGreg Tucker }
65500c1efc1SGreg Tucker
65600c1efc1SGreg Tucker // Random errors
65700c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
65800c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
65900c1efc1SGreg Tucker
66000c1efc1SGreg Tucker // Generate decode matrix
661*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix,
662*300260a4SMarcel Cornu decode_index, src_err_list, src_in_err, nerrs,
663*300260a4SMarcel Cornu nsrcerrs, k, m);
66400c1efc1SGreg Tucker if (re != 0) {
66500c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
666a3e26043SPablo de Lara goto exit;
66700c1efc1SGreg Tucker }
66800c1efc1SGreg Tucker // Pack recovery array as list of valid sources
66900c1efc1SGreg Tucker // Its order must be the same as the order
67000c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
67100c1efc1SGreg Tucker for (i = 0; i < k; i++) {
67200c1efc1SGreg Tucker recov[i] = efence_update_buffs[decode_index[i]];
67300c1efc1SGreg Tucker }
67400c1efc1SGreg Tucker
67500c1efc1SGreg Tucker // Recover data
67600c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
67700c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN);
67800c1efc1SGreg Tucker }
67900c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
68000c1efc1SGreg Tucker for (i = 0; i < k; i++) {
68100c1efc1SGreg Tucker FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i],
68200c1efc1SGreg Tucker &temp_buffs[k]);
68300c1efc1SGreg Tucker }
68400c1efc1SGreg Tucker
68500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
68600c1efc1SGreg Tucker
687*300260a4SMarcel Cornu if (0 != memcmp(temp_buffs[k + i],
68800c1efc1SGreg Tucker efence_update_buffs[src_err_list[i]], size)) {
689*300260a4SMarcel Cornu printf("Efence: Fail error recovery (%d, %d, %d)\n", m, k,
690*300260a4SMarcel Cornu nerrs);
69100c1efc1SGreg Tucker
69200c1efc1SGreg Tucker printf("size = %d\n", size);
69300c1efc1SGreg Tucker
69400c1efc1SGreg Tucker printf("Test erase list = ");
69500c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
69600c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
69700c1efc1SGreg Tucker printf(" - Index = ");
69800c1efc1SGreg Tucker for (p = 0; p < k; p++)
69900c1efc1SGreg Tucker printf(" %d", decode_index[p]);
70000c1efc1SGreg Tucker printf("\nencode_matrix:\n");
70100c1efc1SGreg Tucker dump_u8xu8((u8 *) encode_matrix, m, k);
70200c1efc1SGreg Tucker printf("inv b:\n");
70300c1efc1SGreg Tucker dump_u8xu8((u8 *) invert_matrix, k, k);
70400c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
70500c1efc1SGreg Tucker dump_u8xu8((u8 *) decode_matrix, m, k);
70600c1efc1SGreg Tucker
70700c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
70800c1efc1SGreg Tucker dump(temp_buffs[k + i], align);
70900c1efc1SGreg Tucker printf("orig :");
71000c1efc1SGreg Tucker dump(efence_update_buffs[src_err_list[i]], align);
711a3e26043SPablo de Lara re = 1;
712a3e26043SPablo de Lara goto exit;
71300c1efc1SGreg Tucker }
71400c1efc1SGreg Tucker }
71500c1efc1SGreg Tucker }
7162ca781dfSPablo de Lara #ifdef TEST_VERBOSE
71700c1efc1SGreg Tucker putchar('.');
7182ca781dfSPablo de Lara #endif
71900c1efc1SGreg Tucker }
72000c1efc1SGreg Tucker
72100c1efc1SGreg Tucker // Test rand ptr alignment if available
72200c1efc1SGreg Tucker
72300c1efc1SGreg Tucker for (rtest = 0; rtest < RANDOMS; rtest++) {
724*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
725*300260a4SMarcel Cornu ;
726*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
727*300260a4SMarcel Cornu ;
72800c1efc1SGreg Tucker
72900c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
73000c1efc1SGreg Tucker continue;
73100c1efc1SGreg Tucker
73200c1efc1SGreg Tucker size = (TEST_LEN - PTR_ALIGN_CHK_B) & ~15;
73300c1efc1SGreg Tucker
73400c1efc1SGreg Tucker offset = (PTR_ALIGN_CHK_B != 0) ? 1 : PTR_ALIGN_CHK_B;
73500c1efc1SGreg Tucker // Add random offsets
73600c1efc1SGreg Tucker for (i = 0; i < m; i++) {
73700c1efc1SGreg Tucker memset(buffs[i], 0, TEST_LEN); // zero pad to check write-over
73800c1efc1SGreg Tucker memset(update_buffs[i], 0, TEST_LEN); // zero pad to check write-over
73900c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN); // zero pad to check write-over
74000c1efc1SGreg Tucker ubuffs[i] = buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
741*300260a4SMarcel Cornu update_ubuffs[i] = update_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
74200c1efc1SGreg Tucker temp_ubuffs[i] = temp_buffs[i] + (rand() & (PTR_ALIGN_CHK_B - offset));
74300c1efc1SGreg Tucker }
74400c1efc1SGreg Tucker
74500c1efc1SGreg Tucker // Zero the destination buffer for update function
74600c1efc1SGreg Tucker for (i = k; i < m; i++) {
74700c1efc1SGreg Tucker memset(ubuffs[i], 0, size);
74800c1efc1SGreg Tucker memset(update_ubuffs[i], 0, size);
74900c1efc1SGreg Tucker }
75000c1efc1SGreg Tucker // Make random data
75100c1efc1SGreg Tucker for (i = 0; i < k; i++) {
75200c1efc1SGreg Tucker for (j = 0; j < size; j++) {
75300c1efc1SGreg Tucker ubuffs[i][j] = rand();
75400c1efc1SGreg Tucker update_ubuffs[i][j] = ubuffs[i][j];
75500c1efc1SGreg Tucker }
75600c1efc1SGreg Tucker }
75700c1efc1SGreg Tucker
75800c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
75900c1efc1SGreg Tucker // is always invertable.
76000c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
76100c1efc1SGreg Tucker
76200c1efc1SGreg Tucker // Make parity vects
76300c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
76400c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
76500c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
76600c1efc1SGreg Tucker // using g_tbls from encode matrix a
76700c1efc1SGreg Tucker REF_FUNCTION(size, k, m - k, g_tbls, ubuffs, &ubuffs[k]);
76800c1efc1SGreg Tucker for (i = 0; i < k; i++) {
76900c1efc1SGreg Tucker FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls, update_ubuffs[i],
77000c1efc1SGreg Tucker &update_ubuffs[k]);
77100c1efc1SGreg Tucker }
77200c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
77300c1efc1SGreg Tucker if (0 != memcmp(update_ubuffs[k + i], ubuffs[k + i], size)) {
77400c1efc1SGreg Tucker printf("\nupdate_ubuffs%d :", i);
77500c1efc1SGreg Tucker dump(update_ubuffs[k + i], 25);
77600c1efc1SGreg Tucker printf("ubuffs%d :", i);
77700c1efc1SGreg Tucker dump(ubuffs[k + i], 25);
778a3e26043SPablo de Lara re = -1;
779a3e26043SPablo de Lara goto exit;
78000c1efc1SGreg Tucker }
78100c1efc1SGreg Tucker }
78200c1efc1SGreg Tucker
78300c1efc1SGreg Tucker // Random errors
78400c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
78500c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
78600c1efc1SGreg Tucker
78700c1efc1SGreg Tucker // Generate decode matrix
788*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
789*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
79000c1efc1SGreg Tucker if (re != 0) {
79100c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
792a3e26043SPablo de Lara goto exit;
79300c1efc1SGreg Tucker }
79400c1efc1SGreg Tucker // Pack recovery array as list of valid sources
79500c1efc1SGreg Tucker // Its order must be the same as the order
79600c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
79700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
79800c1efc1SGreg Tucker recov[i] = update_ubuffs[decode_index[i]];
79900c1efc1SGreg Tucker }
80000c1efc1SGreg Tucker
80100c1efc1SGreg Tucker // Recover data
80200c1efc1SGreg Tucker for (i = 0; i < m; i++) {
80300c1efc1SGreg Tucker memset(temp_ubuffs[i], 0, size);
80400c1efc1SGreg Tucker }
80500c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
80600c1efc1SGreg Tucker for (i = 0; i < k; i++) {
807*300260a4SMarcel Cornu FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i], &temp_ubuffs[k]);
80800c1efc1SGreg Tucker }
80900c1efc1SGreg Tucker
81000c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
81100c1efc1SGreg Tucker
812*300260a4SMarcel Cornu if (0 != memcmp(temp_ubuffs[k + i], update_ubuffs[src_err_list[i]], size)) {
81300c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
81400c1efc1SGreg Tucker printf(" - erase list = ");
81500c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
81600c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
81700c1efc1SGreg Tucker printf(" - Index = ");
81800c1efc1SGreg Tucker for (p = 0; p < k; p++)
81900c1efc1SGreg Tucker printf(" %d", decode_index[p]);
82000c1efc1SGreg Tucker printf("\nencode_matrix:\n");
82100c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
82200c1efc1SGreg Tucker printf("inv b:\n");
82300c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
82400c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
82500c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
82600c1efc1SGreg Tucker printf("orig data:\n");
82700c1efc1SGreg Tucker dump_matrix(update_ubuffs, m, 25);
82800c1efc1SGreg Tucker printf("orig :");
82900c1efc1SGreg Tucker dump(update_ubuffs[src_err_list[i]], 25);
83000c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
83100c1efc1SGreg Tucker dump(temp_ubuffs[k + i], 25);
832a3e26043SPablo de Lara re = -1;
833a3e26043SPablo de Lara goto exit;
83400c1efc1SGreg Tucker }
83500c1efc1SGreg Tucker }
83600c1efc1SGreg Tucker
83700c1efc1SGreg Tucker // Confirm that padding around dests is unchanged
83800c1efc1SGreg Tucker memset(temp_buffs[0], 0, PTR_ALIGN_CHK_B); // Make reference zero buff
83900c1efc1SGreg Tucker
84000c1efc1SGreg Tucker for (i = 0; i < m; i++) {
84100c1efc1SGreg Tucker
84200c1efc1SGreg Tucker offset = update_ubuffs[i] - update_buffs[i];
84300c1efc1SGreg Tucker
84400c1efc1SGreg Tucker if (memcmp(update_buffs[i], temp_buffs[0], offset)) {
84500c1efc1SGreg Tucker printf("Fail rand ualign encode pad start\n");
846a3e26043SPablo de Lara re = -1;
847a3e26043SPablo de Lara goto exit;
84800c1efc1SGreg Tucker }
849*300260a4SMarcel Cornu if (memcmp(update_buffs[i] + offset + size, temp_buffs[0],
85000c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
85100c1efc1SGreg Tucker printf("Fail rand ualign encode pad end\n");
852a3e26043SPablo de Lara re = -1;
853a3e26043SPablo de Lara goto exit;
85400c1efc1SGreg Tucker }
85500c1efc1SGreg Tucker }
85600c1efc1SGreg Tucker
85700c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
85800c1efc1SGreg Tucker
85900c1efc1SGreg Tucker offset = temp_ubuffs[k + i] - temp_buffs[k + i];
86000c1efc1SGreg Tucker if (memcmp(temp_buffs[k + i], temp_buffs[0], offset)) {
86100c1efc1SGreg Tucker printf("Fail rand ualign decode pad start\n");
862a3e26043SPablo de Lara re = -1;
863a3e26043SPablo de Lara goto exit;
86400c1efc1SGreg Tucker }
865*300260a4SMarcel Cornu if (memcmp(temp_buffs[k + i] + offset + size, temp_buffs[0],
86600c1efc1SGreg Tucker PTR_ALIGN_CHK_B - offset)) {
86700c1efc1SGreg Tucker printf("Fail rand ualign decode pad end\n");
868a3e26043SPablo de Lara re = -1;
869a3e26043SPablo de Lara goto exit;
87000c1efc1SGreg Tucker }
87100c1efc1SGreg Tucker }
87200c1efc1SGreg Tucker
8732ca781dfSPablo de Lara #ifdef TEST_VERBOSE
87400c1efc1SGreg Tucker putchar('.');
8752ca781dfSPablo de Lara #endif
87600c1efc1SGreg Tucker }
87700c1efc1SGreg Tucker
87800c1efc1SGreg Tucker // Test size alignment
87900c1efc1SGreg Tucker
88000c1efc1SGreg Tucker align = (LEN_ALIGN_CHK_B != 0) ? 13 : ALIGN_SIZE;
88100c1efc1SGreg Tucker
88200c1efc1SGreg Tucker for (size = TEST_LEN; size >= 0; size -= align) {
883*300260a4SMarcel Cornu while ((m = (rand() % MMAX)) < 2)
884*300260a4SMarcel Cornu ;
885*300260a4SMarcel Cornu while ((k = (rand() % KMAX)) >= m || k < 1)
886*300260a4SMarcel Cornu ;
88700c1efc1SGreg Tucker
88800c1efc1SGreg Tucker if (m > MMAX || k > KMAX)
88900c1efc1SGreg Tucker continue;
89000c1efc1SGreg Tucker
89100c1efc1SGreg Tucker // Zero the destination buffer for update function
89200c1efc1SGreg Tucker for (i = k; i < TEST_SOURCES; i++) {
89300c1efc1SGreg Tucker memset(buffs[i], 0, size);
89400c1efc1SGreg Tucker memset(update_buffs[i], 0, size);
89500c1efc1SGreg Tucker }
89600c1efc1SGreg Tucker // Make random data
89700c1efc1SGreg Tucker for (i = 0; i < k; i++) {
89800c1efc1SGreg Tucker for (j = 0; j < size; j++) {
89900c1efc1SGreg Tucker buffs[i][j] = rand();
90000c1efc1SGreg Tucker update_buffs[i][j] = buffs[i][j];
90100c1efc1SGreg Tucker }
90200c1efc1SGreg Tucker }
90300c1efc1SGreg Tucker
90400c1efc1SGreg Tucker // The matrix generated by gf_gen_cauchy1_matrix
90500c1efc1SGreg Tucker // is always invertable.
90600c1efc1SGreg Tucker gf_gen_cauchy1_matrix(encode_matrix, m, k);
90700c1efc1SGreg Tucker
90800c1efc1SGreg Tucker // Make parity vects
90900c1efc1SGreg Tucker // Generate g_tbls from encode matrix a
91000c1efc1SGreg Tucker ec_init_tables(k, m - k, &encode_matrix[k * k], g_tbls);
91100c1efc1SGreg Tucker // Perform matrix dot_prod for EC encoding
91200c1efc1SGreg Tucker // using g_tbls from encode matrix a
91300c1efc1SGreg Tucker REF_FUNCTION(size, k, m - k, g_tbls, buffs, &buffs[k]);
91400c1efc1SGreg Tucker for (i = 0; i < k; i++) {
91500c1efc1SGreg Tucker FUNCTION_UNDER_TEST(size, k, m - k, i, g_tbls, update_buffs[i],
91600c1efc1SGreg Tucker &update_buffs[k]);
91700c1efc1SGreg Tucker }
91800c1efc1SGreg Tucker for (i = 0; i < m - k; i++) {
91900c1efc1SGreg Tucker if (0 != memcmp(update_buffs[k + i], buffs[k + i], size)) {
92000c1efc1SGreg Tucker printf("\nupdate_buffs%d (size=%d) :", i, size);
92100c1efc1SGreg Tucker dump(update_buffs[k + i], 25);
92200c1efc1SGreg Tucker printf("buffs%d (size=%d) :", i, size);
92300c1efc1SGreg Tucker dump(buffs[k + i], 25);
924a3e26043SPablo de Lara re = -1;
925a3e26043SPablo de Lara goto exit;
92600c1efc1SGreg Tucker }
92700c1efc1SGreg Tucker }
92800c1efc1SGreg Tucker
92900c1efc1SGreg Tucker // Random errors
93000c1efc1SGreg Tucker memset(src_in_err, 0, TEST_SOURCES);
93100c1efc1SGreg Tucker gen_err_list(src_err_list, src_in_err, &nerrs, &nsrcerrs, k, m);
93200c1efc1SGreg Tucker // Generate decode matrix
933*300260a4SMarcel Cornu re = gf_gen_decode_matrix(encode_matrix, decode_matrix, invert_matrix, decode_index,
934*300260a4SMarcel Cornu src_err_list, src_in_err, nerrs, nsrcerrs, k, m);
93500c1efc1SGreg Tucker if (re != 0) {
93600c1efc1SGreg Tucker printf("Fail to gf_gen_decode_matrix\n");
937a3e26043SPablo de Lara goto exit;
93800c1efc1SGreg Tucker }
93900c1efc1SGreg Tucker // Pack recovery array as list of valid sources
94000c1efc1SGreg Tucker // Its order must be the same as the order
94100c1efc1SGreg Tucker // to generate matrix b in gf_gen_decode_matrix
94200c1efc1SGreg Tucker for (i = 0; i < k; i++) {
94300c1efc1SGreg Tucker recov[i] = update_buffs[decode_index[i]];
94400c1efc1SGreg Tucker }
94500c1efc1SGreg Tucker
94600c1efc1SGreg Tucker // Recover data
94700c1efc1SGreg Tucker for (i = 0; i < TEST_SOURCES; i++) {
94800c1efc1SGreg Tucker memset(temp_buffs[i], 0, TEST_LEN);
94900c1efc1SGreg Tucker }
95000c1efc1SGreg Tucker ec_init_tables(k, nerrs, decode_matrix, g_tbls);
95100c1efc1SGreg Tucker for (i = 0; i < k; i++) {
952*300260a4SMarcel Cornu FUNCTION_UNDER_TEST(size, k, nerrs, i, g_tbls, recov[i], &temp_buffs[k]);
95300c1efc1SGreg Tucker }
95400c1efc1SGreg Tucker
95500c1efc1SGreg Tucker for (i = 0; i < nerrs; i++) {
95600c1efc1SGreg Tucker
957*300260a4SMarcel Cornu if (0 != memcmp(temp_buffs[k + i], update_buffs[src_err_list[i]], size)) {
95800c1efc1SGreg Tucker printf("Fail error recovery (%d, %d, %d) - ", m, k, nerrs);
95900c1efc1SGreg Tucker printf(" - erase list = ");
96000c1efc1SGreg Tucker for (j = 0; j < nerrs; j++)
96100c1efc1SGreg Tucker printf(" %d", src_err_list[j]);
96200c1efc1SGreg Tucker printf(" - Index = ");
96300c1efc1SGreg Tucker for (p = 0; p < k; p++)
96400c1efc1SGreg Tucker printf(" %d", decode_index[p]);
96500c1efc1SGreg Tucker printf("\nencode_matrix:\n");
96600c1efc1SGreg Tucker dump_u8xu8((unsigned char *) encode_matrix, m, k);
96700c1efc1SGreg Tucker printf("inv b:\n");
96800c1efc1SGreg Tucker dump_u8xu8((unsigned char *) invert_matrix, k, k);
96900c1efc1SGreg Tucker printf("\ndecode_matrix:\n");
97000c1efc1SGreg Tucker dump_u8xu8((unsigned char *) decode_matrix, m, k);
97100c1efc1SGreg Tucker printf("orig data:\n");
97200c1efc1SGreg Tucker dump_matrix(update_buffs, m, 25);
97300c1efc1SGreg Tucker printf("orig :");
97400c1efc1SGreg Tucker dump(update_buffs[src_err_list[i]], 25);
97500c1efc1SGreg Tucker printf("recov %d:", src_err_list[i]);
97600c1efc1SGreg Tucker dump(temp_buffs[k + i], 25);
977a3e26043SPablo de Lara re = -1;
978a3e26043SPablo de Lara goto exit;
97900c1efc1SGreg Tucker }
98000c1efc1SGreg Tucker }
9812ca781dfSPablo de Lara #ifdef TEST_VERBOSE
98200c1efc1SGreg Tucker putchar('.');
9832ca781dfSPablo de Lara #endif
98400c1efc1SGreg Tucker }
98500c1efc1SGreg Tucker
98600c1efc1SGreg Tucker printf("done EC tests: Pass\n");
987a3e26043SPablo de Lara re = 0;
988a3e26043SPablo de Lara
989a3e26043SPablo de Lara exit:
990a3e26043SPablo de Lara for (i = 0; i < TEST_SOURCES; i++) {
991a3e26043SPablo de Lara if (buffs[i])
992a3e26043SPablo de Lara aligned_free(buffs[i]);
993a3e26043SPablo de Lara if (temp_buffs[i])
994a3e26043SPablo de Lara aligned_free(temp_buffs[i]);
995a3e26043SPablo de Lara if (update_buffs[i])
996a3e26043SPablo de Lara aligned_free(update_buffs[i]);
997a3e26043SPablo de Lara }
998a3e26043SPablo de Lara free(encode_matrix);
999a3e26043SPablo de Lara free(decode_matrix);
1000a3e26043SPablo de Lara free(invert_matrix);
1001a3e26043SPablo de Lara free(g_tbls);
100200c1efc1SGreg Tucker return 0;
100300c1efc1SGreg Tucker }
1004