Generalize the features get/ack to be used for both vhost-net and vhost-scsi.
In vhost-net add vhost_net_get_feature_bits to select the feature bit set
depending on the NetClient kind.
Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
NetClientState *nc;
};
-unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+/* Features supported by host kernel. */
+static const int kernel_feature_bits[] = {
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_NET_F_MRG_RXBUF,
+ VHOST_INVALID_FEATURE_BIT
+};
+
+static const int *vhost_net_get_feature_bits(struct vhost_net *net)
{
- /* Clear features not supported by host kernel. */
- if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
- features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- }
- if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
- features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
- }
- if (!(net->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
- features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
- }
- if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))) {
- features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+ const int *feature_bits = 0;
+
+ switch (net->nc->info->type) {
+ case NET_CLIENT_OPTIONS_KIND_TAP:
+ feature_bits = kernel_feature_bits;
+ break;
+ default:
+ error_report("Feature bits not defined for this type: %d",
+ net->nc->info->type);
+ break;
}
- return features;
+
+ return feature_bits;
+}
+
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+{
+ return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
+ features);
}
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
{
- net->dev.acked_features = net->dev.backend_features;
- if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) {
- net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- }
- if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
- net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
- }
- if (features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
- net->dev.acked_features |= (1 << VIRTIO_RING_F_EVENT_IDX);
- }
- if (features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
- net->dev.acked_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
- }
+ vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
}
static int vhost_net_get_fd(NetClientState *backend)
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/virtio-bus.h"
+/* Features supported by host kernel. */
+static const int kernel_feature_bits[] = {
+ VIRTIO_F_NOTIFY_ON_EMPTY,
+ VIRTIO_RING_F_INDIRECT_DESC,
+ VIRTIO_RING_F_EVENT_IDX,
+ VIRTIO_SCSI_F_HOTPLUG,
+ VHOST_INVALID_FEATURE_BIT
+};
+
static int vhost_scsi_set_endpoint(VHostSCSI *s)
{
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
{
VHostSCSI *s = VHOST_SCSI(vdev);
- /* Clear features not supported by host kernel. */
- if (!(s->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
- features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- }
- if (!(s->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
- features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
- }
- if (!(s->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
- features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
- }
- if (!(s->dev.features & (1 << VIRTIO_SCSI_F_HOTPLUG))) {
- features &= ~(1 << VIRTIO_SCSI_F_HOTPLUG);
- }
-
- return features;
+ return vhost_get_features(&s->dev, kernel_feature_bits, features);
}
static void vhost_scsi_set_config(VirtIODevice *vdev,
assert(r >= 0);
}
+unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
+ unsigned features)
+{
+ const int *bit = feature_bits;
+ while (*bit != VHOST_INVALID_FEATURE_BIT) {
+ unsigned bit_mask = (1 << *bit);
+ if (!(hdev->features & bit_mask)) {
+ features &= ~bit_mask;
+ }
+ bit++;
+ }
+ return features;
+}
+
+void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
+ unsigned features)
+{
+ const int *bit = feature_bits;
+ while (*bit != VHOST_INVALID_FEATURE_BIT) {
+ unsigned bit_mask = (1 << *bit);
+ if (features & bit_mask) {
+ hdev->acked_features |= bit_mask;
+ }
+ bit++;
+ }
+}
+
/* Host notifiers must be enabled at this point. */
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
{
#define VHOST_LOG_PAGE 0x1000
#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
+#define VHOST_INVALID_FEATURE_BIT (0xff)
struct vhost_memory;
struct vhost_dev {
*/
void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
bool mask);
+unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
+ unsigned features);
+void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
+ unsigned features);
#endif