aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2024-12-18 20:36:38 +0200
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2024-12-18 21:38:58 +0200
commit6f3574916e3bf880a907b38ec51d98279ceebc0d (patch)
tree9e30b0f083dd262745b247e9070af0d8cdd3c36a
parent7c56b4ab66bab75f629900a1d59d8cae7745525e (diff)
Update virtio-loopback adapter - Add priority featureHEADmaster
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.h3
-rw-r--r--include/virtio_loopback.h5
-rw-r--r--src/adapter/adapter.c2
-rw-r--r--src/adapter/parser.c69
-rw-r--r--src/lib/virtio_loopback.c3
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;
}