doc update
[cryptodev-linux.git] / tests / async_speed.c
blob4aea5e3865331ff7c15cc6a6d3e57e83e6c40971
1 /* cryptodev_test - simple benchmark tool for cryptodev
3 * Copyright (C) 2010 by Phil Sutter <phil.sutter@viprinet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <poll.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <signal.h>
29 #include <crypto/cryptodev.h>
31 static double udifftimeval(struct timeval start, struct timeval end)
33 return (double)(end.tv_usec - start.tv_usec) +
34 (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
37 static int must_finish = 0;
38 static struct pollfd pfd;
40 static void alarm_handler(int signo)
42 must_finish = 1;
43 pfd.events = POLLIN;
46 static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
48 static void value2human(double bytes, double time, double* data, double* speed,char* metric)
50 int unit = 0;
52 *data = bytes;
53 while (*data > 1024 && units[unit + 1]) {
54 *data /= 1024;
55 unit++;
57 *speed = *data / time;
58 sprintf(metric, "%sB", units[unit]);
62 int encrypt_data(struct session_op *sess, int fdc, int chunksize, int alignmask)
64 struct crypt_op cop;
65 char *buffer[64], iv[32];
66 static int val = 23;
67 struct timeval start, end;
68 double total = 0;
69 double secs, ddata, dspeed;
70 char metric[16];
71 int rc, wqueue = 0, bufidx = 0;
73 memset(iv, 0x23, 32);
75 printf("\tEncrypting in chunks of %d bytes: ", chunksize);
76 fflush(stdout);
78 for (rc = 0; rc < 64; rc++) {
79 if (alignmask) {
80 if (posix_memalign((void **)(buffer + rc), alignmask + 1, chunksize)) {
81 printf("posix_memalign() failed!\n");
82 return 1;
84 } else {
85 if (!(buffer[rc] = malloc(chunksize))) {
86 perror("malloc()");
87 return 1;
90 memset(buffer[rc], val++, chunksize);
92 pfd.fd = fdc;
93 pfd.events = POLLOUT | POLLIN;
95 must_finish = 0;
96 alarm(5);
98 gettimeofday(&start, NULL);
99 do {
100 if ((rc = poll(&pfd, 1, 100)) < 0) {
101 if (errno & (ERESTART | EINTR))
102 continue;
103 fprintf(stderr, "errno = %d ", errno);
104 perror("poll()");
105 return 1;
108 if (pfd.revents & POLLOUT) {
109 memset(&cop, 0, sizeof(cop));
110 cop.ses = sess->ses;
111 cop.len = chunksize;
112 cop.iv = (unsigned char *)iv;
113 cop.op = COP_ENCRYPT;
114 cop.src = cop.dst = (unsigned char *)buffer[bufidx];
115 bufidx = (bufidx + 1) % 64;
117 if (ioctl(fdc, CIOCASYNCCRYPT, &cop)) {
118 perror("ioctl(CIOCASYNCCRYPT)");
119 return 1;
121 wqueue++;
123 if (pfd.revents & POLLIN) {
124 if (ioctl(fdc, CIOCASYNCFETCH, &cop)) {
125 perror("ioctl(CIOCASYNCFETCH)");
126 return 1;
128 wqueue--;
129 total += cop.len;
131 } while(!must_finish || wqueue);
132 gettimeofday(&end, NULL);
134 secs = udifftimeval(start, end)/ 1000000.0;
136 value2human(total, secs, &ddata, &dspeed, metric);
137 printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
138 printf ("%.2f %s/sec\n", dspeed, metric);
140 for (rc = 0; rc < 64; rc++)
141 free(buffer[rc]);
142 return 0;
145 int main(void)
147 int fd, i, fdc = -1, alignmask = 0;
148 struct session_op sess;
149 #ifdef CIOCGSESSINFO
150 struct session_info_op siop;
151 #endif
152 char keybuf[32];
154 signal(SIGALRM, alarm_handler);
156 if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
157 perror("open()");
158 return 1;
160 if (ioctl(fd, CRIOGET, &fdc)) {
161 perror("ioctl(CRIOGET)");
162 return 1;
165 fprintf(stderr, "Testing NULL cipher: \n");
166 memset(&sess, 0, sizeof(sess));
167 sess.cipher = CRYPTO_NULL;
168 sess.keylen = 0;
169 sess.key = (unsigned char *)keybuf;
170 if (ioctl(fdc, CIOCGSESSION, &sess)) {
171 perror("ioctl(CIOCGSESSION)");
172 return 1;
174 #ifdef CIOCGSESSINFO
175 siop.ses = sess.ses;
176 if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
177 perror("ioctl(CIOCGSESSINFO)");
178 return 1;
180 alignmask = siop.alignmask;
181 #endif
183 for (i = 256; i <= (64 * 4096); i *= 2) {
184 if (encrypt_data(&sess, fdc, i, alignmask))
185 break;
188 fprintf(stderr, "\nTesting AES-128-CBC cipher: \n");
189 memset(&sess, 0, sizeof(sess));
190 sess.cipher = CRYPTO_AES_CBC;
191 sess.keylen = 16;
192 memset(keybuf, 0x42, 16);
193 sess.key = (unsigned char *)keybuf;
194 if (ioctl(fdc, CIOCGSESSION, &sess)) {
195 perror("ioctl(CIOCGSESSION)");
196 return 1;
198 #ifdef CIOCGSESSINFO
199 siop.ses = sess.ses;
200 if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
201 perror("ioctl(CIOCGSESSINFO)");
202 return 1;
204 alignmask = siop.alignmask;
205 #endif
207 for (i = 256; i <= (64 * 1024); i *= 2) {
208 if (encrypt_data(&sess, fdc, i, alignmask))
209 break;
212 close(fdc);
213 close(fd);
214 return 0;