From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Mya8y-0005tm-7v for qemu-devel@nongnu.org; Thu, 15 Oct 2009 19:54:04 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Mya8t-0005jU-FA for qemu-devel@nongnu.org; Thu, 15 Oct 2009 19:54:03 -0400 Received: from [199.232.76.173] (port=33421 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mya8t-0005jA-5u for qemu-devel@nongnu.org; Thu, 15 Oct 2009 19:53:59 -0400 Received: from phong.sigbus.net ([65.49.35.42]:54796) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Mya8s-0002km-JF for qemu-devel@nongnu.org; Thu, 15 Oct 2009 19:53:58 -0400 Received: from localhost (unknown [71.198.47.97]) by phong.sigbus.net (Postfix) with ESMTPSA id 1728095C0C2 for ; Thu, 15 Oct 2009 16:53:56 -0700 (PDT) From: Nolan Content-Type: text/plain Content-Transfer-Encoding: 7bit Date: Thu, 15 Oct 2009 16:53:55 -0700 Message-Id: <1255650835.4550.14849.camel@voxel> Mime-Version: 1.0 Subject: [Qemu-devel] [PATCH] Send a RARP packet after migration. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "qemu-devel@nongnu.org" Currently, after a migration qemu sends a broadcast packet to update switches' MAC->port mappings. Unfortunately, it picks a random (constant) ethertype and crosses its fingers that no one else is using it. This patch causes it to send a RARP packet instead. RARP was chosen for 2 reasons. One, it is always harmless, and will continue to be so even as new ethertypes are allocated. Two, it is what VMware ESX sends, so people who write filtering rules for switches already know about it. I also changed the code to send SELF_ANNOUNCE_ROUNDS packets, instead of SELF_ANNOUNCE_ROUNDS + 1, and added a simple backoff scheme. Signed-off-by: Nolan Leake sigbus.net> diff --git a/savevm.c b/savevm.c index 181c088..60bd199 100644 --- a/savevm.c +++ b/savevm.c @@ -95,25 +95,37 @@ static BlockDriverState *bs_snapshots; #define SELF_ANNOUNCE_ROUNDS 5 -#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number */ -//#define ETH_P_EXPERIMENTAL 0x0012 /* make it the size of the packet */ -#define EXPERIMENTAL_MAGIC 0xf1f23f4f -static int announce_self_create(uint8_t *buf, +#ifndef ETH_P_RARP +#define ETH_P_RARP 0x0835 +#endif +#define ARP_HTYPE_ETH 0x0001 +#define ARP_PTYPE_IP 0x0800 +#define ARP_OP_REQUEST_REV 0x3 + +static int announce_self_create(uint8_t *buf, uint8_t *mac_addr) { - uint32_t magic = EXPERIMENTAL_MAGIC; - uint16_t proto = htons(ETH_P_EXPERIMENTAL); - - /* FIXME: should we send a different packet (arp/rarp/ping)? */ - - memset(buf, 0, 64); - memset(buf, 0xff, 6); /* h_dst */ - memcpy(buf + 6, mac_addr, 6); /* h_src */ - memcpy(buf + 12, &proto, 2); /* h_proto */ - memcpy(buf + 14, &magic, 4); /* magic */ - - return 64; /* len */ + /* Ethernet header. */ + memset(buf, 0xff, 6); /* destination MAC addr */ + memcpy(buf + 6, mac_addr, 6); /* source MAC addr */ + *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */ + + /* RARP header. */ + *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */ + *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */ + *(buf + 18) = 6; /* hardware addr length (ethernet) */ + *(buf + 19) = 4; /* protocol addr length (IPv4) */ + *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */ + memcpy(buf + 22, mac_addr, 6); /* source hw addr */ + memset(buf + 28, 0x00, 4); /* source protocol addr */ + memcpy(buf + 32, mac_addr, 6); /* target hw addr */ + memset(buf + 38, 0x00, 4); /* target protocol addr */ + + /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */ + memset(buf + 42, 0x00, 18); + + return 60; /* len (FCS will be added by hardware) */ } static void qemu_announce_self_once(void *opaque) @@ -121,7 +133,7 @@ static void qemu_announce_self_once(void *opaque) int i, len; VLANState *vlan; VLANClientState *vc; - uint8_t buf[256]; + uint8_t buf[60]; static int count = SELF_ANNOUNCE_ROUNDS; QEMUTimer *timer = *(QEMUTimer **)opaque; @@ -134,8 +146,10 @@ static void qemu_announce_self_once(void *opaque) vc->receive(vc, buf, len); } } - if (count--) { - qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100); + if (--count) { + /* delay 50ms, 150ms, 250ms, ... */ + qemu_mod_timer(timer, qemu_get_clock(rt_clock) + + 50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100); } else { qemu_del_timer(timer); qemu_free_timer(timer);