1. Move function higher. (we anyway want to split it into two functions,
and change the code a lot, so take an opportunity to get rid of extra
declaration).
2. Split into _set_options() and _init_vhost(): we'll need it later
to implement TAP local migration feature.
3. Split requires to store options somewhere, and to be able to call
_init_vhost() later (from migriation _load() in later commit), store
options in the TAPState.
4. So, take an opportunity to zero-initialize options:
- be safe (avoid uninitialized options)
- don't care to initialize half of the options to zero by hand
5. Also, don't worry too much about poll_us: absent option should be
zero-initialized anyway.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
---
net/tap.c | 124 +++++++++++++++++++++++++++++-------------------------
1 file changed, 67 insertions(+), 57 deletions(-)
diff --git a/net/tap.c b/net/tap.c
index 4f3512a831..cf7f704a92 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -78,6 +78,7 @@ typedef struct TAPState {
bool has_ufo;
bool has_uso;
bool enabled;
+ VhostNetOptions *vhost_options;
VHostNetState *vhost_net;
unsigned host_vnet_hdr_len;
Notifier exit;
@@ -95,8 +96,6 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
const char *downscript,
const char *vhostfdname,
int vnet_hdr, int fd, Error **errp);
-static int net_tap_setup_vhost(TAPState *s, const NetdevTapOptions *tap,
- const char *vhostfdname, Error **errp);
static void tap_update_fd_handler(TAPState *s)
{
@@ -334,6 +333,8 @@ static void tap_cleanup(NetClientState *nc)
s->vhost_net = NULL;
}
+ g_free(s->vhost_options);
+
qemu_purge_queued_packets(nc);
if (s->exit.notify) {
@@ -697,6 +698,64 @@ static int net_tap_open_one(const Netdev *netdev,
#define MAX_TAP_QUEUES 1024
+static int net_tap_set_vhost_options(TAPState *s, const NetdevTapOptions *tap,
+ const char *vhostfdname, Error **errp)
+{
+ int vhostfd;
+ bool vhost_on = tap->has_vhost ? tap->vhost :
+ vhostfdname || (tap->has_vhostforce && tap->vhostforce);
+
+ if (!vhost_on) {
+ return 0;
+ }
+
+ if (vhostfdname) {
+ vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, errp);
+ if (vhostfd == -1) {
+ return -1;
+ }
+ } else {
+ vhostfd = open("/dev/vhost-net", O_RDWR);
+ if (vhostfd < 0) {
+ error_setg_errno(errp, errno,
+ "tap: open vhost char device failed");
+ return -1;
+ }
+ }
+
+ if (!qemu_set_blocking(vhostfd, false, errp)) {
+ return -1;
+ }
+
+ s->vhost_options = g_new(VhostNetOptions, 1);
+ *s->vhost_options = (VhostNetOptions) {
+ .backend_type = VHOST_BACKEND_TYPE_KERNEL,
+ .net_backend = &s->nc,
+ .busyloop_timeout = tap->poll_us,
+ .opaque = (void *)(uintptr_t)vhostfd,
+ .nvqs = 2,
+ .feature_bits = kernel_feature_bits,
+ };
+
+ return 0;
+}
+
+static int net_tap_init_vhost(TAPState *s, Error **errp)
+{
+ if (!s->vhost_options) {
+ return 0;
+ }
+
+ s->vhost_net = vhost_net_init(s->vhost_options);
+ if (!s->vhost_net) {
+ error_setg(errp,
+ "vhost-net requested but could not be initialized");
+ return -1;
+ }
+
+ return 0;
+}
+
static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
const char *model, const char *name,
const char *ifname, const char *script,
@@ -762,7 +821,12 @@ static int net_tap_fd_init_common(const Netdev *netdev, NetClientState *peer,
}
}
- ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
+ ret = net_tap_set_vhost_options(s, tap, vhostfdname, errp);
+ if (ret < 0) {
+ goto failed;
+ }
+
+ ret = net_tap_init_vhost(s, errp);
if (ret < 0) {
goto failed;
}
@@ -774,60 +838,6 @@ failed:
return -1;
}
-static int net_tap_setup_vhost(TAPState *s, const NetdevTapOptions *tap,
- const char *vhostfdname, Error **errp)
-{
- if (tap->has_vhost ? tap->vhost :
- vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
- VhostNetOptions options;
- int vhostfd;
-
- options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
- options.net_backend = &s->nc;
- if (tap->has_poll_us) {
- options.busyloop_timeout = tap->poll_us;
- } else {
- options.busyloop_timeout = 0;
- }
-
- if (vhostfdname) {
- vhostfd = monitor_fd_param(monitor_cur(), vhostfdname, errp);
- if (vhostfd == -1) {
- return -1;
- }
- if (!qemu_set_blocking(vhostfd, false, errp)) {
- return -1;
- }
- } else {
- vhostfd = open("/dev/vhost-net", O_RDWR);
- if (vhostfd < 0) {
- error_setg_errno(errp, errno,
- "tap: open vhost char device failed");
- return -1;
- }
- if (!qemu_set_blocking(vhostfd, false, errp)) {
- return -1;
- }
- }
- 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) {
- error_setg(errp,
- "vhost-net requested but could not be initialized");
- return -1;
- }
- }
-
- return 0;
-}
-
static int net_tap_from_monitor_fd(const Netdev *netdev, NetClientState *peer,
const char *name, const char *vhostfdname,
int *pvnet_hdr, const char *fdname,
--
2.48.1