]> xenbits.xensource.com Git - qemu-xen-3.3-testing.git/commitdiff
send arp like packets for hvm live migration
authorIan Jackson <ian.jackson@eu.citrix.com>
Thu, 12 Feb 2009 11:18:40 +0000 (11:18 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Thu, 12 Feb 2009 11:18:40 +0000 (11:18 +0000)
When two servers connect different switch/hub and do live migration
between them, network connect will no reponse about 30 seconds,
it caused by migration finished, target server do not broadcast
guest os's network info.

In pvm, when backend changed, netfront driver will send fake arp
to network, so, hvm also need this.

Uri Lublin [wrote] the patch for it:
http://www.mail-archive.com/qemu-devel@nongnu.org/msg09306.html

I [Joe] add send arp like packets at tap_receive(), and it looked like
work fine.

Signed-off-by: Joe Jin <joe.jin@oracle.com>
Tested-by: Deepak Patel <deepak.patel@oracle.com>
CC: Keir Fraser <keir.fraser@eu.citrix.com>
CC: Kurt C. Hackel <kurt.hackel@oracle.com>
(cherry picked from commit 73b0037b2278812fcadadec9d8eac656f1716074)
Conflicts:
vl.c

vl.c

diff --git a/vl.c b/vl.c
index 57b88f31cb6b39751c9b823fcde5cc3cd7ec0cd7..4d620064d778c5c2c26d283df7a6cfc6e10cdc23 100644 (file)
--- a/vl.c
+++ b/vl.c
 int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
+#if defined(__linux__)
+#include <linux/if_ether.h>
+#endif
+
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
 #endif
@@ -4056,10 +4060,22 @@ typedef struct TAPState {
     char script_arg[1024];
 } TAPState;
 
+static void qemu_tap_announce_self(void);
+
 static void tap_receive(void *opaque, const uint8_t *buf, int size)
 {
+    static int arp_state = 0;
     TAPState *s = opaque;
     int ret;
+
+    if (!arp_state ) {
+        arp_state = 1;
+        /* send arp like package to vlan when enter is the first.
+           for xen migration.
+        */
+        qemu_tap_announce_self();
+    }
+
     for(;;) {
         ret = write(s->fd, buf, size); /* No error handling ?! */
         if (ret < 0 && (errno == EINTR || errno == EAGAIN)) {
@@ -4337,6 +4353,56 @@ static int launch_script(const char *setup_script, const char *ifname,
     return 0;
 }
 
+#if defined(__linux__)
+#define SELF_ANNOUNCE_ROUNDS 5
+#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number in experimental range */
+#define EXPERIMENTAL_MAGIC 0xf1f23f4f
+static 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) */
+}
+
+static 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 */
+        fprintf(logfile, "Send fake arp for domain %d, MAC: [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+                          domid, nd_table[i].macaddr[0], 
+                          nd_table[i].macaddr[1], nd_table[i].macaddr[2], 
+                          nd_table[i].macaddr[3], nd_table[i].macaddr[4], 
+                          nd_table[i].macaddr[5]);
+        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
+static void qemu_tap_announce_self(void) {}
+#endif
+
 static int net_tap_init(VLANState *vlan, const char *ifname1,
                         const char *setup_script, const char *down_script,
                         const char *script_arg)