liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
alg_sig.c
Go to the documentation of this file.
1/* * Copyright (c) 2013, Kevin Greenan (kmgreen2@gmail.com)
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY
13 * THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
20 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
21 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include <dlfcn.h>
26#include <alg_sig.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#define GALOIS_SINGLE_MULTIPLY "galois_single_multiply"
31#define GALOIS_UNINIT "galois_uninit_field"
32
33/* valid GF w values: 8, 16 */
34static int valid_pairs[][2] = { { 8, 32}, {16, 32}, {16, 64}, {-1, -1} };
35
36static galois_single_multiply_func get_galois_multi_func(void *handle) {
37 /*
38 * ISO C forbids casting a void* to a function pointer.
39 * Since dlsym return returns a void*, we use this union to
40 * "transform" the void* to a function pointer.
41 */
42 union {
43 galois_single_multiply_func fptr;
44 void *vptr;
45 } func_handle = {.vptr = NULL};
46 func_handle.vptr = dlsym(handle, GALOIS_SINGLE_MULTIPLY);
47 return func_handle.fptr;
48}
49
50static void stub_galois_uninit_field(int w){}
51
53 /*
54 * ISO C forbids casting a void* to a function pointer.
55 * Since dlsym return returns a void*, we use this union to
56 * "transform" the void* to a function pointer.
57 */
58 union {
60 void *vptr;
61 } func_handle = {.vptr = NULL};
62 func_handle.vptr = dlsym(handle, GALOIS_UNINIT);
63 return func_handle.fptr;
64}
65
66
67static void *get_jerasure_sohandle(void)
68{
69 return dlopen(JERASURE_SONAME, RTLD_LAZY | RTLD_LOCAL);
70}
71
72static int load_gf_functions(void *sohandle, struct jerasure_mult_routines *routines)
73{
74 routines->galois_single_multiply = get_galois_multi_func(sohandle);
75 routines->galois_uninit_field = get_galois_uninit_func(sohandle);
76 if (NULL == routines->galois_single_multiply) {
77 return -1;
78 }
88 if (NULL == routines->galois_uninit_field) {
89 routines->galois_uninit_field = &stub_galois_uninit_field;
90 }
91
92 return 0;
93}
94
95static
96alg_sig_t *init_alg_sig_w8(void *jerasure_sohandle, int sig_len)
97{
98 alg_sig_t *alg_sig_handle;
99 int num_gf_lr_table_syms;
100 int i;
101 int w = 8;
102 int alpha = 2, beta = 4, gamma = 8;
103 int num_components = sig_len / w;
104
105 alg_sig_handle = (alg_sig_t *)malloc(sizeof(alg_sig_t));
106 if (NULL == alg_sig_handle) {
107 return NULL;
108 }
109
110 alg_sig_handle->jerasure_sohandle = jerasure_sohandle;
111
112 if (load_gf_functions(alg_sig_handle->jerasure_sohandle, &(alg_sig_handle->mult_routines)) < 0) {
113 free(alg_sig_handle);
114 return NULL;
115 }
116
117 alg_sig_handle->sig_len = sig_len;
118 alg_sig_handle->gf_w = w;
119
120 num_gf_lr_table_syms = 1 << (w >> 1);
121
122 if (num_components >= 4) {
123 alg_sig_handle->tbl1_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
124 alg_sig_handle->tbl1_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
125 alg_sig_handle->tbl2_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
126 alg_sig_handle->tbl2_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
127 alg_sig_handle->tbl3_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
128 alg_sig_handle->tbl3_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
129 }
130
131 /*
132 * Note that \alpha = 2
133 * Note that \beta = 4 (\alpha ^ 2)
134 * Note that \gamme = 8 (\alpha ^ 3)
135 */
136 for (i = 0; i < 16; i++) {
137 if (num_components >= 4) {
138 alg_sig_handle->tbl1_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char)(i << 4) & 0xf0, alpha, w);
139 alg_sig_handle->tbl1_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char) i, alpha, w);
140
141 alg_sig_handle->tbl2_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char) (i << 4) & 0xf0, beta, w);
142 alg_sig_handle->tbl2_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char) i, beta, w);
143
144 alg_sig_handle->tbl3_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char) (i << 4) & 0xf0, gamma, w);
145 alg_sig_handle->tbl3_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned char) i, gamma, w);
146 }
147 }
148
149 return alg_sig_handle;
150}
151
152static
153alg_sig_t *init_alg_sig_w16(void *jerasure_sohandle, int sig_len)
154{
155 alg_sig_t *alg_sig_handle;
156 int num_gf_lr_table_syms;
157 int i;
158 int w = 16;
159 int alpha = 2, beta = 4, gamma = 8;
160 int num_components = sig_len / w;
161
162 if (NULL == jerasure_sohandle) {
163 return NULL;
164 }
165
166 alg_sig_handle = (alg_sig_t *)malloc(sizeof(alg_sig_t));
167 if (NULL == alg_sig_handle) {
168 return NULL;
169 }
170
171 alg_sig_handle->jerasure_sohandle = jerasure_sohandle;
172
173 if (load_gf_functions(alg_sig_handle->jerasure_sohandle, &(alg_sig_handle->mult_routines)) < 0) {
174 free(alg_sig_handle);
175 return NULL;
176 }
177
178 alg_sig_handle->sig_len = sig_len;
179 alg_sig_handle->gf_w = w;
180
181 num_gf_lr_table_syms = 1 << (w >> 1);
182
183 if (num_components >= 2) {
184 alg_sig_handle->tbl1_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
185 alg_sig_handle->tbl1_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
186 if (NULL == alg_sig_handle->tbl1_l || NULL == alg_sig_handle->tbl1_r) {
187 free(alg_sig_handle->tbl1_l);
188 free(alg_sig_handle->tbl1_r);
189 free(alg_sig_handle);
190 return NULL;
191 }
192 }
193
194 if (num_components >= 4) {
195 alg_sig_handle->tbl2_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
196 alg_sig_handle->tbl2_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
197 alg_sig_handle->tbl3_l = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
198 alg_sig_handle->tbl3_r = (int*)malloc(sizeof(int) * num_gf_lr_table_syms);
199 if (NULL == alg_sig_handle->tbl2_l || NULL == alg_sig_handle->tbl2_r ||
200 NULL == alg_sig_handle->tbl3_l || NULL == alg_sig_handle->tbl3_r) {
201 free(alg_sig_handle->tbl2_l);
202 free(alg_sig_handle->tbl2_r);
203 free(alg_sig_handle->tbl3_l);
204 free(alg_sig_handle->tbl3_r);
205 free(alg_sig_handle);
206 return NULL;
207 }
208 }
209
210 /*
211 * Note that \alpha = 2
212 * Note that \beta = 4 (\alpha ^ 2 MOD 2^16)
213 * Note that \gamme = 8 (\alpha ^ 3 MOD 2^16)
214 */
215 for (i = 0; i < 256; i++) {
216 if (num_components >= 2) {
217 alg_sig_handle->tbl1_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) (i << 8), alpha, w);
218 alg_sig_handle->tbl1_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) i, alpha, w);
219 }
220
221 if (num_components >= 4) {
222 alg_sig_handle->tbl2_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) (i << 8), beta, w);
223 alg_sig_handle->tbl2_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) i, beta, w);
224
225 alg_sig_handle->tbl3_l[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) (i << 8), gamma, w);
226 alg_sig_handle->tbl3_r[i] = alg_sig_handle->mult_routines.galois_single_multiply((unsigned short) i, gamma, w);
227 }
228 }
229
230 return alg_sig_handle;
231}
232
233__attribute__ ((visibility ("internal")))
234alg_sig_t *init_alg_sig(int sig_len, int gf_w)
235{
236 int i=0;
237 void *jerasure_sohandle = get_jerasure_sohandle();
238
239 if (NULL == jerasure_sohandle) {
240 fprintf (stderr, "Could not open Jerasure backend. Install Jerasure or fix LD_LIBRARY_PATH. Passing.\n");
241 return NULL;
242 }
243
244 while (valid_pairs[i][0] > -1) {
245 if (gf_w == valid_pairs[i][0] &&
246 sig_len == valid_pairs[i][1]) {
247 break;
248 }
249 i++;
250 }
251
252 if (valid_pairs[i][0] == -1) {
253 return NULL;
254 }
255
256 if (gf_w == 8) {
257 return init_alg_sig_w8(jerasure_sohandle, sig_len);
258 } else if (gf_w == 16) {
259 return init_alg_sig_w16(jerasure_sohandle, sig_len);
260 }
261 return NULL;
262}
263
264__attribute__ ((visibility ("internal")))
265void destroy_alg_sig(alg_sig_t* alg_sig_handle)
266{
267 if (alg_sig_handle == NULL) {
268 return;
269 }
270 if (alg_sig_handle->gf_w == 0) {
271 free(alg_sig_handle);
272 return;
273 }
274
275 alg_sig_handle->mult_routines.galois_uninit_field(alg_sig_handle->gf_w);
276 dlclose(alg_sig_handle->jerasure_sohandle);
277
278 int num_components = alg_sig_handle->sig_len / alg_sig_handle->gf_w;
279
280 if (num_components >= 2) {
281 free(alg_sig_handle->tbl1_l);
282 free(alg_sig_handle->tbl1_r);
283 }
284 if (num_components >= 4) {
285 free(alg_sig_handle->tbl2_l);
286 free(alg_sig_handle->tbl2_r);
287 free(alg_sig_handle->tbl3_l);
288 free(alg_sig_handle->tbl3_r);
289 }
290
291 free(alg_sig_handle);
292}
293
294
295static
296int compute_w8_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
297{
298 int i;
299
300 if (len == 0) {
301 bzero(sig, 4);
302 return 0;
303 }
304
305 sig[0] = buf[len-1];
306 sig[1] = buf[len-1];
307 sig[2] = buf[len-1];
308 sig[3] = buf[len-1];
309
314 for (i = len - 2; i >= 0; i--) {
315 sig[0] ^= buf[i];
316 sig[1] = (buf[i] ^ (alg_sig_handle->tbl1_l[(sig[1] >> 4) & 0x0f] ^ alg_sig_handle->tbl1_r[sig[1] & 0x0f]));
317 sig[2] = (buf[i] ^ (alg_sig_handle->tbl2_l[(sig[2] >> 4) & 0x0f] ^ alg_sig_handle->tbl2_r[sig[2] & 0x0f]));
318 sig[3] = (buf[i] ^ (alg_sig_handle->tbl3_l[(sig[3] >> 4) & 0x0f] ^ alg_sig_handle->tbl3_r[sig[3] & 0x0f]));
319 }
320
321 return 0;
322}
323
324static
325int compute_w16_alg_sig_64(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
326{
327 int bit_mask;
328 int adj_len = len / 2;
329 int i;
330 unsigned short *_buf = (unsigned short *)buf;
331 unsigned short sig_buf[4];
332
333 if (len == 0) {
334 bzero(sig, 8);
335 return 0;
336 }
337
338 switch (len % 2) {
339 case 1:
340 bit_mask = 0x00ff;
341 break;
342 default:
343 bit_mask = 0xffff;
344 break;
345 }
346
347 if (len % 2 > 0) {
348 adj_len++;
349 }
350
351 // Account for buffer not being uint16_t aligned
352 sig_buf[0] = (_buf[adj_len - 1] & bit_mask);
353 sig_buf[1] = (_buf[adj_len - 1] & bit_mask);
354 sig_buf[2] = (_buf[adj_len - 1] & bit_mask);
355 sig_buf[3] = (_buf[adj_len - 1] & bit_mask);
356
361 for (i = adj_len - 2; i >= 0; i--) {
362 sig_buf[0] ^= _buf[i];
363 sig_buf[1] = (_buf[i] ^ (alg_sig_handle->tbl1_l[(sig_buf[1] >> 8) & 0x00ff] ^ alg_sig_handle->tbl1_r[sig_buf[1] & 0x00ff]));
364 sig_buf[2] = (_buf[i] ^ (alg_sig_handle->tbl2_l[(sig_buf[2] >> 8) & 0x00ff] ^ alg_sig_handle->tbl2_r[sig_buf[2] & 0x00ff]));
365 sig_buf[3] = (_buf[i] ^ (alg_sig_handle->tbl3_l[(sig_buf[3] >> 8) & 0x00ff] ^ alg_sig_handle->tbl3_r[sig_buf[3] & 0x00ff]));
366 }
367
368 sig[0] = (char) (sig_buf[0] & 0x000ff);
369 sig[1] = (char) ((sig_buf[0] >> 8) & 0x000ff);
370 sig[2] = (char) (sig_buf[1] & 0x00ff);
371 sig[3] = (char) ((sig_buf[1] >> 8) & 0x00ff);
372 sig[4] = (char) (sig_buf[2] & 0x00ff);
373 sig[5] = (char) ((sig_buf[2] >> 8) & 0x00ff);
374 sig[6] = (char) (sig_buf[3] & 0x00ff);
375 sig[7] = (char) ((sig_buf[3] >> 8) & 0x00ff);
376 return 0;
377}
378
379static
380int compute_w16_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
381{
382 int bit_mask;
383 int adj_len = len / 2;
384 int i;
385 unsigned short *_buf = (unsigned short *)buf;
386 unsigned short sig_buf[2];
387
388 if (len == 0) {
389 bzero(sig, 8);
390 return 0;
391 }
392
393 switch (len % 2) {
394 case 1:
395 bit_mask = 0x00ff;
396 break;
397 default:
398 bit_mask = 0xffff;
399 break;
400 }
401
402 if (len % 2 > 0) {
403 adj_len++;
404 }
405
406 // Account for buffer not being uint16_t aligned
407 sig_buf[0] = (_buf[adj_len - 1] & bit_mask);
408 sig_buf[1] = (_buf[adj_len - 1] & bit_mask);
409
414 for (i = adj_len - 2; i >= 0; i--) {
415 sig_buf[0] ^= _buf[i];
416 sig_buf[1] = (_buf[i] ^ (alg_sig_handle->tbl1_l[(sig_buf[1] >> 8) & 0x00ff] ^ alg_sig_handle->tbl1_r[sig_buf[1] & 0x00ff]));
417 }
418
419 sig[0] = (char) (sig_buf[0] & 0x000ff);
420 sig[1] = (char) ((sig_buf[0] >> 8) & 0x000ff);
421 sig[2] = (char) (sig_buf[1] & 0x00ff);
422 sig[3] = (char) ((sig_buf[1] >> 8) & 0x00ff);
423 return 0;
424}
425
426static
427int compute_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
428{
429 if (alg_sig_handle->gf_w == 8) {
430 return compute_w8_alg_sig_32(alg_sig_handle, buf, len, sig);
431 } else if (alg_sig_handle->gf_w == 16) {
432 return compute_w16_alg_sig_32(alg_sig_handle, buf, len, sig);
433 }
434 return -1;
435}
436
437static
438int compute_alg_sig_64(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
439{
440 if (alg_sig_handle->gf_w == 16) {
441 return compute_w16_alg_sig_64(alg_sig_handle, buf, len, sig);
442 }
443 return -1;
444}
445
446__attribute__ ((visibility ("internal")))
447int compute_alg_sig(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
448{
449 if (alg_sig_handle->sig_len == 32) {
450 return compute_alg_sig_32(alg_sig_handle, buf, len, sig);
451 } else if (alg_sig_handle->sig_len == 64) {
452 return compute_alg_sig_64(alg_sig_handle, buf, len, sig);
453 }
454 return -1;
455}
static int compute_w16_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
Definition: alg_sig.c:380
static void stub_galois_uninit_field(int w)
Definition: alg_sig.c:50
static void * get_jerasure_sohandle(void)
Definition: alg_sig.c:67
static alg_sig_t * init_alg_sig_w16(void *jerasure_sohandle, int sig_len)
Definition: alg_sig.c:153
static int compute_w8_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
Definition: alg_sig.c:296
#define GALOIS_SINGLE_MULTIPLY
Definition: alg_sig.c:30
static galois_single_multiply_func get_galois_multi_func(void *handle)
Definition: alg_sig.c:36
#define GALOIS_UNINIT
Definition: alg_sig.c:31
static int compute_w16_alg_sig_64(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
Definition: alg_sig.c:325
static int valid_pairs[][2]
Definition: alg_sig.c:34
__attribute__((visibility("internal")))
Definition: alg_sig.c:233
static int load_gf_functions(void *sohandle, struct jerasure_mult_routines *routines)
Definition: alg_sig.c:72
static int compute_alg_sig_64(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
Definition: alg_sig.c:438
static alg_sig_t * init_alg_sig_w8(void *jerasure_sohandle, int sig_len)
Definition: alg_sig.c:96
static int compute_alg_sig_32(alg_sig_t *alg_sig_handle, char *buf, int len, char *sig)
Definition: alg_sig.c:427
static galois_uninit_field_func get_galois_uninit_func(void *handle)
Definition: alg_sig.c:52
void(* galois_uninit_field_func)(int)