| 1 | /* |
| 2 | * A loadable module that benchmarks the OCF crypto speed from kernel space. |
| 3 | * |
| 4 | * Copyright (C) 2004-2010 David McCullough <david_mccullough@mcafee.com> |
| 5 | * |
| 6 | * LICENSE TERMS |
| 7 | * |
| 8 | * The free distribution and use of this software in both source and binary |
| 9 | * form is allowed (with or without changes) provided that: |
| 10 | * |
| 11 | * 1. distributions of this source code include the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer; |
| 13 | * |
| 14 | * 2. distributions in binary form include the above copyright |
| 15 | * notice, this list of conditions and the following disclaimer |
| 16 | * in the documentation and/or other associated materials; |
| 17 | * |
| 18 | * 3. the copyright holder's name is not used to endorse products |
| 19 | * built using this software without specific written permission. |
| 20 | * |
| 21 | * ALTERNATIVELY, provided that this notice is retained in full, this product |
| 22 | * may be distributed under the terms of the GNU General Public License (GPL), |
| 23 | * in which case the provisions of the GPL apply INSTEAD OF those given above. |
| 24 | * |
| 25 | * DISCLAIMER |
| 26 | * |
| 27 | * This software is provided 'as is' with no explicit or implied warranties |
| 28 | * in respect of its properties, including, but not limited to, correctness |
| 29 | * and/or fitness for purpose. |
| 30 | */ |
| 31 | |
| 32 | |
| 33 | #include <linux/version.h> |
| 34 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) |
| 35 | #include <generated/autoconf.h> |
| 36 | #else |
| 37 | #include <linux/autoconf.h> |
| 38 | #endif |
| 39 | #include <linux/module.h> |
| 40 | #include <linux/init.h> |
| 41 | #include <linux/list.h> |
| 42 | #include <linux/slab.h> |
| 43 | #include <linux/wait.h> |
| 44 | #include <linux/sched.h> |
| 45 | #include <linux/spinlock.h> |
| 46 | #include <linux/version.h> |
| 47 | #include <linux/interrupt.h> |
| 48 | #include <cryptodev.h> |
| 49 | |
| 50 | #ifdef I_HAVE_AN_XSCALE_WITH_INTEL_SDK |
| 51 | #define BENCH_IXP_ACCESS_LIB 1 |
| 52 | #endif |
| 53 | #ifdef BENCH_IXP_ACCESS_LIB |
| 54 | #include <IxTypes.h> |
| 55 | #include <IxOsBuffMgt.h> |
| 56 | #include <IxNpeDl.h> |
| 57 | #include <IxCryptoAcc.h> |
| 58 | #include <IxQMgr.h> |
| 59 | #include <IxOsServices.h> |
| 60 | #include <IxOsCacheMMU.h> |
| 61 | #endif |
| 62 | |
| 63 | /* |
| 64 | * support for access lib version 1.4 |
| 65 | */ |
| 66 | #ifndef IX_MBUF_PRIV |
| 67 | #define IX_MBUF_PRIV(x) ((x)->priv) |
| 68 | #endif |
| 69 | |
| 70 | /* |
| 71 | * the number of simultaneously active requests |
| 72 | */ |
| 73 | static int request_q_len = 20; |
| 74 | module_param(request_q_len, int, 0); |
| 75 | MODULE_PARM_DESC(request_q_len, "Number of outstanding requests"); |
| 76 | /* |
| 77 | * how many requests we want to have processed |
| 78 | */ |
| 79 | static int request_num = 1024; |
| 80 | module_param(request_num, int, 0); |
| 81 | MODULE_PARM_DESC(request_num, "run for at least this many requests"); |
| 82 | /* |
| 83 | * the size of each request |
| 84 | */ |
| 85 | static int request_size = 1500; |
| 86 | module_param(request_size, int, 0); |
| 87 | MODULE_PARM_DESC(request_size, "size of each request"); |
| 88 | |
| 89 | /* |
| 90 | * a structure for each request |
| 91 | */ |
| 92 | typedef struct { |
| 93 | struct work_struct work; |
| 94 | #ifdef BENCH_IXP_ACCESS_LIB |
| 95 | IX_MBUF mbuf; |
| 96 | #endif |
| 97 | unsigned char *buffer; |
| 98 | } request_t; |
| 99 | |
| 100 | static request_t *requests; |
| 101 | |
| 102 | static int outstanding; |
| 103 | static int total; |
| 104 | |
| 105 | /*************************************************************************/ |
| 106 | /* |
| 107 | * OCF benchmark routines |
| 108 | */ |
| 109 | |
| 110 | static uint64_t ocf_cryptoid; |
| 111 | static int ocf_init(void); |
| 112 | static int ocf_cb(struct cryptop *crp); |
| 113 | static void ocf_request(void *arg); |
| 114 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 115 | static void ocf_request_wq(struct work_struct *work); |
| 116 | #endif |
| 117 | |
| 118 | static int |
| 119 | ocf_init(void) |
| 120 | { |
| 121 | int error; |
| 122 | struct cryptoini crie, cria; |
| 123 | struct cryptodesc crda, crde; |
| 124 | |
| 125 | memset(&crie, 0, sizeof(crie)); |
| 126 | memset(&cria, 0, sizeof(cria)); |
| 127 | memset(&crde, 0, sizeof(crde)); |
| 128 | memset(&crda, 0, sizeof(crda)); |
| 129 | |
| 130 | cria.cri_alg = CRYPTO_SHA1_HMAC; |
| 131 | cria.cri_klen = 20 * 8; |
| 132 | cria.cri_key = "0123456789abcdefghij"; |
| 133 | |
| 134 | crie.cri_alg = CRYPTO_3DES_CBC; |
| 135 | crie.cri_klen = 24 * 8; |
| 136 | crie.cri_key = "0123456789abcdefghijklmn"; |
| 137 | |
| 138 | crie.cri_next = &cria; |
| 139 | |
| 140 | error = crypto_newsession(&ocf_cryptoid, &crie, 0); |
| 141 | if (error) { |
| 142 | printk("crypto_newsession failed %d\n", error); |
| 143 | return -1; |
| 144 | } |
| 145 | return 0; |
| 146 | } |
| 147 | |
| 148 | static int |
| 149 | ocf_cb(struct cryptop *crp) |
| 150 | { |
| 151 | request_t *r = (request_t *) crp->crp_opaque; |
| 152 | |
| 153 | if (crp->crp_etype) |
| 154 | printk("Error in OCF processing: %d\n", crp->crp_etype); |
| 155 | total++; |
| 156 | crypto_freereq(crp); |
| 157 | crp = NULL; |
| 158 | |
| 159 | if (total > request_num) { |
| 160 | outstanding--; |
| 161 | return 0; |
| 162 | } |
| 163 | |
| 164 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 165 | INIT_WORK(&r->work, ocf_request_wq); |
| 166 | #else |
| 167 | INIT_WORK(&r->work, ocf_request, r); |
| 168 | #endif |
| 169 | schedule_work(&r->work); |
| 170 | return 0; |
| 171 | } |
| 172 | |
| 173 | |
| 174 | static void |
| 175 | ocf_request(void *arg) |
| 176 | { |
| 177 | request_t *r = arg; |
| 178 | struct cryptop *crp = crypto_getreq(2); |
| 179 | struct cryptodesc *crde, *crda; |
| 180 | |
| 181 | if (!crp) { |
| 182 | outstanding--; |
| 183 | return; |
| 184 | } |
| 185 | |
| 186 | crde = crp->crp_desc; |
| 187 | crda = crde->crd_next; |
| 188 | |
| 189 | crda->crd_skip = 0; |
| 190 | crda->crd_flags = 0; |
| 191 | crda->crd_len = request_size; |
| 192 | crda->crd_inject = request_size; |
| 193 | crda->crd_alg = CRYPTO_SHA1_HMAC; |
| 194 | crda->crd_key = "0123456789abcdefghij"; |
| 195 | crda->crd_klen = 20 * 8; |
| 196 | |
| 197 | crde->crd_skip = 0; |
| 198 | crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_ENCRYPT; |
| 199 | crde->crd_len = request_size; |
| 200 | crde->crd_inject = request_size; |
| 201 | crde->crd_alg = CRYPTO_3DES_CBC; |
| 202 | crde->crd_key = "0123456789abcdefghijklmn"; |
| 203 | crde->crd_klen = 24 * 8; |
| 204 | |
| 205 | crp->crp_ilen = request_size + 64; |
| 206 | crp->crp_flags = CRYPTO_F_CBIMM; |
| 207 | crp->crp_buf = (caddr_t) r->buffer; |
| 208 | crp->crp_callback = ocf_cb; |
| 209 | crp->crp_sid = ocf_cryptoid; |
| 210 | crp->crp_opaque = (caddr_t) r; |
| 211 | crypto_dispatch(crp); |
| 212 | } |
| 213 | |
| 214 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 215 | static void |
| 216 | ocf_request_wq(struct work_struct *work) |
| 217 | { |
| 218 | request_t *r = container_of(work, request_t, work); |
| 219 | ocf_request(r); |
| 220 | } |
| 221 | #endif |
| 222 | |
| 223 | /*************************************************************************/ |
| 224 | #ifdef BENCH_IXP_ACCESS_LIB |
| 225 | /*************************************************************************/ |
| 226 | /* |
| 227 | * CryptoAcc benchmark routines |
| 228 | */ |
| 229 | |
| 230 | static IxCryptoAccCtx ixp_ctx; |
| 231 | static UINT32 ixp_ctx_id; |
| 232 | static IX_MBUF ixp_pri; |
| 233 | static IX_MBUF ixp_sec; |
| 234 | static int ixp_registered = 0; |
| 235 | |
| 236 | static void ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, |
| 237 | IxCryptoAccStatus status); |
| 238 | static void ixp_perform_cb(UINT32 ctx_id, IX_MBUF *sbufp, IX_MBUF *dbufp, |
| 239 | IxCryptoAccStatus status); |
| 240 | static void ixp_request(void *arg); |
| 241 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 242 | static void ixp_request_wq(struct work_struct *work); |
| 243 | #endif |
| 244 | |
| 245 | static int |
| 246 | ixp_init(void) |
| 247 | { |
| 248 | IxCryptoAccStatus status; |
| 249 | |
| 250 | ixp_ctx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES; |
| 251 | ixp_ctx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC; |
| 252 | ixp_ctx.cipherCtx.cipherKeyLen = 24; |
| 253 | ixp_ctx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64; |
| 254 | ixp_ctx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64; |
| 255 | memcpy(ixp_ctx.cipherCtx.key.cipherKey, "0123456789abcdefghijklmn", 24); |
| 256 | |
| 257 | ixp_ctx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1; |
| 258 | ixp_ctx.authCtx.authDigestLen = 12; |
| 259 | ixp_ctx.authCtx.aadLen = 0; |
| 260 | ixp_ctx.authCtx.authKeyLen = 20; |
| 261 | memcpy(ixp_ctx.authCtx.key.authKey, "0123456789abcdefghij", 20); |
| 262 | |
| 263 | ixp_ctx.useDifferentSrcAndDestMbufs = 0; |
| 264 | ixp_ctx.operation = IX_CRYPTO_ACC_OP_ENCRYPT_AUTH ; |
| 265 | |
| 266 | IX_MBUF_MLEN(&ixp_pri) = IX_MBUF_PKT_LEN(&ixp_pri) = 128; |
| 267 | IX_MBUF_MDATA(&ixp_pri) = (unsigned char *) kmalloc(128, SLAB_ATOMIC); |
| 268 | IX_MBUF_MLEN(&ixp_sec) = IX_MBUF_PKT_LEN(&ixp_sec) = 128; |
| 269 | IX_MBUF_MDATA(&ixp_sec) = (unsigned char *) kmalloc(128, SLAB_ATOMIC); |
| 270 | |
| 271 | status = ixCryptoAccCtxRegister(&ixp_ctx, &ixp_pri, &ixp_sec, |
| 272 | ixp_register_cb, ixp_perform_cb, &ixp_ctx_id); |
| 273 | |
| 274 | if (IX_CRYPTO_ACC_STATUS_SUCCESS == status) { |
| 275 | while (!ixp_registered) |
| 276 | schedule(); |
| 277 | return ixp_registered < 0 ? -1 : 0; |
| 278 | } |
| 279 | |
| 280 | printk("ixp: ixCryptoAccCtxRegister failed %d\n", status); |
| 281 | return -1; |
| 282 | } |
| 283 | |
| 284 | static void |
| 285 | ixp_register_cb(UINT32 ctx_id, IX_MBUF *bufp, IxCryptoAccStatus status) |
| 286 | { |
| 287 | if (bufp) { |
| 288 | IX_MBUF_MLEN(bufp) = IX_MBUF_PKT_LEN(bufp) = 0; |
| 289 | kfree(IX_MBUF_MDATA(bufp)); |
| 290 | IX_MBUF_MDATA(bufp) = NULL; |
| 291 | } |
| 292 | |
| 293 | if (IX_CRYPTO_ACC_STATUS_WAIT == status) |
| 294 | return; |
| 295 | if (IX_CRYPTO_ACC_STATUS_SUCCESS == status) |
| 296 | ixp_registered = 1; |
| 297 | else |
| 298 | ixp_registered = -1; |
| 299 | } |
| 300 | |
| 301 | static void |
| 302 | ixp_perform_cb( |
| 303 | UINT32 ctx_id, |
| 304 | IX_MBUF *sbufp, |
| 305 | IX_MBUF *dbufp, |
| 306 | IxCryptoAccStatus status) |
| 307 | { |
| 308 | request_t *r = NULL; |
| 309 | |
| 310 | total++; |
| 311 | if (total > request_num) { |
| 312 | outstanding--; |
| 313 | return; |
| 314 | } |
| 315 | |
| 316 | if (!sbufp || !(r = IX_MBUF_PRIV(sbufp))) { |
| 317 | printk("crappo %p %p\n", sbufp, r); |
| 318 | outstanding--; |
| 319 | return; |
| 320 | } |
| 321 | |
| 322 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 323 | INIT_WORK(&r->work, ixp_request_wq); |
| 324 | #else |
| 325 | INIT_WORK(&r->work, ixp_request, r); |
| 326 | #endif |
| 327 | schedule_work(&r->work); |
| 328 | } |
| 329 | |
| 330 | static void |
| 331 | ixp_request(void *arg) |
| 332 | { |
| 333 | request_t *r = arg; |
| 334 | IxCryptoAccStatus status; |
| 335 | |
| 336 | memset(&r->mbuf, 0, sizeof(r->mbuf)); |
| 337 | IX_MBUF_MLEN(&r->mbuf) = IX_MBUF_PKT_LEN(&r->mbuf) = request_size + 64; |
| 338 | IX_MBUF_MDATA(&r->mbuf) = r->buffer; |
| 339 | IX_MBUF_PRIV(&r->mbuf) = r; |
| 340 | status = ixCryptoAccAuthCryptPerform(ixp_ctx_id, &r->mbuf, NULL, |
| 341 | 0, request_size, 0, request_size, request_size, r->buffer); |
| 342 | if (IX_CRYPTO_ACC_STATUS_SUCCESS != status) { |
| 343 | printk("status1 = %d\n", status); |
| 344 | outstanding--; |
| 345 | return; |
| 346 | } |
| 347 | return; |
| 348 | } |
| 349 | |
| 350 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 351 | static void |
| 352 | ixp_request_wq(struct work_struct *work) |
| 353 | { |
| 354 | request_t *r = container_of(work, request_t, work); |
| 355 | ixp_request(r); |
| 356 | } |
| 357 | #endif |
| 358 | |
| 359 | /*************************************************************************/ |
| 360 | #endif /* BENCH_IXP_ACCESS_LIB */ |
| 361 | /*************************************************************************/ |
| 362 | |
| 363 | int |
| 364 | ocfbench_init(void) |
| 365 | { |
| 366 | int i, jstart, jstop; |
| 367 | |
| 368 | printk("Crypto Speed tests\n"); |
| 369 | |
| 370 | requests = kmalloc(sizeof(request_t) * request_q_len, GFP_KERNEL); |
| 371 | if (!requests) { |
| 372 | printk("malloc failed\n"); |
| 373 | return -EINVAL; |
| 374 | } |
| 375 | |
| 376 | for (i = 0; i < request_q_len; i++) { |
| 377 | /* +64 for return data */ |
| 378 | requests[i].buffer = kmalloc(request_size + 128, GFP_DMA); |
| 379 | if (!requests[i].buffer) { |
| 380 | printk("malloc failed\n"); |
| 381 | return -EINVAL; |
| 382 | } |
| 383 | memset(requests[i].buffer, '0' + i, request_size + 128); |
| 384 | } |
| 385 | |
| 386 | /* |
| 387 | * OCF benchmark |
| 388 | */ |
| 389 | printk("OCF: testing ...\n"); |
| 390 | ocf_init(); |
| 391 | total = outstanding = 0; |
| 392 | jstart = jiffies; |
| 393 | for (i = 0; i < request_q_len; i++) { |
| 394 | outstanding++; |
| 395 | ocf_request(&requests[i]); |
| 396 | } |
| 397 | while (outstanding > 0) |
| 398 | schedule(); |
| 399 | jstop = jiffies; |
| 400 | |
| 401 | printk("OCF: %d requests of %d bytes in %d jiffies\n", total, request_size, |
| 402 | jstop - jstart); |
| 403 | |
| 404 | #ifdef BENCH_IXP_ACCESS_LIB |
| 405 | /* |
| 406 | * IXP benchmark |
| 407 | */ |
| 408 | printk("IXP: testing ...\n"); |
| 409 | ixp_init(); |
| 410 | total = outstanding = 0; |
| 411 | jstart = jiffies; |
| 412 | for (i = 0; i < request_q_len; i++) { |
| 413 | outstanding++; |
| 414 | ixp_request(&requests[i]); |
| 415 | } |
| 416 | while (outstanding > 0) |
| 417 | schedule(); |
| 418 | jstop = jiffies; |
| 419 | |
| 420 | printk("IXP: %d requests of %d bytes in %d jiffies\n", total, request_size, |
| 421 | jstop - jstart); |
| 422 | #endif /* BENCH_IXP_ACCESS_LIB */ |
| 423 | |
| 424 | for (i = 0; i < request_q_len; i++) |
| 425 | kfree(requests[i].buffer); |
| 426 | kfree(requests); |
| 427 | return -EINVAL; /* always fail to load so it can be re-run quickly ;-) */ |
| 428 | } |
| 429 | |
| 430 | static void __exit ocfbench_exit(void) |
| 431 | { |
| 432 | } |
| 433 | |
| 434 | module_init(ocfbench_init); |
| 435 | module_exit(ocfbench_exit); |
| 436 | |
| 437 | MODULE_LICENSE("BSD"); |
| 438 | MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>"); |
| 439 | MODULE_DESCRIPTION("Benchmark various in-kernel crypto speeds"); |
| 440 | |