cfm: Expose remote CFM opstate in the database.
[sliver-openvswitch.git] / vswitchd / bridge.c
index 3a3e58b..9bafa66 100644 (file)
@@ -148,10 +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;
+#define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */
+static long long int iface_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.
@@ -220,6 +220,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 *);
@@ -456,6 +459,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             iface_clear_db_record(if_cfg->cfg);
         }
     }
+
+    reconfigure_system_stats(ovs_cfg);
 }
 
 static bool
@@ -556,6 +561,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;
@@ -1689,7 +1696,7 @@ 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;
@@ -1720,6 +1727,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) {
@@ -1870,19 +1885,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;
 
-    ovsdb_datum_from_shash(&datum, &stats);
-    ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics,
-                        &datum);
+    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);
+
+        free(stats);
+    }
 }
 
 static inline const char *
@@ -1994,6 +2026,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);
@@ -2078,8 +2112,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;
 
@@ -2102,15 +2136,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;
+        iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL;
     }
 
+    run_system_stats();
+
     if (time_msec() >= db_limiter) {
         struct ovsdb_idl_txn *txn;
 
@@ -2175,12 +2210,14 @@ bridge_wait(void)
         HMAP_FOR_EACH (br, node, &all_bridges) {
             ofproto_wait(br->ofproto);
         }
-        poll_timer_wait_until(stats_timer);
+        poll_timer_wait_until(iface_stats_timer);
 
         if (db_limiter > time_msec()) {
             poll_timer_wait_until(db_limiter);
         }
     }
+
+    system_stats_wait();
 }
 
 /* Adds some memory usage statistics for bridges into 'usage', for use with