gre: Ensure skb properties are consistently set.
[openvswitch] / ofproto / in-band.c
index 82e51c726897cba787bbb834d9523fc8c3a4151b..9f4bc597144b9f0263604bac4e4875d2a0f44f5c 100644 (file)
  *      problems and amount of processing, we decided to hold off for
  *      the time-being.
  *
- *    - Multiple Controllers.  There is nothing intrinsic in the high-
- *      level design that prevents using multiple (known) controllers, 
- *      however, the current implementation's data structures assume
- *      only one.
- *
  *    - Differing Controllers for Switches.  All switches must know
  *      the L3 addresses for all the controllers that other switches 
  *      may use, since rules need to be set up to allow traffic related
@@ -257,12 +252,19 @@ refresh_remote(struct in_band *ib, struct in_band_remote *r)
     char *next_hop_dev;
     int retval;
 
+    memset(r->remote_mac, 0, sizeof r->remote_mac);
+
     /* Get remote IP address. */
     r->remote_ip = rconn_get_remote_ip(r->rconn);
+    if (!r->remote_ip) {
+        /* No remote IP address means that this rconn is probably either
+         * configured for a non-IP based protocol (e.g. "unix:") or
+         * misconfigured entirely.  No point in refreshing quickly. */
+        return 10;
+    }
 
     /* Find the next-hop IP address. */
     remote_inaddr.s_addr = r->remote_ip;
-    memset(r->remote_mac, 0, sizeof r->remote_mac);
     retval = netdev_get_next_hop(ib->local_netdev, &remote_inaddr,
                                  &next_hop_inaddr, &next_hop_dev);
     if (retval) {
@@ -300,10 +302,10 @@ refresh_remote(struct in_band *ib, struct in_band_remote *r)
                     IP_ARGS(&next_hop_inaddr.s_addr), strerror(retval));
     }
 
-    /* If we have an IP address but not a MAC address, then refresh quickly,
-     * since we probably will get a MAC address soon (via ARP).  Otherwise, we
-     * can afford to wait a little while. */
-    return r->remote_ip && eth_addr_is_zero(r->remote_mac) ? 1 : 10;
+    /* If we don't have a MAC address, then refresh quickly, since we probably
+     * will get a MAC address soon (via ARP).  Otherwise, we can afford to wait
+     * a little while. */
+    return eth_addr_is_zero(r->remote_mac) ? 1 : 10;
 }
 
 static bool
@@ -311,35 +313,25 @@ refresh_remotes(struct in_band *ib)
 {
     struct in_band_remote *r;
     bool any_changes;
-    int min_refresh;
 
     if (time_now() < ib->next_remote_refresh) {
         return false;
     }
 
     any_changes = false;
-    min_refresh = 10;
+    ib->next_remote_refresh = TIME_MAX;
     for (r = ib->remotes; r < &ib->remotes[ib->n_remotes]; r++) {
         uint8_t old_remote_mac[ETH_ADDR_LEN];
-        uint32_t old_remote_ip;
-        int refresh_interval;
+        time_t next_refresh;
 
-        /* Save old remote information. */
-        old_remote_ip = r->remote_ip;
+        /* Save old MAC. */
         memcpy(old_remote_mac, r->remote_mac, ETH_ADDR_LEN);
 
         /* Refresh remote information. */
-        refresh_interval = refresh_remote(ib, r);
-        min_refresh = MIN(min_refresh, refresh_interval);
+        next_refresh = refresh_remote(ib, r) + time_now();
+        ib->next_remote_refresh = MIN(ib->next_remote_refresh, next_refresh);
 
-        /* If anything changed, log the changes. */
-        if (old_remote_ip != r->remote_ip) {
-            any_changes = true;
-            if (r->remote_ip) {
-                VLOG_DBG("remote IP address changed from "IP_FMT" to "IP_FMT,
-                         IP_ARGS(&old_remote_ip), IP_ARGS(&r->remote_ip));
-            }
-        }
+        /* If the MAC changed, log the changes. */
         if (!eth_addr_equals(r->remote_mac, old_remote_mac)) {
             any_changes = true;
             if (!eth_addr_is_zero(r->remote_mac)
@@ -352,7 +344,6 @@ refresh_remotes(struct in_band *ib)
             }
         }
     }
-    ib->next_remote_refresh = time_now() + min_refresh;
 
     return any_changes;
 }
@@ -634,20 +625,6 @@ make_rules(struct in_band *ib,
     }
 }
 
-static void
-clear_rules(struct in_band *ib)
-{
-    memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac);
-
-    free(ib->remote_ips);
-    ib->remote_ips = NULL;
-    ib->n_remote_ips = 0;
-
-    free(ib->remote_macs);
-    ib->remote_macs = NULL;
-    ib->n_remote_macs = 0;
-}
-
 static void
 drop_rule(struct in_band *ib, const struct in_band_rule *rule)
 {
@@ -655,11 +632,25 @@ drop_rule(struct in_band *ib, const struct in_band_rule *rule)
                         rule->wildcards, rule->priority);
 }
 
+/* Drops from the flow table all of the flows set up by 'ib', then clears out
+ * the information about the installed flows so that they can be filled in
+ * again if necessary. */
 static void
 drop_rules(struct in_band *ib)
 {
+    /* Drop rules. */
     make_rules(ib, drop_rule);
-    clear_rules(ib);
+
+    /* Clear out state. */
+    memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac);
+
+    free(ib->remote_ips);
+    ib->remote_ips = NULL;
+    ib->n_remote_ips = 0;
+
+    free(ib->remote_macs);
+    ib->remote_macs = NULL;
+    ib->n_remote_macs = 0;
 }
 
 static void
@@ -675,6 +666,7 @@ add_rule(struct in_band *ib, const struct in_band_rule *rule)
                      rule->priority, &action, 1, 0);
 }
 
+/* Inserts flows into the flow table for the current state of 'ib'. */
 static void
 add_rules(struct in_band *ib)
 {
@@ -697,8 +689,11 @@ void
 in_band_run(struct in_band *ib)
 {
     struct in_band_remote *r;
+    bool local_change, remote_change;
 
-    if (!refresh_local(ib) && !refresh_remotes(ib)) {
+    local_change = refresh_local(ib);
+    remote_change = refresh_remotes(ib);
+    if (!local_change && !remote_change) {
         /* Nothing changed, nothing to do. */
         return;
     }
@@ -745,10 +740,12 @@ in_band_wait(struct in_band *in_band)
     }
 }
 
+/* ofproto has flushed all flows from the flow table and it is calling us back
+ * to allow us to reinstall the ones that are important to us. */
 void
 in_band_flushed(struct in_band *in_band)
 {
-    clear_rules(in_band);
+    add_rules(in_band);
 }
 
 int
@@ -800,33 +797,48 @@ in_band_destroy(struct in_band *ib)
     }
 }
 
+static bool
+any_rconns_changed(const struct in_band *ib, struct rconn **remotes, size_t n)
+{
+    size_t i;
+
+    if (n != ib->n_remotes) {
+        return true;
+    }
+
+    for (i = 0; i < n; i++) {
+        if (ib->remotes[i].rconn != remotes[i]) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void
 in_band_set_remotes(struct in_band *ib, struct rconn **remotes, size_t n)
 {
     size_t i;
 
     /* Optimize the case where the rconns are the same as last time. */
-    if (n == ib->n_remotes) {
-        for (i = 0; i < n; i++) {
-            if (ib->remotes[i].rconn != remotes[i]) {
-                goto different;
-            }
-        }
+    if (!any_rconns_changed(ib, remotes, n)) {
         return;
-
-    different:;
     }
 
+    /* Clear old remotes. */
     for (i = 0; i < ib->n_remotes; i++) {
         /* We don't own the rconn. */
         netdev_close(ib->remotes[i].remote_netdev);
     }
     free(ib->remotes);
 
-    ib->next_remote_refresh = TIME_MIN;
-    ib->remotes = n ? xzalloc(n * sizeof *ib->remotes) : 0;
+    /* Set up new remotes. */
+    ib->remotes = n ? xzalloc(n * sizeof *ib->remotes) : NULL;
     ib->n_remotes = n;
     for (i = 0; i < n; i++) {
         ib->remotes[i].rconn = remotes[i];
     }
+
+    /* Force refresh in next call to in_band_run(). */
+    ib->next_remote_refresh = TIME_MIN;
 }