Handle local-incoming option:

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@yandex-team.ru>
---
 include/net/tap.h |   4 ++
 net/tap.c         | 129 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 99 insertions(+), 34 deletions(-)

diff --git a/include/net/tap.h b/include/net/tap.h
index 6f34f13eae..3ef2e2dbae 100644
--- a/include/net/tap.h
+++ b/include/net/tap.h
@@ -30,7 +30,11 @@
 
 int tap_enable(NetClientState *nc);
 int tap_disable(NetClientState *nc);
+bool tap_local_incoming(NetClientState *nc);
 
 int tap_get_fd(NetClientState *nc);
 
+int tap_load(NetClientState *nc, QEMUFile *f);
+int tap_save(NetClientState *nc, QEMUFile *f);
+
 #endif /* QEMU_NET_TAP_H */
diff --git a/net/tap.c b/net/tap.c
index c07af762b0..4d3cdc0662 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -35,6 +35,8 @@
 #include "net/eth.h"
 #include "net/net.h"
 #include "clients.h"
+#include "migration/migration.h"
+#include "migration/qemu-file.h"
 #include "monitor/monitor.h"
 #include "system/system.h"
 #include "qapi/error.h"
@@ -81,6 +83,7 @@ typedef struct TAPState {
     VHostNetState *vhost_net;
     unsigned host_vnet_hdr_len;
     Notifier exit;
+    bool local_incoming;
 } TAPState;
 
 static void launch_script(const char *setup_script, const char *ifname,
@@ -727,21 +730,25 @@ static int net_tap_open_one(const Netdev *netdev,
         vnet_hdr_required = 0;
     }
 
-    fd = RETRY_ON_EINTR(tap_open(ifname, ifname_sz, &vnet_hdr,
-                                 vnet_hdr_required, mq_required, errp));
-    if (fd < 0) {
-        return -1;
-    }
-
-    if (script &&
-        script[0] != '\0' &&
-        strcmp(script, "no") != 0) {
-        launch_script(script, ifname, fd, &err);
-        if (err) {
-            error_propagate(errp, err);
-            close(fd);
+    if (tap->local_incoming) {
+        fd = -1;
+    } else {
+        fd = RETRY_ON_EINTR(tap_open(ifname, ifname_sz, &vnet_hdr,
+                                     vnet_hdr_required, mq_required, errp));
+        if (fd < 0) {
             return -1;
         }
+
+        if (script &&
+            script[0] != '\0' &&
+            strcmp(script, "no") != 0) {
+            launch_script(script, ifname, fd, &err);
+            if (err) {
+                error_propagate(errp, err);
+                close(fd);
+                return -1;
+            }
+        }
     }
 
     ret = net_tap_fd_init_common(netdev, peer, "tap", name, ifname,
@@ -757,6 +764,42 @@ static int net_tap_open_one(const Netdev *netdev,
 
 #define MAX_TAP_QUEUES 1024
 
+int tap_save(NetClientState *nc, QEMUFile *f)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+    qemu_file_put_fd(f, s->fd);
+    qemu_put_byte(f, s->using_vnet_hdr);
+    qemu_put_byte(f, s->has_ufo);
+    qemu_put_byte(f, s->has_uso);
+    qemu_put_byte(f, s->enabled);
+    qemu_put_be32(f, s->host_vnet_hdr_len);
+
+    return 0;
+}
+
+int tap_load(NetClientState *nc, QEMUFile *f)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+    s->fd = qemu_file_get_fd(f);
+    if (s->fd < 0) {
+        return -1;
+    }
+
+    s->using_vnet_hdr = qemu_get_byte(f);
+    s->has_ufo = qemu_get_byte(f);
+    s->has_uso = qemu_get_byte(f);
+    s->enabled = qemu_get_byte(f);
+    qemu_get_be32s(f, &s->host_vnet_hdr_len);
+
+    tap_read_poll(s, true);
+    s->exit.notify = tap_exit_notify;
+    qemu_add_exit_notifier(&s->exit);
+
+    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,
@@ -764,30 +807,40 @@ static int net_tap_fd_init_common(const Netdev *netdev, 
NetClientState *peer,
                                   const char *vhostfdname,
                                   int vnet_hdr, int fd, Error **errp)
 {
-    const NetdevTapOptions *tap;
+    const NetdevTapOptions *tap = NULL;
     int ret;
     NetClientState *nc;
     TAPState *s;
+    bool local_incoming = false;
+
+    if (netdev->type == NET_CLIENT_DRIVER_TAP) {
+        tap = &netdev->u.tap;
+        local_incoming = tap->local_incoming;
+    }
 
     nc = qemu_new_net_client(&net_tap_info, peer, model, name);
 
     s = DO_UPCAST(TAPState, nc, nc);
-
-    s->fd = fd;
-    s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
-    s->using_vnet_hdr = false;
-    s->has_ufo = tap_probe_has_ufo(s->fd);
-    s->has_uso = tap_probe_has_uso(s->fd);
-    s->enabled = true;
-    tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0);
-    /*
-     * Make sure host header length is set correctly in tap:
-     * it might have been modified by another instance of qemu.
-     */
-    if (vnet_hdr) {
-        tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
+    s->local_incoming = local_incoming;
+
+    if (!local_incoming) {
+        s->fd = fd;
+        s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
+        s->using_vnet_hdr = false;
+        s->has_ufo = tap_probe_has_ufo(s->fd);
+        s->has_uso = tap_probe_has_uso(s->fd);
+        s->enabled = true;
+        tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0);
+        /*
+         * Make sure host header length is set correctly in tap:
+         * it might have been modified by another instance of qemu.
+         */
+        if (vnet_hdr) {
+            tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
+        }
+        tap_read_poll(s, true);
     }
-    tap_read_poll(s, true);
+
     s->vhost_net = NULL;
     s->exit.notify = NULL;
 
@@ -799,9 +852,8 @@ static int net_tap_fd_init_common(const Netdev *netdev, 
NetClientState *peer,
     }
 
     assert(netdev->type == NET_CLIENT_DRIVER_TAP);
-    tap = &netdev->u.tap;
 
-    if (tap_set_sndbuf(s->fd, tap, errp) < 0) {
+    if (!local_incoming && tap_set_sndbuf(s->fd, tap, errp) < 0) {
         goto failed;
     }
 
@@ -822,9 +874,11 @@ static int net_tap_fd_init_common(const Netdev *netdev, 
NetClientState *peer,
         }
     }
 
-    ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
-    if (ret < 0) {
-        goto failed;
+    if (!local_incoming) {
+        ret = net_tap_setup_vhost(s, tap, vhostfdname, errp);
+        if (ret < 0) {
+            goto failed;
+        }
     }
 
     return 0;
@@ -1081,3 +1135,10 @@ int tap_disable(NetClientState *nc)
         return ret;
     }
 }
+
+bool tap_local_incoming(NetClientState *nc)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+    return s->local_incoming && runstate_check(RUN_STATE_INMIGRATE);
+}
-- 
2.48.1


Reply via email to