Acked-by: Alex Wang <al...@nicira.com> I'm about to apply it with the following additional fold in.
Basically, move the 'bool force' before the struct which holds returned bfd/cfm status. diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index bae5e6a..7f59b94 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1826,8 +1826,8 @@ out: } static int -get_cfm_status(const struct ofport *ofport_, - struct ofproto_cfm_status *status, bool force) +get_cfm_status(const struct ofport *ofport_, bool force, + struct ofproto_cfm_status *status) { struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); int ret = 0; @@ -1868,7 +1868,7 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg) } static int -get_bfd_status(struct ofport *ofport_, struct smap *smap, bool force) +get_bfd_status(struct ofport *ofport_, bool force, struct smap *smap) { struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); int ret = 0; diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 84b726d..639b501 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1449,8 +1449,8 @@ struct ofproto_class { * The caller must provide and own '*status', and it must free the array * returned in 'status->rmps'. '*status' is indeterminate if the return * value is non-zero. */ - int (*get_cfm_status)(const struct ofport *ofport, - struct ofproto_cfm_status *status, bool force); + int (*get_cfm_status)(const struct ofport *ofport, bool force, + struct ofproto_cfm_status *status); /* Configures BFD on 'ofport'. * @@ -1472,7 +1472,7 @@ struct ofproto_class { * * EOPNOTSUPP as a return value indicates that this ofproto_class does not * support BFD, as does a null pointer. */ - int (*get_bfd_status)(struct ofport *ofport, struct smap *smap, bool force); + int (*get_bfd_status)(struct ofport *ofport, bool force, struct smap *smap); /* Configures spanning tree protocol (STP) on 'ofproto' using the * settings defined in 's'. diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index a501032..608ddad 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1026,11 +1026,11 @@ ofproto_port_set_bfd(struct ofproto *ofproto, ofp_port_t ofp_port, * The caller must provide and own '*status'. */ int ofproto_port_get_bfd_status(struct ofproto *ofproto, ofp_port_t ofp_port, - struct smap *status, bool force) + bool force, struct smap *status) { struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); return (ofport && ofproto->ofproto_class->get_bfd_status - ? ofproto->ofproto_class->get_bfd_status(ofport, status, force) + ? ofproto->ofproto_class->get_bfd_status(ofport, force, status) : EOPNOTSUPP); } @@ -3730,11 +3730,11 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto, * '*status' is indeterminate if the return value is non-zero. */ int ofproto_port_get_cfm_status(const struct ofproto *ofproto, ofp_port_t ofp_port, - struct ofproto_cfm_status *status, bool force) + bool force, struct ofproto_cfm_status *status) { struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); return (ofport && ofproto->ofproto_class->get_cfm_status - ? ofproto->ofproto_class->get_cfm_status(ofport, status, force) + ? ofproto->ofproto_class->get_cfm_status(ofport, force, status) : EOPNOTSUPP); } diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index b18e11a..9a06849 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -265,7 +265,7 @@ void ofproto_port_set_cfm(struct ofproto *, ofp_port_t ofp_port, void ofproto_port_set_bfd(struct ofproto *, ofp_port_t ofp_port, const struct smap *cfg); int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port, - struct smap *, bool force); + bool force, struct smap *); int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port); int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port, const struct ofproto_port_stp_settings *); @@ -420,9 +420,8 @@ struct ofproto_cfm_status { }; int ofproto_port_get_cfm_status(const struct ofproto *, - ofp_port_t ofp_port, - struct ofproto_cfm_status *, - bool force); + ofp_port_t ofp_port, bool force, + struct ofproto_cfm_status *); ^L /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 57eb817..039c62e 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1913,8 +1913,8 @@ iface_refresh_ofproto_status(struct iface *iface) smap_init(&smap); error = ofproto_port_get_bfd_status(iface->port->bridge->ofproto, - iface->ofp_port, &smap, - force_status_commit); + iface->ofp_port, force_status_commit, + &smap); if (error >= 0) { ovsrec_interface_set_bfd_status(iface->cfg, &smap); } @@ -1931,8 +1931,8 @@ iface_refresh_cfm_stats(struct iface *iface) int error; error = ofproto_port_get_cfm_status(iface->port->bridge->ofproto, - iface->ofp_port, &status, - force_status_commit); + iface->ofp_port, force_status_commit, + &status); if (error < 0) { /* Do nothing if there is no status change since last update. */ } else if (error > 0) { On Fri, May 30, 2014 at 11:38 AM, Ryan Wilson <wr...@nicira.com> wrote: > Bridge, port and interface status changes are not sent to the > database if the connectivity and netdev sequence numbers have not > changed. However, if the previous database transaction fails, then > status changes will not be updated in the database until the > connectivity and netdev sequence numbers change again. This could > leave the database in an incorrect state for a long period of time. > > This patch always sends status changes to the database if the last > transaction was not successful. > > Bug #1256577 > Signed-off-by: Ryan Wilson <wr...@nicira.com> > > --- > v2: Addressed Alex's comments, edited commit message to be more > accurate > v3: Remove iface_refresh_netdev_status() from iface_create() upon > further discussion with Alex > v4: Changed force_status_update to force_status_commit since it now > is set to true when status == 'TXN_INCOMPLETE'. Status txn also > needs to be run every STATUS_CHECK_AGAIN_MSEC if last transaction > was not successful. > v5: Add static identifier to force_status_commit.Add force update > BFD and CFM status. > --- > ofproto/ofproto-dpif.c | 8 ++++---- > ofproto/ofproto-provider.h | 25 ++++++++++++++++--------- > ofproto/ofproto.c | 31 ++++++++++++++++++------------- > ofproto/ofproto.h | 5 +++-- > vswitchd/bridge.c | 41 > ++++++++++++++++++++++++++++++----------- > 5 files changed, 71 insertions(+), 39 deletions(-) > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 06be234..4b73158 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -1821,13 +1821,13 @@ out: > > static int > get_cfm_status(const struct ofport *ofport_, > - struct ofproto_cfm_status *status) > + struct ofproto_cfm_status *status, bool force) > { > struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); > int ret = 0; > > if (ofport->cfm) { > - if (cfm_check_status_change(ofport->cfm)) { > + if (cfm_check_status_change(ofport->cfm) || force) { > status->faults = cfm_get_fault(ofport->cfm); > status->flap_count = cfm_get_flap_count(ofport->cfm); > status->remote_opstate = cfm_get_opup(ofport->cfm); > @@ -1862,13 +1862,13 @@ set_bfd(struct ofport *ofport_, const struct smap > *cfg) > } > > static int > -get_bfd_status(struct ofport *ofport_, struct smap *smap) > +get_bfd_status(struct ofport *ofport_, struct smap *smap, bool force) > { > struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); > int ret = 0; > > if (ofport->bfd) { > - if (bfd_check_status_change(ofport->bfd)) { > + if (bfd_check_status_change(ofport->bfd) || force) { > bfd_get_status(ofport->bfd, smap); > } else { > ret = NO_STATUS_CHANGE; > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h > index ff539b9..212ed24 100644 > --- a/ofproto/ofproto-provider.h > +++ b/ofproto/ofproto-provider.h > @@ -1442,10 +1442,13 @@ struct ofproto_class { > * support CFM, as does a null pointer. */ > int (*set_cfm)(struct ofport *ofport, const struct cfm_settings *s); > > - /* Checks the status of CFM configured on 'ofport'. Returns 0 if the > - * port's CFM status was successfully stored into '*status'. Returns > - * negative number if there is no status change since last update. > - * Returns positive errno otherwise. > + /* Checks the status of CFM configured on 'ofport' and stores port's > CFM > + * status in '*status'. If 'force' is set to true, status will be > returned > + * even if there is no status change since last update. > + * > + * Returns 0 on success. Returns a negative number if there is no > status > + * change since last update and 'force' is set to false. Returns > positive > + * errno otherwise. > * > * EOPNOTSUPP as a return value indicates that this ofproto_class > does not > * support CFM, as does a null pointer. > @@ -1454,7 +1457,7 @@ struct ofproto_class { > * returned in 'status->rmps'. '*status' is indeterminate if the > return > * value is non-zero. */ > int (*get_cfm_status)(const struct ofport *ofport, > - struct ofproto_cfm_status *status); > + struct ofproto_cfm_status *status, bool force); > > /* Configures BFD on 'ofport'. > * > @@ -1466,13 +1469,17 @@ struct ofproto_class { > * support BFD, as does a null pointer. */ > int (*set_bfd)(struct ofport *ofport, const struct smap *cfg); > > - /* Populates 'smap' with the status of BFD on 'ofport'. Returns 0 on > - * success. Returns a negative number if there is no status change > since > - * last update. Returns a positive errno otherwise. > + /* Populates 'smap' with the status of BFD on 'ofport'. If 'force' > is set > + * to true, status will be returned even if there is no status change > since > + * last update. > + * > + * Returns 0 on success. Returns a negative number if there is no > status > + * change since last update and 'force' is set to false. Returns a > positive > + * errno otherwise. > * > * EOPNOTSUPP as a return value indicates that this ofproto_class > does not > * support BFD, as does a null pointer. */ > - int (*get_bfd_status)(struct ofport *ofport, struct smap *smap); > + int (*get_bfd_status)(struct ofport *ofport, struct smap *smap, bool > force); > > /* Configures spanning tree protocol (STP) on 'ofproto' using the > * settings defined in 's'. > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index 24a709b..2b872b7 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -1020,19 +1020,22 @@ ofproto_port_set_bfd(struct ofproto *ofproto, > ofp_port_t ofp_port, > } > } > > -/* Populates 'status' with the status of BFD on 'ofport'. Returns 0 on > - * success. Returns a negative number if there is no status change since > - * last update. Returns a positive errno otherwise. Has no effect if > - * 'ofp_port' is not an OpenFlow port in 'ofproto'. > +/* Populates 'status' with the status of BFD on 'ofport'. If 'force' is > set to > + * true, status will be returned even if there is no status change since > last > + * update. > + * > + * Returns 0 on success. Returns a negative number if there is no status > change > + * since last update and 'force' is set to false. Returns a positive > errno > + * otherwise. Has no effect if 'ofp_port' is not an OpenFlow port in > 'ofproto'. > * > * The caller must provide and own '*status'. */ > int > ofproto_port_get_bfd_status(struct ofproto *ofproto, ofp_port_t ofp_port, > - struct smap *status) > + struct smap *status, bool force) > { > struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); > return (ofport && ofproto->ofproto_class->get_bfd_status > - ? ofproto->ofproto_class->get_bfd_status(ofport, status) > + ? ofproto->ofproto_class->get_bfd_status(ofport, status, > force) > : EOPNOTSUPP); > } > > @@ -3738,21 +3741,23 @@ ofproto_get_netflow_ids(const struct ofproto > *ofproto, > ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, > engine_id); > } > > -/* Checks the status of CFM configured on 'ofp_port' within 'ofproto'. > - * Returns 0 if the port's CFM status was successfully stored into > - * '*status'. Returns positive errno if the port did not have CFM > - * configured. Returns negative number if there is no status change > - * since last update. > +/* Checks the status of CFM configured on 'ofp_port' within 'ofproto' and > stores > + * the port's CFM status in '*status'. If 'force' is set to true, status > will > + * be returned even if there is no status change since last update. > + * > + * Returns 0 on success. Returns a negative number if there is no status > + * change since last update and 'force' is set to false. Returns > positive errno > + * if the port did not have CFM configured. > * > * The caller must provide and own '*status', and must free > 'status->rmps'. > * '*status' is indeterminate if the return value is non-zero. */ > int > ofproto_port_get_cfm_status(const struct ofproto *ofproto, ofp_port_t > ofp_port, > - struct ofproto_cfm_status *status) > + struct ofproto_cfm_status *status, bool force) > { > struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); > return (ofport && ofproto->ofproto_class->get_cfm_status > - ? ofproto->ofproto_class->get_cfm_status(ofport, status) > + ? ofproto->ofproto_class->get_cfm_status(ofport, status, > force) > : EOPNOTSUPP); > } > > diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h > index de078b7..aa7b95d 100644 > --- a/ofproto/ofproto.h > +++ b/ofproto/ofproto.h > @@ -265,7 +265,7 @@ void ofproto_port_set_cfm(struct ofproto *, ofp_port_t > ofp_port, > void ofproto_port_set_bfd(struct ofproto *, ofp_port_t ofp_port, > const struct smap *cfg); > int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port, > - struct smap *); > + struct smap *, bool force); > int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port); > int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port, > const struct ofproto_port_stp_settings *); > @@ -424,7 +424,8 @@ struct ofproto_cfm_status { > > int ofproto_port_get_cfm_status(const struct ofproto *, > ofp_port_t ofp_port, > - struct ofproto_cfm_status *); > + struct ofproto_cfm_status *, > + bool force); > > /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) > * > diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c > index 9764c1f..a20e950 100644 > --- a/vswitchd/bridge.c > +++ b/vswitchd/bridge.c > @@ -172,9 +172,15 @@ static uint64_t connectivity_seqno = LLONG_MIN; > * we check the return status of each update transaction and do not start > new > * update if the previous transaction status is 'TXN_INCOMPLETE'. > * > - * 'statux_txn' is NULL if there is no ongoing status update. > + * 'status_txn' is NULL if there is no ongoing status update. > + * > + * If the previous database transaction was incomplete or failed (is not > + * 'TXN_SUCCESS' or 'TXN_UNCHANGED'), 'force_status_commit' is set to > true. > + * This means that 'status_txn' must be committed next iteration of > bridge_run() > + * even if the connectivity or netdev sequence numbers do not change. > */ > static struct ovsdb_idl_txn *status_txn; > +static bool force_status_commit = true; > > /* When the status update transaction returns 'TXN_INCOMPLETE', should > register a > * timeout in 'STATUS_CHECK_AGAIN_MSEC' to check again. */ > @@ -1547,7 +1553,6 @@ iface_create(struct bridge *br, const struct > ovsrec_interface *iface_cfg, > > /* Populate initial status in database. */ > iface_refresh_stats(iface); > - iface_refresh_netdev_status(iface); > > /* Add bond fake iface if necessary. */ > if (port_is_bond_fake_iface(port)) { > @@ -1820,7 +1825,8 @@ iface_refresh_netdev_status(struct iface *iface) > return; > } > > - if (iface->change_seq == netdev_get_change_seq(iface->netdev)) { > + if (iface->change_seq == netdev_get_change_seq(iface->netdev) > + && !force_status_commit) { > return; > } > > @@ -1913,7 +1919,8 @@ iface_refresh_ofproto_status(struct iface *iface) > > smap_init(&smap); > error = ofproto_port_get_bfd_status(iface->port->bridge->ofproto, > - iface->ofp_port, &smap); > + iface->ofp_port, &smap, > + force_status_commit); > if (error >= 0) { > ovsrec_interface_set_bfd_status(iface->cfg, &smap); > } > @@ -1930,7 +1937,8 @@ iface_refresh_cfm_stats(struct iface *iface) > int error; > > error = ofproto_port_get_cfm_status(iface->port->bridge->ofproto, > - iface->ofp_port, &status); > + iface->ofp_port, &status, > + force_status_commit); > if (error < 0) { > /* Do nothing if there is no status change since last update. */ > } else if (error > 0) { > @@ -2420,7 +2428,7 @@ bridge_run(void) > > /* Check the need to update status. */ > seq = seq_read(connectivity_seq_get()); > - if (seq != connectivity_seqno) { > + if (seq != connectivity_seqno || force_status_commit) { > connectivity_seqno = seq; > status_txn = ovsdb_idl_txn_create(idl); > HMAP_FOR_EACH (br, node, &all_bridges) { > @@ -2444,6 +2452,17 @@ bridge_run(void) > enum ovsdb_idl_txn_status status; > > status = ovsdb_idl_txn_commit(status_txn); > + > + /* If the transaction is incomplete or fails, 'status_txn' > + * needs to be committed next iteration of bridge_run() even if > + * connectivity or netdev sequence numbers do not change. */ > + if (status == TXN_SUCCESS || status == TXN_UNCHANGED) > + { > + force_status_commit = false; > + } else { > + force_status_commit = true; > + } > + > /* Do not destroy "status_txn" if the transaction is > * "TXN_INCOMPLETE". */ > if (status != TXN_INCOMPLETE) { > @@ -2483,11 +2502,11 @@ bridge_wait(void) > poll_timer_wait_until(stats_timer); > } > > - /* If the status database transaction is 'TXN_INCOMPLETE' in this run, > - * register a timeout in 'STATUS_CHECK_AGAIN_MSEC'. Else, wait on the > - * global connectivity sequence number. Note, this also helps batch > - * multiple status changes into one transaction. */ > - if (status_txn) { > + /* If the status database transaction is 'TXN_INCOMPLETE' or is > + * unsuccessful, register a timeout in 'STATUS_CHECK_AGAIN_MSEC'. > Else, > + * wait on the global connectivity sequence number. Note, this also > helps > + * batch multiple status changes into one transaction. */ > + if (force_status_commit) { > poll_timer_wait_until(time_msec() + STATUS_CHECK_AGAIN_MSEC); > } else { > seq_wait(connectivity_seq_get(), connectivity_seqno); > -- > 1.7.9.5 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev