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 <[email protected]>
> Signed-off-by: Ramu Ramamurthy <[email protected]>
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev