xref: /isa-l/erasure_code/erasure_code_base_test.c (revision 300260a4d902423a8a69f0f7d74e6abaa33ded27)
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