From: Ben Pfaff Date: Wed, 6 Mar 2013 17:25:40 +0000 (-0800) Subject: ofproto: Merge all the CFM query functions into one. X-Git-Tag: sliver-openvswitch-1.10.90-1~10^2~103 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=9a9e3786b3a8;p=sliver-openvswitch.git ofproto: Merge all the CFM query functions into one. This eliminates several function calls and in particular several hash table lookups to find structures corresponding to a port number from iface_refresh_cfm_stats(). This does not seem to reduce CPU use, but the code is shorter and more readable. Bug #15171. Signed-off-by: Ben Pfaff Acked-by: Ethan Jackson --- diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ff7f6534b..f37d8406d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1778,43 +1778,22 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s) return error; } -static int -get_cfm_fault(const struct ofport *ofport_) -{ - struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); - - return ofport->cfm ? cfm_get_fault(ofport->cfm) : -1; -} - -static int -get_cfm_opup(const struct ofport *ofport_) -{ - struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); - - return ofport->cfm ? cfm_get_opup(ofport->cfm) : -1; -} - -static int -get_cfm_remote_mpids(const struct ofport *ofport_, const uint64_t **rmps, - size_t *n_rmps) +static bool +get_cfm_status(const struct ofport *ofport_, + struct ofproto_cfm_status *status) { struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); if (ofport->cfm) { - cfm_get_remote_mpids(ofport->cfm, rmps, n_rmps); - return 0; + status->faults = cfm_get_fault(ofport->cfm); + status->remote_opstate = cfm_get_opup(ofport->cfm); + status->health = cfm_get_health(ofport->cfm); + cfm_get_remote_mpids(ofport->cfm, &status->rmps, &status->n_rmps); + return true; } else { - return -1; + return false; } } - -static int -get_cfm_health(const struct ofport *ofport_) -{ - struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); - - return ofport->cfm ? cfm_get_health(ofport->cfm) : -1; -} /* Spanning Tree. */ @@ -8414,10 +8393,7 @@ const struct ofproto_class ofproto_dpif_class = { get_netflow_ids, set_sflow, set_cfm, - get_cfm_fault, - get_cfm_opup, - get_cfm_remote_mpids, - get_cfm_health, + get_cfm_status, set_stp, get_stp_status, set_stp_port, diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 95bda33a1..d8db3aee7 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1120,44 +1120,15 @@ struct ofproto_class { * support CFM, as does a null pointer. */ int (*set_cfm)(struct ofport *ofport, const struct cfm_settings *s); - /* Checks the fault status of CFM configured on 'ofport'. Returns a - * bitmask of 'cfm_fault_reason's to indicate a CFM fault (generally - * indicating a connectivity problem). Returns zero if CFM is not faulted, - * and -1 if CFM is not enabled on 'port'. + /* Checks the status of CFM configured on 'ofport'. Returns true if the + * port's CFM status was successfully stored into '*status'. Returns false + * if the port did not have CFM configured, in which case '*status' is + * indeterminate. * - * This function may be a null pointer if the ofproto implementation does - * not support CFM. */ - int (*get_cfm_fault)(const struct ofport *ofport); - - /* Check the operational status reported by the remote CFM endpoint of - * 'ofp_port' Returns 1 if operationally up, 0 if operationally down, and - * -1 if CFM is not enabled on 'ofp_port' or does not support operational - * status. - * - * This function may be a null pointer if the ofproto implementation does - * not support CFM. */ - int (*get_cfm_opup)(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); - - /* Checks the health of CFM configured on 'ofport'. Returns an integer - * to indicate the health percentage of the 'ofport' which is an average of - * the health of all the remote_mps. Returns an integer between 0 and 100 - * where 0 means that the 'ofport' is very unhealthy and 100 means the - * 'ofport' is perfectly healthy. Returns -1 if CFM is not enabled on - * 'port' or if the number of remote_mpids is > 1. - * - * This function may be a null pointer if the ofproto implementation does - * not support CFM. */ - int (*get_cfm_health)(const struct ofport *ofport); + * The caller must provide and owns '*status', but it does not own and must + * not modify or free the array returned in 'status->rmps'. */ + bool (*get_cfm_status)(const struct ofport *ofport, + struct ofproto_cfm_status *status); /* Configures spanning tree protocol (STP) on 'ofproto' using the * settings defined in 's'. diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index a9c7e7672..03ca59b95 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2843,62 +2843,21 @@ 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 a - * bitmask of 'cfm_fault_reason's to indicate a CFM fault (generally - * indicating a connectivity problem). Returns zero 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); -} - -/* Checks the operational status reported by the remote CFM endpoint of - * 'ofp_port' Returns 1 if operationally up, 0 if operationally down, and -1 - * if CFM is not enabled on 'ofp_port' or does not support operational status. - */ -int -ofproto_port_get_cfm_opup(const struct ofproto *ofproto, uint16_t ofp_port) -{ - struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); - return (ofport && ofproto->ofproto_class->get_cfm_opup - ? ofproto->ofproto_class->get_cfm_opup(ofport) - : -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); -} - -/* Checks the health of the CFM for 'ofp_port' within 'ofproto'. Returns an - * integer value between 0 and 100 to indicate the health of the port as a - * percentage which is the average of cfm health of all the remote_mpids or - * returns -1 if CFM is not enabled on 'ofport'. */ -int -ofproto_port_get_cfm_health(const struct ofproto *ofproto, uint16_t ofp_port) +/* Checks the status of CFM configured on 'ofp_port' within 'ofproto'. Returns + * true if the port's CFM status was successfully stored into '*status'. + * Returns false if the port did not have CFM configured, in which case + * '*status' is indeterminate. + * + * The caller must provide and owns '*status', but it does not own and must not + * modify or free the array returned in 'status->rmps'. */ +bool +ofproto_port_get_cfm_status(const struct ofproto *ofproto, uint16_t ofp_port, + struct ofproto_cfm_status *status) { struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); - return (ofport && ofproto->ofproto_class->get_cfm_health - ? ofproto->ofproto_class->get_cfm_health(ofport) - : -1); + return (ofport + && ofproto->ofproto_class->get_cfm_status + && ofproto->ofproto_class->get_cfm_status(ofport, status)); } static enum ofperr diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 3a66d1bf1..a3c52b5e4 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -356,15 +356,23 @@ 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); -int ofproto_port_get_cfm_opup(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); -int ofproto_port_get_cfm_health(const struct ofproto *ofproto, - uint16_t ofp_port); + void ofproto_get_ofproto_controller_info(const struct ofproto *, struct shash *); void ofproto_free_ofproto_controller_info(struct shash *); + +/* CFM status query. */ +struct ofproto_cfm_status { + enum cfm_fault_reason faults; /* 0 if not faulted. */ + bool remote_opstate; /* True if remote CFM endpoint is up. */ + int health; /* Health status in [0,100] range. */ + + /* MPIDs of remote maintenance points whose CCMs have been received. */ + const uint64_t *rmps; + size_t n_rmps; +}; + +bool ofproto_port_get_cfm_status(const struct ofproto *, uint16_t ofp_port, + struct ofproto_cfm_status *); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index ab0ecd6df..b28ef26c9 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1743,57 +1743,38 @@ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - int fault, opup, error; - const uint64_t *rmps; - size_t n_rmps; - int health; - - fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto, - iface->ofp_port); - if (fault >= 0) { + struct ofproto_cfm_status status; + + if (!ofproto_port_get_cfm_status(iface->port->bridge->ofproto, + iface->ofp_port, &status)) { + ovsrec_interface_set_cfm_fault(cfg, NULL, 0); + ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); + ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); + ovsrec_interface_set_cfm_health(cfg, NULL, 0); + ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0); + } else { const char *reasons[CFM_FAULT_N_REASONS]; - bool fault_bool = fault; + int64_t cfm_health = status.health; + bool faulted = status.faults != 0; size_t i, j; + ovsrec_interface_set_cfm_fault(cfg, &faulted, 1); + j = 0; for (i = 0; i < CFM_FAULT_N_REASONS; i++) { int reason = 1 << i; - if (fault & reason) { + if (status.faults & reason) { reasons[j++] = cfm_fault_reason_to_str(reason); } } - - ovsrec_interface_set_cfm_fault(cfg, &fault_bool, 1); ovsrec_interface_set_cfm_fault_status(cfg, (char **) reasons, j); - } else { - ovsrec_interface_set_cfm_fault(cfg, NULL, 0); - ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); - } - - opup = ofproto_port_get_cfm_opup(iface->port->bridge->ofproto, - iface->ofp_port); - if (opup >= 0) { - ovsrec_interface_set_cfm_remote_opstate(cfg, opup ? "up" : "down"); - } else { - ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); - } - 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); - } - - health = ofproto_port_get_cfm_health(iface->port->bridge->ofproto, - iface->ofp_port); - if (health >= 0) { - int64_t cfm_health = health; + ovsrec_interface_set_cfm_remote_opstate(cfg, (status.remote_opstate + ? "up" : "down")); + ovsrec_interface_set_cfm_remote_mpids(cfg, + (const int64_t *)status.rmps, + status.n_rmps); ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); - } else { - ovsrec_interface_set_cfm_health(cfg, NULL, 0); } }