On Tue, Apr 26, 2016 at 05:31:07PM -0400, Ramu Ramamurthy wrote: > In some usecases such as VM migration or when VMs reuse IP addresses, > VMs become unreachable externally because > external switches/routers on localnet > have stale port-mac or arp caches. The problem resolves > after some time when the caches ageout which could be > minutes for port-mac bindings or hours for arp caches. > > To fix this, send some gratuitous ARPs when a logical > port on a localnet datapath gets added. Such gratuitous arps > help on a best-effort basis to update the mac-port bindings and arp-caches > of external switches and routers on the localnet. > > Reported-at: https://bugs.launchpad.net/networking-ovn/+bug/1545897 > Reported-by: Kyle Mestery <mest...@mestery.com> > Signed-off-by: Ramu Ramamurthy <ramu.ramamur...@us.ibm.com>
Thanks, I folded in the following style changes and applied these patches to master. diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 43dfc32..1611bcd 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -500,27 +500,27 @@ flush_put_arps(void) free(pa); } } - + /* - * Send gratuitous arp for vif on localnet. + * Send gratuitous ARP for vif on localnet. * - * When a new vif on localnet is added, gratuitous arps are sent announcing + * When a new vif on localnet is added, gratuitous ARPs are sent announcing * the port's mac,ip mapping. On localnet, such announcements are needed for * switches and routers on the broadcast segment to update their port-mac - * and arp tables. + * and ARP tables. */ struct garp_data { struct eth_addr ea; /* Ethernet address of port. */ ovs_be32 ipv4; /* Ipv4 address of port. */ long long int announce_time; /* Next announcement in ms. */ int backoff; /* Backoff for the next announcement. */ - int ofport; /* Ofport used to output this garp. */ + int ofport; /* ofport used to output this GARP. */ }; -/* Contains garps to be sent. */ +/* Contains GARPs to be sent. */ static struct shash send_garp_data; -/* Next garp announcement in ms. */ +/* Next GARP announcement in ms. */ static long long int send_garp_time; static void @@ -533,15 +533,15 @@ init_send_garps(void) static void destroy_send_garps(void) { - shash_destroy(&send_garp_data); + shash_destroy_free_data(&send_garp_data); } -/* Add or update a vif for which garps need to be announced. */ +/* Add or update a vif for which GARPs need to be announced. */ static void send_garp_update(const struct sbrec_port_binding *binding_rec, struct simap *localnet_ofports, struct hmap *local_datapaths) { - /* Find the localnet ofport to send this garp. */ + /* Find the localnet ofport to send this GARP. */ struct local_datapath *ld = get_local_datapath(local_datapaths, binding_rec->datapath->tunnel_key); @@ -549,14 +549,16 @@ send_garp_update(const struct sbrec_port_binding *binding_rec, return; } int ofport = simap_get(localnet_ofports, ld->localnet_port->logical_port); - /* Update garp if it exists. */ + + /* Update GARP if it exists. */ struct garp_data *garp = shash_find_data(&send_garp_data, binding_rec->logical_port); if (garp) { garp->ofport = ofport; return; } - /* Add garp for new vif. */ + + /* Add GARP for new vif. */ int i; for (i = 0; i < binding_rec->n_mac; i++) { struct lport_addresses laddrs; @@ -564,20 +566,21 @@ send_garp_update(const struct sbrec_port_binding *binding_rec, || !laddrs.n_ipv4_addrs) { continue; } + struct garp_data *garp = xmalloc(sizeof *garp); - garp->ofport = ofport; garp->ea = laddrs.ea; - garp->ipv4 = 0; garp->ipv4 = laddrs.ipv4_addrs[0].addr; - free(laddrs.ipv4_addrs); - garp->backoff = 1; garp->announce_time = time_msec() + 1000; + garp->backoff = 1; + garp->ofport = ofport; shash_add(&send_garp_data, binding_rec->logical_port, garp); + + free(laddrs.ipv4_addrs); break; } } -/* Remove a vif from garp announcements. */ +/* Remove a vif from GARP announcements. */ static void send_garp_delete(const char *lport) { @@ -591,6 +594,7 @@ send_garp(struct garp_data *garp, long long int current_time) if (current_time < garp->announce_time) { return garp->announce_time; } + /* Compose a GARP request packet. */ uint64_t packet_stub[128 / 8]; struct dp_packet packet; @@ -617,7 +621,8 @@ send_garp(struct garp_data *garp, long long int current_time) dp_packet_uninit(&packet); ofpbuf_uninit(&ofpacts); - /* Set the next announcement. Atmost 5 announcements are sent for a vif */ + /* Set the next announcement. At most 5 announcements are sent for a + * vif. */ if (garp->backoff < 16) { garp->backoff *= 2; garp->announce_time = current_time + garp->backoff * 1000; @@ -682,7 +687,8 @@ get_localnet_vifs(const struct ovsrec_bridge *br_int, } static void -send_garp_wait(void) { +send_garp_wait(void) +{ poll_timer_wait_until(send_garp_time); } @@ -699,24 +705,26 @@ send_garp_run(const struct ovsrec_bridge *br_int, const char *chassis_id, /* For deleted ports, remove from send_garp_data. */ struct shash_node *iter, *next; - SHASH_FOR_EACH_SAFE(iter, next, &send_garp_data) { + SHASH_FOR_EACH_SAFE (iter, next, &send_garp_data) { if (!sset_contains(&localnet_vifs, iter->name)) { send_garp_delete(iter->name); } } + /* Update send_garp_data. */ const char *iface_id; - SSET_FOR_EACH(iface_id, &localnet_vifs) { + SSET_FOR_EACH (iface_id, &localnet_vifs) { const struct sbrec_port_binding *pb = lport_lookup_by_name(lports, iface_id); if (pb) { send_garp_update(pb, &localnet_ofports, local_datapaths); } } - /* Send garps, and update the next announcement. */ + + /* Send GARPs, and update the next announcement. */ long long int current_time = time_msec(); send_garp_time = LLONG_MAX; - SHASH_FOR_EACH(iter, &send_garp_data) { + SHASH_FOR_EACH (iter, &send_garp_data) { long long int next_announce = send_garp(iter->data, current_time); if (send_garp_time > next_announce) { send_garp_time = next_announce; _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev