debian: openvswitch-common ethtool should not be required
[openvswitch] / vswitchd / bridge.c
index 952049e4166eeb33c451b3f37879264bfdbf4122..6c271fb7acf80807d733d2b859b827537ff46a02 100644 (file)
@@ -57,6 +57,7 @@
 #include "socket-util.h"
 #include "stream-ssl.h"
 #include "svec.h"
+#include "system-stats.h"
 #include "timeval.h"
 #include "util.h"
 #include "unixctl.h"
@@ -188,10 +189,10 @@ static struct list all_bridges = LIST_INITIALIZER(&all_bridges);
 /* OVSDB IDL used to obtain configuration. */
 static struct ovsdb_idl *idl;
 
-/* Each time this timer expires, the bridge fetches statistics for every
- * interface and pushes them into the database. */
-#define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */
-static long long int iface_stats_timer = LLONG_MIN;
+/* Each time this timer expires, the bridge fetches systems and interface
+ * statistics and pushes them into the database. */
+#define STATS_INTERVAL (5 * 1000) /* In milliseconds. */
+static long long int stats_timer = LLONG_MIN;
 
 static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg);
 static void bridge_destroy(struct bridge *);
@@ -244,7 +245,7 @@ static void mirror_reconfigure(struct bridge *);
 static void mirror_reconfigure_one(struct mirror *, struct ovsrec_mirror *);
 static bool vlan_is_mirrored(const struct mirror *, int vlan);
 
-static struct iface *iface_create(struct port *port, 
+static struct iface *iface_create(struct port *port,
                                   const struct ovsrec_interface *if_cfg);
 static void iface_destroy(struct iface *);
 static struct iface *iface_lookup(const struct bridge *, const char *name);
@@ -306,7 +307,7 @@ bridge_configure_once(const struct ovsrec_open_vswitch *cfg)
     }
     already_configured_once = true;
 
-    iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL;
+    stats_timer = time_msec() + STATS_INTERVAL;
 
     /* Get all the configured bridges' names from 'cfg' into 'bridge_names'. */
     svec_init(&bridge_names);
@@ -373,6 +374,20 @@ set_up_iface(const struct ovsrec_interface *iface_cfg, struct iface *iface,
                   xstrdup(iface_cfg->value_options[i]));
     }
 
+    /* Include 'other_config' keys in hash of netdev options.  The
+     * namespace of 'other_config' and 'options' must be disjoint.
+     * Prefer 'options' keys over 'other_config' keys. */
+    for (i = 0; i < iface_cfg->n_other_config; i++) {
+        char *value = xstrdup(iface_cfg->value_other_config[i]);
+        if (!shash_add_once(&options, iface_cfg->key_other_config[i],
+                            value)) {
+            VLOG_WARN("%s: \"other_config\" key %s conflicts with existing "
+                      "\"other_config\" or \"options\" entry...ignoring",
+                      iface_cfg->name, iface_cfg->key_other_config[i]);
+            free(value);
+        }
+    }
+
     if (create) {
         struct netdev_options netdev_options;
 
@@ -632,7 +647,6 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         struct odp_port *dpif_ports;
         size_t n_dpif_ports;
         struct shash cur_ifaces, want_ifaces;
-        struct shash_node *node;
 
         /* Get the set of interfaces currently in this datapath. */
         dpif_port_list(br->dpif, &dpif_ports, &n_dpif_ports);
@@ -752,7 +766,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             opts.collectors.n = nf_cfg->n_targets;
             opts.collectors.names = nf_cfg->targets;
             if (ofproto_set_netflow(br->ofproto, &opts)) {
-                VLOG_ERR("bridge %s: problem setting netflow collectors", 
+                VLOG_ERR("bridge %s: problem setting netflow collectors",
                          br->name);
             }
         } else {
@@ -765,7 +779,6 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
             struct ovsrec_controller **controllers;
             struct ofproto_sflow_options oso;
             size_t n_controllers;
-            size_t i;
 
             memset(&oso, 0, sizeof oso);
 
@@ -1098,6 +1111,20 @@ iface_refresh_stats(struct iface *iface)
     ovsrec_interface_set_statistics(iface->cfg, keys, values, n);
 }
 
+static void
+refresh_system_stats(const struct ovsrec_open_vswitch *cfg)
+{
+    struct ovsdb_datum datum;
+    struct shash stats;
+
+    shash_init(&stats);
+    get_system_stats(&stats);
+
+    ovsdb_datum_from_shash(&datum, &stats);
+    ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics,
+                        &datum);
+}
+
 void
 bridge_run(void)
 {
@@ -1153,28 +1180,31 @@ bridge_run(void)
     }
 #endif
 
-    /* Refresh interface stats if necessary. */
-    if (time_msec() >= iface_stats_timer) {
-        struct ovsdb_idl_txn *txn;
+    /* Refresh system and interface stats if necessary. */
+    if (time_msec() >= stats_timer) {
+        if (cfg) {
+            struct ovsdb_idl_txn *txn;
 
-        txn = ovsdb_idl_txn_create(idl);
-        LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
-            size_t i;
+            txn = ovsdb_idl_txn_create(idl);
+            LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
+                size_t i;
 
-            for (i = 0; i < br->n_ports; i++) {
-                struct port *port = br->ports[i];
-                size_t j;
+                for (i = 0; i < br->n_ports; i++) {
+                    struct port *port = br->ports[i];
+                    size_t j;
 
-                for (j = 0; j < port->n_ifaces; j++) {
-                    struct iface *iface = port->ifaces[j];
-                    iface_refresh_stats(iface);
+                    for (j = 0; j < port->n_ifaces; j++) {
+                        struct iface *iface = port->ifaces[j];
+                        iface_refresh_stats(iface);
+                    }
                 }
             }
+            refresh_system_stats(cfg);
+            ovsdb_idl_txn_commit(txn);
+            ovsdb_idl_txn_destroy(txn); /* XXX */
         }
-        ovsdb_idl_txn_commit(txn);
-        ovsdb_idl_txn_destroy(txn); /* XXX */
 
-        iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL;
+        stats_timer = time_msec() + STATS_INTERVAL;
     }
 }
 
@@ -1193,7 +1223,7 @@ bridge_wait(void)
         bond_wait(br);
     }
     ovsdb_idl_wait(idl);
-    poll_timer_wait_until(iface_stats_timer);
+    poll_timer_wait_until(stats_timer);
 }
 
 /* Forces 'br' to revalidate all of its flows.  This is appropriate when 'br''s
@@ -1350,7 +1380,7 @@ bridge_unixctl_dump_flows(struct unixctl_conn *conn,
 {
     struct bridge *br;
     struct ds results;
-    
+
     br = bridge_lookup(args);
     if (!br) {
         unixctl_command_reply(conn, 501, "Unknown bridge");
@@ -2361,7 +2391,7 @@ is_admissible(struct bridge *br, const flow_t *flow, bool have_packet,
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
             VLOG_WARN_RL(&rl, "bridge %s: received packet on unknown "
-                         "interface %"PRIu16, br->name, flow->in_port); 
+                         "interface %"PRIu16, br->name, flow->in_port);
         }
 
         *in_portp = NULL;
@@ -2822,7 +2852,6 @@ bond_rebalance_port(struct port *port)
              * smallest hashes instead of the biggest ones.  There is little
              * reason behind this decision; we could use the opposite sort
              * order to shift away big hashes ahead of small ones. */
-            size_t i;
             bool order_swapped;
 
             for (i = 0; i < from->n_hashes; i++) {
@@ -3407,7 +3436,6 @@ port_reconfigure(struct port *port, const struct ovsrec_port *cfg)
     trunks = NULL;
     if (vlan < 0 && cfg->n_trunks) {
         size_t n_errors;
-        size_t i;
 
         trunks = bitmap_allocate(4096);
         n_errors = 0;
@@ -3570,15 +3598,15 @@ port_update_bond_compat(struct port *port)
 
         /* We need to make the same determination as the Linux bonding
          * code to determine whether a slave should be consider "up".
-         * The Linux function bond_miimon_inspect() supports four 
+         * The Linux function bond_miimon_inspect() supports four
          * BOND_LINK_* states:
-         *      
+         *
          *    - BOND_LINK_UP: carrier detected, updelay has passed.
          *    - BOND_LINK_FAIL: carrier lost, downdelay in progress.
          *    - BOND_LINK_DOWN: carrier lost, downdelay has passed.
          *    - BOND_LINK_BACK: carrier detected, updelay in progress.
          *
-         * The function bond_info_show_slave() only considers BOND_LINK_UP 
+         * The function bond_info_show_slave() only considers BOND_LINK_UP
          * to be "up" and anything else to be "down".
          */
         slave->up = iface->enabled && iface->delay_expires == LLONG_MAX;