datapath: Strip down vport interface : OVS_VPORT_ATTR_MTU
[sliver-openvswitch.git] / vswitchd / bridge.c
index ada82ff..f1c306d 100644 (file)
@@ -197,7 +197,7 @@ static void iface_set_mac(struct iface *);
 static void iface_set_ofport(const struct ovsrec_interface *, int64_t ofport);
 static void iface_configure_qos(struct iface *, const struct ovsrec_qos *);
 static void iface_configure_cfm(struct iface *);
-static bool iface_refresh_cfm_stats(struct iface *);
+static void iface_refresh_cfm_stats(struct iface *);
 static void iface_refresh_stats(struct iface *);
 static void iface_refresh_status(struct iface *);
 static bool iface_get_carrier(const struct iface *);
@@ -243,6 +243,7 @@ bridge_init(const char *remote)
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics);
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_status);
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault);
+    ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids);
     ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current);
     ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids);
 
@@ -1079,7 +1080,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
             !eth_addr_is_local(iface_ea) &&
             !eth_addr_is_reserved(iface_ea) &&
             !eth_addr_is_zero(iface_ea) &&
-            eth_addr_compare_3way(iface_ea, ea) < 0)
+            (!found_addr || eth_addr_compare_3way(iface_ea, ea) < 0))
         {
             memcpy(ea, iface_ea, ETH_ADDR_LEN);
             *hw_addr_iface = iface;
@@ -1247,7 +1248,7 @@ iface_refresh_status(struct iface *iface)
                                     iface_get_carrier(iface) ? "up" : "down");
 
     error = netdev_get_mtu(iface->netdev, &mtu);
-    if (!error && mtu != INT_MAX) {
+    if (!error) {
         mtu_64 = mtu;
         ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1);
     }
@@ -1258,27 +1259,31 @@ iface_refresh_status(struct iface *iface)
 
 /* Writes 'iface''s CFM statistics to the database.  Returns true if anything
  * changed, false otherwise. */
-static bool
+static void
 iface_refresh_cfm_stats(struct iface *iface)
 {
     const struct ovsrec_interface *cfg = iface->cfg;
-    bool changed = false;
-    int fault;
+    int fault, error;
+    const uint64_t *rmps;
+    size_t n_rmps;
 
     fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto,
                                        iface->ofp_port);
-
-    if (fault < 0) {
-        return false;
-    }
-
-    if (cfg->n_cfm_fault != 1 || cfg->cfm_fault[0] != fault) {
+    if (fault >= 0) {
         bool fault_bool = fault;
         ovsrec_interface_set_cfm_fault(cfg, &fault_bool, 1);
-        changed = true;
+    } else {
+        ovsrec_interface_set_cfm_fault(cfg, NULL, 0);
     }
 
-    return changed;
+    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);
+    }
 }
 
 static bool
@@ -1422,6 +1427,31 @@ refresh_controller_status(void)
     ofproto_free_ofproto_controller_info(&info);
 }
 
+static void
+refresh_cfm_stats(void)
+{
+    static struct ovsdb_idl_txn *txn = NULL;
+
+    if (!txn) {
+        struct bridge *br;
+
+        txn = ovsdb_idl_txn_create(idl);
+
+        HMAP_FOR_EACH (br, node, &all_bridges) {
+            struct iface *iface;
+
+            HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) {
+                iface_refresh_cfm_stats(iface);
+            }
+        }
+    }
+
+    if (ovsdb_idl_txn_commit(txn) != TXN_INCOMPLETE) {
+        ovsdb_idl_txn_destroy(txn);
+        txn = NULL;
+    }
+}
+
 void
 bridge_run(void)
 {
@@ -1531,7 +1561,9 @@ bridge_run(void)
                 struct iface *iface;
 
                 LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
-                    changed = iface_refresh_cfm_stats(iface) || changed;
+                    /* XXX: Eventually we need to remove the lacp_current flag
+                     * from the database so that we can completely get rid of
+                     * this rate limiter code. */
                     changed = iface_refresh_lacp_stats(iface) || changed;
                 }
             }
@@ -1544,6 +1576,8 @@ bridge_run(void)
         ovsdb_idl_txn_commit(txn);
         ovsdb_idl_txn_destroy(txn);
     }
+
+    refresh_cfm_stats();
 }
 
 void
@@ -2584,25 +2618,25 @@ static void
 iface_configure_cfm(struct iface *iface)
 {
     const struct ovsrec_interface *cfg = iface->cfg;
+    const char *extended_str;
     struct cfm_settings s;
-    uint16_t remote_mpid;
 
-    if (!cfg->n_cfm_mpid || !cfg->n_cfm_remote_mpid) {
+    if (!cfg->n_cfm_mpid) {
         ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port);
         return;
     }
 
     s.mpid = *cfg->cfm_mpid;
-    remote_mpid = *cfg->cfm_remote_mpid;
-    s.remote_mpids = &remote_mpid;
-    s.n_remote_mpids = 1;
-
     s.interval = atoi(get_interface_other_config(iface->cfg, "cfm_interval",
                                                  "0"));
     if (s.interval <= 0) {
         s.interval = 1000;
     }
 
+    extended_str = get_interface_other_config(iface->cfg, "cfm_extended",
+                                              "false");
+    s.extended = !strcasecmp("true", extended_str);
+
     ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, &s);
 }