On Tue, Nov 21, 2023 at 3:58 PM Markus Armbruster <arm...@redhat.com> wrote:
> Laurent, there's a question for you at the end. > > Yong Huang <yong.hu...@smartx.com> writes: > > > On Thu, Nov 16, 2023 at 10:44 PM Markus Armbruster <arm...@redhat.com> > > wrote: > > > >> Hyman Huang <yong.hu...@smartx.com> writes: > >> > >> > This patch allows to display feature and status bits in virtio-status. > >> > > >> > An optional argument is introduced: show-bits. For example: > >> > {"execute": "x-query-virtio-status", > >> > "arguments": {"path": > "/machine/peripheral-anon/device[1]/virtio-backend", > >> > "show-bits": true} > >> > > >> > Features and status bits could be helpful for applications to compare > >> > directly. For instance, when an upper application aims to ensure the > >> > virtio negotiation correctness between guest, QEMU, and OVS-DPDK, it > use > >> > the "ovs-vsctl list interface" command to retrieve interface features > >> > (in number format) and the QMP command x-query-virtio-status to > retrieve > >> > vhost-user net device features. If "show-bits" is added, the > application > >> > can compare the two features directly; No need to encoding the > features > >> > returned by the QMP command. > >> > > >> > This patch also serves as a preparation for the next one, which > implements > >> > a vhost-user test case about acked features of vhost-user protocol. > >> > > >> > Note that since the matching HMP command is typically used for human, > >> > leave it unchanged. > >> > > >> > Signed-off-by: Hyman Huang <yong.hu...@smartx.com> > >> > --- > >> > hw/virtio/virtio-hmp-cmds.c | 2 +- > >> > hw/virtio/virtio-qmp.c | 21 +++++++++++++++- > >> > qapi/virtio.json | 49 > ++++++++++++++++++++++++++++++++++--- > >> > 3 files changed, 67 insertions(+), 5 deletions(-) > >> > > >> > diff --git a/hw/virtio/virtio-hmp-cmds.c b/hw/virtio/virtio-hmp-cmds.c > >> > index 477c97dea2..3774f3d4bf 100644 > >> > --- a/hw/virtio/virtio-hmp-cmds.c > >> > +++ b/hw/virtio/virtio-hmp-cmds.c > >> > @@ -108,7 +108,7 @@ void hmp_virtio_status(Monitor *mon, const QDict > *qdict) > >> > { > >> > Error *err = NULL; > >> > const char *path = qdict_get_try_str(qdict, "path"); > >> > - VirtioStatus *s = qmp_x_query_virtio_status(path, &err); > >> > + VirtioStatus *s = qmp_x_query_virtio_status(path, false, false, > &err); > >> > > >> > if (err != NULL) { > >> > hmp_handle_error(mon, err); > >> > diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c > >> > index 1dd96ed20f..2e92bf28ac 100644 > >> > --- a/hw/virtio/virtio-qmp.c > >> > +++ b/hw/virtio/virtio-qmp.c > >> > @@ -718,10 +718,15 @@ VirtIODevice *qmp_find_virtio_device(const char > *path) > >> > return VIRTIO_DEVICE(dev); > >> > } > >> > > >> > -VirtioStatus *qmp_x_query_virtio_status(const char *path, Error > **errp) > >> > +VirtioStatus *qmp_x_query_virtio_status(const char *path, > >> > + bool has_show_bits, > >> > + bool show_bits, > >> > + Error **errp) > >> > { > >> > VirtIODevice *vdev; > >> > VirtioStatus *status; > >> > + bool display_bits = > >> > + has_show_bits ? show_bits : false; > >> > >> Since !has_show_bits implies !show_bits, you can simply use > >> if (show_bits). > >> > > Ok > > > >> > >> > > >> > vdev = qmp_find_virtio_device(path); > >> > if (vdev == NULL) { > >> > @@ -733,6 +738,11 @@ VirtioStatus *qmp_x_query_virtio_status(const > char *path, Error **errp) > >> > status->name = g_strdup(vdev->name); > >> > status->device_id = vdev->device_id; > >> > status->vhost_started = vdev->vhost_started; > >> > + if (display_bits) { > >> > + status->guest_features_bits = vdev->guest_features; > >> > + status->host_features_bits = vdev->host_features; > >> > + status->backend_features_bits = vdev->backend_features; > >> > + } > >> > status->guest_features = qmp_decode_features(vdev->device_id, > >> > > vdev->guest_features); > >> > status->host_features = qmp_decode_features(vdev->device_id, > >> > @@ -753,6 +763,9 @@ VirtioStatus *qmp_x_query_virtio_status(const > char *path, Error **errp) > >> > } > >> > > >> > status->num_vqs = virtio_get_num_queues(vdev); > >> > + if (display_bits) { > >> > + status->status_bits = vdev->status; > >> > + } > >> > status->status = qmp_decode_status(vdev->status); > >> > status->isr = vdev->isr; > >> > status->queue_sel = vdev->queue_sel; > >> > @@ -775,6 +788,12 @@ VirtioStatus *qmp_x_query_virtio_status(const > char *path, Error **errp) > >> > status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections; > >> > status->vhost_dev->nvqs = hdev->nvqs; > >> > status->vhost_dev->vq_index = hdev->vq_index; > >> > + if (display_bits) { > >> > + status->vhost_dev->features_bits = hdev->features; > >> > + status->vhost_dev->acked_features_bits = > hdev->acked_features; > >> > + status->vhost_dev->backend_features_bits = > hdev->backend_features; > >> > + status->vhost_dev->protocol_features_bits = > hdev->protocol_features; > >> > + } > >> > status->vhost_dev->features = > >> > qmp_decode_features(vdev->device_id, hdev->features); > >> > status->vhost_dev->acked_features = > >> > diff --git a/qapi/virtio.json b/qapi/virtio.json > >> > index e6dcee7b83..608b841a89 100644 > >> > --- a/qapi/virtio.json > >> > +++ b/qapi/virtio.json > >> > @@ -79,12 +79,20 @@ > >> > # > >> > # @vq-index: vhost_dev vq_index > >> > # > >> > +# @features-bits: vhost_dev features in decimal format > >> > >> Say "encoded as a number". The number is decimal just because the > >> transport is JSON. We could have another transport some day. Or > >> language bindings wrapping around the JSON transport. > >> > >> > +# > >> > # @features: vhost_dev features > >> > >> Double-checking... @feature-bits provides the exact same information as > >> @features, only in another encoding. Correct? > > > > > >> Same for all the other new -bits. Correct? > > > > Yes, all the new fields are only about providing another encoding. > > Why do we want to return the same information in two different > encodings? I figure the commit message tries to answer this question: > > Features and status bits could be helpful for applications to compare > directly. For instance, when an upper application aims to ensure the > virtio negotiation correctness between guest, QEMU, and OVS-DPDK, it > use > the "ovs-vsctl list interface" command to retrieve interface features > (in number format) and the QMP command x-query-virtio-status to > retrieve > vhost-user net device features. If "show-bits" is added, the > application > can compare the two features directly; No need to encoding the > features > returned by the QMP command. > > This patch also serves as a preparation for the next one, which > implements > a vhost-user test case about acked features of vhost-user protocol. > > I guess you're trying to simplify use cases where the QMP client wants > to compare entire feature sets without caring for individual features. > > The comparison is easy if both sets are represented the same way, > e.g. both are numbers, or both are lists of symbols. Yes, quite correct, this patch just aims to keep the unencoded bits for easy comparison. > > With different representations, we first have to map to a common > representation. Unfortunately, the design of x-query-virtio-status > makes this harder than it should be. > > We use QAPI types VirtioDeviceStatus, VhostDeviceProtocols, > VirtioDeviceFeatures to represent feature sets. They all work the same > way: array of strings plus a number. For each bit QEMU knows, there's a > string in the array. Any remaining bits go into the number. > > The format of the string is undocumented. They look like > > "WELL_KNOWN_SYMBOL: human readable explanation" > > Mapping from bit to this string in a client would require duplicating > QEMU's code exactly. > > Mapping both bit and string to just "WELL_KNOWN_SYMBOL" could perhaps be > done. > > The mapping between symbols and bits is not visible in QMP. Mapping > from string to bit requires exploiting the undocumented format: extract > the well-known symbol and decode it. > > This encoding of feature sets goes back to commit f3034ad71fc (qmp: > decode feature & status bits in virtio-status) v7.2. Before that, the > command returned the bits as a number. > > For example, return value "member "status": > > Before f3034ad71fc: > > "status": 15, > > Since f3034ad71fc: > > "status": { > "statuses": [ > "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", > "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", > "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation > complete", > "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" > ]}, > > With your patch: > > "status": { > "statuses": [ > "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", > "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", > "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation > complete", > "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" > ]}, > "status-bits": 15, > > Looks like commit f3034ad71fc improved one use case at the expense of > another, and your patch tries to revert the damage. Which one exactly > it improved is unclear; the commit message doesn't tell. Laurent? > > [...] > > -- Best regards