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
[email protected]
http://openvswitch.org/mailman/listinfo/dev