From: Ben Pfaff Date: Thu, 27 May 2010 17:06:36 +0000 (-0700) Subject: vswitchd: Treat gratuitous ARP requests like gratuitous ARP replies. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d0ae1387c968859b390dba9768ce44ac788405b;p=openvswitch vswitchd: Treat gratuitous ARP requests like gratuitous ARP replies. vswitchd has long used a gratuitous ARP reply as an indication that a VM has migrated, because traditional xen.org Linux DomUs send such packets out when they complete migration. Relatively recently, however, we realized that upstream Linux does not do this. Ian Campbell tracked this down to two separate issues: 1. A bug prevented gratuitous ARPs from being sent. 2. When this was fixed, the gratuitous ARPs that were sent were requests, not replies, although kernel documentation sent that replies were to be sent. Ian submitted patches to fix both bugs. #1 is in process of revision for acceptance. #2 was rejected: according to Dave Miller, the documentation is wrong, not the implementation, because ARP replies would unnecessarily fill up the ARP tables of devices on the network. OVS has not until now treated gratuitous ARP requests specially, only replies. Now that Linux will be using ARP requests to indicate migration, OVS should also treat them as such.! This commit does so. See http://marc.info/?l=linux-netdev&m=127367215620212&w=2 for Ian's original patch and http://marc.info/?l=linux-netdev&m=127468303701361&w=2 for Dave Miller's response. CC: Ian Campbell NIC-74. --- diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 8314c539..61813bb4 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2269,12 +2269,17 @@ update_learning_table(struct bridge *br, const flow_t *flow, int vlan, } } +/* A VM broadcasts a gratuitous ARP to indicate that it has resumed after + * migration. Older Citrix-patched Linux DomU used gratuitous ARP replies to + * indicate this; newer upstream kernels use gratuitous ARP requests. */ static bool -is_bcast_arp_reply(const flow_t *flow) +is_gratuitous_arp(const flow_t *flow) { return (flow->dl_type == htons(ETH_TYPE_ARP) - && flow->nw_proto == ARP_OP_REPLY - && eth_addr_is_broadcast(flow->dl_dst)); + && eth_addr_is_broadcast(flow->dl_dst) + && (flow->nw_proto == ARP_OP_REPLY + || (flow->nw_proto == ARP_OP_REQUEST + && flow->nw_src == flow->nw_dst))); } /* Determines whether packets in 'flow' within 'br' should be forwarded or @@ -2366,11 +2371,11 @@ is_admissible(struct bridge *br, const flow_t *flow, bool have_packet, /* Drop all packets for which we have learned a different input * port, because we probably sent the packet on one slave and got - * it back on the other. Broadcast ARP replies are an exception + * it back on the other. Gratuitous ARP packets are an exception * to this rule: the host has moved to another switch. */ src_idx = mac_learning_lookup(br->ml, flow->dl_src, vlan); if (src_idx != -1 && src_idx != in_port->port_idx && - !is_bcast_arp_reply(flow)) { + !is_gratuitous_arp(flow)) { return false; } }