xref: /isa-l_crypto/rolling_hash/chunking_with_mb_hash.c (revision 1e0b122e090c8ad3a8d8c56e182f754ea26fe70d)
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