2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +00:00

bridge: Refactor the stats and status update.

This commit refactors the stats and status update in bridge_run()
by moving the corresponding code to separate functions.  This
makes the code more organized.

Signed-off-by: Alex Wang <alexw@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Alex Wang
2014-09-18 14:35:30 -07:00
parent e03bce9c95
commit 9c537baf61

View File

@@ -192,10 +192,6 @@ static bool status_txn_try_again;
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
@@ -2597,6 +2593,133 @@ refresh_controller_status(void)
ofproto_free_ofproto_controller_info(&info);
}
/* Update interface and mirror statistics if necessary. */
static void
run_stats_update(void)
{
static struct ovsdb_idl_txn *stats_txn;
const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl);
int stats_interval;
if (!cfg) {
return;
}
/* Statistics update interval should always be greater than or equal to
* 5000 ms. */
stats_interval = MAX(smap_get_int(&cfg->other_config,
"stats-update-interval",
5000), 5000);
if (stats_timer_interval != stats_interval) {
stats_timer_interval = stats_interval;
stats_timer = LLONG_MIN;
}
if (time_msec() >= stats_timer) {
enum ovsdb_idl_txn_status status;
/* Rate limit the update. Do not start a new update if the
* previous one is not done. */
if (!stats_txn) {
struct bridge *br;
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);
}
}
refresh_controller_status();
}
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;
}
}
}
/* Update bridge/port/interface status if necessary. */
static void
run_status_update(void)
{
uint64_t seq;
/* Check the need to update status. */
seq = seq_read(connectivity_seq_get());
if (seq != connectivity_seqno || status_txn_try_again) {
enum ovsdb_idl_txn_status status;
/* Rate limit the update. Do not start a new update if the
* previous one is not done. */
if (!status_txn) {
struct bridge *br;
connectivity_seqno = seq;
status_txn = ovsdb_idl_txn_create(idl);
HMAP_FOR_EACH (br, node, &all_bridges) {
struct port *port;
br_refresh_stp_status(br);
br_refresh_rstp_status(br);
HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
port_refresh_stp_status(port);
port_refresh_rstp_status(port);
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
iface_refresh_netdev_status(iface);
iface_refresh_ofproto_status(iface);
}
}
}
}
status = ovsdb_idl_txn_commit(status_txn);
if (status != TXN_INCOMPLETE) {
ovsdb_idl_txn_destroy(status_txn);
status_txn = NULL;
/* Sets the 'status_txn_try_again' if the transaction fails. */
if (status == TXN_SUCCESS || status == TXN_UNCHANGED) {
status_txn_try_again = false;
} else {
status_txn_try_again = true;
}
}
}
}
static void
status_update_wait(void)
{
/* If the 'status_txn' is non-null (transaction incomplete), waits for the
* transaction to complete. If the status update to database needs to be
* run again (transaction fails), registers a timeout in
* 'STATUS_CHECK_AGAIN_MSEC'. Otherwise, waits on the global connectivity
* sequence number. */
if (status_txn) {
ovsdb_idl_txn_wait(status_txn);
} else if (status_txn_try_again) {
poll_timer_wait_until(time_msec() + STATUS_CHECK_AGAIN_MSEC);
} else {
seq_wait(connectivity_seq_get(), connectivity_seqno);
}
}
static void
bridge_run__(void)
{
@@ -2625,8 +2748,6 @@ bridge_run(void)
const struct ovsrec_open_vswitch *cfg;
bool vlan_splinters_changed;
struct bridge *br;
int stats_interval;
ovsrec_open_vswitch_init(&null_cfg);
@@ -2685,6 +2806,8 @@ bridge_run(void)
* usage has changed. */
vlan_splinters_changed = false;
if (vlan_splinters_enabled_anywhere) {
struct bridge *br;
HMAP_FOR_EACH (br, node, &all_bridges) {
if (ofproto_has_vlan_usage_changed(br->ofproto)) {
vlan_splinters_changed = true;
@@ -2735,103 +2858,8 @@ bridge_run(void)
}
}
/* Statistics update interval should always be greater than or equal to
* 5000 ms. */
if (cfg) {
stats_interval = MAX(smap_get_int(&cfg->other_config,
"stats-update-interval",
5000), 5000);
} else {
stats_interval = 5000;
}
if (stats_timer_interval != stats_interval) {
stats_timer_interval = stats_interval;
stats_timer = LLONG_MIN;
}
/* Refresh interface and mirror stats if necessary. */
if (time_msec() >= stats_timer) {
enum ovsdb_idl_txn_status status;
/* 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);
}
}
refresh_controller_status();
}
}
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) {
uint64_t seq;
/* Check the need to update status. */
seq = seq_read(connectivity_seq_get());
if (seq != connectivity_seqno || status_txn_try_again) {
connectivity_seqno = seq;
status_txn = ovsdb_idl_txn_create(idl);
HMAP_FOR_EACH (br, node, &all_bridges) {
struct port *port;
br_refresh_stp_status(br);
br_refresh_rstp_status(br);
HMAP_FOR_EACH (port, hmap_node, &br->ports) {
struct iface *iface;
port_refresh_stp_status(port);
port_refresh_rstp_status(port);
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
iface_refresh_netdev_status(iface);
iface_refresh_ofproto_status(iface);
}
}
}
}
}
if (status_txn) {
enum ovsdb_idl_txn_status status;
status = ovsdb_idl_txn_commit(status_txn);
/* Do not destroy "status_txn" if the transaction is
* "TXN_INCOMPLETE". */
if (status != TXN_INCOMPLETE) {
ovsdb_idl_txn_destroy(status_txn);
status_txn = NULL;
/* Sets the 'status_txn_try_again' if the transaction fails. */
if (status == TXN_SUCCESS || status == TXN_UNCHANGED) {
status_txn_try_again = false;
} else {
status_txn_try_again = true;
}
}
}
run_stats_update();
run_status_update();
run_system_stats();
}
@@ -2863,19 +2891,7 @@ bridge_wait(void)
poll_timer_wait_until(stats_timer);
}
/* If the 'status_txn' is non-null (transaction incomplete), waits for the
* transaction to complete. If the status update to database needs to be
* run again (transaction fails), registers a timeout in
* 'STATUS_CHECK_AGAIN_MSEC'. Otherwise, waits on the global connectivity
* sequence number. */
if (status_txn) {
ovsdb_idl_txn_wait(status_txn);
} else if (status_txn_try_again) {
poll_timer_wait_until(time_msec() + STATUS_CHECK_AGAIN_MSEC);
} else {
seq_wait(connectivity_seq_get(), connectivity_seqno);
}
status_update_wait();
system_stats_wait();
}