migration: set data_fd to -1 in device state response (#876)

* migration: set data_fd to -1 in device state response

The vfio-user protocol specification requires that data_fd must be set
to -1 in both the request and response of VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE,
as migration data transport relies on socket messages rather than a file descriptor.

Force data_fd to -1 in both the GET and SET migration feature handlers
to ensure the server properly complies with the specification.

Signed-off-by: Hugo Komatsu <hugo.komatsu@nutanix.com>
Co-authored-by: John Levon <john.levon@nutanix.com>
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 7f083a1..62a5f13 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -1018,6 +1018,7 @@
             struct vfio_user_device_feature_mig_state *state =
                 (void *)res->data;
             state->device_state = migration_get_state(vfu_ctx);
+            state->data_fd = -1;
             return 0;
         }
         
@@ -1032,11 +1033,14 @@
 handle_migration_device_feature_set(vfu_ctx_t *vfu_ctx, uint32_t feature,
                                     struct vfio_user_device_feature *res)
 {
+    int ret;
     assert(feature == VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE);
 
     struct vfio_user_device_feature_mig_state *state = (void *)res->data;
 
-    return migration_set_state(vfu_ctx, state->device_state);
+    ret = migration_set_state(vfu_ctx, state);
+
+    return ret;
 }
 
 static int
diff --git a/lib/migration.c b/lib/migration.c
index f995fca..603dc92 100644
--- a/lib/migration.c
+++ b/lib/migration.c
@@ -262,16 +262,17 @@
 }
 
 ssize_t
-migration_set_state(vfu_ctx_t *vfu_ctx, uint32_t device_state)
+migration_set_state(vfu_ctx_t *vfu_ctx, struct vfio_user_device_feature_mig_state *mig_state)
 {
     struct migration *migr = vfu_ctx->migration;
     uint32_t state;
     ssize_t ret = 0;
-    
+    uint32_t device_state = mig_state->device_state;
+
     if (device_state >= VFIO_USER_DEVICE_NUM_STATES) {
         return ERROR_INT(EINVAL);
     }
-    
+
     while (migr->state != device_state && ret == 0) {
         state = next_state[migr->state][device_state];
 
@@ -280,8 +281,11 @@
         }
 
         ret = handle_device_state(vfu_ctx, migr, state, true);
-    };
-    
+    }
+
+    /* Force data_fd to -1 in the response per the vfio-user protocol */
+    mig_state->data_fd = -1;
+
     return ret;
 }
 
diff --git a/lib/migration.h b/lib/migration.h
index 928a7e5..513cf59 100644
--- a/lib/migration.h
+++ b/lib/migration.h
@@ -51,7 +51,7 @@
 migration_get_state(vfu_ctx_t *vfu_ctx);
 
 ssize_t
-migration_set_state(vfu_ctx_t *vfu_ctx, uint32_t device_state);
+migration_set_state(vfu_ctx_t *vfu_ctx, struct vfio_user_device_feature_mig_state *mig_state);
 
 ssize_t
 handle_mig_data_read(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg);
diff --git a/test/py/test_migration.py b/test/py/test_migration.py
index 3fc3d19..6c0878f 100644
--- a/test/py/test_migration.py
+++ b/test/py/test_migration.py
@@ -347,6 +347,8 @@
     _, result = vfio_user_device_feature.pop_from_buffer(result)
     state, _ = vfio_user_device_feature_mig_state.pop_from_buffer(result)
     assert state.device_state == VFIO_USER_DEVICE_STATE_RUNNING
+    # defined as -1 embedded into a uint32_t
+    assert state.data_fd == 4294967295
 
 
 def test_handle_mig_data_read():