ovs-brcompatd: Delete write-only variable.
[openvswitch] / vswitchd / bridge.c
index b57860f94485e3ebb1869da6029f41f46f2a7bfc..9660aef9021f5f617d847465e7090e258d1f01d5 100644 (file)
@@ -238,6 +238,11 @@ static struct ovsdb_idl *idl;
 #define STATS_INTERVAL (5 * 1000) /* In milliseconds. */
 static long long int stats_timer = LLONG_MIN;
 
+/* Stores the time after which CFM statistics may be written to the database.
+ * Only updated when changes to the database require rate limiting. */
+#define CFM_LIMIT_INTERVAL (1 * 1000) /* In milliseconds. */
+static long long int cfm_limiter = LLONG_MIN;
+
 static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
 static void bridge_destroy(struct bridge *);
 static struct bridge *bridge_lookup(const char *name);
@@ -262,6 +267,7 @@ static uint64_t bridge_pick_datapath_id(struct bridge *,
 static uint64_t dpid_from_hash(const void *, size_t nbytes);
 
 static unixctl_cb_func bridge_unixctl_fdb_show;
+static unixctl_cb_func cfm_unixctl_show;
 static unixctl_cb_func qos_unixctl_show;
 
 static void bond_init(void);
@@ -302,7 +308,7 @@ static void iface_set_mac(struct iface *);
 static void iface_set_ofport(const struct ovsrec_interface *, int64_t ofport);
 static void iface_update_qos(struct iface *, const struct ovsrec_qos *);
 static void iface_update_cfm(struct iface *);
-static void iface_refresh_cfm_stats(struct iface *iface);
+static bool iface_refresh_cfm_stats(struct iface *iface);
 static void iface_update_carrier(struct iface *);
 static bool iface_get_carrier(const struct iface *);
 
@@ -340,6 +346,7 @@ bridge_init(const char *remote)
 
     /* Register unixctl commands. */
     unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
+    unixctl_command_register("cfm/show", cfm_unixctl_show, NULL);
     unixctl_command_register("qos/show", qos_unixctl_show, NULL);
     unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
                              NULL);
@@ -1196,18 +1203,21 @@ iface_refresh_status(struct iface *iface)
     }
 }
 
-static void
+/* Writes 'iface''s CFM statistics to the database.  Returns true if anything
+ * changed, false otherwise. */
+static bool
 iface_refresh_cfm_stats(struct iface *iface)
 {
     const struct ovsrec_monitor *mon;
     const struct cfm *cfm;
+    bool changed = false;
     size_t i;
 
     mon = iface->cfg->monitor;
     cfm = ofproto_iface_get_cfm(iface->port->bridge->ofproto, iface->dp_ifidx);
 
     if (!cfm || !mon) {
-        return;
+        return false;
     }
 
     for (i = 0; i < mon->n_remote_mps; i++) {
@@ -1217,59 +1227,18 @@ iface_refresh_cfm_stats(struct iface *iface)
         mp = mon->remote_mps[i];
         rmp = cfm_get_remote_mp(cfm, mp->mpid);
 
-        ovsrec_maintenance_point_set_fault(mp, &rmp->fault, 1);
-    }
-
-    if (hmap_is_empty(&cfm->x_remote_mps)) {
-        ovsrec_monitor_set_unexpected_remote_mpids(mon, NULL, 0);
-    } else {
-        size_t length;
-        struct remote_mp *rmp;
-        int64_t *x_remote_mps;
-
-        length = hmap_count(&cfm->x_remote_mps);
-        x_remote_mps = xzalloc(length * sizeof *x_remote_mps);
-
-        i = 0;
-        HMAP_FOR_EACH (rmp, node, &cfm->x_remote_mps) {
-            x_remote_mps[i++] = rmp->mpid;
+        if (mp->n_fault != 1 || mp->fault[0] != rmp->fault) {
+            ovsrec_maintenance_point_set_fault(mp, &rmp->fault, 1);
+            changed = true;
         }
-
-        ovsrec_monitor_set_unexpected_remote_mpids(mon, x_remote_mps, length);
-        free(x_remote_mps);
     }
 
-    if (hmap_is_empty(&cfm->x_remote_maids)) {
-        ovsrec_monitor_set_unexpected_remote_maids(mon, NULL, 0);
-    } else {
-        size_t length;
-        char **x_remote_maids;
-        struct remote_maid *rmaid;
-
-        length = hmap_count(&cfm->x_remote_maids);
-        x_remote_maids = xzalloc(length * sizeof *x_remote_maids);
-
-        i = 0;
-        HMAP_FOR_EACH (rmaid, node, &cfm->x_remote_maids) {
-            size_t j;
-
-            x_remote_maids[i] = xzalloc(CCM_MAID_LEN * 2 + 1);
-
-            for (j = 0; j < CCM_MAID_LEN; j++) {
-                 snprintf(&x_remote_maids[i][j * 2], 3, "%02hhx",
-                          rmaid->maid[j]);
-            }
-            i++;
-        }
-        ovsrec_monitor_set_unexpected_remote_maids(mon, x_remote_maids, length);
-
-        for (i = 0; i < length; i++) {
-            free(x_remote_maids[i]);
-        }
-        free(x_remote_maids);
+    if (mon->n_fault != 1 || mon->fault[0] != cfm->fault) {
+        ovsrec_monitor_set_fault(mon, &cfm->fault, 1);
+        changed = true;
     }
 
-    ovsrec_monitor_set_fault(mon, &cfm->fault, 1);
+    return changed;
 }
 
 static void
@@ -1447,7 +1416,6 @@ bridge_run(void)
 
                     LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
                         iface_refresh_stats(iface);
-                        iface_refresh_cfm_stats(iface);
                         iface_refresh_status(iface);
                     }
                 }
@@ -1460,6 +1428,31 @@ bridge_run(void)
 
         stats_timer = time_msec() + STATS_INTERVAL;
     }
+
+    if (time_msec() >= cfm_limiter) {
+        struct ovsdb_idl_txn *txn;
+        bool changed = false;
+
+        txn = ovsdb_idl_txn_create(idl);
+        LIST_FOR_EACH (br, node, &all_bridges) {
+            struct port *port;
+
+            HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+                struct iface *iface;
+
+                LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                    changed = iface_refresh_cfm_stats(iface) || changed;
+                }
+            }
+        }
+
+        if (changed) {
+            cfm_limiter = time_msec() + CFM_LIMIT_INTERVAL;
+        }
+
+        ovsdb_idl_txn_commit(txn);
+        ovsdb_idl_txn_destroy(txn);
+    }
 }
 
 void
@@ -1483,6 +1476,10 @@ bridge_wait(void)
     }
     ovsdb_idl_wait(idl);
     poll_timer_wait_until(stats_timer);
+
+    if (cfm_limiter > time_msec()) {
+        poll_timer_wait_until(cfm_limiter);
+    }
 }
 
 /* Forces 'br' to revalidate all of its flows.  This is appropriate when 'br''s
@@ -1520,6 +1517,33 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
     ds_destroy(&ds);
 }
 \f
+/* CFM unixctl user interface functions. */
+static void
+cfm_unixctl_show(struct unixctl_conn *conn,
+                 const char *args, void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    struct iface *iface;
+    const struct cfm *cfm;
+
+    iface = iface_find(args);
+    if (!iface) {
+        unixctl_command_reply(conn, 501, "no such interface");
+        return;
+    }
+
+    cfm = ofproto_iface_get_cfm(iface->port->bridge->ofproto, iface->dp_ifidx);
+
+    if (!cfm) {
+        unixctl_command_reply(conn, 501, "CFM not enabled");
+        return;
+    }
+
+    cfm_dump_ds(cfm, &ds);
+    unixctl_command_reply(conn, 200, ds_cstr(&ds));
+    ds_destroy(&ds);
+}
+\f
 /* QoS unixctl user interface functions. */
 
 struct qos_unixctl_show_cbdata {