X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=d161c4c14c6a5113d5a5f8f43406bb0c53b7c105;hb=c2725b60074755713b2fdd73559b6d24d5eb7970;hp=5a2b25170d8a2019875ac3f94159a99034d8b164;hpb=a699f6143e09b1d63ea284b7d8180c74f27dea60;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 5a2b2517..d161c4c1 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -148,16 +148,10 @@ static struct ovsdb_idl *idl; /* Most recently processed IDL sequence number. */ static unsigned int idl_seqno; -/* Each time this timer expires, the bridge fetches systems and interface +/* Each time this timer expires, the bridge fetches interface and mirror * statistics and pushes them into the database. */ -#define STATS_INTERVAL (5 * 1000) /* In milliseconds. */ -static long long int stats_timer = LLONG_MIN; - -/* Stores the time after which rate limited statistics may be written to the - * database. Only updated when changes to the database require rate limiting. - */ -#define DB_LIMIT_INTERVAL (1 * 1000) /* In milliseconds. */ -static long long int db_limiter = LLONG_MIN; +#define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ +static long long int iface_stats_timer = LLONG_MIN; /* In some datapaths, creating and destroying OpenFlow ports can be extremely * expensive. This can cause bridge_reconfigure() to take a long time during @@ -220,6 +214,9 @@ static void port_configure_bond(struct port *, struct bond_settings *, uint32_t *bond_stable_ids); static bool port_is_synthetic(const struct port *); +static void reconfigure_system_stats(const struct ovsrec_open_vswitch *); +static void run_system_stats(void); + static void bridge_configure_mirrors(struct bridge *); static struct mirror *mirror_create(struct bridge *, const struct ovsrec_mirror *); @@ -277,6 +274,7 @@ bridge_init(const char *remote) idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true); idl_seqno = ovsdb_idl_get_seqno(idl); ovsdb_idl_set_lock(idl, "ovs_vswitchd"); + ovsdb_idl_verify_write_only(idl); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_cur_cfg); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_statistics); @@ -308,6 +306,7 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_health); + ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_opstate); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current); ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids); @@ -456,6 +455,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) iface_clear_db_record(if_cfg->cfg); } } + + reconfigure_system_stats(ovs_cfg); } static bool @@ -474,6 +475,11 @@ bridge_reconfigure_ofp(void) struct ofpp_garbage *garbage, *next; LIST_FOR_EACH_SAFE (garbage, next, list_node, &br->ofpp_garbage) { + /* It's a bit dangerous to call bridge_run_fast() here as ofproto's + * internal datastructures may not be consistent. Eventually, when + * port additions and deletions are cheaper, these calls should be + * removed. */ + bridge_run_fast(); ofproto_port_del(br->ofproto, garbage->ofp_port); list_remove(&garbage->list_node); free(garbage); @@ -482,6 +488,7 @@ bridge_reconfigure_ofp(void) if (time_msec() >= deadline) { return false; } + bridge_run_fast(); } } @@ -550,6 +557,8 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) * forked us to exit successfully. */ daemonize_complete(); reconfiguring = false; + + VLOG_INFO("%s (Open vSwitch) %s", program_name, VERSION); } return done; @@ -748,7 +757,10 @@ bridge_configure_datapath_id(struct bridge *br) memcpy(br->ea, ea, ETH_ADDR_LEN); dpid = bridge_pick_datapath_id(br, ea, hw_addr_iface); - ofproto_set_datapath_id(br->ofproto, dpid); + if (dpid != ofproto_get_datapath_id(br->ofproto)) { + VLOG_INFO("bridge %s: using datapath ID %016"PRIx64, br->name, dpid); + ofproto_set_datapath_id(br->ofproto, dpid); + } dpid_string = xasprintf("%016"PRIx64, dpid); ovsrec_bridge_set_datapath_id(br->cfg, dpid_string); @@ -875,7 +887,7 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, const char *config_str; struct iface *iface; - if (smap_get_bool(&port->cfg->other_config, "stp-enable", false)) { + if (!smap_get_bool(&port->cfg->other_config, "stp-enable", true)) { port_s->enable = false; return; } else { @@ -927,7 +939,7 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, bitmap_set1(port_num_bitmap, port_idx); port_s->port_num = port_idx; } else { - if (*port_num_counter > STP_MAX_PORTS) { + if (*port_num_counter >= STP_MAX_PORTS) { VLOG_ERR("port %s: too many STP ports, disabling", port->name); port_s->enable = false; return; @@ -1329,9 +1341,15 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) hmap_remove(&br->if_cfg_todo, &if_cfg->hmap_node); free(if_cfg); - /* Do the bits that can fail up front. */ + /* Do the bits that can fail up front. + * + * It's a bit dangerous to call bridge_run_fast() here as ofproto's + * internal datastructures may not be consistent. Eventually, when port + * additions and deletions are cheaper, these calls should be removed. */ + bridge_run_fast(); assert(!iface_lookup(br, iface_cfg->name)); error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev); + bridge_run_fast(); if (error) { iface_clear_db_record(iface_cfg); return false; @@ -1616,7 +1634,6 @@ iface_refresh_status(struct iface *iface) struct smap smap; enum netdev_features current; - enum netdev_flags flags; int64_t bps; int mtu; int64_t mtu_64; @@ -1636,15 +1653,6 @@ iface_refresh_status(struct iface *iface) smap_destroy(&smap); - error = netdev_get_flags(iface->netdev, &flags); - if (!error) { - ovsrec_interface_set_admin_state(iface->cfg, - flags & NETDEV_UP ? "up" : "down"); - } - else { - ovsrec_interface_set_admin_state(iface->cfg, NULL); - } - error = netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); if (!error) { ovsrec_interface_set_duplex(iface->cfg, @@ -1669,20 +1677,17 @@ iface_refresh_status(struct iface *iface) } } -/* Writes 'iface''s CFM statistics to the database. */ +/* Writes 'iface''s CFM statistics to the database. 'iface' must not be + * synthetic. */ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - int fault, error; + int fault, opup, error; const uint64_t *rmps; size_t n_rmps; int health; - if (iface_is_synthetic(iface)) { - return; - } - fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto, iface->ofp_port); if (fault >= 0) { @@ -1705,6 +1710,14 @@ iface_refresh_cfm_stats(struct iface *iface) 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) { @@ -1855,19 +1868,36 @@ enable_system_stats(const struct ovsrec_open_vswitch *cfg) } static void -refresh_system_stats(const struct ovsrec_open_vswitch *cfg) +reconfigure_system_stats(const struct ovsrec_open_vswitch *cfg) { - struct ovsdb_datum datum; - struct shash stats; + bool enable = enable_system_stats(cfg); - shash_init(&stats); - if (enable_system_stats(cfg)) { - get_system_stats(&stats); + system_stats_enable(enable); + if (!enable) { + ovsrec_open_vswitch_set_statistics(cfg, NULL); } +} + +static void +run_system_stats(void) +{ + const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl); + struct smap *stats; + + stats = system_stats_run(); + if (stats && cfg) { + struct ovsdb_idl_txn *txn; + struct ovsdb_datum datum; + + txn = ovsdb_idl_txn_create(idl); + ovsdb_datum_from_smap(&datum, stats); + ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics, + &datum); + ovsdb_idl_txn_commit(txn); + ovsdb_idl_txn_destroy(txn); - ovsdb_datum_from_shash(&datum, &stats); - ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics, - &datum); + free(stats); + } } static inline const char * @@ -1929,7 +1959,7 @@ refresh_controller_status(void) } static void -refresh_cfm_stats(void) +refresh_instant_stats(void) { static struct ovsdb_idl_txn *txn = NULL; @@ -1940,8 +1970,47 @@ refresh_cfm_stats(void) HMAP_FOR_EACH (br, node, &all_bridges) { struct iface *iface; + struct port *port; + + br_refresh_stp_status(br); + + HMAP_FOR_EACH (port, hmap_node, &br->ports) { + port_refresh_stp_status(port); + } HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) { + enum netdev_flags flags; + const char *link_state; + int64_t link_resets; + int current, error; + + if (iface_is_synthetic(iface)) { + continue; + } + + current = ofproto_port_is_lacp_current(br->ofproto, + iface->ofp_port); + if (current >= 0) { + bool bl = current; + ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); + } else { + ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); + } + + error = netdev_get_flags(iface->netdev, &flags); + if (!error) { + const char *state = flags & NETDEV_UP ? "up" : "down"; + ovsrec_interface_set_admin_state(iface->cfg, state); + } else { + ovsrec_interface_set_admin_state(iface->cfg, NULL); + } + + link_state = netdev_get_carrier(iface->netdev) ? "up" : "down"; + ovsrec_interface_set_link_state(iface->cfg, link_state); + + link_resets = netdev_get_carrier_resets(iface->netdev); + ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); + iface_refresh_cfm_stats(iface); } } @@ -1979,6 +2048,8 @@ bridge_run(void) bool vlan_splinters_changed; struct bridge *br; + ovsrec_open_vswitch_init((struct ovsrec_open_vswitch *) &null_cfg); + /* (Re)configure if necessary. */ if (!reconfiguring) { ovsdb_idl_run(idl); @@ -2063,8 +2134,8 @@ bridge_run(void) reconf_txn = NULL; } - /* Refresh system and interface stats if necessary. */ - if (time_msec() >= stats_timer) { + /* Refresh interface and mirror stats if necessary. */ + if (time_msec() >= iface_stats_timer) { if (cfg) { struct ovsdb_idl_txn *txn; @@ -2087,62 +2158,16 @@ bridge_run(void) } } - refresh_system_stats(cfg); refresh_controller_status(); ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); /* XXX */ } - stats_timer = time_msec() + STATS_INTERVAL; - } - - if (time_msec() >= db_limiter) { - struct ovsdb_idl_txn *txn; - - txn = ovsdb_idl_txn_create(idl); - HMAP_FOR_EACH (br, node, &all_bridges) { - struct iface *iface; - struct port *port; - - br_refresh_stp_status(br); - - HMAP_FOR_EACH (port, hmap_node, &br->ports) { - port_refresh_stp_status(port); - } - - HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) { - const char *link_state; - int64_t link_resets; - int current; - - if (iface_is_synthetic(iface)) { - continue; - } - - current = ofproto_port_is_lacp_current(br->ofproto, - iface->ofp_port); - if (current >= 0) { - bool bl = current; - ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); - } else { - ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); - } - - link_state = netdev_get_carrier(iface->netdev) ? "up" : "down"; - ovsrec_interface_set_link_state(iface->cfg, link_state); - - link_resets = netdev_get_carrier_resets(iface->netdev); - ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); - } - } - - if (ovsdb_idl_txn_commit(txn) != TXN_UNCHANGED) { - db_limiter = time_msec() + DB_LIMIT_INTERVAL; - } - ovsdb_idl_txn_destroy(txn); + iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL; } - refresh_cfm_stats(); + run_system_stats(); + refresh_instant_stats(); } void @@ -2160,12 +2185,10 @@ bridge_wait(void) HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_wait(br->ofproto); } - poll_timer_wait_until(stats_timer); - - if (db_limiter > time_msec()) { - poll_timer_wait_until(db_limiter); - } + poll_timer_wait_until(iface_stats_timer); } + + system_stats_wait(); } /* Adds some memory usage statistics for bridges into 'usage', for use with @@ -2504,7 +2527,12 @@ bridge_add_del_ports(struct bridge *br, if (iface) { iface->cfg = cfg; iface->type = type; - } else if (strcmp(type, "null")) { + } else if (!strcmp(type, "null")) { + VLOG_WARN_ONCE("%s: The null interface type is deprecated and" + " may be removed in February 2013. Please email" + " dev@openvswitch.org with concerns.", + cfg->name); + } else { bridge_queue_if_cfg(br, cfg, port); } }