Hello,

We, kvm developers at Qumranet, have been developing a Live Migration solution
    for qemu (and kvm) too (http://kvm.sourceforge.net/migration.html).
We are working with qemu-0.8.2 and are planning to upgrade to the current 
    qemu CVS.
Anthony Liguori sent patches implementing Live Migration 
    (http://lists.gnu.org/archive/html/qemu-devel/2007-01/msg00245.html).
Some differences are:
  - Anthony's solution uses ssh our solution uses TCP sockets.
  - Anthony's interface is a single qemu-monitor command accepting a uri,
        our interface is a single qemu command accepting a few subcommands.
  - Anthony's solution supports migration start without any preparations,
        our solution requires starting a guest (qemu) on the destination host, 
and
        establish connection before starting the migration.

Naturally, Anthony's solution can be easily enhanced to support most of our 
interface.

Since there is no need for two different migration solutions, we'd like to
    cooperate with Anthony (and with you) and contribute some patches which
    are additions to his solution.
Those patches would be based on Anthony's solution (and have to be applied 
after 
    his patches are applied).

The first patch (attached) is an arp-like packet sent (broadcast) when a 
    migration successfully completes.
The purpose of this packet is to inform network switches that the guest moved.
Although the most known unsolicited packet is the famous "gratuitous arp",  
    we are not sending an arp packet since we do not know the guest's ip 
address,
    and we do not want to receive replies.
Instead we use an ethernet "experimental" packet.
The packet is sent only through tap interfaces.
Our implementation currently supports only linux hosts (adding support for 
    other operating systems is probably/hopefully as easy as changing the 
include
    preprocessor directive).

Regards,
    Uri Lublin.
--- qemu/vl.c	2007-01-23 10:37:50.000000000 +0200
+++ qemu-new/vl.c	2007-01-23 10:26:49.000000000 +0200
@@ -51,6 +51,7 @@
 #ifndef __sun__
 #include <linux/if.h>
 #include <linux/if_tun.h>
+#include <linux/if_ether.h>
 #include <pty.h>
 #include <malloc.h>
 #include <linux/rtc.h>
@@ -3940,6 +3941,50 @@
     }
 }
 
+#if defined(__linux__)
+#define SELF_ANNOUNCE_ROUNDS 5
+#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number in experimental range */
+#define EXPERIMENTAL_MAGIC 0xf1f23f4f
+int announce_self_create(unsigned char *buf, 
+                         unsigned char mac_addr[ETH_ALEN])
+{
+    struct ethhdr *eh = (struct ethhdr*)buf;
+    uint32_t *magic   = (uint32_t*)(eh+1);
+    unsigned char *p  = (unsigned char*)(magic + 1);
+
+    /* ethernet header */
+    memset(eh->h_dest,   0xff,     ETH_ALEN);
+    memcpy(eh->h_source, mac_addr, ETH_ALEN);
+    eh->h_proto = htons(ETH_P_EXPERIMENTAL);
+
+    /* magic data */
+    *magic = EXPERIMENTAL_MAGIC;
+
+    return p - buf; /* sizeof(*eh) + sizeof(*magic) */
+}
+
+void qemu_tap_announce_self(void)
+{
+    int i, j, len;
+    VLANState *vlan;
+    VLANClientState *vc;
+    uint8_t buf[256];
+
+    for (i=0; i<nb_nics; i++) {     /* for all nics */
+        len = announce_self_create(buf, nd_table[i].macaddr);
+        vlan = nd_table[i].vlan;
+        for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+            if (vc->fd_read == tap_receive) { /* send only if tap */
+                for (j=0; j<SELF_ANNOUNCE_ROUNDS ; j++) {
+                    vc->fd_read(vc->opaque, buf, len);
+                }
+            }
+        } /* for vc -- look for tap_receive */
+    } /* for i -- all nics */
+}
+#else
+void qemu_tap_announce_self(void) {}
+#endif
 /***********************************************************/
 /* USB devices */
 
@@ -7480,6 +7525,9 @@
 	    printf("Migration failed\n");
 	    exit(1);
 	}
+        else {
+            qemu_tap_announce_self();
+        }
     }
 
     {

Reply via email to