aboutsummaryrefslogtreecommitdiff
path: root/net/tap.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tap.c')
-rw-r--r--net/tap.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/net/tap.c b/net/tap.c
index ae1c7e3..f7df702 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -42,11 +42,29 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "qemu/sockets.h"
+#include "hw/virtio/vhost.h"
#include "net/tap.h"
#include "net/vhost_net.h"
+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,
+ VIRTIO_F_VERSION_1,
+ VIRTIO_NET_F_MTU,
+ VIRTIO_F_IOMMU_PLATFORM,
+ VIRTIO_F_RING_PACKED,
+ VIRTIO_F_RING_RESET,
+ VIRTIO_F_IN_ORDER,
+ VIRTIO_F_NOTIFICATION_DATA,
+ VIRTIO_NET_F_RSC_EXT,
+ VIRTIO_NET_F_HASH_REPORT,
+ VHOST_INVALID_FEATURE_BIT
+};
+
typedef struct TAPState {
NetClientState nc;
int fd;
@@ -172,6 +190,11 @@ static void tap_send(void *opaque)
break;
}
+ if (s->host_vnet_hdr_len && size <= s->host_vnet_hdr_len) {
+ /* Invalid packet */
+ break;
+ }
+
if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
buf += s->host_vnet_hdr_len;
size -= s->host_vnet_hdr_len;
@@ -329,6 +352,18 @@ int tap_get_fd(NetClientState *nc)
return s->fd;
}
+/*
+ * tap_get_vhost_net() can return NULL if a tap net-device backend is
+ * created with 'vhost=off' option, 'vhostforce=off' or no vhost or
+ * vhostforce or vhostfd options at all. Please see net_init_tap_one().
+ */
+static VHostNetState *tap_get_vhost_net(NetClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+ assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
+ return s->vhost_net;
+}
+
/* fd support */
static NetClientInfo net_tap_info = {
@@ -347,6 +382,7 @@ static NetClientInfo net_tap_info = {
.set_vnet_le = tap_set_vnet_le,
.set_vnet_be = tap_set_vnet_be,
.set_steering_ebpf = tap_set_steering_ebpf,
+ .get_vhost_net = tap_get_vhost_net,
};
static TAPState *net_tap_fd_init(NetClientState *peer,
@@ -712,6 +748,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
}
options.opaque = (void *)(uintptr_t)vhostfd;
options.nvqs = 2;
+ options.feature_bits = kernel_feature_bits;
+ options.get_acked_features = NULL;
+ options.save_acked_features = NULL;
+ options.max_tx_queue_size = 0;
+ options.is_vhost_user = false;
s->vhost_net = vhost_net_init(&options);
if (!s->vhost_net) {
@@ -854,8 +895,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
goto free_fail;
}
- ret = g_unix_set_fd_nonblocking(fd, true, NULL);
- if (!ret) {
+ if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
+ ret = -1;
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
name, fd);
goto free_fail;
@@ -980,13 +1021,6 @@ free_fail:
return 0;
}
-VHostNetState *tap_get_vhost_net(NetClientState *nc)
-{
- TAPState *s = DO_UPCAST(TAPState, nc, nc);
- assert(nc->info->type == NET_CLIENT_DRIVER_TAP);
- return s->vhost_net;
-}
-
int tap_enable(NetClientState *nc)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);