diff options
| -rw-r--r-- | ChangeLog | 2 | ||||
| -rw-r--r-- | lib/cfm.c | 41 | ||||
| -rw-r--r-- | lib/cfm.h | 13 | ||||
| -rw-r--r-- | ofproto/ofproto.c | 15 | ||||
| -rw-r--r-- | ofproto/ofproto.h | 3 | ||||
| -rw-r--r-- | utilities/ovs-vsctl.8.in | 19 | ||||
| -rw-r--r-- | utilities/ovs-vsctl.c | 10 | ||||
| -rw-r--r-- | vswitchd/bridge.c | 48 | ||||
| -rw-r--r-- | vswitchd/vswitch.gv | 4 | ||||
| -rw-r--r-- | vswitchd/vswitch.ovsschema | 51 | ||||
| -rw-r--r-- | vswitchd/vswitch.xml | 100 |
11 files changed, 98 insertions, 208 deletions
@@ -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 ------------------------ @@ -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", @@ -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 be0fccc7a..6ba5561ab 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 ea9f98b3d..125e977f9 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 fcfec0246..97944dfb6 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 780d24277..664b9daac 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 c7b0262d6..4f20e804a 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 b5c2b562e..35d1bacd3 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 0622512c6..4ad5c38b2 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 f9a82ccf0..214864682 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -1266,12 +1266,39 @@ </column> </group> - <group title="Other Features"> + <group title="Connectivity Fault Management"> + <p> + 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. + </p> + + <column name="cfm_mpid"> + 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 <ref table="Interface"/>. + </column> - <column name="monitor"> - Connectivity monitor configuration for this interface. + <column name="cfm_remote_mpid"> + The MPID of the remote endpoint being monitored. If this + <ref table="Interface"/> does not have connectivity to an endpoint + advertising the configured MPID, a fault is signalled. Must be + configured to enable CFM on this <ref table="Interface"/> </column> + <column name="cfm_fault"> + Indicates a connectivity fault triggered by an inability to receive + heartbeats from the remote endpoint. + </column> + </group> + + <group title="Other Features"> + <column name="lacp_current"> 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 @@ <column name="other_config"> Key-value pairs for rarely used interface features. <dl> + <dt><code>cfm_interval</code></dt> + <dd> The transmission interval of CFM heartbeats in milliseconds. + Three missed heartbeat receptions indicate a connectivity fault. + Defaults to 1000ms. </dd> <dt><code>bond-stable-id</code></dt> <dd> A positive integer using in <code>stable</code> bond mode to make slave selection decisions. Allocating @@ -1534,69 +1565,6 @@ </column> </table> - <table name="Monitor" title="Connectivity Monitor configuration"> - <p> - A <ref table="Monitor"/> attaches to an <ref table="Interface"/> 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 <ref table="Monitor"/> is - responsible for collecting data about other MPs in its MA and - broadcasting CCMs. - </p> - - <group title="Monitor Configuration"> - <column name="mpid"> - A Maintenance Point ID (MPID) uniquely identifies each endpoint within - a Maintenance Association. The MPID is used to identify this - <ref table="Monitor"/> to other endpoints in the MA. - </column> - - <column name="remote_mps"> - A set of <ref table="Maintenance_Points"/> which this - <ref table="Monitor"/> should have connectivity to. If this - <ref table="Monitor"/> does not have connectivity to any MPs in this - set, or has connectivity to any MPs not in this set, a fault is - signaled. - </column> - - <column name="interval"> - The transmission interval of CCMs in milliseconds. Three missed CCMs - indicate a connectivity fault. Defaults to 1000ms. - </column> - </group> - - <group title="Monitor Status"> - <column name="fault"> - Indicates a Connectivity Fault caused by a configuration error, a down - remote MP, or unexpected connectivity to a remote MAID or remote MP. - </column> - </group> - </table> - - <table name="Maintenance_Point" title="Maintenance Point configuration"> - <p> - A <ref table="Maintenance_Point"/> represents a MP which a - <ref table="Monitor"/> has or should have connectivity to. - </p> - - <group title="Maintenance_Point Configuration"> - <column name="mpid"> - A Maintenance Point ID (MPID) uniquely identifies each endpoint within - a Maintenance Association. All MPs within a MA should have a unique - MPID. - </column> - </group> - - <group title="Maintenance_Point Status"> - <column name="fault"> - Indicates a connectivity fault. - </column> - </group> - </table> - <table name="Mirror" title="Port mirroring (SPAN/RSPAN)."> <p>A port mirror within a <ref table="Bridge"/>.</p> <p>A port mirror configures a bridge to send selected frames to special |
