Adds the session creatation logic for MUX mode. Signed-off-by: Longpeng(Mike) <longpe...@huawei.com> --- hw/virtio/virtio-crypto.c | 79 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 13 deletions(-)
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 19c82e0..78f75c2 100755 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -33,6 +33,11 @@ static inline int virtio_crypto_vq2q(int queue_index) return queue_index; } +static inline bool virtio_crypto_in_mux_mode(VirtIODevice *vdev) +{ + return virtio_vdev_has_feature(vdev, VIRTIO_CRYPTO_F_MUX_MODE); +} + static int virtio_crypto_cipher_session_helper(VirtIODevice *vdev, CryptoDevBackendSymSessionInfo *info, @@ -210,18 +215,24 @@ virtio_crypto_handle_close_session(VirtIOCrypto *vcrypto, static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) { VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); - struct virtio_crypto_op_ctrl_req ctrl; VirtQueueElement *elem; + struct virtio_crypto_session_input input; + struct virtio_crypto_ctrl_header *generic_hdr; + union { + struct virtio_crypto_op_ctrl_req ctrl; + struct virtio_crypto_op_ctrl_req_mux mux_ctrl; + } req; + struct iovec *in_iov; struct iovec *out_iov; unsigned in_num; unsigned out_num; uint32_t queue_id; uint32_t opcode; - struct virtio_crypto_session_input input; int64_t session_id; uint8_t status; - size_t s; + size_t s, exp_len; + void *sess; for (;;) { elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); @@ -239,25 +250,49 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) out_iov = elem->out_sg; in_num = elem->in_num; in_iov = elem->in_sg; - if (unlikely(iov_to_buf(out_iov, out_num, 0, &ctrl, sizeof(ctrl)) - != sizeof(ctrl))) { + + if (virtio_crypto_in_mux_mode(vdev)) { + exp_len = sizeof(req.mux_ctrl); + generic_hdr = (struct virtio_crypto_ctrl_header *)(&req.mux_ctrl); + } else { + exp_len = sizeof(req.ctrl); + generic_hdr = (struct virtio_crypto_ctrl_header *)(&req.ctrl); + } + + s = iov_to_buf(out_iov, out_num, 0, generic_hdr, exp_len); + if (unlikely(s != exp_len)) { virtio_error(vdev, "virtio-crypto request ctrl_hdr too short"); virtqueue_detach_element(vq, elem, 0); g_free(elem); break; } - iov_discard_front(&out_iov, &out_num, sizeof(ctrl)); - opcode = ldl_le_p(&ctrl.header.opcode); - queue_id = ldl_le_p(&ctrl.header.queue_id); + iov_discard_front(&out_iov, &out_num, exp_len); + + opcode = ldl_le_p(&generic_hdr->opcode); + queue_id = ldl_le_p(&generic_hdr->queue_id); switch (opcode) { case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION: + if (virtio_crypto_in_mux_mode(vdev)) { + sess = g_new0(struct virtio_crypto_sym_create_session_req, 1); + exp_len = sizeof(struct virtio_crypto_sym_create_session_req); + s = iov_to_buf(out_iov, out_num, 0, sess, exp_len); + if (unlikely(s != exp_len)) { + virtio_error(vdev, "virtio-crypto request additional " + "parameters too short"); + virtqueue_detach_element(vq, elem, 0); + break; + } + iov_discard_front(&out_iov, &out_num, exp_len); + } else { + sess = &req.ctrl.u.sym_create_session; + } + memset(&input, 0, sizeof(input)); - session_id = virtio_crypto_create_sym_session(vcrypto, - &ctrl.u.sym_create_session, - queue_id, opcode, - out_iov, out_num); + + session_id = virtio_crypto_create_sym_session(vcrypto, sess, + queue_id, opcode, out_iov, out_num); /* Serious errors, need to reset virtio crypto device */ if (session_id == -EFAULT) { virtqueue_detach_element(vq, elem, 0); @@ -285,8 +320,23 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) case VIRTIO_CRYPTO_HASH_DESTROY_SESSION: case VIRTIO_CRYPTO_MAC_DESTROY_SESSION: case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION: + if (virtio_crypto_in_mux_mode(vdev)) { + sess = g_new0(struct virtio_crypto_destroy_session_req, 1); + exp_len = sizeof(struct virtio_crypto_destroy_session_req); + s = iov_to_buf(out_iov, out_num, 0, sess, exp_len); + if (unlikely(s != exp_len)) { + virtio_error(vdev, "virtio-crypto request additional " + "parameters too short"); + virtqueue_detach_element(vq, elem, 0); + break; + } + iov_discard_front(&out_iov, &out_num, exp_len); + } else { + sess = &req.ctrl.u.destroy_session; + } + status = virtio_crypto_handle_close_session(vcrypto, - &ctrl.u.destroy_session, queue_id); + sess, queue_id); /* The status only occupy one byte, we can directly use it */ s = iov_from_buf(in_iov, in_num, 0, &status, sizeof(status)); if (unlikely(s != sizeof(status))) { @@ -316,6 +366,9 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) break; } /* end switch case */ + if (virtio_crypto_in_mux_mode(vdev)) { + g_free(sess); + } g_free(elem); } /* end for loop */ } -- 1.8.3.1