On 02/01/2015 10:31 AM, Stephan Mueller wrote:
> Hi Tadeusz,
> 
>> > The way the algif_skcipher works currently is that on sendmsg/sendpage it
>> > builds an sgl for the input data and then on read/recvmsg it sends the job
>> > for encryption putting the user to sleep till the data is processed.
>> > This way it can only handle one job at a given time.
>> > To be able to fuly utilize the potential of existing crypto hardware
>> > accelerators it is required to submit multiple jobs in asynchronously.
>> > First patch enables asynchronous read and write on socket.
>> > Second patch enables af_alg sgl to be linked.
>> > Third patch implement asynch read for skcipher.
> Do you have a code fragment on how to test that patch? I would like to see 
> whether I can test that with my libkcapi.

Hi Stephan,
This is what I'm using.

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/types.h>
#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <sys/uio.h>

#define SOL_ALG 279

#define SPLICE_F_GIFT   (0x08)  /* pages passed in are a gift */
struct sockaddr_alg {
        __u16   salg_family;
        __u8    salg_type[14];
        __u32   salg_feat;
        __u32   salg_mask;
        __u8    salg_name[64];
};
struct af_alg_iv {
        __u32   ivlen;
        __u8    iv[0];
};
/* Socket options */
#define ALG_SET_KEY                     1
#define ALG_SET_IV                      2
#define ALG_SET_OP                      3
#define ALG_SET_AEAD_ASSOCLEN           4
#define ALG_SET_AEAD_AUTHSIZE           5

/* Operations */
#define ALG_OP_DECRYPT                  0
#define ALG_OP_ENCRYPT                  1

#define BUFFSIZE (4096)
//#define BUFFSIZE (4096)
#define PKGSIZE (4096)

#define INFLIGTHS 256
#define TO_SEND (1024 * 1024)
//#define OUT_OFFSET 2048;
//#define IN_OFFSET 4064;
#define OUT_OFFSET 0;
#define IN_OFFSET 0;

static char buf[BUFFSIZE] __attribute__((__aligned__(BUFFSIZE)));
static char *buf_out = buf;

static inline int io_setup(unsigned n, aio_context_t *ctx)
{
        return syscall(__NR_io_setup, n, ctx);
}

static inline int io_destroy(aio_context_t ctx)
{
        return syscall(__NR_io_destroy, ctx);
}

static inline int io_read(aio_context_t ctx, long n,  struct iocb **iocb)
{
        return syscall(__NR_io_submit, ctx, n, iocb);
}

static inline int io_getevents(aio_context_t ctx, long min, long max,
                        struct io_event *events, struct timespec *timeout)
{
        return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
}

static inline int eventfd(int n)
{
        return syscall(__NR_eventfd, n);
}

static int crypt_kernel(const char *key, char *oiv, int zcp)
{
        int opfd;
        int tfmfd;
        int efd;
        struct timespec timeout;
        fd_set rfds;
        struct timeval tv;
        struct sockaddr_alg sa = {
                .salg_family = AF_ALG,
                .salg_type = "skcipher",
                .salg_name = "cbc(aes)"
        };
        struct msghdr msg = {};
        struct cmsghdr *cmsg;
        char cbuf[CMSG_SPACE(4) + CMSG_SPACE(20)] = {};
        struct aes_iv {
                __u32 len;
                __u8 iv[16];
        } *iv;
        struct iovec iov;
        int pipes[2];
        aio_context_t aio_ctx;
        struct iocb *cb;
        struct iocb cbt[INFLIGTHS];
        struct io_event events[INFLIGTHS];
        unsigned int received = 0;
        int i, r;

        timeout.tv_sec = 0;
        timeout.tv_nsec = 0;
        pipe(pipes);
        memset(cbt, 0, sizeof(cbt));
        efd = eventfd(0);
        tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
        bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa));
        setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, 16);
        opfd = accept(tfmfd, NULL, 0);

        msg.msg_control = cbuf;
        msg.msg_controllen = sizeof(cbuf);

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_level = SOL_ALG;
        cmsg->cmsg_type = ALG_SET_OP;
        cmsg->cmsg_len = CMSG_LEN(4);
        *(__u32 *)CMSG_DATA(cmsg) = ALG_OP_ENCRYPT;

        cmsg = CMSG_NXTHDR(&msg, cmsg);
        cmsg->cmsg_level = SOL_ALG;
        cmsg->cmsg_type = ALG_SET_IV;
        cmsg->cmsg_len = CMSG_LEN(20);
        iv = (void *)CMSG_DATA(cmsg);
        iv->len = 16;
        memcpy(iv->iv, oiv, 16);

        iov.iov_base = buf + IN_OFFSET;
        iov.iov_len = PKGSIZE;
        msg.msg_flags = MSG_MORE;

        aio_ctx = 0;
        r = io_setup(INFLIGTHS, &aio_ctx);
        if (r < 0) {
                perror("io_setup error");
                return -1;
        }

        for (i = 0; i < TO_SEND; i++) {
                if (zcp) {
                        msg.msg_iovlen = 0;
                        msg.msg_iov = NULL;

                        r = sendmsg(opfd, &msg, 0);
                        if (r < 0)
                                printf("sendmsg returned Error: %d\n", errno);

                        r = vmsplice(pipes[1], &iov, 1, SPLICE_F_GIFT);
                        if (r < 0)
                                printf("vmsplice returned Error: %d\n", errno);

                        r = splice(pipes[0], NULL, opfd, NULL, PKGSIZE, 0);
                        if (r < 0)
                                printf("splice returned Error: %d\n", errno);
                } else {
                        msg.msg_iovlen = 1;
                        msg.msg_iov = &iov;
                        r = sendmsg(opfd, &msg, PKGSIZE);
                        if (r < 0)
                                printf("zero cp sendmsg returned Error: %d\n", 
errno);
                }

                cb = &cbt[i % INFLIGTHS];
                if (cb->aio_fildes) {
                        printf("req %d not processed yet???\n", i - INFLIGTHS);
                        return -1;
                }
                memset(cb, '\0', sizeof(*cb));
                cb->aio_fildes = opfd;
                cb->aio_lio_opcode = IOCB_CMD_PREAD;
                cb->aio_buf = (unsigned long)buf_out + OUT_OFFSET;
                cb->aio_offset = 0;
                cb->aio_nbytes = PKGSIZE;
                cb->aio_flags = IOCB_FLAG_RESFD;
                cb->aio_resfd = efd;
                r = io_read(aio_ctx, 1, &cb);
                if (r != 1) {
                        if (r < 0) {
                                printf("io_read Error: %d\n", errno);
                                return -1;
                        } else {
                                printf("Could not sumbit AIO read\n");
                                return -1;
                        }
                }

                FD_ZERO(&rfds);
                FD_SET(efd, &rfds);
                tv.tv_sec = 0;
                tv.tv_usec = 0;
                r = select(efd + 1, &rfds, NULL, NULL, &tv);

                if (r == -1) {
                        printf("Select Error: %d\n", errno);
                        return -1;
                } else if (FD_ISSET(efd, &rfds)) {
                        r = io_getevents(aio_ctx, 1, INFLIGTHS, events + 
(received % INFLIGTHS),
                                         &timeout);
                        if (r > 0) {
                                int y;

                                for (y = 0; y < r; y++) {
                                        cb = (void*) events[(received + y) % 
INFLIGTHS].obj;
                                        cb->aio_fildes = 0;
                                        if (events[(received + y) % 
INFLIGTHS].res)
                                                printf("req %d failed\n", 
received + y);
                                }
                                received += r;
                        } else if (r < 0) {
                                printf("io_getevents Error: %d\n", errno);
                                return -1;
                        }
                }

                if (i == 0) {
                        msg.msg_control = NULL;
                        msg.msg_controllen = 0;
                }
        }

        while (received != TO_SEND) {
                r = io_getevents(aio_ctx, 1, TO_SEND - received,
                                events + (received % INFLIGTHS), NULL);
                if (r > 0)
                        received += r;
        }
        printf("All done!\n");
        close(efd);
        close(opfd);
        close(tfmfd);
        close(pipes[0]);
        close(pipes[1]);
        io_destroy(aio_ctx);
        return 0;
}

int main(int argc, char **argv)
{
        const char key[16] =
                "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
                "\x51\x2e\x03\xd5\x34\x12\x00\x06";
        char iv[16] =
                "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
                "\xb4\x22\xda\x80\x2c\x9f\xac\x41";

        memcpy(buf, "Single block msg", 16);

        if (argc == 2) {
                printf("zero copy\n");
                crypt_kernel(key, iv, 1);
        }
        else {
                printf("copy\n");
                crypt_kernel(key, iv, 0);
        }
        return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to