X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=6dc3db228081248a87cb95d6e1d94e84045d7c42;hb=0cc70daec76f59571d56a96bd86a960e18d13e9f;hp=fdd7c64064354e4da1b17a4db64e1ffeff8f7b1e;hpb=2c487bc808ba6a4a297523f2c6b78ca3e358073a;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index fdd7c6406..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 @@ -1743,57 +1753,47 @@ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - int fault, opup, error; - const uint64_t *rmps; - size_t n_rmps; - int health; - - fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto, - iface->ofp_port); - if (fault >= 0) { + struct ofproto_cfm_status status; + + if (!ofproto_port_get_cfm_status(iface->port->bridge->ofproto, + iface->ofp_port, &status)) { + ovsrec_interface_set_cfm_fault(cfg, NULL, 0); + ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); + ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); + ovsrec_interface_set_cfm_health(cfg, NULL, 0); + ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0); + } else { const char *reasons[CFM_FAULT_N_REASONS]; - bool fault_bool = fault; + int64_t cfm_health = status.health; + bool faulted = status.faults != 0; size_t i, j; + ovsrec_interface_set_cfm_fault(cfg, &faulted, 1); + j = 0; for (i = 0; i < CFM_FAULT_N_REASONS; i++) { int reason = 1 << i; - if (fault & reason) { + if (status.faults & reason) { reasons[j++] = cfm_fault_reason_to_str(reason); } } - - ovsrec_interface_set_cfm_fault(cfg, &fault_bool, 1); ovsrec_interface_set_cfm_fault_status(cfg, (char **) reasons, j); - } else { - ovsrec_interface_set_cfm_fault(cfg, NULL, 0); - ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); - } - opup = ofproto_port_get_cfm_opup(iface->port->bridge->ofproto, - iface->ofp_port); - if (opup >= 0) { - ovsrec_interface_set_cfm_remote_opstate(cfg, opup ? "up" : "down"); - } else { - ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); - } - - error = ofproto_port_get_cfm_remote_mpids(iface->port->bridge->ofproto, - iface->ofp_port, &rmps, &n_rmps); - if (error >= 0) { - ovsrec_interface_set_cfm_remote_mpids(cfg, (const int64_t *)rmps, - n_rmps); - } else { - ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0); - } + 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); + } - health = ofproto_port_get_cfm_health(iface->port->bridge->ofproto, - iface->ofp_port); - if (health >= 0) { - int64_t cfm_health = health; - ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); - } else { - ovsrec_interface_set_cfm_health(cfg, NULL, 0); + ovsrec_interface_set_cfm_remote_mpids(cfg, + (const int64_t *)status.rmps, + status.n_rmps); + if (cfm_health >= 0) { + ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); + } else { + ovsrec_interface_set_cfm_health(cfg, NULL, 0); + } } } @@ -1961,15 +1961,16 @@ run_system_stats(void) } static inline const char * -nx_role_to_str(enum nx_role role) +ofp12_controller_role_to_str(enum ofp12_controller_role role) { switch (role) { - case NX_ROLE_OTHER: + case OFPCR12_ROLE_EQUAL: return "other"; - case NX_ROLE_MASTER: + case OFPCR12_ROLE_MASTER: return "master"; - case NX_ROLE_SLAVE: + case OFPCR12_ROLE_SLAVE: return "slave"; + case OFPCR12_ROLE_NOCHANGE: default: return "*** INVALID ROLE ***"; } @@ -2005,7 +2006,8 @@ refresh_controller_status(void) } ovsrec_controller_set_is_connected(cfg, cinfo->is_connected); - ovsrec_controller_set_role(cfg, nx_role_to_str(cinfo->role)); + ovsrec_controller_set_role(cfg, ofp12_controller_role_to_str( + cinfo->role)); ovsrec_controller_set_status(cfg, &smap); smap_destroy(&smap); } else { @@ -2017,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; + + instant_stats_could_have_changed = true; - if (!txn) { + 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; @@ -2076,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. * @@ -2252,7 +2312,7 @@ bridge_run(void) } run_system_stats(); - refresh_instant_stats(); + instant_stats_run(); } void @@ -2284,6 +2344,7 @@ bridge_wait(void) } system_stats_wait(); + instant_stats_wait(); } /* Adds some memory usage statistics for bridges into 'usage', for use with @@ -3340,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);