[dpdk-dev] [PATCH v4 07/12] virtio, qtest: Add functionality to share memory between QTest guest

Tetsuya Mukawa mukawa at igel.co.jp
Wed Mar 9 09:33:24 CET 2016


The patch adds functionality to share memory between QTest guest and
DPDK application using ivshmem device.
The shared memory will be all EAL memory on hugepages. This memory will
be accessed by QEMU vcpu and DPDK application using same address.

Signed-off-by: Tetsuya Mukawa <mukawa at igel.co.jp>
---
 drivers/net/virtio/qtest_utils.c | 106 ++++++++++++++++++++++++++++++++++++++-
 drivers/net/virtio/qtest_utils.h |   4 +-
 2 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/qtest_utils.c b/drivers/net/virtio/qtest_utils.c
index 000c7e8..338224a 100644
--- a/drivers/net/virtio/qtest_utils.c
+++ b/drivers/net/virtio/qtest_utils.c
@@ -43,6 +43,9 @@
 #include "virtio_ethdev.h"
 #include "qtest_utils.h"
 
+/* ivshmem configuration */
+#define IVSHMEM_PROTOCOL_VERSION        0
+
 #define PCI_CONFIG_ADDR(_bus, _device, _function, _offset) ( \
 	(1 << 31) | ((_bus) & 0xff) << 16 | ((_device) & 0x1f) << 11 | \
 	((_function) & 0x7) << 8 | ((_offset) & 0xfc))
@@ -59,6 +62,7 @@ union qtest_pipefds {
 
 struct qtest_session {
 	int qtest_socket;
+	int ivshmem_socket;
 	pthread_mutex_t qtest_session_lock;
 
 	struct qtest_pci_device_list head;
@@ -411,6 +415,7 @@ qtest_close_sockets(struct qtest_session *s)
 	qtest_close_one_socket(&s->qtest_socket);
 	qtest_close_one_socket(&s->msgfds.readfd);
 	qtest_close_one_socket(&s->msgfds.writefd);
+	qtest_close_one_socket(&s->ivshmem_socket);
 }
 
 static void
@@ -716,6 +721,93 @@ qtest_register_target_devices(struct qtest_session *s,
 }
 
 static int
+qtest_send_message_to_ivshmem(int sock_fd, uint64_t client_id, int shm_fd)
+{
+	struct iovec iov;
+	struct msghdr msgh;
+	size_t fdsize = sizeof(int);
+	char control[CMSG_SPACE(fdsize)];
+	struct cmsghdr *cmsg;
+	int ret;
+
+	memset(&msgh, 0, sizeof(msgh));
+	iov.iov_base = &client_id;
+	iov.iov_len = sizeof(client_id);
+
+	msgh.msg_iov = &iov;
+	msgh.msg_iovlen = 1;
+
+	if (shm_fd >= 0) {
+		msgh.msg_control = &control;
+		msgh.msg_controllen = sizeof(control);
+		cmsg = CMSG_FIRSTHDR(&msgh);
+		cmsg->cmsg_len = CMSG_LEN(fdsize);
+		cmsg->cmsg_level = SOL_SOCKET;
+		cmsg->cmsg_type = SCM_RIGHTS;
+		memcpy(CMSG_DATA(cmsg), &shm_fd, fdsize);
+	}
+
+	do {
+		ret = sendmsg(sock_fd, &msgh, 0);
+	} while (ret < 0 && errno == EINTR);
+
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "sendmsg error\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int
+qtest_setup_shared_memory(struct qtest_session *s)
+{
+	int shm_fd, num, ret;
+	struct back_file *huges;
+
+	num = rte_eal_get_backfile_info(&huges);
+	if (num != 1) {
+		PMD_DRV_LOG(ERR,
+			"Not supported memory configuration\n");
+		return -1;
+	}
+
+	shm_fd = open(huges[0].filepath, O_RDWR);
+	if (shm_fd < 0) {
+		PMD_DRV_LOG(ERR,
+			"Cannot open file: %s\n", huges[0].filepath);
+		return -1;
+	}
+
+	/* send our protocol version first */
+	ret = qtest_send_message_to_ivshmem(s->ivshmem_socket,
+			IVSHMEM_PROTOCOL_VERSION, -1);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR,
+			"Failed to send protocol version to ivshmem\n");
+		return -1;
+	}
+
+	/* send client id */
+	ret = qtest_send_message_to_ivshmem(s->ivshmem_socket, 0, -1);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Failed to send VMID to ivshmem\n");
+		return -1;
+	}
+
+	/* send message to ivshmem */
+	ret = qtest_send_message_to_ivshmem(s->ivshmem_socket, -1, shm_fd);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Failed to file descriptor to ivshmem\n");
+		return -1;
+	}
+
+	close(shm_fd);
+
+	return 0;
+}
+
+static int
 qtest_open_socket(char *path)
 {
 	struct sockaddr_un sa = {0};
@@ -769,7 +861,7 @@ qtest_vdev_uninit(struct qtest_session *s)
 }
 
 struct qtest_session *
-qtest_vdev_init(char *qtest_path,
+qtest_vdev_init(char *qtest_path, char *ivshmem_path,
 		struct qtest_pci_device *devices, int devnum)
 {
 	struct qtest_session *s;
@@ -800,6 +892,12 @@ qtest_vdev_init(char *qtest_path,
 		goto error;
 	}
 
+	s->ivshmem_socket = qtest_open_socket(ivshmem_path);
+	if (s->ivshmem_socket < 0) {
+		PMD_DRV_LOG(ERR, "Failed to open %s\n", ivshmem_path);
+		goto error;
+	}
+
 	s->qtest_socket = qtest_open_socket(qtest_path);
 	if (s->qtest_socket < 0) {
 		PMD_DRV_LOG(ERR, "Failed to open %s\n", qtest_path);
@@ -813,6 +911,12 @@ qtest_vdev_init(char *qtest_path,
 	}
 	s->event_th_started = 1;
 
+	ret = qtest_setup_shared_memory(s);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to setup shared memory\n");
+		goto error;
+	}
+
 	ret = qtest_init_pci_devices(s, devices, devnum);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "Failed to initialize devices\n");
diff --git a/drivers/net/virtio/qtest_utils.h b/drivers/net/virtio/qtest_utils.h
index ba70754..26994b1 100644
--- a/drivers/net/virtio/qtest_utils.h
+++ b/drivers/net/virtio/qtest_utils.h
@@ -132,6 +132,8 @@ struct qtest_pci_device {
  *
  * @param qtest_path
  *   Path of qtest socket.
+ * @param ivshmem_path
+ *   Path of ivshmem socket.
  * @param devices
  *   Array of device information. It should contain piix3, ivshmem and target
  *   device(virtio-net device).
@@ -140,7 +142,7 @@ struct qtest_pci_device {
  * @return
  *   The pointer to qtest session structure.
  */
-struct qtest_session *qtest_vdev_init(char *qtest_path,
+struct qtest_session *qtest_vdev_init(char *qtest_path, char *ivshmem_path,
 		struct qtest_pci_device *devices, int devnum);
 
 /**
-- 
2.1.4



More information about the dev mailing list