aboutsummaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
Diffstat (limited to 'samples')
-rw-r--r--samples/client.c110
1 files changed, 69 insertions, 41 deletions
diff --git a/samples/client.c b/samples/client.c
index 12eee21..13880c5 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -51,6 +51,9 @@
#define CLIENT_MAX_FDS (32)
+/* This is low, so we get testing of vfu_dma_read/write() chunking. */
+#define CLIENT_MAX_DATA_XFER_SIZE (1024)
+
static char *irq_to_str[] = {
[VFU_DEV_INTX_IRQ] = "INTx",
[VFU_DEV_MSI_IRQ] = "MSI",
@@ -105,11 +108,12 @@ send_version(int sock)
"{"
"\"capabilities\":{"
"\"max_msg_fds\":%u,"
+ "\"max_data_xfer_size\":%u,"
"\"migration\":{"
"\"pgsize\":%zu"
"}"
"}"
- "}", CLIENT_MAX_FDS, sysconf(_SC_PAGESIZE));
+ "}", CLIENT_MAX_FDS, CLIENT_MAX_DATA_XFER_SIZE, sysconf(_SC_PAGESIZE));
cversion.major = LIB_VFIO_USER_MAJOR;
cversion.minor = LIB_VFIO_USER_MINOR;
@@ -130,7 +134,8 @@ send_version(int sock)
}
static void
-recv_version(int sock, int *server_max_fds, size_t *pgsize)
+recv_version(int sock, int *server_max_fds, size_t *server_max_data_xfer_size,
+ size_t *pgsize)
{
struct vfio_user_version *sversion = NULL;
struct vfio_user_header hdr;
@@ -167,6 +172,7 @@ recv_version(int sock, int *server_max_fds, size_t *pgsize)
}
*server_max_fds = 1;
+ *server_max_data_xfer_size = VFIO_USER_DEFAULT_MAX_DATA_XFER_SIZE;
*pgsize = sysconf(_SC_PAGESIZE);
if (vlen > sizeof(*sversion)) {
@@ -177,7 +183,8 @@ recv_version(int sock, int *server_max_fds, size_t *pgsize)
errx(EXIT_FAILURE, "ignoring invalid JSON from server");
}
- ret = tran_parse_version_json(json_str, server_max_fds, pgsize);
+ ret = tran_parse_version_json(json_str, server_max_fds,
+ server_max_data_xfer_size, pgsize);
if (ret < 0) {
err(EXIT_FAILURE, "failed to parse server JSON \"%s\"", json_str);
@@ -188,10 +195,11 @@ recv_version(int sock, int *server_max_fds, size_t *pgsize)
}
static void
-negotiate(int sock, int *server_max_fds, size_t *pgsize)
+negotiate(int sock, int *server_max_fds, size_t *server_max_data_xfer_size,
+ size_t *pgsize)
{
send_version(sock);
- recv_version(sock, server_max_fds, pgsize);
+ recv_version(sock, server_max_fds, server_max_data_xfer_size, pgsize);
}
static void
@@ -562,21 +570,27 @@ handle_dma_write(int sock, struct vfio_user_dma_map *dma_regions,
}
for (i = 0; i < nr_dma_regions; i++) {
- if (dma_regions[i].addr == dma_access.addr) {
- ret = pwrite(dma_region_fds[i], data, dma_access.count,
- dma_regions[i].offset);
- if (ret < 0) {
- err(EXIT_FAILURE,
- "failed to write data to fd=%d at %#lx-%#lx",
- dma_region_fds[i],
- dma_regions[i].offset,
- dma_regions[i].offset + dma_access.count - 1);
- }
- break;
- }
+ off_t offset;
+ ssize_t c;
+
+ if (dma_access.addr < dma_regions[i].addr ||
+ dma_access.addr >= dma_regions[i].addr + dma_regions[i].size) {
+ continue;
+ }
+
+ offset = dma_regions[i].offset + dma_access.addr;
+
+ c = pwrite(dma_region_fds[i], data, dma_access.count, offset);
+
+ if (c != (ssize_t)dma_access.count) {
+ err(EXIT_FAILURE, "failed to write to fd=%d at [%#lx-%#lx)",
+ dma_region_fds[i], offset, offset + dma_access.count);
+ }
+ break;
}
- dma_access.count = 0;
+ assert(i != nr_dma_regions);
+
ret = tran_sock_send(sock, msg_id, true, VFIO_USER_DMA_WRITE,
&dma_access, sizeof(dma_access));
if (ret < 0) {
@@ -606,24 +620,36 @@ handle_dma_read(int sock, struct vfio_user_dma_map *dma_regions,
if (response == NULL) {
err(EXIT_FAILURE, NULL);
}
+ response->addr = dma_access.addr;
response->count = dma_access.count;
data = (char *)response->data;
for (i = 0; i < nr_dma_regions; i++) {
- if (dma_regions[i].addr == dma_access.addr) {
- if (pread(dma_region_fds[i], data, dma_access.count, dma_regions[i].offset) == -1) {
- err(EXIT_FAILURE, "failed to write data at %#lx-%#lx",
- dma_regions[i].offset,
- dma_regions[i].offset + dma_access.count);
- }
- break;
- }
+ off_t offset;
+ ssize_t c;
+
+ if (dma_access.addr < dma_regions[i].addr ||
+ dma_access.addr >= dma_regions[i].addr + dma_regions[i].size) {
+ continue;
+ }
+
+ offset = dma_regions[i].offset + dma_access.addr;
+
+ c = pread(dma_region_fds[i], data, dma_access.count, offset);
+
+ if (c != (ssize_t)dma_access.count) {
+ err(EXIT_FAILURE, "failed to read from fd=%d at [%#lx-%#lx)",
+ dma_region_fds[i], offset, offset + dma_access.count);
+ }
+ break;
}
+ assert(i != nr_dma_regions);
+
ret = tran_sock_send(sock, msg_id, true, VFIO_USER_DMA_READ,
response, response_sz);
if (ret < 0) {
- err(EXIT_FAILURE, "failed to send reply of DMA write");
+ err(EXIT_FAILURE, "failed to send reply of DMA read");
}
free(response);
}
@@ -632,8 +658,14 @@ static void
handle_dma_io(int sock, struct vfio_user_dma_map *dma_regions,
int nr_dma_regions, int *dma_region_fds)
{
- handle_dma_write(sock, dma_regions, nr_dma_regions, dma_region_fds);
- handle_dma_read(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ size_t i;
+
+ for (i = 0; i < 4096 / CLIENT_MAX_DATA_XFER_SIZE; i++) {
+ handle_dma_write(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ }
+ for (i = 0; i < 4096 / CLIENT_MAX_DATA_XFER_SIZE; i++) {
+ handle_dma_read(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ }
}
static void
@@ -678,12 +710,6 @@ get_dirty_bitmap(int sock, struct vfio_user_dma_map *dma_region)
free(data);
}
-enum migration {
- NO_MIGRATION,
- MIGRATION_SOURCE,
- MIGRATION_DESTINATION,
-};
-
static void
usage(char *argv0)
{
@@ -891,8 +917,9 @@ migrate_from(int sock, size_t *nr_iters, struct iovec **migr_iters,
static int
migrate_to(char *old_sock_path, int *server_max_fds,
- size_t *pgsize, size_t nr_iters, struct iovec *migr_iters,
- char *path_to_server, unsigned char *src_md5sum, size_t bar1_size)
+ size_t *server_max_data_xfer_size, size_t *pgsize, size_t nr_iters,
+ struct iovec *migr_iters, char *path_to_server,
+ unsigned char *src_md5sum, size_t bar1_size)
{
int ret, sock;
char *sock_path;
@@ -947,7 +974,7 @@ migrate_to(char *old_sock_path, int *server_max_fds,
sock = init_sock(sock_path);
free(sock_path);
- negotiate(sock, server_max_fds, pgsize);
+ negotiate(sock, server_max_fds, server_max_data_xfer_size, pgsize);
/* XXX set device state to resuming */
ret = access_region(sock, VFU_PCI_DEV_MIGR_REGION_IDX, true,
@@ -1060,6 +1087,7 @@ int main(int argc, char *argv[])
int i;
FILE *fp;
int server_max_fds;
+ size_t server_max_data_xfer_size;
size_t pgsize;
int nr_dma_regions;
struct vfio_user_dirty_pages dirty_pages = {0};
@@ -1095,7 +1123,7 @@ int main(int argc, char *argv[])
*
* Do intial negotiation with the server, and discover parameters.
*/
- negotiate(sock, &server_max_fds, &pgsize);
+ negotiate(sock, &server_max_fds, &server_max_data_xfer_size, &pgsize);
/* try to access a bogus region, we should get an error */
ret = access_region(sock, 0xdeadbeef, false, 0, &ret, sizeof(ret));
@@ -1240,8 +1268,8 @@ int main(int argc, char *argv[])
err(EXIT_FAILURE, "failed to asprintf");
}
- sock = migrate_to(argv[optind], &server_max_fds, &pgsize,
- nr_iters, migr_iters, path_to_server,
+ sock = migrate_to(argv[optind], &server_max_fds, &server_max_data_xfer_size,
+ &pgsize, nr_iters, migr_iters, path_to_server,
md5sum, bar1_size);
free(path_to_server);
for (i = 0; i < (int)nr_iters; i++) {