aboutsummaryrefslogtreecommitdiffstats
path: root/adapter.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-11-10 15:47:34 +0100
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-11-29 12:43:41 +0100
commit9ad83030ef18c04beae09a6acf9800378a8378bc (patch)
tree55fb7db83e7c99cf1260d9e3fbc6dce2f545eee9 /adapter.c
parent247ecdad23065b8e8df08c939915d7551b6e0c21 (diff)
Add virtio-loopback-adapter
The virtio-loopback-adapter is part of the Virtio Loopback architecture detailed in the following link: https://git.virtualopensystems.com/virtio-loopback/docs The following vhost-user devices are supported: - vhost-user-blk - vhost-user-rng - vhost-user-input - vhost-user-gpio - vhost-user-sound Bug-AGL: SPEC-4834 Change-Id: I4edb28faf370992f5f45390f5c4240a0f5c3084c Signed-off-by: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Diffstat (limited to 'adapter.c')
-rw-r--r--adapter.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/adapter.c b/adapter.c
new file mode 100644
index 0000000..75b5681
--- /dev/null
+++ b/adapter.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2022-2023 Virtual Open Systems SAS
+ *
+ * Authors:
+ * Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
+ * Stefanos Gerangelos <s.gerangelos@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/eventfd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <sys/param.h>
+#include <assert.h>
+
+/* For socket */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/* Project header files */
+#include "virtio_loopback.h"
+#include "vhost_user_loopback.h"
+#include "virtio_rng.h"
+#include "vhost_user_rng.h"
+#include "vhost_user_blk.h"
+#include "vhost_user_input.h"
+#include "vhost_user_gpio.h"
+#include "vhost_user_sound.h"
+
+
+#ifdef DEBUG
+#define DBG(...) printf("adapter: " __VA_ARGS__)
+#else
+#define DBG(...)
+#endif /* DEBUG */
+
+
+/* Global variables */
+int client_sock;
+struct vhost_dev *dev;
+struct adapter_dev *adev;
+struct vhost_user *vudev;
+
+
+void vhost_user_adapter_init(void)
+{
+
+ DBG("Setup adapter data structures\n");
+
+ /* Init vhost-user device */
+ vudev = (struct vhost_user *)malloc(sizeof(struct vhost_user));
+
+ /* Init vhost device */
+ dev = (struct vhost_dev *)malloc(sizeof(struct vhost_dev));
+
+ /* Init virtio device */
+ global_vdev = (VirtIODevice *)malloc(sizeof(VirtIODevice));
+
+ /* Init virtio bus */
+ global_vbus = (VirtioBus *)malloc(sizeof(VirtioBus));
+ global_vbus->vdev = global_vdev;
+ global_vdev->vbus = global_vbus;
+ global_vdev->vhdev = dev;
+
+
+ /* Store virtio_dev reference into vhost_dev struct*/
+ dev->vdev = global_vdev;
+
+ /* Init adapter device */
+ adev = (struct adapter_dev *)malloc(sizeof(struct adapter_dev));
+ adev->vdev = dev;
+ adev->vudev = vudev;
+ adev->virtio_dev = global_vdev;
+ adev->vbus = global_vbus;
+}
+
+
+void client(char *sock_path)
+{
+ int rc, len;
+ struct sockaddr_un client_sockaddr;
+
+ DBG("Create shared socket with vhost-user-device\n");
+
+ /* Initialize the struct to zero */
+ memset(&client_sockaddr, 0, sizeof(struct sockaddr_un));
+
+ /*
+ * Create a UNIX socket
+ */
+ client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (client_sock == -1) {
+ DBG("SOCKET ERROR\n");
+ exit(1);
+ }
+
+ /*
+ * Set up the UNIX sockaddr structure
+ * by using AF_UNIX for the family and
+ * giving it a filepath to connect.
+ */
+ client_sockaddr.sun_family = AF_UNIX;
+ strcpy(client_sockaddr.sun_path, sock_path);
+ len = sizeof(client_sockaddr);
+ rc = connect(client_sock, (struct sockaddr *) &client_sockaddr, len);
+ if (rc == -1) {
+ printf("CONNECT ERROR: Check the \"-s\" parameter\n");
+ close(client_sock);
+ exit(1);
+ }
+}
+
+static void help_args(void)
+{
+ printf("Run example:\n\t./adapter -s /path_to_socket/rng.sock\n"
+ "\t\t -d device_name\n"
+ "\t\t [ -qn number of queues ]\n"
+ "\t\t [ -qs size of queues ]\n"
+ "The 'device_name' can be one of the following:\n"
+ "\tvrng, vhurng, vhublk, vhuinput, vhusnd, vhugpio\n");
+}
+
+int find_arg(int argc, char **argv, char *str)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], str)) {
+ return i + 1;
+ }
+ }
+ return -1;
+}
+
+int val_device_arg(char *str)
+{
+ char *adapter_devices[] = {"vrng", "vhurng", "vhublk", "vhuinput",
+ "vhusnd", "vhugpio"};
+ char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput", "vhusnd", "vhugpio"};
+ int adapter_devices_num = 6, i;
+
+ for (i = 0; i < adapter_devices_num; i++) {
+ if (!strcmp(adapter_devices[i], str)) {
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+bool check_vhu_device(char *str)
+{
+ char *vhu_devices[] = {"vhurng", "vhublk", "vhuinput", "vhusnd", "vhugpio"};
+ int vhu_devices_num = 5, i;
+
+ for (i = 0; i < vhu_devices_num; i++) {
+ if (!strcmp(vhu_devices[i], str)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void get_queue_num_size_args(int argc, char **argv,
+ int *eval_queue_num, int *eval_queue_size)
+{
+ int queue_num, queue_size, queue_num_id, queue_size_id;
+
+ if (argc < 9) {
+ return;
+ }
+
+ queue_num_id = find_arg(argc, argv, "-qn");
+ queue_size_id = find_arg(argc, argv, "-qs");
+
+ /* Check if both qs ans qn exist */
+ if (queue_num_id < 0 || queue_size_id < 0) {
+ return;
+ }
+
+ queue_num = atoi(argv[queue_num_id]);
+ queue_size = atoi(argv[queue_size_id]);
+
+ /* Evaluate number of queues */
+ if (queue_num <= 0 || queue_num > 16) {
+ return;
+ }
+
+ /* Evaluate queues' size */
+ if (queue_size <= 0 || queue_size > 1024) {
+ return;
+ }
+
+ *eval_queue_num = queue_num;
+ *eval_queue_size = queue_size;
+}
+
+
+int main(int argc, char **argv)
+{
+ int socket_idx, device_idx, device_id;
+ bool vhost_user_enabled;
+ /* Assign default queue num and size */
+ int queue_num = 1, queue_size = 64;
+
+ /*
+ * Check if the user has provided all the required arguments.
+ * If not, print the help messages.
+ */
+
+ if (argc < 3) {
+ goto error_args;
+ }
+
+ device_idx = find_arg(argc, argv, "-d");
+
+ if (device_idx < 0) {
+ printf("You have not specified parameter \"-d\"\n");
+ goto error_args;
+ }
+
+ /* Validate the argumetns */
+ device_id = val_device_arg(argv[device_idx]);
+
+ if (device_id == 0) {
+ goto error_args;
+ }
+
+ /* Check if this is a vhost-user device */
+ vhost_user_enabled = check_vhu_device(argv[device_idx]);
+
+ /* Check if a socket is needed and provided */
+ socket_idx = find_arg(argc, argv, "-s");
+
+ if ((socket_idx < 0) && (vhost_user_enabled)) {
+ printf("You have not specified parameter \"-s\"\n");
+ goto error_args;
+ }
+
+ /*
+ * Create the socket and connect to the backend.
+ * Enabled on vhost-user case
+ */
+ if (vhost_user_enabled) {
+ client(argv[socket_idx]);
+ }
+
+ /* Initialize the adapter data structures */
+ vhost_user_adapter_init();
+
+ /* Initialize the virtio/vhost-user device */
+ /* TODO: Switch numbers with name defs */
+ switch (device_id) {
+ case 1:
+ virtio_rng_realize();
+ break;
+ case 2:
+ vhost_user_rng_realize();
+ break;
+ case 3:
+ get_queue_num_size_args(argc, argv, &queue_num, &queue_size);
+ printf("Running vhublk with num %d and size %d\n",
+ queue_num, queue_size);
+ vhost_user_blk_realize(queue_num, queue_size);
+ break;
+ case 4:
+ vhost_user_input_init(global_vdev);
+ virtio_input_device_realize();
+ break;
+ case 5:
+ vus_device_realize();
+ break;
+ case 6:
+ vu_gpio_device_realize();
+ break;
+ default:
+ exit(1);
+ }
+
+ /*
+ * Start loopback trasnport layer and communiation with the loopback driver
+ */
+ virtio_loopback_start();
+
+ return 0;
+
+error_args:
+ help_args();
+ return 1;
+}