X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=6dc3db228081248a87cb95d6e1d94e84045d7c42;hb=4d5f814dfb737aae820b8ce70ff0a8b94c291ec3;hp=b28ef26c9c012fdd7eda37c31388bceb9929a2e8;hpb=9a9e3786b3a8065723887ab009aedb7f6d2667aa;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index b28ef26c9..6dc3db228 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -318,7 +318,7 @@ void bridge_init(const char *remote) { /* Create connection to database. */ - idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true); + idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true, true); idl_seqno = ovsdb_idl_get_seqno(idl); ovsdb_idl_set_lock(idl, "ovs_vswitchd"); ovsdb_idl_verify_write_only(idl); @@ -345,6 +345,7 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_speed); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_state); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_resets); + ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mac_in_use); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mtu); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ofport); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics); @@ -1698,6 +1699,7 @@ iface_refresh_status(struct iface *iface) int64_t bps; int mtu; int64_t mtu_64; + uint8_t mac[ETH_ADDR_LEN]; int error; if (iface_is_synthetic(iface)) { @@ -1721,8 +1723,7 @@ iface_refresh_status(struct iface *iface) netdev_features_is_full_duplex(current) ? "full" : "half"); ovsrec_interface_set_link_speed(iface->cfg, &bps, 1); - } - else { + } else { ovsrec_interface_set_duplex(iface->cfg, NULL); ovsrec_interface_set_link_speed(iface->cfg, NULL, 0); } @@ -1731,10 +1732,19 @@ iface_refresh_status(struct iface *iface) if (!error) { mtu_64 = mtu; ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1); - } - else { + } else { ovsrec_interface_set_mtu(iface->cfg, NULL, 0); } + + error = netdev_get_etheraddr(iface->netdev, mac); + if (!error) { + char mac_string[32]; + + sprintf(mac_string, ETH_ADDR_FMT, ETH_ADDR_ARGS(mac)); + ovsrec_interface_set_mac_in_use(iface->cfg, mac_string); + } else { + ovsrec_interface_set_mac_in_use(iface->cfg, NULL); + } } /* Writes 'iface''s CFM statistics to the database. 'iface' must not be @@ -1769,12 +1779,21 @@ iface_refresh_cfm_stats(struct iface *iface) } ovsrec_interface_set_cfm_fault_status(cfg, (char **) reasons, j); - ovsrec_interface_set_cfm_remote_opstate(cfg, (status.remote_opstate - ? "up" : "down")); + if (status.remote_opstate >= 0) { + const char *remote_opstate = status.remote_opstate ? "up" : "down"; + ovsrec_interface_set_cfm_remote_opstate(cfg, remote_opstate); + } else { + ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); + } + ovsrec_interface_set_cfm_remote_mpids(cfg, (const int64_t *)status.rmps, status.n_rmps); - ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); + if (cfm_health >= 0) { + ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); + } else { + ovsrec_interface_set_cfm_health(cfg, NULL, 0); + } } } @@ -2000,17 +2019,61 @@ refresh_controller_status(void) ofproto_free_ofproto_controller_info(&info); } + +/* "Instant" stats. + * + * Some information in the database must be kept as up-to-date as possible to + * allow controllers to respond rapidly to network outages. We call these + * statistics "instant" stats. + * + * We wish to update these statistics every INSTANT_INTERVAL_MSEC milliseconds, + * assuming that they've changed. The only means we have to determine whether + * they have changed are: + * + * - Try to commit changes to the database. If nothing changed, then + * ovsdb_idl_txn_commit() returns TXN_UNCHANGED, otherwise some other + * value. + * + * - instant_stats_run() is called late in the run loop, after anything that + * might change any of the instant stats. + * + * We use these two facts together to avoid waking the process up every + * INSTANT_INTERVAL_MSEC whether there is any change or not. + */ + +/* Minimum interval between writing updates to the instant stats to the + * database. */ +#define INSTANT_INTERVAL_MSEC 100 + +/* Current instant stats database transaction, NULL if there is no ongoing + * transaction. */ +static struct ovsdb_idl_txn *instant_txn; + +/* Next time (in msec on monotonic clock) at which we will update the instant + * stats. */ +static long long int instant_next_txn = LLONG_MIN; + +/* True if the run loop has run since we last saw that the instant stats were + * unchanged, that is, this is true if we need to wake up at 'instant_next_txn' + * to refresh the instant stats. */ +static bool instant_stats_could_have_changed; static void -refresh_instant_stats(void) +instant_stats_run(void) { - static struct ovsdb_idl_txn *txn = NULL; + enum ovsdb_idl_txn_status status; - if (!txn) { + instant_stats_could_have_changed = true; + + if (!instant_txn) { struct bridge *br; - txn = ovsdb_idl_txn_create(idl); + if (time_msec() < instant_next_txn) { + return; + } + instant_next_txn = time_msec() + INSTANT_INTERVAL_MSEC; + instant_txn = ovsdb_idl_txn_create(idl); HMAP_FOR_EACH (br, node, &all_bridges) { struct iface *iface; struct port *port; @@ -2059,12 +2122,26 @@ refresh_instant_stats(void) } } - if (ovsdb_idl_txn_commit(txn) != TXN_INCOMPLETE) { - ovsdb_idl_txn_destroy(txn); - txn = NULL; + status = ovsdb_idl_txn_commit(instant_txn); + if (status != TXN_INCOMPLETE) { + ovsdb_idl_txn_destroy(instant_txn); + instant_txn = NULL; + } + if (status == TXN_UNCHANGED) { + instant_stats_could_have_changed = false; } } +static void +instant_stats_wait(void) +{ + if (instant_txn) { + ovsdb_idl_txn_wait(instant_txn); + } else if (instant_stats_could_have_changed) { + poll_timer_wait_until(instant_next_txn); + } +} + /* Performs periodic activity required by bridges that needs to be done with * the least possible latency. * @@ -2235,7 +2312,7 @@ bridge_run(void) } run_system_stats(); - refresh_instant_stats(); + instant_stats_run(); } void @@ -2267,6 +2344,7 @@ bridge_wait(void) } system_stats_wait(); + instant_stats_wait(); } /* Adds some memory usage statistics for bridges into 'usage', for use with @@ -3323,6 +3401,7 @@ iface_clear_db_record(const struct ovsrec_interface *if_cfg) ovsrec_interface_set_duplex(if_cfg, NULL); ovsrec_interface_set_link_speed(if_cfg, NULL, 0); ovsrec_interface_set_link_state(if_cfg, NULL); + ovsrec_interface_set_mac_in_use(if_cfg, NULL); ovsrec_interface_set_mtu(if_cfg, NULL, 0); ovsrec_interface_set_cfm_fault(if_cfg, NULL, 0); ovsrec_interface_set_cfm_fault_status(if_cfg, NULL, 0);