From 62c5c3e2036486765083a68c6d1f06f3c897c917 Mon Sep 17 00:00:00 2001 From: Alex Wang Date: Thu, 18 Sep 2014 14:10:24 -0700 Subject: [PATCH] bridge: Rate limit the statistics update. When ovs is running with large topology (e.g. large number of interfaces), the stats update to ovsdb becomes huge and normally requires multiple run of ovsdb jsonrpc message processing loop to consume. To prevent the periodic stats update from backlogging in the jsonrpc sending queue, this commit adds rate limiting logic which only allows new update if the previous one is done. Signed-off-by: Alex Wang Acked-by: Ben Pfaff Acked-by: Flavio Leitner --- vswitchd/bridge.c | 54 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 5dcd3bae9..656182f13 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -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) { -- 2.20.1