diff options
author | Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> | 2024-12-18 20:36:38 +0200 |
---|---|---|
committer | Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> | 2024-12-18 21:38:58 +0200 |
commit | 6f3574916e3bf880a907b38ec51d98279ceebc0d (patch) | |
tree | 9e30b0f083dd262745b247e9070af0d8cdd3c36a | |
parent | 7c56b4ab66bab75f629900a1d59d8cae7745525e (diff) |
Add scheduling mechanism for virtio interrupts and
messages. This mechanism can be used to prioritize
one virtio-device's requests over the other by
setting the args "credits=" and "priority=" into
the adapter's arguments.
Change-Id: Id322c21b87b41317153b649191d9e7e66d2fb317
Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
-rw-r--r-- | include/vhost_user_loopback.h | 3 | ||||
-rw-r--r-- | include/virtio_loopback.h | 5 | ||||
-rw-r--r-- | src/adapter/adapter.c | 2 | ||||
-rw-r--r-- | src/adapter/parser.c | 69 | ||||
-rw-r--r-- | src/lib/virtio_loopback.c | 3 |
5 files changed, 72 insertions, 10 deletions
diff --git a/include/vhost_user_loopback.h b/include/vhost_user_loopback.h index 8b0294f..25f9a25 100644 --- a/include/vhost_user_loopback.h +++ b/include/vhost_user_loopback.h @@ -239,6 +239,9 @@ typedef struct Device { int device_index; int requires_socket; int client_socket; + bool priority_enabled; + int credits; + int priority_group; } Device; typedef struct adapter_dev { diff --git a/include/virtio_loopback.h b/include/virtio_loopback.h index e3f4a78..878bd4f 100644 --- a/include/virtio_loopback.h +++ b/include/virtio_loopback.h @@ -493,10 +493,11 @@ typedef struct virtio_device_info_struct { unsigned long version; unsigned long device_id; unsigned long vendor; - + bool priority_enabled; + unsigned long credits; + unsigned long priority_group; } virtio_device_info_struct_t; - /* Negotiation structs */ typedef struct { int counter; } atomic_t; diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index 55de251..3d65ce3 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -123,7 +123,7 @@ static void client(Device *device) len = sizeof(client_sockaddr); rc = connect(device->client_socket, (struct sockaddr *) &client_sockaddr, len); if (rc == -1) { - printf("CONNECT ERROR: Check the \"-s\" parameter\n"); + printf("CONNECT ERROR: Check the \"socket\" parameter: %s\n", sock_path); close(device->client_socket); exit(1); } diff --git a/src/adapter/parser.c b/src/adapter/parser.c index 0300baa..2a3914a 100644 --- a/src/adapter/parser.c +++ b/src/adapter/parser.c @@ -70,6 +70,24 @@ static int check_queue_size(const char *queue_size_str) { return (queue_size > 0) && ((queue_size & (queue_size - 1)) == 0); } +static int check_credits(const char *credits_str) { + if (!is_number(credits_str)) { + return 0; + } + int credits = atoi(credits_str); + // Check if the queue_size is a power of 2 + return (credits > 0); +} + +static int check_priority(const char *priority_str) { + if (!is_number(priority_str)) { + return 0; + } + int priority = atoi(priority_str); + // Check if the queue_size is a power of 2 + return (priority > 0); +} + // Function to check if the socket path is valid static int check_socket(const char *socket_path) { if (socket_path == NULL || strlen(socket_path) == 0) { @@ -93,6 +111,7 @@ static int check_socket(const char *socket_path) { // Function to check if the device name is valid and get its index static int check_device_name(const char *device_name, int *device_index, int *requires_socket) { + for (unsigned int i = 0; i < num_adapter_devices; i++) { if (strcmp(device_name, adapter_devices[i]) == 0) { *device_index = i; @@ -101,7 +120,7 @@ static int check_device_name(const char *device_name, int *device_index, int *re for (unsigned int j = 0; j < num_vhu_devices; j++) { if (strcmp(device_name, vhu_devices[j]) == 0) { *requires_socket = 1; - break; + return 1; } } return 1; // Valid device name @@ -112,11 +131,15 @@ static int check_device_name(const char *device_name, int *device_index, int *re static int parse_device_arg(const char *arg, Device *device) { - char *token; + char *token; + bool socket_provided = false; // Initialize with default values device->queue_num = DEFAULT_QUEUE_NUM; device->queue_size = DEFAULT_QUEUE_SIZE; + device->credits = 10; + device->priority_enabled = false; + device->priority_group = 1; // Extract device name token = strtok((char *)arg, ","); @@ -126,6 +149,7 @@ static int parse_device_arg(const char *arg, Device *device) { // Check if the device name is valid and get the index and socket requirement if (!check_device_name(token, &device->device_index, &device->requires_socket)) { + printf("no device recognised\n"); return -1; // Invalid device name } strncpy(device->device_name, token, MAX_NAME_LENGTH - 1); @@ -137,10 +161,12 @@ static int parse_device_arg(const char *arg, Device *device) { const char *socket_path = token + 7; // Skip "socket=" if (device->requires_socket) { if (!check_socket(socket_path)) { + fprintf(stderr, "Error: Socket path: %s is invalid\n", socket_path); return -1; // Invalid socket path } strncpy(device->socket, socket_path, MAX_SOCKET_LENGTH - 1); device->socket[MAX_SOCKET_LENGTH - 1] = '\0'; // Ensure null termination + socket_provided = true; } else { // If device does not allow socket, return an error fprintf(stderr, "Error: Socket path is not allowed for device: %s\n", device->device_name); @@ -158,17 +184,43 @@ static int parse_device_arg(const char *arg, Device *device) { return -1; // Invalid queue_size } device->queue_size = atoi(queue_size_str); // Skip "queue_size=" + } else if (strncmp(token, "credits=", 8) == 0) { + const char *credits_str = token + 8; + if (!check_credits(credits_str)) { + return -1; // Invalid queue_size + } + device->credits = atoi(credits_str); + device->priority_enabled = true; + } else if (strncmp(token, "priority=", 9) == 0) { + const char *priority_str = token + 9; + if (!check_priority(priority_str)) { + return -1; // Invalid queue_size + } + device->priority_group = atoi(priority_str); + device->priority_enabled = true; } else { + printf("Error: there is no argument: \"%s\"\n", token); return -1; // Unknown parameter } } + /* Overall check */ + if (device->requires_socket & !socket_provided) { + printf("No socket is provided\n"); + return -1; + } + return 0; } int parse_args(int argc, char *argv[]) { int device_count = 0; + if (argc == 0) { + printf("No device available\n"); + return -1; + } + // Iterate over the command line arguments for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-device") == 0) { @@ -176,19 +228,17 @@ int parse_args(int argc, char *argv[]) { if (parse_device_arg(argv[i + 1], &devices[device_count]) == 0) { device_count++; } else { - fprintf(stderr, "Error: Failed to parse device argument: %s\n", argv[i + 1]); - return EXIT_FAILURE; + return -1; } i++; // Skip next argument as it's already processed } else { fprintf(stderr, "Error: Missing or too many device arguments.\n"); - return EXIT_FAILURE; + return -1; } } } - // Output parsed devices - printf("Parsed %d devices:\n", device_count); + // If everything parsed syccessfully, uutput parsed devices for (int i = 0; i < device_count; i++) { printf("Device %d:\n", i + 1); printf(" Device index: %d\n", devices[i].device_index); @@ -196,6 +246,11 @@ int parse_args(int argc, char *argv[]) { printf(" Socket: %s\n", devices[i].socket); printf(" Queue Num: %d\n", devices[i].queue_num); printf(" Queue Size: %d\n", devices[i].queue_size); + printf(" Priority: %d\n", devices[i].priority_enabled); + if (devices[i].priority_enabled) { + printf(" Credits: %d\n", devices[i].credits); + printf(" Group: %d\n", devices[i].priority_group); + } } return device_count; diff --git a/src/lib/virtio_loopback.c b/src/lib/virtio_loopback.c index 6f84bc3..9016188 100644 --- a/src/lib/virtio_loopback.c +++ b/src/lib/virtio_loopback.c @@ -1107,6 +1107,9 @@ void virtio_dev_init(VirtIODevice *vdev, const char *name, adev->device_info.version = 0x1; adev->device_info.device_id = device_id; adev->device_info.vendor = 0x554d4551; + adev->device_info.priority_enabled = adev->device_params->priority_enabled; + adev->device_info.credits = (unsigned long)adev->device_params->credits; + adev->device_info.priority_group = (unsigned long)adev->device_params->priority_group; vdev->use_guest_notifier_mask = true; } |