From 1de11730e612b09e28892880c2845185497a3741 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Fri, 26 Aug 2011 14:54:34 -0700 Subject: [PATCH] cfm: Write remote MPIDs to the database. 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 | 24 ++++++++++++++++++++++++ lib/cfm.h | 2 ++ ofproto/ofproto-dpif.c | 15 +++++++++++++++ ofproto/ofproto-provider.h | 11 +++++++++++ ofproto/ofproto.c | 19 +++++++++++++++++++ ofproto/ofproto.h | 4 ++++ vswitchd/bridge.c | 14 +++++++++++++- vswitchd/vswitch.ovsschema | 7 ++++++- 8 files changed, 94 insertions(+), 2 deletions(-) diff --git a/lib/cfm.c b/lib/cfm.c index 245ce4487..bc59b62c1 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -88,6 +88,11 @@ struct cfm { struct timer fault_timer; /* Check for faults when expired. */ struct hmap remote_mps; /* Remote MPs. */ + + /* Result of cfm_get_remote_mpids(). Updated only during fault check to + * avoid flapping. */ + uint64_t *rmps_array; /* Cache of remote_mps. */ + size_t rmps_array_len; /* Number of rmps in 'rmps_array'. */ }; /* Remote MPs represent foreign network entities that are configured to have @@ -249,6 +254,7 @@ cfm_destroy(struct cfm *cfm) hmap_destroy(&cfm->remote_mps); hmap_remove(&all_cfms, &cfm->hmap_node); + free(cfm->rmps_array); free(cfm->name); free(cfm); } @@ -264,6 +270,11 @@ cfm_run(struct cfm *cfm) cfm->fault = cfm->unexpected_recv; cfm->unexpected_recv = false; + cfm->rmps_array_len = 0; + free(cfm->rmps_array); + cfm->rmps_array = xmalloc(hmap_count(&cfm->remote_mps) * + sizeof *cfm->rmps_array); + HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfm->remote_mps) { if (!rmp->recv) { @@ -285,6 +296,8 @@ cfm_run(struct cfm *cfm) rmp->mpid); cfm->fault = true; } + + cfm->rmps_array[cfm->rmps_array_len++] = rmp->mpid; } } @@ -480,6 +493,17 @@ cfm_get_fault(const struct cfm *cfm) return cfm->fault; } +/* Populates 'rmps' with an array of remote maintenance points reachable by + * 'cfm'. The number of remote maintenance points is written to 'n_rmps'. + * 'cfm' retains ownership of the array written to 'rmps' */ +void +cfm_get_remote_mpids(const struct cfm *cfm, const uint64_t **rmps, + size_t *n_rmps) +{ + *rmps = cfm->rmps_array; + *n_rmps = cfm->rmps_array_len; +} + static struct cfm * cfm_find(const char *name) { diff --git a/lib/cfm.h b/lib/cfm.h index 86d62d760..a031ab225 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -41,5 +41,7 @@ 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 *, const uint64_t **rmps, + size_t *n_rmps); #endif /* cfm.h */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 9a7132141..5d93153a1 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -813,6 +813,20 @@ 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_, const uint64_t **rmps, + size_t *n_rmps) +{ + struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); + + if (ofport->cfm) { + cfm_get_remote_mpids(ofport->cfm, rmps, n_rmps); + return 0; + } else { + return -1; + } +} /* Bundles. */ @@ -4252,6 +4266,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 82844186f..fa583f869 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" @@ -878,6 +879,16 @@ 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'. Populates 'rmps' with a provider owned array of MPIDs, and + * 'n_rmps' with the number of MPIDs in '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, + const uint64_t **rmps, size_t *n_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 15bcd1350..cbd892815 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2003,6 +2003,25 @@ 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'. Populates 'rmps' with an array of MPIDs owned by + * 'ofproto', and 'n_rmps' with the number of MPIDs in 'rmps'. 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, const uint64_t **rmps, + size_t *n_rmps) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + + *rmps = NULL; + *n_rmps = 0; + return (ofport && ofproto->ofproto_class->get_cfm_remote_mpids + ? ofproto->ofproto_class->get_cfm_remote_mpids(ofport, rmps, + n_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 e0c99eac8..3552aac4d 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -22,6 +22,7 @@ #include #include #include +#include "cfm.h" #include "flow.h" #include "netflow.h" #include "sset.h" @@ -235,6 +236,9 @@ 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, const uint64_t **rmps, + size_t *n_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 44b5fbe94..abea4f348 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -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); @@ -1262,7 +1263,9 @@ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - 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); @@ -1272,6 +1275,15 @@ iface_refresh_cfm_stats(struct iface *iface) } else { ovsrec_interface_set_cfm_fault(cfg, NULL, 0); } + + 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 diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 4a009b0df..25047b5ce 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", "version": "6.0.0", - "cksum": "277444055 14339", + "cksum": "3439303729 14480", "tables": { "Open_vSwitch": { "columns": { @@ -171,6 +171,11 @@ "key": {"type": "integer"}, "min": 0, "max": 1}}, + "cfm_remote_mpids": { + "type": { + "key": {"type": "integer"}, + "min": 0, + "max": "unlimited"}}, "cfm_fault": { "type": { "key": { "type": "boolean"}, -- 2.43.0