From 93b8df3853659238df58b1e1e69a0c5608e208f8 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Thu, 12 May 2011 15:28:43 -0700 Subject: [PATCH] cfm: Remove Maintenance_Point and Monitor tables. In an effort to make CFM easier to understand and configure, this patch removes the Maintenance_Point and Monitor tables from the database. As a consequence, users will only be able to configure one remote maintenance point. Furthermore, before this patch each remote maintenance point maintained its own separate fault flag in the database. This flag is no longer reported, users will need to infer the fault status from the global CFM fault flag. --- ChangeLog | 2 + lib/cfm.c | 41 ++++++++------- lib/cfm.h | 13 ----- ofproto/ofproto.c | 15 +++--- ofproto/ofproto.h | 3 +- utilities/ovs-vsctl.8.in | 19 ++----- utilities/ovs-vsctl.c | 10 ---- vswitchd/bridge.c | 48 +++++------------- vswitchd/vswitch.gv | 4 -- vswitchd/vswitch.ovsschema | 51 ++++++------------- vswitchd/vswitch.xml | 100 +++++++++++++------------------------ 11 files changed, 98 insertions(+), 208 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd0c40da..3c76a789 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ post v1.1.0 - Feature removals: - Dropped support for "tun_id_from_cookie" OpenFlow extension. (Use the extensible match extensions instead.) + - Removed the Maintenance_Point and Monitor tables in an effort + to simplify 802.1ag configuration. v1.1.0 - 05 Apr 2011 ------------------------ diff --git a/lib/cfm.c b/lib/cfm.c index e0a5121d..05c23828 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -49,6 +49,18 @@ struct cfm_internal { struct timer tx_timer; /* Send CCM when expired. */ struct timer fault_timer; /* Check for faults when expired. */ + + struct hmap remote_mps; /* Expected remote MPs. */ +}; + +/* Remote MPs represent foreign network entities that are configured to have + * the same MAID as this CFM instance. */ +struct remote_mp { + uint16_t mpid; /* The Maintenance Point ID of this 'remote_mp'. */ + struct hmap_node node; /* Node in 'remote_mps' map. */ + + bool recv; /* CCM was received since last fault check. */ + bool fault; /* Indicates a connectivity fault. */ }; static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); @@ -180,7 +192,7 @@ cfm_create(void) cfmi = xzalloc(sizeof *cfmi); cfm = &cfmi->cfm; - hmap_init(&cfm->remote_mps); + hmap_init(&cfmi->remote_mps); cfm_generate_maid(cfmi); list_push_back(&all_cfms, &cfmi->list_node); return cfm; @@ -196,12 +208,12 @@ cfm_destroy(struct cfm *cfm) return; } - HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfm->remote_mps) { - hmap_remove(&cfm->remote_mps, &rmp->node); + HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfmi->remote_mps) { + hmap_remove(&cfmi->remote_mps, &rmp->node); free(rmp); } - hmap_destroy(&cfm->remote_mps); + hmap_destroy(&cfmi->remote_mps); list_remove(&cfmi->list_node); free(cfmi); } @@ -217,7 +229,7 @@ cfm_run(struct cfm *cfm) struct remote_mp *rmp; cfm->fault = false; - HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) { + HMAP_FOR_EACH (rmp, node, &cfmi->remote_mps) { rmp->fault = !rmp->recv; rmp->recv = false; @@ -303,6 +315,7 @@ cfm_configure(struct cfm *cfm) void cfm_update_remote_mps(struct cfm *cfm, const uint16_t *mpids, size_t n_mpids) { + struct cfm_internal *cfmi = cfm_to_internal(cfm); size_t i; struct hmap new_rmps; struct remote_mp *rmp, *rmp_next; @@ -317,8 +330,8 @@ cfm_update_remote_mps(struct cfm *cfm, const uint16_t *mpids, size_t n_mpids) continue; } - if ((rmp = lookup_remote_mp(&cfm->remote_mps, mpid))) { - hmap_remove(&cfm->remote_mps, &rmp->node); + if ((rmp = lookup_remote_mp(&cfmi->remote_mps, mpid))) { + hmap_remove(&cfmi->remote_mps, &rmp->node); } else { rmp = xzalloc(sizeof *rmp); rmp->mpid = mpid; @@ -327,7 +340,7 @@ cfm_update_remote_mps(struct cfm *cfm, const uint16_t *mpids, size_t n_mpids) hmap_insert(&new_rmps, &rmp->node, hash_mpid(mpid)); } - hmap_swap(&new_rmps, &cfm->remote_mps); + hmap_swap(&new_rmps, &cfmi->remote_mps); HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &new_rmps) { hmap_remove(&new_rmps, &rmp->node); @@ -337,14 +350,6 @@ cfm_update_remote_mps(struct cfm *cfm, const uint16_t *mpids, size_t n_mpids) hmap_destroy(&new_rmps); } -/* Finds a 'remote_mp' with 'mpid' in 'cfm'. If no such 'remote_mp' exists - * returns NULL. */ -const struct remote_mp * -cfm_get_remote_mp(const struct cfm *cfm, uint16_t mpid) -{ - return lookup_remote_mp(&cfm->remote_mps, mpid); -} - /* Returns true if the CFM library should process packets from 'flow'. */ bool cfm_should_process_flow(const struct flow *flow) @@ -396,7 +401,7 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) ccm_mpid = ntohs(ccm->mpid); ccm_interval = ccm->flags & 0x7; - rmp = lookup_remote_mp(&cfm->remote_mps, ccm_mpid); + rmp = lookup_remote_mp(&cfmi->remote_mps, ccm_mpid); if (rmp) { rmp->recv = true; @@ -453,7 +458,7 @@ cfm_unixctl_show(struct unixctl_conn *conn, timer_msecs_until_expired(&cfmi->fault_timer)); ds_put_cstr(&ds, "\n"); - HMAP_FOR_EACH (rmp, node, &cfmi->cfm.remote_mps) { + HMAP_FOR_EACH (rmp, node, &cfmi->remote_mps) { ds_put_format(&ds, "Remote MPID %"PRIu16": %s\n", rmp->mpid, rmp->fault ? "fault" : ""); ds_put_format(&ds, "\trecv since check: %s", diff --git a/lib/cfm.h b/lib/cfm.h index 60e234ef..5472cda6 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -57,20 +57,9 @@ struct cfm { const char *name; /* Name of this CFM object. */ /* Statistics. */ - struct hmap remote_mps; /* Expected remote MPs. */ bool fault; /* Indicates connectivity vaults. */ }; -/* Remote MPs represent foreign network entities that are configured to have - * the same MAID as this CFM instance. */ -struct remote_mp { - uint16_t mpid; /* The Maintenance Point ID of this 'remote_mp'. */ - struct hmap_node node; /* In 'cfm' 'remote_mps' or 'x_remote_mps'. */ - - bool recv; /* CCM was received since last fault check. */ - bool fault; /* Indicates a connectivity fault. */ -}; - void cfm_init(void); struct cfm *cfm_create(void); @@ -89,8 +78,6 @@ bool cfm_configure(struct cfm *); void cfm_update_remote_mps(struct cfm *, const uint16_t *mpid, size_t n_mpids); -const struct remote_mp *cfm_get_remote_mp(const struct cfm *, uint16_t mpid); - bool cfm_should_process_flow(const struct flow *); void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index be0fccc7..6ba5561a 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -437,15 +437,14 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port) } /* Configures connectivity fault management on 'ofp_port' in 'ofproto'. Takes - * basic configuration from the configuration members in 'cfm', and the set of - * remote maintenance points from the 'n_remote_mps' elements in 'remote_mps'. - * Ignores the statistics members of 'cfm'. + * basic configuration from the configuration members in 'cfm', and the remote + * maintenance point ID from remote_mpid. Ignores the statistics members of + * 'cfm'. * * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */ void ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, - const struct cfm *cfm, - const uint16_t *remote_mps, size_t n_remote_mps) + const struct cfm *cfm, uint16_t remote_mpid) { struct ofport *ofport; int error; @@ -457,9 +456,11 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, return; } + /* XXX: For configuration simplicity, we only support one remote_mpid + * outside of the CFM module. It's not clear if this is the correct long + * term solution or not. */ error = (ofproto->ofproto_class->set_cfm - ? ofproto->ofproto_class->set_cfm(ofport, cfm, - remote_mps, n_remote_mps) + ? ofproto->ofproto_class->set_cfm(ofport, cfm, &remote_mpid, 1) : EOPNOTSUPP); if (error) { VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)", diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index ea9f98b3..125e977f 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -171,8 +171,7 @@ void ofproto_port_unregister(struct ofproto *, uint16_t ofp_port); void ofproto_port_clear_cfm(struct ofproto *, uint16_t ofp_port); void ofproto_port_set_cfm(struct ofproto *, uint16_t ofp_port, - const struct cfm *, - const uint16_t *remote_mps, size_t n_remote_mps); + const struct cfm *, uint16_t remote_mpid); const struct cfm *ofproto_port_get_cfm(struct ofproto *, uint16_t ofp_port); int ofproto_port_is_lacp_current(struct ofproto *, uint16_t ofp_port); diff --git a/utilities/ovs-vsctl.8.in b/utilities/ovs-vsctl.8.in index fcfec024..97944dfb 100644 --- a/utilities/ovs-vsctl.8.in +++ b/utilities/ovs-vsctl.8.in @@ -483,11 +483,6 @@ identified by port name. .IP "\fBQueue\fR" Configuration for one queue within a \fBQoS\fR configuration. Records may only be identified by UUID. -.IP "\fBMonitor\fR" -Connectivity Monitoring attached to an \fBInterface\fR. Records may be -identified by \fBInterface\fR name. -.IP "\fBMaintenance_Point\fR" -Maintenance Point managed by a \fBMonitor\fR. .IP "\fBMirror\fR" A port mirroring configuration attached to a bridge. Records may be identified by mirror name. @@ -783,19 +778,13 @@ their UUIDs, then "\fBovs\-vsctl destroy Queue \fIuuid1\fR \fIuuid2\fR" to destroy each of them.) .SS "Connectivity Monitoring" .PP -Create a Monitor which manages a couple of remote Maintenance Points on eth0. +Monitor connectivity to a remote maintenance point on eth0. .IP -.B "ovs\-vsctl \-\- set Interface eth0 Monitor=@newmon \(rs" -.IP -.B "\-\- \-\-id=@newmon create Monitor mpid=1 remote_mps=@mp2,@mp3 \(rs" -.IP -.B "\-\- \-\-id=@mp2 create Maintenance_Point mpid=2 \(rs" -.IP -.B "\-\- \-\-id=@mp3 create Maintenance_Point mpid=3" +.B "ovs\-vsctl set Interface eth0 cfm_mpid=1 cfm_remote_mpid=2" .PP -Deconfigure the Monitor record from above: +Deconfigure connectivity monitoring from above: .IP -.B "ovs\-vsctl clear Interface eth0 Monitor" +.B "ovs\-vsctl clear Interface eth0 cfm_mpid cfm_remote_mpid" .SS "NetFlow" .PP Configure bridge \fBbr0\fR to send NetFlow records to UDP port 5566 on diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 780d2427..664b9daa 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -2115,16 +2115,6 @@ static const struct vsctl_table_class tables[] = { {{&ovsrec_table_port, &ovsrec_port_col_name, &ovsrec_port_col_qos}, {NULL, NULL, NULL}}}, - {&ovsrec_table_monitor, - {{&ovsrec_table_interface, - &ovsrec_interface_col_name, - &ovsrec_interface_col_monitor}, - {NULL, NULL, NULL}}}, - - {&ovsrec_table_maintenance_point, - {{NULL, NULL, NULL}, - {NULL, NULL, NULL}}}, - {&ovsrec_table_queue, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}, diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index c7b0262d..4f20e804 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -244,10 +244,6 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_controller_col_status); ovsdb_idl_omit(idl, &ovsrec_controller_col_external_ids); - ovsdb_idl_omit_alert(idl, &ovsrec_maintenance_point_col_fault); - - ovsdb_idl_omit_alert(idl, &ovsrec_monitor_col_fault); - ovsdb_idl_omit(idl, &ovsrec_qos_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_queue_col_external_ids); @@ -1219,33 +1215,18 @@ iface_refresh_status(struct iface *iface) static bool iface_refresh_cfm_stats(struct iface *iface) { - const struct ovsrec_monitor *mon; + const struct ovsrec_interface *cfg = iface->cfg; const struct cfm *cfm; bool changed = false; - size_t i; - mon = iface->cfg->monitor; cfm = ofproto_port_get_cfm(iface->port->bridge->ofproto, iface->ofp_port); - if (!cfm || !mon) { + if (!cfm) { return false; } - for (i = 0; i < mon->n_remote_mps; i++) { - const struct ovsrec_maintenance_point *mp; - const struct remote_mp *rmp; - - mp = mon->remote_mps[i]; - rmp = cfm_get_remote_mp(cfm, mp->mpid); - - if (mp->n_fault != 1 || mp->fault[0] != rmp->fault) { - ovsrec_maintenance_point_set_fault(mp, &rmp->fault, 1); - changed = true; - } - } - - if (mon->n_fault != 1 || mon->fault[0] != cfm->fault) { - ovsrec_monitor_set_fault(mon, &cfm->fault, 1); + if (cfg->n_cfm_fault != 1 || cfg->cfm_fault[0] != cfm->fault) { + ovsrec_interface_set_cfm_fault(cfg, &cfm->fault, 1); changed = true; } @@ -2501,30 +2482,25 @@ iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos) static void iface_configure_cfm(struct iface *iface) { - size_t i; + const struct ovsrec_interface *cfg = iface->cfg; struct cfm cfm; - uint16_t *remote_mps; - struct ovsrec_monitor *mon; - - mon = iface->cfg->monitor; - if (!mon) { + if (!cfg->n_cfm_mpid || !cfg->n_cfm_remote_mpid) { ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port); return; } - cfm.mpid = mon->mpid; - cfm.interval = mon->interval ? *mon->interval : 1000; + cfm.mpid = *cfg->cfm_mpid; cfm.name = iface->name; + cfm.interval = atoi(get_interface_other_config(iface->cfg, + "cfm_interval", "0")); - remote_mps = xzalloc(mon->n_remote_mps * sizeof *remote_mps); - for(i = 0; i < mon->n_remote_mps; i++) { - remote_mps[i] = mon->remote_mps[i]->mpid; + if (cfm.interval <= 0) { + cfm.interval = 1000; } ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, - &cfm, remote_mps, mon->n_remote_mps); - free(remote_mps); + &cfm, *cfg->cfm_remote_mpid); } /* Read carrier or miimon status directly from 'iface''s netdev, according to diff --git a/vswitchd/vswitch.gv b/vswitchd/vswitch.gv index b5c2b562..35d1bacd 100644 --- a/vswitchd/vswitch.gv +++ b/vswitchd/vswitch.gv @@ -11,8 +11,6 @@ digraph Open_vSwitch { Bridge -> NetFlow [label="netflow"]; QoS [style=bold]; QoS -> Queue [label="queues value"]; - Monitor []; - Monitor -> Maintenance_Point [label="remote_mps"]; sFlow []; Open_vSwitch [style=bold]; Open_vSwitch -> Bridge [label="bridges"]; @@ -29,9 +27,7 @@ digraph Open_vSwitch { Mirror -> Port [style=dotted, constraint=false, label="output_port"]; Mirror -> Port [style=dotted, constraint=false, label="select_dst_port"]; Interface []; - Interface -> Monitor [label="monitor"]; NetFlow []; - Maintenance_Point []; Port []; Port -> QoS [label="qos"]; Port -> Interface [label="interfaces"]; diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 0622512c..4ad5c38b 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "3.5.0", - "cksum": "1684955806 14964", + "version": "4.0.0", + "cksum": "2606080158 14328", "tables": { "Open_vSwitch": { "columns": { @@ -162,9 +162,19 @@ "ofport": { "type": {"key": "integer", "min": 0, "max": 1}, "ephemeral": true}, - "monitor": { + "cfm_mpid": { "type": { - "key": {"type": "uuid", "refTable": "Monitor"}, + "key": {"type": "integer", "minInteger": 1, "maxInteger": 8191}, + "min": 0, + "max": 1}}, + "cfm_remote_mpid": { + "type" : { + "key": { "type": "integer", "minInteger": 1, "maxInteger": 8191}, + "min": 0, + "max": 1}}, + "cfm_fault": { + "type": { + "key": { "type": "boolean"}, "min": 0, "max": 1}}, "lacp_current": { @@ -199,39 +209,6 @@ "mtu": { "type": {"key": "integer", "min": 0, "max": 1}, "ephemeral": true}}}, - "Monitor": { - "columns": { - "mpid": { - "type" : { - "key": { "type": "integer", "minInteger": 1, "maxInteger": 8191}}}, - "interval": { - "type": { - "key": { "type": "integer", "minInteger": 100}, - "min": 0, - "max": 1}}, - "remote_mps": { - "type": { - "key": { "type": "uuid", "refTable": "Maintenance_Point"}, - "min": 0, - "max": "unlimited"}}, - "fault": { - "type": { - "key": { "type": "boolean"}, - "min": 0, - "max": 1}, - "ephemeral": true}}}, - "Maintenance_Point": { - "columns": { - "mpid": { - "type" : { - "key": { "type": "integer", "minInteger": 1, "maxInteger": 8191}}, - "mutable": false}, - "fault": { - "type": { - "key": { "type": "boolean"}, - "min": 0, - "max": 1}, - "ephemeral": true}}}, "QoS": { "columns": { "type": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index f9a82ccf..21486468 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1266,12 +1266,39 @@ - + +

+ 802.1ag Connectivity Fault Management (CFM) allows a group of + Maintenance Points (MPs) called a Maintenance Association (MA) to + detect connectivity problems with each other. MPs within a MA should + have complete and exclusive interconnectivity. This is verified by + occasionally broadcasting Continuity Check Messages (CCMs) at a + configurable transmission interval. +

+ + + A Maintenance Point ID (MPID) uniquely identifies each endpoint within + a Maintenance Association. The MPID is used to identify this endpoint + to other Maintenance Points in the MA. Each end of a link being + monitored should have a different MPID. Must be configured to enable + CFM on this . + - - Connectivity monitor configuration for this interface. + + The MPID of the remote endpoint being monitored. If this + does not have connectivity to an endpoint + advertising the configured MPID, a fault is signalled. Must be + configured to enable CFM on this + + Indicates a connectivity fault triggered by an inability to receive + heartbeats from the remote endpoint. + +
+ + + Boolean value indicating LACP status for this interface. If true, this interface has current LACP information about its LACP partner. This @@ -1322,6 +1349,10 @@ Key-value pairs for rarely used interface features.
+
cfm_interval
+
The transmission interval of CFM heartbeats in milliseconds. + Three missed heartbeat receptions indicate a connectivity fault. + Defaults to 1000ms.
bond-stable-id
A positive integer using in stable bond mode to make slave selection decisions. Allocating @@ -1534,69 +1565,6 @@ - -

- A attaches to an to - implement 802.1ag Connectivity Fault Management (CFM). CFM allows a - group of Maintenance Points (MPs) called a Maintenance Association (MA) - to detect connectivity problems with each other. MPs within a MA should - have complete and exclusive interconnectivity. This is verified by - occasionally broadcasting Continuity Check Messages (CCMs) at a - configurable transmission interval. A is - responsible for collecting data about other MPs in its MA and - broadcasting CCMs. -

- - - - A Maintenance Point ID (MPID) uniquely identifies each endpoint within - a Maintenance Association. The MPID is used to identify this - to other endpoints in the MA. - - - - A set of which this - should have connectivity to. If this - does not have connectivity to any MPs in this - set, or has connectivity to any MPs not in this set, a fault is - signaled. - - - - The transmission interval of CCMs in milliseconds. Three missed CCMs - indicate a connectivity fault. Defaults to 1000ms. - - - - - - Indicates a Connectivity Fault caused by a configuration error, a down - remote MP, or unexpected connectivity to a remote MAID or remote MP. - - -
- - -

- A represents a MP which a - has or should have connectivity to. -

- - - - A Maintenance Point ID (MPID) uniquely identifies each endpoint within - a Maintenance Association. All MPs within a MA should have a unique - MPID. - - - - - - Indicates a connectivity fault. - - -
-

A port mirror within a .

A port mirror configures a bridge to send selected frames to special -- 2.30.2