From: Ethan Jackson Date: Fri, 13 May 2011 22:37:23 +0000 (-0700) Subject: cfm: Cleanup CFM module interface. X-Git-Tag: v1.2.0~315 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=a56104575c4db202bfc5db3079ea969820d77867;p=sliver-openvswitch.git cfm: Cleanup CFM module interface. This patch makes the CFM module interface a bit more like the LACP module interface. In my opinion it's much cleaner. --- diff --git a/lib/cfm.c b/lib/cfm.c index 05c23828d..85af22c42 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -38,10 +38,13 @@ VLOG_DEFINE_THIS_MODULE(cfm); #define CCM_OPCODE 1 /* CFM message opcode meaning CCM. */ -struct cfm_internal { - struct cfm cfm; +struct cfm { + uint16_t mpid; struct list list_node; /* Node in all_cfms list. */ + bool fault; /* Indicates connectivity fault. */ + char *name; /* Name of this CFM object. */ + uint32_t seq; /* The sequence number of our last CCM. */ uint8_t ccm_interval; /* The CCM transmission interval. */ int ccm_interval_ms; /* 'ccm_interval' in milliseconds. */ @@ -70,25 +73,25 @@ static void cfm_unixctl_show(struct unixctl_conn *, const char *args, void *aux); static void -cfm_generate_maid(struct cfm_internal *cfmi) +cfm_generate_maid(struct cfm *cfm) { const char *ovs_md_name = "ovs_md"; const char *ovs_ma_name = "ovs_ma"; uint8_t *ma_p; size_t md_len, ma_len; - memset(cfmi->maid, 0, CCM_MAID_LEN); + memset(cfm->maid, 0, CCM_MAID_LEN); md_len = strlen(ovs_md_name); ma_len = strlen(ovs_ma_name); assert(md_len && ma_len && md_len + ma_len + 4 <= CCM_MAID_LEN); - cfmi->maid[0] = 4; /* MD name string format. */ - cfmi->maid[1] = md_len; /* MD name size. */ - memcpy(&cfmi->maid[2], ovs_md_name, md_len); /* MD name. */ + cfm->maid[0] = 4; /* MD name string format. */ + cfm->maid[1] = md_len; /* MD name size. */ + memcpy(&cfm->maid[2], ovs_md_name, md_len); /* MD name. */ - ma_p = cfmi->maid + 2 + md_len; + ma_p = cfm->maid + 2 + md_len; ma_p[0] = 2; /* MA name string format. */ ma_p[1] = ma_len; /* MA name size. */ memcpy(&ma_p[2], ovs_ma_name, ma_len); /* MA name. */ @@ -113,7 +116,7 @@ ccm_interval_to_ms(uint8_t interval) } static long long int -cfm_fault_interval(struct cfm_internal *cfmi) +cfm_fault_interval(struct cfm *cfm) { /* According to the 802.1ag specification we should assume every other MP * with the same MAID has the same transmission interval that we have. If @@ -123,7 +126,7 @@ cfm_fault_interval(struct cfm_internal *cfmi) * * According to the specification we should check when (ccm_interval_ms * * 3.5)ms have passed. */ - return (cfmi->ccm_interval_ms * 7) / 2; + return (cfm->ccm_interval_ms * 7) / 2; } static uint8_t @@ -140,12 +143,6 @@ ms_to_ccm_interval(int interval_ms) return 1; } -static struct cfm_internal * -cfm_to_internal(const struct cfm *cfm) -{ - return CONTAINER_OF(cfm, struct cfm_internal, cfm); -} - static uint32_t hash_mpid(uint8_t mpid) { @@ -187,49 +184,44 @@ struct cfm * cfm_create(void) { struct cfm *cfm; - struct cfm_internal *cfmi; - cfmi = xzalloc(sizeof *cfmi); - cfm = &cfmi->cfm; - - hmap_init(&cfmi->remote_mps); - cfm_generate_maid(cfmi); - list_push_back(&all_cfms, &cfmi->list_node); + cfm = xzalloc(sizeof *cfm); + hmap_init(&cfm->remote_mps); + cfm_generate_maid(cfm); + list_push_back(&all_cfms, &cfm->list_node); return cfm; } void cfm_destroy(struct cfm *cfm) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); struct remote_mp *rmp, *rmp_next; if (!cfm) { return; } - HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfmi->remote_mps) { - hmap_remove(&cfmi->remote_mps, &rmp->node); + HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &cfm->remote_mps) { + hmap_remove(&cfm->remote_mps, &rmp->node); free(rmp); } - hmap_destroy(&cfmi->remote_mps); - list_remove(&cfmi->list_node); - free(cfmi); + hmap_destroy(&cfm->remote_mps); + list_remove(&cfm->list_node); + free(cfm); } /* Should be run periodically to update fault statistics messages. */ void cfm_run(struct cfm *cfm) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); - if (timer_expired(&cfmi->fault_timer)) { - long long int interval = cfm_fault_interval(cfmi); + if (timer_expired(&cfm->fault_timer)) { + long long int interval = cfm_fault_interval(cfm); struct remote_mp *rmp; cfm->fault = false; - HMAP_FOR_EACH (rmp, node, &cfmi->remote_mps) { + HMAP_FOR_EACH (rmp, node, &cfm->remote_mps) { rmp->fault = !rmp->recv; rmp->recv = false; @@ -244,7 +236,7 @@ cfm_run(struct cfm *cfm) VLOG_DBG("All RMPs received CCMs in the last %lldms", interval); } - timer_set_duration(&cfmi->fault_timer, interval); + timer_set_duration(&cfm->fault_timer, interval); } } @@ -253,9 +245,8 @@ cfm_run(struct cfm *cfm) bool cfm_should_send_ccm(struct cfm *cfm) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); - return timer_expired(&cfmi->tx_timer); + return timer_expired(&cfm->tx_timer); } /* Composes a CCM message into 'ccm'. Messages generated with this function @@ -263,75 +254,66 @@ cfm_should_send_ccm(struct cfm *cfm) void cfm_compose_ccm(struct cfm *cfm, struct ccm *ccm) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); - - timer_set_duration(&cfmi->tx_timer, cfmi->ccm_interval_ms); + timer_set_duration(&cfm->tx_timer, cfm->ccm_interval_ms); ccm->mdlevel_version = 0; ccm->opcode = CCM_OPCODE; ccm->tlv_offset = 70; - ccm->seq = htonl(++cfmi->seq); - ccm->mpid = htons(cfmi->cfm.mpid); - ccm->flags = cfmi->ccm_interval; - memcpy(ccm->maid, cfmi->maid, sizeof ccm->maid); + ccm->seq = htonl(++cfm->seq); + ccm->mpid = htons(cfm->mpid); + ccm->flags = cfm->ccm_interval; + memcpy(ccm->maid, cfm->maid, sizeof ccm->maid); } void cfm_wait(struct cfm *cfm) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); - timer_wait(&cfmi->tx_timer); - timer_wait(&cfmi->fault_timer); + timer_wait(&cfm->tx_timer); + timer_wait(&cfm->fault_timer); } -/* Should be called whenever a client of the cfm library changes the internals - * of 'cfm'. Returns true if 'cfm' is valid. */ +/* Configures 'cfm' with settings from 's'. */ bool -cfm_configure(struct cfm *cfm) +cfm_configure(struct cfm *cfm, const struct cfm_settings *s) { - struct cfm_internal *cfmi = cfm_to_internal(cfm); + size_t i; uint8_t interval; + struct hmap new_rmps; + struct remote_mp *rmp, *rmp_next; - if (!cfm_is_valid_mpid(cfm->mpid) || !cfm->interval) { + if (!cfm_is_valid_mpid(s->mpid) || s->interval <= 0 + || s->n_remote_mpids <= 0) { return false; } - interval = ms_to_ccm_interval(cfm->interval); - - if (interval != cfmi->ccm_interval) { - cfmi->ccm_interval = interval; - cfmi->ccm_interval_ms = ccm_interval_to_ms(interval); + cfm->mpid = s->mpid; + interval = ms_to_ccm_interval(s->interval); - timer_set_expired(&cfmi->tx_timer); - timer_set_duration(&cfmi->fault_timer, cfm_fault_interval(cfmi)); + if (!cfm->name || strcmp(s->name, cfm->name)) { + free(cfm->name); + cfm->name = xstrdup(s->name); } - return true; -} + if (interval != cfm->ccm_interval) { + cfm->ccm_interval = interval; + cfm->ccm_interval_ms = ccm_interval_to_ms(interval); -/* Given an array of MPIDs, updates the 'remote_mps' map of 'cfm' to reflect - * it. Invalid MPIDs are skipped. */ -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; + timer_set_expired(&cfm->tx_timer); + timer_set_duration(&cfm->fault_timer, cfm_fault_interval(cfm)); + } hmap_init(&new_rmps); - - for (i = 0; i < n_mpids; i++) { - uint16_t mpid = mpids[i]; + for (i = 0; i < s->n_remote_mpids; i++) { + uint16_t mpid = s->remote_mpids[i]; if (!cfm_is_valid_mpid(mpid) || lookup_remote_mp(&new_rmps, mpid)) { continue; } - if ((rmp = lookup_remote_mp(&cfmi->remote_mps, mpid))) { - hmap_remove(&cfmi->remote_mps, &rmp->node); + if ((rmp = lookup_remote_mp(&cfm->remote_mps, mpid))) { + hmap_remove(&cfm->remote_mps, &rmp->node); } else { rmp = xzalloc(sizeof *rmp); rmp->mpid = mpid; @@ -340,14 +322,14 @@ 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, &cfmi->remote_mps); - + hmap_swap(&new_rmps, &cfm->remote_mps); HMAP_FOR_EACH_SAFE (rmp, rmp_next, node, &new_rmps) { hmap_remove(&new_rmps, &rmp->node); free(rmp); } - hmap_destroy(&new_rmps); + + return true; } /* Returns true if the CFM library should process packets from 'flow'. */ @@ -369,7 +351,6 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) uint8_t ccm_interval; struct remote_mp *rmp; struct eth_header *eth; - struct cfm_internal *cfmi = cfm_to_internal(cfm); eth = p->l2; ccm = ofpbuf_at(p, (uint8_t *)p->l3 - (uint8_t *)p->data, CCM_LEN); @@ -394,19 +375,19 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) * them judiciously, especially when CFM is used to check slave status of * bonds. Furthermore, faults can be maliciously triggered by crafting * invalid CCMs. */ - if (memcmp(ccm->maid, cfmi->maid, sizeof ccm->maid)) { + if (memcmp(ccm->maid, cfm->maid, sizeof ccm->maid)) { VLOG_WARN_RL(&rl, "Received unexpected remote MAID from MAC " ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src)); } else { ccm_mpid = ntohs(ccm->mpid); ccm_interval = ccm->flags & 0x7; - rmp = lookup_remote_mp(&cfmi->remote_mps, ccm_mpid); + rmp = lookup_remote_mp(&cfm->remote_mps, ccm_mpid); if (rmp) { rmp->recv = true; - if (ccm_interval != cfmi->ccm_interval) { + if (ccm_interval != cfm->ccm_interval) { VLOG_WARN_RL(&rl, "received a CCM with an invalid interval" " (%"PRIu8") from RMP %"PRIu16, ccm_interval, rmp->mpid); @@ -421,14 +402,22 @@ cfm_process_heartbeat(struct cfm *cfm, const struct ofpbuf *p) } } -static struct cfm_internal * +/* Gets the fault status of 'cfm'. Returns true when 'cfm' has detected + * connectivity problems, false otherwise. */ +bool +cfm_get_fault(const struct cfm *cfm) +{ + return cfm->fault; +} + +static struct cfm * cfm_find(const char *name) { - struct cfm_internal *cfmi; + struct cfm *cfm; - LIST_FOR_EACH (cfmi, list_node, &all_cfms) { - if (cfmi->cfm.name && !strcmp(cfmi->cfm.name, name)) { - return cfmi; + LIST_FOR_EACH (cfm, list_node, &all_cfms) { + if (cfm->name && !strcmp(cfm->name, name)) { + return cfm; } } return NULL; @@ -439,26 +428,26 @@ cfm_unixctl_show(struct unixctl_conn *conn, const char *args, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; - const struct cfm_internal *cfmi; + const struct cfm *cfm; struct remote_mp *rmp; - cfmi = cfm_find(args); - if (!cfmi) { + cfm = cfm_find(args); + if (!cfm) { unixctl_command_reply(conn, 501, "no such CFM object"); return; } - ds_put_format(&ds, "MPID %"PRIu16": %s\n", cfmi->cfm.mpid, - cfmi->cfm.fault ? "fault" : ""); + ds_put_format(&ds, "MPID %"PRIu16": %s\n", cfm->mpid, + cfm->fault ? "fault" : ""); - ds_put_format(&ds, "\tinterval: %dms\n", cfmi->ccm_interval_ms); + ds_put_format(&ds, "\tinterval: %dms\n", cfm->ccm_interval_ms); ds_put_format(&ds, "\tnext CCM tx: %lldms\n", - timer_msecs_until_expired(&cfmi->tx_timer)); + timer_msecs_until_expired(&cfm->tx_timer)); ds_put_format(&ds, "\tnext fault check: %lldms\n", - timer_msecs_until_expired(&cfmi->fault_timer)); + timer_msecs_until_expired(&cfm->fault_timer)); ds_put_cstr(&ds, "\n"); - HMAP_FOR_EACH (rmp, node, &cfmi->remote_mps) { + HMAP_FOR_EACH (rmp, node, &cfm->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 5472cda67..02f50d5fd 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -47,17 +47,13 @@ struct ccm { } __attribute__((packed)); BUILD_ASSERT_DECL(CCM_LEN == sizeof(struct ccm)); -/* A 'cfm' represent a local Maintenance Point (MP) and its Connectivity Fault - * Management (CFM) state machine. Its configuration variables should be set - * by clients of the CFM library. */ -struct cfm { - /* Configuration Variables. */ +struct cfm_settings { uint16_t mpid; /* The MPID of this CFM. */ int interval; /* The requested transmission interval. */ const char *name; /* Name of this CFM object. */ - /* Statistics. */ - bool fault; /* Indicates connectivity vaults. */ + const uint16_t *remote_mpids; /* Array of remote MPIDs */ + size_t n_remote_mpids; /* Number of MPIDs in 'remote_mpids'. */ }; void cfm_init(void); @@ -74,12 +70,12 @@ void cfm_compose_ccm(struct cfm *, struct ccm *); void cfm_wait(struct cfm *); -bool cfm_configure(struct cfm *); - -void cfm_update_remote_mps(struct cfm *, const uint16_t *mpid, size_t n_mpids); +bool cfm_configure(struct cfm *, const struct cfm_settings *); bool cfm_should_process_flow(const struct flow *); void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet); +bool cfm_get_fault(const struct cfm *); + #endif /* cfm.h */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 77022213b..0e55f0c41 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -296,8 +296,7 @@ ofport_dpif_cast(const struct ofport *ofport) static void port_run(struct ofport_dpif *); static void port_wait(struct ofport_dpif *); -static int set_cfm(struct ofport *, const struct cfm *, - const uint16_t *remote_mps, size_t n_remote_mps); +static int set_cfm(struct ofport *, const struct cfm_settings *); struct ofproto_dpif { struct ofproto up; @@ -681,7 +680,7 @@ port_destruct(struct ofport *port_) struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto); bundle_remove(port_); - set_cfm(port_, NULL, NULL, 0); + set_cfm(port_, NULL); if (ofproto->sflow) { ofproto_sflow_del_port(ofproto->sflow, port->odp_port); } @@ -735,26 +734,19 @@ set_sflow(struct ofproto *ofproto_, } static int -set_cfm(struct ofport *ofport_, const struct cfm *cfm, - const uint16_t *remote_mps, size_t n_remote_mps) +set_cfm(struct ofport *ofport_, const struct cfm_settings *s) { struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); int error; - if (!cfm) { + if (!s) { error = 0; } else { if (!ofport->cfm) { ofport->cfm = cfm_create(); } - ofport->cfm->mpid = cfm->mpid; - ofport->cfm->interval = cfm->interval; - ofport->cfm->name = cfm->name; - - cfm_update_remote_mps(ofport->cfm, remote_mps, n_remote_mps); - - if (cfm_configure(ofport->cfm)) { + if (cfm_configure(ofport->cfm, s)) { return 0; } @@ -766,11 +758,11 @@ set_cfm(struct ofport *ofport_, const struct cfm *cfm, } static int -get_cfm(struct ofport *ofport_, const struct cfm **cfmp) +get_cfm_fault(const struct ofport *ofport_) { struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); - *cfmp = ofport->cfm; - return 0; + + return ofport->cfm ? cfm_get_fault(ofport->cfm) : -1; } /* Bundles. */ @@ -3947,7 +3939,7 @@ const struct ofproto_class ofproto_dpif_class = { get_netflow_ids, set_sflow, set_cfm, - get_cfm, + get_cfm_fault, bundle_set, bundle_remove, mirror_set, diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 6ba5561ab..ac646e504 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -432,7 +432,7 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port) { struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); if (ofport && ofproto->ofproto_class->set_cfm) { - ofproto->ofproto_class->set_cfm(ofport, NULL, NULL, 0); + ofproto->ofproto_class->set_cfm(ofport, NULL); } } @@ -444,7 +444,7 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port) * 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, uint16_t remote_mpid) + const struct cfm_settings *s) { struct ofport *ofport; int error; @@ -460,7 +460,7 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, * 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_mpid, 1) + ? ofproto->ofproto_class->set_cfm(ofport, s) : EOPNOTSUPP); if (error) { VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)", @@ -469,22 +469,6 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, } } -/* Returns the connectivity fault management object associated with 'ofp_port' - * within 'ofproto', or a null pointer if 'ofproto' does not have a port - * 'ofp_port' or if that port does not have CFM configured. The caller must - * not modify or destroy the returned object. */ -const struct cfm * -ofproto_port_get_cfm(struct ofproto *ofproto, uint16_t ofp_port) -{ - struct ofport *ofport; - const struct cfm *cfm; - - ofport = ofproto_get_port(ofproto, ofp_port); - return (ofport - && ofproto->ofproto_class->get_cfm - && !ofproto->ofproto_class->get_cfm(ofport, &cfm)) ? cfm : NULL; -} - /* Checks the status of LACP negotiation for 'ofp_port' within ofproto. * Returns 1 if LACP partner information for 'ofp_port' is up-to-date, * 0 if LACP partner information is not current (generally indicating a @@ -1107,7 +1091,7 @@ ofproto_port_unregister(struct ofproto *ofproto, uint16_t ofp_port) struct ofport *port = ofproto_get_port(ofproto, ofp_port); if (port) { if (port->ofproto->ofproto_class->set_cfm) { - port->ofproto->ofproto_class->set_cfm(port, NULL, NULL, 0); + port->ofproto->ofproto_class->set_cfm(port, NULL); } if (port->ofproto->ofproto_class->bundle_remove) { port->ofproto->ofproto_class->bundle_remove(port); @@ -2003,6 +1987,18 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto, ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id); } +/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'. Returns 1 + * if CFM is faulted (generally indiciating a connectivity problem), 0 if CFM + * is not faulted, and -1 if CFM is not enabled on 'ofp_port'. */ +int +ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + return (ofport && ofproto->ofproto_class->get_cfm_fault + ? ofproto->ofproto_class->get_cfm_fault(ofport) + : -1); +} + static void query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target, ovs_be16 out_port, uint8_t table_id, diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 125e977f9..53ed69128 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -31,7 +31,7 @@ extern "C" { #endif -struct cfm; +struct cfm_settings; struct cls_rule; struct netdev; struct ofproto; @@ -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 *, uint16_t remote_mpid); -const struct cfm *ofproto_port_get_cfm(struct ofproto *, uint16_t ofp_port); + const struct cfm_settings *); int ofproto_port_is_lacp_current(struct ofproto *, uint16_t ofp_port); /* Configuration of bundles. */ @@ -230,6 +229,7 @@ void ofproto_get_snoops(const struct ofproto *, struct sset *); 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); void ofproto_get_ofproto_controller_info(const struct ofproto *, struct shash *); void ofproto_free_ofproto_controller_info(struct shash *); diff --git a/ofproto/private.h b/ofproto/private.h index 16d30d502..db0edef1e 100644 --- a/ofproto/private.h +++ b/ofproto/private.h @@ -653,25 +653,22 @@ struct ofproto_class { /* Configures connectivity fault management on 'ofport'. * - * If 'cfm' is nonnull, 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'. + * If 'cfm_settings' is nonnull, configures CFM according to its members. * - * If 'cfm' is null, removes any connectivity fault management + * If 'cfm_settings' is null, removes any connectivity fault management * configuration from 'ofport'. * * EOPNOTSUPP as a return value indicates that this ofproto_class does not * support CFM, as does a null pointer. */ - int (*set_cfm)(struct ofport *ofport, const struct cfm *cfm, - const uint16_t *remote_mps, size_t n_remote_mps); + int (*set_cfm)(struct ofport *ofport, const struct cfm_settings *s); - /* Stores the connectivity fault management object associated with 'ofport' - * in '*cfmp'. Stores a null pointer in '*cfmp' if CFM is not configured - * on 'ofport'. The caller must not modify or destroy the returned object. + /* Checks the fault status of CFM configured on 'ofport'. Returns 1 if CFM + * is faulted (generally indicating a connectivity problem), 0 if CFM is + * not faulted, or -1 if CFM is not enabled on 'port' * - * This function may be NULL if this ofproto_class does not support CFM. */ - int (*get_cfm)(struct ofport *ofport, const struct cfm **cfmp); + * This function may be a null pointer if the ofproto implementation does + * not support CFM. */ + int (*get_cfm_fault)(const struct ofport *ofport); /* If 's' is nonnull, this function registers a "bundle" associated with * client data pointer 'aux' in 'ofproto'. A bundle is the same concept as diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 4f20e804a..aead34657 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1216,17 +1216,19 @@ static bool iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - const struct cfm *cfm; bool changed = false; + int fault; - cfm = ofproto_port_get_cfm(iface->port->bridge->ofproto, iface->ofp_port); + fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto, + iface->ofp_port); - if (!cfm) { + if (fault < 0) { return false; } - if (cfg->n_cfm_fault != 1 || cfg->cfm_fault[0] != cfm->fault) { - ovsrec_interface_set_cfm_fault(cfg, &cfm->fault, 1); + 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; } @@ -2483,24 +2485,27 @@ static void iface_configure_cfm(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - struct cfm cfm; + struct cfm_settings s; + uint16_t remote_mpid; if (!cfg->n_cfm_mpid || !cfg->n_cfm_remote_mpid) { ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port); return; } - cfm.mpid = *cfg->cfm_mpid; - cfm.name = iface->name; - cfm.interval = atoi(get_interface_other_config(iface->cfg, - "cfm_interval", "0")); + s.name = iface->name; + s.mpid = *cfg->cfm_mpid; + remote_mpid = *cfg->cfm_remote_mpid; + s.remote_mpids = &remote_mpid; + s.n_remote_mpids = 1; - if (cfm.interval <= 0) { - cfm.interval = 1000; + s.interval = atoi(get_interface_other_config(iface->cfg, "cfm_interval", + "0")); + if (s.interval <= 0) { + s.interval = 1000; } - ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, - &cfm, *cfg->cfm_remote_mpid); + ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, &s); } /* Read carrier or miimon status directly from 'iface''s netdev, according to