netdev: Log a warning when netdev_set_config() fails.
[sliver-openvswitch.git] / vswitchd / bridge.c
index 555f45d..8ccb8da 100644 (file)
@@ -21,7 +21,6 @@
 #include "async-append.h"
 #include "bfd.h"
 #include "bitmap.h"
-#include "bond.h"
 #include "cfm.h"
 #include "coverage.h"
 #include "daemon.h"
@@ -39,6 +38,7 @@
 #include "ofp-print.h"
 #include "ofp-util.h"
 #include "ofpbuf.h"
+#include "ofproto/bond.h"
 #include "ofproto/ofproto.h"
 #include "poll-loop.h"
 #include "sha1.h"
@@ -984,28 +984,44 @@ bridge_configure_sflow(struct bridge *br, int *sflow_bridge_number)
     sset_destroy(&oso.targets);
 }
 
+/* Returns whether a IPFIX row is valid. */
+static bool
+ovsrec_ipfix_is_valid(const struct ovsrec_ipfix *ipfix)
+{
+    return ipfix && ipfix->n_targets > 0;
+}
+
+/* Returns whether a Flow_Sample_Collector_Set row is valid. */
+static bool
+ovsrec_fscs_is_valid(const struct ovsrec_flow_sample_collector_set *fscs,
+                     const struct bridge *br)
+{
+    return ovsrec_ipfix_is_valid(fscs->ipfix) && fscs->bridge == br->cfg;
+}
+
 /* Set IPFIX configuration on 'br'. */
 static void
 bridge_configure_ipfix(struct bridge *br)
 {
     const struct ovsrec_ipfix *be_cfg = br->cfg->ipfix;
+    bool valid_be_cfg = ovsrec_ipfix_is_valid(be_cfg);
     const struct ovsrec_flow_sample_collector_set *fe_cfg;
     struct ofproto_ipfix_bridge_exporter_options be_opts;
     struct ofproto_ipfix_flow_exporter_options *fe_opts = NULL;
     size_t n_fe_opts = 0;
 
     OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
-        if (fe_cfg->bridge == br->cfg) {
+        if (ovsrec_fscs_is_valid(fe_cfg, br)) {
             n_fe_opts++;
         }
     }
 
-    if (!be_cfg && n_fe_opts == 0) {
+    if (!valid_be_cfg && n_fe_opts == 0) {
         ofproto_set_ipfix(br->ofproto, NULL, NULL, 0);
         return;
     }
 
-    if (be_cfg) {
+    if (valid_be_cfg) {
         memset(&be_opts, 0, sizeof be_opts);
 
         sset_init(&be_opts.targets);
@@ -1035,7 +1051,7 @@ bridge_configure_ipfix(struct bridge *br)
         fe_opts = xcalloc(n_fe_opts, sizeof *fe_opts);
         opts = fe_opts;
         OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) {
-            if (fe_cfg->bridge == br->cfg) {
+            if (ovsrec_fscs_is_valid(fe_cfg, br)) {
                 opts->collector_set_id = fe_cfg->id;
                 sset_init(&opts->targets);
                 sset_add_array(&opts->targets, fe_cfg->ipfix->targets,
@@ -1049,10 +1065,10 @@ bridge_configure_ipfix(struct bridge *br)
         }
     }
 
-    ofproto_set_ipfix(br->ofproto, be_cfg ? &be_opts : NULL, fe_opts,
+    ofproto_set_ipfix(br->ofproto, valid_be_cfg ? &be_opts : NULL, fe_opts,
                       n_fe_opts);
 
-    if (be_cfg) {
+    if (valid_be_cfg) {
         sset_destroy(&be_opts.targets);
     }
 
@@ -1327,14 +1343,7 @@ static int
 iface_set_netdev_config(const struct ovsrec_interface *iface_cfg,
                         struct netdev *netdev)
 {
-    int error;
-
-    error = netdev_set_config(netdev, &iface_cfg->options);
-    if (error) {
-        VLOG_WARN("could not configure network device %s (%s)",
-                  iface_cfg->name, ovs_strerror(error));
-    }
-    return error;
+    return netdev_set_config(netdev, &iface_cfg->options);
 }
 
 /* This function determines whether 'ofproto_port', which is attached to
@@ -2016,8 +2025,6 @@ port_refresh_stp_status(struct port *port)
     struct ofproto *ofproto = port->bridge->ofproto;
     struct iface *iface;
     struct ofproto_port_stp_status status;
-    char *keys[3];
-    int64_t int_values[3];
     struct smap smap;
 
     if (port_is_synthetic(port)) {
@@ -2031,14 +2038,12 @@ port_refresh_stp_status(struct port *port)
     }
 
     iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem);
-
     if (ofproto_port_get_stp_status(ofproto, iface->ofp_port, &status)) {
         return;
     }
 
     if (!status.enabled) {
         ovsrec_port_set_status(port->cfg, NULL);
-        ovsrec_port_set_statistics(port->cfg, NULL, NULL, 0);
         return;
     }
 
@@ -2050,14 +2055,43 @@ port_refresh_stp_status(struct port *port)
     smap_add(&smap, "stp_role", stp_role_name(status.role));
     ovsrec_port_set_status(port->cfg, &smap);
     smap_destroy(&smap);
+}
+
+static void
+port_refresh_stp_stats(struct port *port)
+{
+    struct ofproto *ofproto = port->bridge->ofproto;
+    struct iface *iface;
+    struct ofproto_port_stp_stats stats;
+    char *keys[3];
+    int64_t int_values[3];
+
+    if (port_is_synthetic(port)) {
+        return;
+    }
+
+    /* STP doesn't currently support bonds. */
+    if (!list_is_singleton(&port->ifaces)) {
+        return;
+    }
+
+    iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem);
+    if (ofproto_port_get_stp_stats(ofproto, iface->ofp_port, &stats)) {
+        return;
+    }
+
+    if (!stats.enabled) {
+        ovsrec_port_set_statistics(port->cfg, NULL, NULL, 0);
+        return;
+    }
 
     /* Set Statistics column. */
     keys[0] = "stp_tx_count";
-    int_values[0] = status.tx_count;
+    int_values[0] = stats.tx_count;
     keys[1] = "stp_rx_count";
-    int_values[1] = status.rx_count;
+    int_values[1] = stats.rx_count;
     keys[2] = "stp_error_count";
-    int_values[2] = status.error_count;
+    int_values[2] = stats.error_count;
 
     ovsrec_port_set_statistics(port->cfg, keys, int_values,
                                ARRAY_SIZE(int_values));
@@ -2483,6 +2517,8 @@ bridge_run(void)
                         iface_refresh_stats(iface);
                         iface_refresh_status(iface);
                     }
+
+                    port_refresh_stp_stats(port);
                 }
 
                 HMAP_FOR_EACH (m, hmap_node, &br->mirrors) {
@@ -3124,7 +3160,7 @@ bridge_configure_tables(struct bridge *br)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     int n_tables;
-    int i, j;
+    int i, j, k;
 
     n_tables = ofproto_get_n_tables(br->ofproto);
     j = 0;
@@ -3135,6 +3171,8 @@ bridge_configure_tables(struct bridge *br)
         s.max_flows = UINT_MAX;
         s.groups = NULL;
         s.n_groups = 0;
+        s.n_prefix_fields = 0;
+        memset(s.prefix_fields, ~0, sizeof(s.prefix_fields));
 
         if (j < br->cfg->n_flow_tables && i == br->cfg->key_flow_tables[j]) {
             struct ovsrec_flow_table *cfg = br->cfg->value_flow_tables[j++];
@@ -3145,7 +3183,6 @@ bridge_configure_tables(struct bridge *br)
             }
             if (cfg->overflow_policy
                 && !strcmp(cfg->overflow_policy, "evict")) {
-                size_t k;
 
                 s.groups = xmalloc(cfg->n_groups * sizeof *s.groups);
                 for (k = 0; k < cfg->n_groups; k++) {
@@ -3166,6 +3203,41 @@ bridge_configure_tables(struct bridge *br)
                     }
                 }
             }
+            /* Prefix lookup fields. */
+            s.n_prefix_fields = 0;
+            for (k = 0; k < cfg->n_prefixes; k++) {
+                const char *name = cfg->prefixes[k];
+                const struct mf_field *mf = mf_from_name(name);
+                if (!mf) {
+                    VLOG_WARN("bridge %s: 'prefixes' with unknown field: %s",
+                              br->name, name);
+                    continue;
+                }
+                if (mf->flow_be32ofs < 0 || mf->n_bits % 32) {
+                    VLOG_WARN("bridge %s: 'prefixes' with incompatible field: "
+                              "%s", br->name, name);
+                    continue;
+                }
+                if (s.n_prefix_fields >= ARRAY_SIZE(s.prefix_fields)) {
+                    VLOG_WARN("bridge %s: 'prefixes' with too many fields, "
+                              "field not used: %s", br->name, name);
+                    continue;
+                }
+                s.prefix_fields[s.n_prefix_fields++] = mf->id;
+            }
+            if (s.n_prefix_fields > 0) {
+                int k;
+                struct ds ds = DS_EMPTY_INITIALIZER;
+                for (k = 0; k < s.n_prefix_fields; k++) {
+                    if (k) {
+                        ds_put_char(&ds, ',');
+                    }
+                    ds_put_cstr(&ds, mf_from_id(s.prefix_fields[k])->name);
+                }
+                VLOG_INFO("bridge %s table %d: Prefix lookup with: %s.",
+                          br->name, i, ds_cstr(&ds));
+                ds_destroy(&ds);
+            }
         }
 
         ofproto_configure_table(br->ofproto, i, &s);
@@ -3578,10 +3650,9 @@ iface_set_mac(struct iface *iface)
 static void
 iface_set_ofport(const struct ovsrec_interface *if_cfg, ofp_port_t ofport)
 {
-    int64_t port_;
-    port_ = (ofport == OFPP_NONE) ? -1 : ofp_to_u16(ofport);
     if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
-        ovsrec_interface_set_ofport(if_cfg, &port_, 1);
+        int64_t port = ofport == OFPP_NONE ? -1 : ofp_to_u16(ofport);
+        ovsrec_interface_set_ofport(if_cfg, &port, 1);
     }
 }