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

Reply via email to