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 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 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 * 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 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 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 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 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