bridge: Rate limit the statistics update.
[cascardo/ovs.git] / vswitchd / bridge.c
index 5dcd3ba..656182f 100644 (file)
@@ -191,6 +191,10 @@ static bool force_status_commit = true;
 static int stats_timer_interval;
 static long long int stats_timer = LLONG_MIN;
 
+/* Current stats database transaction, NULL if there is no ongoing
+ * transaction. */
+static struct ovsdb_idl_txn *stats_txn;
+
 /* In some datapaths, creating and destroying OpenFlow ports can be extremely
  * expensive.  This can cause bridge_reconfigure() to take a long time during
  * which no other work can be done.  To deal with this problem, we limit port
@@ -2386,35 +2390,39 @@ bridge_run(void)
 
     /* Refresh interface and mirror stats if necessary. */
     if (time_msec() >= stats_timer) {
-        if (cfg) {
-            struct ovsdb_idl_txn *txn;
-
-            txn = ovsdb_idl_txn_create(idl);
-            HMAP_FOR_EACH (br, node, &all_bridges) {
-                struct port *port;
-                struct mirror *m;
-
-                HMAP_FOR_EACH (port, hmap_node, &br->ports) {
-                    struct iface *iface;
+        enum ovsdb_idl_txn_status status;
 
-                    LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
-                        iface_refresh_stats(iface);
+        /* Rate limit the update.  Do not start a new update if the
+         * previous one is not done. */
+        if (!stats_txn) {
+            if (cfg) {
+                stats_txn = ovsdb_idl_txn_create(idl);
+                HMAP_FOR_EACH (br, node, &all_bridges) {
+                    struct port *port;
+                    struct mirror *m;
+
+                    HMAP_FOR_EACH (port, hmap_node, &br->ports) {
+                        struct iface *iface;
+
+                        LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
+                            iface_refresh_stats(iface);
+                        }
+                        port_refresh_stp_stats(port);
+                    }
+                    HMAP_FOR_EACH (m, hmap_node, &br->mirrors) {
+                        mirror_refresh_stats(m);
                     }
-
-                    port_refresh_stp_stats(port);
-                }
-
-                HMAP_FOR_EACH (m, hmap_node, &br->mirrors) {
-                    mirror_refresh_stats(m);
                 }
-
+                refresh_controller_status();
             }
-            refresh_controller_status();
-            ovsdb_idl_txn_commit(txn);
-            ovsdb_idl_txn_destroy(txn); /* XXX */
         }
 
-        stats_timer = time_msec() + stats_timer_interval;
+        status = ovsdb_idl_txn_commit(stats_txn);
+        if (status != TXN_INCOMPLETE) {
+            stats_timer = time_msec() + stats_timer_interval;
+            ovsdb_idl_txn_destroy(stats_txn);
+            stats_txn = NULL;
+        }
     }
 
     if (!status_txn) {