1 /**********************************************************************
2 Copyright(c) 2011-2017 Intel Corporation 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
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include "isal_crypto_api.h"
36 #include "rolling_hashx.h"
37 #include "sha256_mb.h"
38 #include "test.h"
39
40 #define MAX_BUFFER_SIZE 128 * 1024 * 1024
41 #define HASH_POOL_SIZE ISAL_SHA256_MAX_LANES
42
43 #ifndef TEST_SEED
44 #define TEST_SEED 0x1234
45 #endif
46
47 #define FILTER_BITS 10
48 #define FILTER_SIZE (1 << FILTER_BITS)
49 #define FILTER_MASK (FILTER_SIZE - 1)
50
51 #define BITS_TO_INDEX_LONG 6
52 #define MASK_TO_INDEX_LONG ((1 << BITS_TO_INDEX_LONG) - 1)
53
54 // Globals
55 ISAL_SHA256_HASH_CTX ctxpool[ISAL_SHA256_MAX_LANES], *last_ctx;
56 ISAL_SHA256_HASH_CTX_MGR mb_hash_mgr;
57 uint64_t filter_table[FILTER_SIZE];
58 unsigned long chunks_created = 0;
59 unsigned long filter_hits = 0;
60
61 // Example function to run on each chunk
62
63 void
run_fragment(ISAL_SHA256_HASH_CTX * ctx)64 run_fragment(ISAL_SHA256_HASH_CTX *ctx)
65 {
66 uint64_t lookup, set_hash;
67 unsigned int lookup_hash;
68 uint32_t idx;
69
70 chunks_created++;
71
72 // Run a simple lookup filter on chunk using digest
73 lookup_hash = ctx->job.result_digest[0] & FILTER_MASK;
74 lookup = filter_table[lookup_hash];
75
76 idx = ctx->job.result_digest[1];
77
78 set_hash = 1 << (idx & MASK_TO_INDEX_LONG) |
79 1 << ((idx >> BITS_TO_INDEX_LONG) & MASK_TO_INDEX_LONG) |
80 1 << ((idx >> (2 * BITS_TO_INDEX_LONG)) & MASK_TO_INDEX_LONG);
81
82 if ((lookup & set_hash) == set_hash)
83 filter_hits++;
84 else
85 filter_table[lookup_hash] = lookup | set_hash;
86 }
87
88 static int
setup_chunk_processing(void)89 setup_chunk_processing(void)
90 {
91 int i;
92 int ret = isal_sha256_ctx_mgr_init(&mb_hash_mgr);
93
94 if (ret)
95 return -1;
96
97 for (i = 0; i < HASH_POOL_SIZE; i++)
98 isal_hash_ctx_init(&ctxpool[i]);
99
100 last_ctx = &ctxpool[0];
101
102 return 0;
103 }
104
105 static ISAL_SHA256_HASH_CTX *
get_next_job_ctx(void)106 get_next_job_ctx(void)
107 {
108 int i, ret;
109 ISAL_SHA256_HASH_CTX *ctx;
110
111 if (last_ctx && isal_hash_ctx_complete(last_ctx))
112 return last_ctx;
113
114 for (i = 0; i < HASH_POOL_SIZE; i++) {
115 if (isal_hash_ctx_complete(&ctxpool[i]))
116 return &ctxpool[i];
117 }
118 ret = isal_sha256_ctx_mgr_flush(&mb_hash_mgr, &ctx);
119 if (ret)
120 return NULL;
121
122 return ctx;
123 }
124
125 void
put_next_job_ctx(ISAL_SHA256_HASH_CTX * ctx)126 put_next_job_ctx(ISAL_SHA256_HASH_CTX *ctx)
127 {
128 if (ctx && isal_hash_ctx_complete(ctx))
129 last_ctx = ctx;
130
131 run_fragment(ctx);
132 }
133
134 static int
process_chunk(uint8_t * buff,int len)135 process_chunk(uint8_t *buff, int len)
136 {
137 ISAL_SHA256_HASH_CTX *ctx;
138 int ret;
139
140 ctx = get_next_job_ctx();
141 if (ctx != NULL)
142 return -1;
143
144 ret = isal_sha256_ctx_mgr_submit(&mb_hash_mgr, ctx, &ctx, buff, len, ISAL_HASH_ENTIRE);
145 if (ret)
146 return -1;
147
148 if (ctx)
149 put_next_job_ctx(ctx);
150
151 return 0;
152 }
153
154 static int
finish_chunk_processing(void)155 finish_chunk_processing(void)
156 {
157 ISAL_SHA256_HASH_CTX *ctx;
158 int ret;
159
160 do {
161 ret = isal_sha256_ctx_mgr_flush(&mb_hash_mgr, &ctx);
162 if (ret)
163 return -1;
164 if (ctx != NULL)
165 run_fragment(ctx);
166 } while (ctx != NULL);
167
168 return 0;
169 }
170
171 int
main(void)172 main(void)
173 {
174 int i, w, match, ret, res = -1;
175 uint8_t *buffer, *p;
176 uint32_t mask, trigger, offset = 0;
177 uint32_t min_chunk, max_chunk, mean_chunk;
178 long remain;
179 struct isal_rh_state2 state;
180 struct perf start, stop;
181
182 // Chunking parameters
183 w = 32;
184 min_chunk = 1024;
185 mean_chunk = 4 * 1024;
186 max_chunk = 32 * 1024;
187 ret = isal_rolling_hashx_mask_gen(mean_chunk, 0, &mask);
188
189 if (ret != ISAL_CRYPTO_ERR_NONE) {
190 printf(" Error generating mask");
191 return -1;
192 }
193
194 trigger = rand() & mask;
195
196 printf("chunk and hash test w=%d, min=%d, target_ave=%d, max=%d:\n", w, min_chunk,
197 mean_chunk, max_chunk);
198
199 if (min_chunk < w || min_chunk > max_chunk) {
200 printf(" Improper parameters selected\n");
201 return -1;
202 }
203
204 if ((buffer = malloc(MAX_BUFFER_SIZE)) == NULL) {
205 printf("cannot allocate mem\n");
206 return -1;
207 }
208 // Initialize buffer with random data
209 srand(TEST_SEED);
210 for (i = 0; i < MAX_BUFFER_SIZE; i++)
211 buffer[i] = rand();
212
213 // Start chunking test with multi-buffer hashing of results
214 perf_start(&start);
215
216 isal_rolling_hash2_init(&state, w);
217 if (setup_chunk_processing() < 0) {
218 printf("Setup chunk failed\n");
219 goto end;
220 }
221
222 p = buffer;
223 remain = MAX_BUFFER_SIZE;
224
225 while (remain > max_chunk) {
226 // Skip to min chunk
227 isal_rolling_hash2_reset(&state, p + min_chunk - w);
228 isal_rolling_hash2_run(&state, p + min_chunk, max_chunk - min_chunk, mask, trigger,
229 &offset, &match);
230
231 process_chunk(p, min_chunk + offset);
232
233 p += offset + min_chunk;
234 remain -= (offset + min_chunk);
235 }
236
237 while (remain > min_chunk) {
238 isal_rolling_hash2_reset(&state, p + min_chunk - w);
239 isal_rolling_hash2_run(&state, p + min_chunk, remain - min_chunk, mask, trigger,
240 &offset, &match);
241
242 process_chunk(p, min_chunk + offset);
243
244 p += offset + min_chunk;
245 remain -= (offset + min_chunk);
246 }
247
248 if (remain > 0)
249 process_chunk(p, remain);
250
251 if (finish_chunk_processing() < 0)
252 goto end;
253
254 perf_stop(&stop);
255
256 printf("chunking_with_mb_hash: ");
257 perf_print(stop, start, MAX_BUFFER_SIZE);
258
259 printf(" found %ld chunks, ave_len=%ld, filter hits=%ld\n", chunks_created,
260 MAX_BUFFER_SIZE / chunks_created, filter_hits);
261
262 res = 0;
263 end:
264 free(buffer);
265 return res;
266 }
267