A controller may want to know which MPIDs are reachable from an
interface configured with CFM.  This patch regularly writes this
information to the database.

Bug #7014.
---
 lib/cfm.c                  |   23 +++++++++++++++++++++++
 lib/cfm.h                  |    2 ++
 ofproto/ofproto-dpif.c     |   14 ++++++++++++++
 ofproto/ofproto-provider.h |   10 ++++++++++
 ofproto/ofproto.c          |   14 ++++++++++++++
 ofproto/ofproto.h          |    3 +++
 vswitchd/bridge.c          |   41 ++++++++++++++++++++++++++++++++++++++++-
 vswitchd/vswitch.ovsschema |    7 ++++++-
 8 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/lib/cfm.c b/lib/cfm.c
index 829b862..5d2615c 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -29,6 +29,7 @@
 #include "ofpbuf.h"
 #include "packets.h"
 #include "poll-loop.h"
+#include "sset.h"
 #include "timer.h"
 #include "timeval.h"
 #include "unixctl.h"
@@ -508,6 +509,28 @@ cfm_get_fault(const struct cfm *cfm)
     return cfm->fault;
 }
 
+/* Writes the MPIDs of the remote maintenance points reachable by 'cfm' to
+ * 'remote_mps'. No more than CFM_MAX_RMPS MPIDs will be written to
+ * 'remote_mps'.  Clears 'remote_mps' before modifying it. */
+void
+cfm_get_remote_mpids(const struct cfm *cfm, struct sset *remote_mps)
+{
+    struct remote_mp *rmp;
+
+    sset_clear(remote_mps);
+    HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) {
+        char *rmp_str;
+
+        if (cfm->extended) {
+            rmp_str = xasprintf(ETH_ADDR_FMT, ETH_ADDR_ARGS(rmp->mpid.mpidx));
+        } else {
+            rmp_str = xasprintf("%"PRIu16, rmp->mpid.mpid);
+        }
+
+        sset_add_and_free(remote_mps, rmp_str);
+    }
+}
+
 static struct cfm *
 cfm_find(const char *name)
 {
diff --git a/lib/cfm.h b/lib/cfm.h
index c167258..acd8c41 100644
--- a/lib/cfm.h
+++ b/lib/cfm.h
@@ -25,6 +25,7 @@
 
 struct flow;
 struct ofpbuf;
+struct sset;
 
 struct cfm_settings {
     uint16_t mpid;              /* The MPID of this CFM. */
@@ -45,5 +46,6 @@ bool cfm_configure(struct cfm *, const struct cfm_settings *);
 bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *);
 void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet);
 bool cfm_get_fault(const struct cfm *);
+void cfm_get_remote_mpids(const struct cfm *, struct sset *remote_mps);
 
 #endif /* cfm.h */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index a8c3b16..1aa1db6 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -813,6 +813,19 @@ get_cfm_fault(const struct ofport *ofport_)
 
     return ofport->cfm ? cfm_get_fault(ofport->cfm) : -1;
 }
+
+static int
+get_cfm_remote_mpids(const struct ofport *ofport_, struct sset *rmps)
+{
+    struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+
+    if (ofport->cfm) {
+        cfm_get_remote_mpids(ofport->cfm, rmps);
+        return 0;
+    } else {
+        return -1;
+    }
+}
 
 /* Bundles. */
 
@@ -4252,6 +4265,7 @@ const struct ofproto_class ofproto_dpif_class = {
     set_sflow,
     set_cfm,
     get_cfm_fault,
+    get_cfm_remote_mpids,
     bundle_set,
     bundle_remove,
     mirror_set,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 037dbae..02d2333 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -20,6 +20,7 @@
 /* Definitions for use within ofproto. */
 
 #include "ofproto/ofproto.h"
+#include "cfm.h"
 #include "classifier.h"
 #include "list.h"
 #include "shash.h"
@@ -873,6 +874,15 @@ struct ofproto_class {
      * not support CFM. */
     int (*get_cfm_fault)(const struct ofport *ofport);
 
+    /* Gets the MPIDs of the remote maintenance points broadcasting to
+     * 'ofport'.  Writes its result to 'rmps'  Returns a number less than 0 if
+     * CFM is not enabled of 'ofport'.
+     *
+     * This function may be a null pointer if the ofproto implementation does
+     * not support CFM. */
+    int (*get_cfm_remote_mpids)(const struct ofport *ofport,
+                                struct sset *rmps);
+
     /* If 's' is nonnull, this function registers a "bundle" associated with
      * client data pointer 'aux' in 'ofproto'.  A bundle is the same concept as
      * a Port in OVSDB, that is, it consists of one or more "slave" devices
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 849a376..d55ad65 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2003,6 +2003,20 @@ ofproto_port_get_cfm_fault(const struct ofproto 
*ofproto, uint16_t ofp_port)
             : -1);
 }
 
+/* Gets the MPIDs of the remote maintenance points broadcasting to 'ofp_port'
+ * within 'ofproto'.  Returns a number less than 0 if CFM is not enabled on
+ * 'ofp_port'. */
+int
+ofproto_port_get_cfm_remote_mpids(const struct ofproto *ofproto,
+                                  uint16_t ofp_port,
+                                  struct sset *rmps)
+{
+    struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
+    return (ofport && ofproto->ofproto_class->get_cfm_remote_mpids
+            ? ofproto->ofproto_class->get_cfm_remote_mpids(ofport, rmps)
+            : -1);
+}
+
 static int
 handle_aggregate_stats_request(struct ofconn *ofconn,
                                const struct ofp_stats_msg *osm)
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index e0c99ea..d0e4803 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include "cfm.h"
 #include "flow.h"
 #include "netflow.h"
 #include "sset.h"
@@ -235,6 +236,8 @@ void ofproto_get_all_flows(struct ofproto *p, struct ds *);
 void ofproto_get_netflow_ids(const struct ofproto *,
                              uint8_t *engine_type, uint8_t *engine_id);
 int ofproto_port_get_cfm_fault(const struct ofproto *, uint16_t ofp_port);
+int ofproto_port_get_cfm_remote_mpids(const struct ofproto *,
+                                      uint16_t ofp_port, struct sset *rmps);
 
 void ofproto_get_ofproto_controller_info(const struct ofproto *, struct shash 
*);
 void ofproto_free_ofproto_controller_info(struct shash *);
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index fbcaa2e..413fce4 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -1261,7 +1261,10 @@ iface_refresh_cfm_stats(struct iface *iface)
 {
     const struct ovsrec_interface *cfg = iface->cfg;
     bool changed = false;
-    int fault;
+
+    struct sset rmps = SSET_INITIALIZER(&rmps);
+    struct sset rmps_db = SSET_INITIALIZER(&rmps_db);
+    int fault, error;
 
     fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto,
                                        iface->ofp_port);
@@ -1269,12 +1272,43 @@ iface_refresh_cfm_stats(struct iface *iface)
         goto error;
     }
 
+    error = ofproto_port_get_cfm_remote_mpids(iface->port->bridge->ofproto,
+                                              iface->ofp_port, &rmps);
+    if (error) {
+        goto error;
+    }
+
     if (cfg->n_cfm_fault != 1 || cfg->cfm_fault[0] != fault) {
         bool fault_bool = fault;
         ovsrec_interface_set_cfm_fault(cfg, &fault_bool, 1);
         changed = true;
     }
 
+    sset_add_array(&rmps_db, cfg->cfm_remote_mpids,
+                   cfg->n_cfm_remote_mpids);
+
+    if (!sset_equals(&rmps, &rmps_db)) {
+        char *rmps_array[CFM_MAX_RMPS];
+        size_t n_rmps;
+
+        n_rmps = sset_to_array(&rmps, rmps_array, CFM_MAX_RMPS);
+
+        if (n_rmps < sset_count(&rmps)) {
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+
+            /* XXX:  Perhaps this information should be communicated in the
+             * database somehow. */
+            VLOG_WARN_RL(&rl, "%s: too many remote_mpids to write",
+                         iface->name);
+        }
+
+        ovsrec_interface_set_cfm_remote_mpids(cfg, rmps_array, n_rmps);
+        changed = true;
+    }
+
+    sset_destroy(&rmps);
+    sset_destroy(&rmps_db);
+
     return changed;
 
 error:
@@ -1284,6 +1318,11 @@ error:
         changed = true;
     }
 
+    if (cfg->n_cfm_remote_mpids) {
+        ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0);
+        changed = true;
+    }
+
     return changed;
 }
 
diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema
index 53cd1f0..5c550c0 100644
--- a/vswitchd/vswitch.ovsschema
+++ b/vswitchd/vswitch.ovsschema
@@ -1,6 +1,6 @@
 {"name": "Open_vSwitch",
  "version": "6.0.0",
- "cksum": "2055559034 14338",
+ "cksum": "1007312010 14478",
  "tables": {
    "Open_vSwitch": {
      "columns": {
@@ -171,6 +171,11 @@
            "key": {"type": "string"},
            "min": 0,
            "max": 1}},
+       "cfm_remote_mpids": {
+         "type": {
+           "key": {"type": "string"},
+           "min": 0,
+           "max": "unlimited"}},
        "cfm_fault": {
          "type": {
            "key": { "type": "boolean"},
-- 
1.7.6.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to