Applied, thx~
On Thu, Apr 24, 2014 at 5:54 AM, Joe Stringer <joestrin...@nicira.com>wrote: > Acked-by: Joe Stringer <joestrin...@nicira.com> > > > On 18 April 2014 08:32, Alex Wang <al...@nicira.com> wrote: > >> This commit adds boolean flag in bfd/cfm module for checking >> status change. If there is no status change, the current >> update to OVS database will skip the bfd/cfm session. >> >> In the experiment with 5K bfd sessions, when one session is >> flapping at rate of every 0.3 second, this patch reduces the >> cpu utilization of the ovs-vswitchd thread from 13 to 6. >> >> Signed-off-by: Alex Wang <al...@nicira.com> >> --- >> V3 -> V4: >> - mirror the comment format of putting 'EOPNOTSUPP...' in newline. >> - state in comment that '*status' is indeterminate if get_cfm_status() >> returns non-zero value. >> - fix the comment of get_cfm_status(), since the caller do free the >> 'status->rmps' array. >> - update the comment of ofproto_port_get_bfd_status(). >> - always destroy the smap in instant_stats_run(). >> >> V2 -> V3: >> - rebase. >> >> PATCH -> V2: >> - replace the callback function to boolean flag. >> - add experiment results. >> --- >> lib/bfd.c | 35 ++++++++++++++++++++++++++++++++--- >> lib/bfd.h | 1 + >> lib/cfm.c | 32 ++++++++++++++++++++++++++++++-- >> lib/cfm.h | 1 + >> ofproto/ofproto-dpif.c | 37 ++++++++++++++++++++++++++----------- >> ofproto/ofproto-provider.h | 27 +++++++++++++++++---------- >> ofproto/ofproto.c | 30 +++++++++++++++++------------- >> ofproto/ofproto.h | 6 +++--- >> vswitchd/bridge.c | 16 +++++++++++----- >> 9 files changed, 138 insertions(+), 47 deletions(-) >> >> diff --git a/lib/bfd.c b/lib/bfd.c >> index 8bfe385..e3e3ae5 100644 >> --- a/lib/bfd.c >> +++ b/lib/bfd.c >> @@ -213,6 +213,10 @@ struct bfd { >> long long int decay_detect_time; /* Decay detection time. */ >> >> uint64_t flap_count; /* Counts bfd forwarding flaps. */ >> + >> + /* True when the variables returned by bfd_get_status() are changed >> + * since last check. */ >> + bool status_changed; >> }; >> >> static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; >> @@ -240,6 +244,7 @@ static void bfd_put_details(struct ds *, const struct >> bfd *) >> static uint64_t bfd_rx_packets(const struct bfd *) OVS_REQUIRES(mutex); >> static void bfd_try_decay(struct bfd *) OVS_REQUIRES(mutex); >> static void bfd_decay_update(struct bfd *) OVS_REQUIRES(mutex); >> +static void bfd_status_changed(struct bfd *) OVS_REQUIRES(mutex); >> >> static void bfd_forwarding_if_rx_update(struct bfd *) >> OVS_REQUIRES(mutex); >> static void bfd_unixctl_show(struct unixctl_conn *, int argc, >> @@ -279,6 +284,20 @@ bfd_account_rx(struct bfd *bfd, const struct >> dpif_flow_stats *stats) >> } >> } >> >> +/* Returns and resets the 'bfd->status_changed'. */ >> +bool >> +bfd_check_status_change(struct bfd *bfd) OVS_EXCLUDED(mutex) >> +{ >> + bool ret; >> + >> + ovs_mutex_lock(&mutex); >> + ret = bfd->status_changed; >> + bfd->status_changed = false; >> + ovs_mutex_unlock(&mutex); >> + >> + return ret; >> +} >> + >> /* Returns a 'smap' of key value pairs representing the status of 'bfd' >> * intended for the OVS database. */ >> void >> @@ -749,7 +768,7 @@ bfd_process_packet(struct bfd *bfd, const struct flow >> *flow, >> } >> >> if (bfd->rmt_state != rmt_state) { >> - seq_change(connectivity_seq_get()); >> + bfd_status_changed(bfd); >> } >> >> bfd->rmt_disc = ntohl(msg->my_disc); >> @@ -872,7 +891,7 @@ bfd_forwarding__(struct bfd *bfd) OVS_REQUIRES(mutex) >> && bfd->rmt_diag != DIAG_RCPATH_DOWN; >> if (bfd->last_forwarding != last_forwarding) { >> bfd->flap_count++; >> - seq_change(connectivity_seq_get()); >> + bfd_status_changed(bfd); >> } >> return bfd->last_forwarding; >> } >> @@ -1085,7 +1104,7 @@ bfd_set_state(struct bfd *bfd, enum state state, >> enum diag diag) >> bfd_decay_update(bfd); >> } >> >> - seq_change(connectivity_seq_get()); >> + bfd_status_changed(bfd); >> } >> } >> >> @@ -1132,6 +1151,14 @@ bfd_decay_update(struct bfd * bfd) >> OVS_REQUIRES(mutex) >> bfd->decay_detect_time = MAX(bfd->decay_min_rx, 2000) + time_msec(); >> } >> >> +/* Records the status change and changes the global connectivity seq. */ >> +static void >> +bfd_status_changed(struct bfd *bfd) OVS_REQUIRES(mutex) >> +{ >> + seq_change(connectivity_seq_get()); >> + bfd->status_changed = true; >> +} >> + >> static void >> bfd_forwarding_if_rx_update(struct bfd *bfd) OVS_REQUIRES(mutex) >> { >> @@ -1279,9 +1306,11 @@ bfd_unixctl_set_forwarding_override(struct >> unixctl_conn *conn, int argc, >> goto out; >> } >> bfd->forwarding_override = forwarding_override; >> + bfd_status_changed(bfd); >> } else { >> HMAP_FOR_EACH (bfd, node, all_bfds) { >> bfd->forwarding_override = forwarding_override; >> + bfd_status_changed(bfd); >> } >> } >> >> diff --git a/lib/bfd.h b/lib/bfd.h >> index 4e7d4cb..039b4dd 100644 >> --- a/lib/bfd.h >> +++ b/lib/bfd.h >> @@ -49,6 +49,7 @@ void bfd_unref(struct bfd *); >> >> void bfd_account_rx(struct bfd *, const struct dpif_flow_stats *); >> bool bfd_forwarding(struct bfd *); >> +bool bfd_check_status_change(struct bfd *); >> void bfd_get_status(const struct bfd *, struct smap *); >> void bfd_set_netdev(struct bfd *, const struct netdev *); >> long long int bfd_wake_time(const struct bfd *); >> diff --git a/lib/cfm.c b/lib/cfm.c >> index ce0c471..6a173a7 100644 >> --- a/lib/cfm.c >> +++ b/lib/cfm.c >> @@ -133,6 +133,10 @@ struct cfm { >> struct ovs_refcount ref_cnt; >> >> uint64_t flap_count; /* Count the flaps since boot. */ >> + >> + /* True when the variables returned by cfm_get_*() are changed >> + * since last check. */ >> + bool status_changed; >> }; >> >> /* Remote MPs represent foreign network entities that are configured to >> have >> @@ -343,6 +347,7 @@ cfm_create(const struct netdev *netdev) >> OVS_EXCLUDED(mutex) >> cfm_generate_maid(cfm); >> hmap_insert(all_cfms, &cfm->hmap_node, hash_string(cfm->name, 0)); >> ovs_mutex_unlock(&mutex); >> + >> return cfm; >> } >> >> @@ -385,6 +390,14 @@ cfm_ref(const struct cfm *cfm_) >> return cfm; >> } >> >> +/* Records the status change and changes the global connectivity seq. */ >> +static void >> +cfm_status_changed(struct cfm *cfm) OVS_REQUIRES(mutex) >> +{ >> + seq_change(connectivity_seq_get()); >> + cfm->status_changed = true; >> +} >> + >> /* Should be run periodically to update fault statistics messages. */ >> void >> cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) >> @@ -510,7 +523,7 @@ cfm_run(struct cfm *cfm) OVS_EXCLUDED(mutex) >> || (old_rmps_array_len != cfm->rmps_array_len || >> old_rmps_deleted) >> || old_cfm_fault != cfm->fault >> || old_flap_count != cfm->flap_count) { >> - seq_change(connectivity_seq_get()); >> + cfm_status_changed(cfm); >> } >> >> cfm->booted = true; >> @@ -836,6 +849,20 @@ out: >> ovs_mutex_unlock(&mutex); >> } >> >> +/* Returns and resets the 'cfm->status_changed'. */ >> +bool >> +cfm_check_status_change(struct cfm *cfm) OVS_EXCLUDED(mutex) >> +{ >> + bool ret; >> + >> + ovs_mutex_lock(&mutex); >> + ret = cfm->status_changed; >> + cfm->status_changed = false; >> + ovs_mutex_unlock(&mutex); >> + >> + return ret; >> +} >> + >> static int >> cfm_get_fault__(const struct cfm *cfm) OVS_REQUIRES(mutex) >> { >> @@ -1029,13 +1056,14 @@ cfm_unixctl_set_fault(struct unixctl_conn *conn, >> int argc, const char *argv[], >> goto out; >> } >> cfm->fault_override = fault_override; >> + cfm_status_changed(cfm); >> } else { >> HMAP_FOR_EACH (cfm, hmap_node, all_cfms) { >> cfm->fault_override = fault_override; >> + cfm_status_changed(cfm); >> } >> } >> >> - seq_change(connectivity_seq_get()); >> unixctl_command_reply(conn, "OK"); >> >> out: >> diff --git a/lib/cfm.h b/lib/cfm.h >> index 4213eb5..13fdc60 100644 >> --- a/lib/cfm.h >> +++ b/lib/cfm.h >> @@ -76,6 +76,7 @@ void cfm_set_netdev(struct cfm *, const struct netdev >> *); >> bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *, >> struct flow_wildcards *); >> void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet); >> +bool cfm_check_status_change(struct cfm *); >> int cfm_get_fault(const struct cfm *); >> uint64_t cfm_get_flap_count(const struct cfm *); >> int cfm_get_health(const struct cfm *); >> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c >> index 3648dd7..5b0f6bd 100644 >> --- a/ofproto/ofproto-dpif.c >> +++ b/ofproto/ofproto-dpif.c >> @@ -78,6 +78,9 @@ enum { N_TABLES = 255 }; >> enum { TBL_INTERNAL = N_TABLES - 1 }; /* Used for internal hidden >> rules. */ >> BUILD_ASSERT_DECL(N_TABLES >= 2 && N_TABLES <= 255); >> >> +/* No bfd/cfm status change. */ >> +#define NO_STATUS_CHANGE -1 >> + >> struct flow_miss; >> >> struct rule_dpif { >> @@ -1801,22 +1804,28 @@ out: >> return error; >> } >> >> -static bool >> +static int >> get_cfm_status(const struct ofport *ofport_, >> struct ofproto_cfm_status *status) >> { >> struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); >> + int ret = 0; >> >> if (ofport->cfm) { >> - status->faults = cfm_get_fault(ofport->cfm); >> - status->flap_count = cfm_get_flap_count(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; >> + if (cfm_check_status_change(ofport->cfm)) { >> + status->faults = cfm_get_fault(ofport->cfm); >> + status->flap_count = cfm_get_flap_count(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); >> + } else { >> + ret = NO_STATUS_CHANGE; >> + } >> } else { >> - return false; >> + ret = ENOENT; >> } >> + >> + return ret; >> } >> >> static int >> @@ -1841,13 +1850,19 @@ static int >> get_bfd_status(struct ofport *ofport_, struct smap *smap) >> { >> struct ofport_dpif *ofport = ofport_dpif_cast(ofport_); >> + int ret = 0; >> >> if (ofport->bfd) { >> - bfd_get_status(ofport->bfd, smap); >> - return 0; >> + if (bfd_check_status_change(ofport->bfd)) { >> + bfd_get_status(ofport->bfd, smap); >> + } else { >> + ret = NO_STATUS_CHANGE; >> + } >> } else { >> - return ENOENT; >> + ret = ENOENT; >> } >> + >> + return ret; >> } >> >> /* Spanning Tree. */ >> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h >> index 0e22b7c..a3591df 100644 >> --- a/ofproto/ofproto-provider.h >> +++ b/ofproto/ofproto-provider.h >> @@ -1460,15 +1460,19 @@ 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 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. >> + /* 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. >> * >> - * 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); >> + * EOPNOTSUPP as a return value indicates that this ofproto_class >> does not >> + * support CFM, as does a null pointer. >> + * >> + * 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); >> >> /* Configures BFD on 'ofport'. >> * >> @@ -1481,8 +1485,11 @@ struct ofproto_class { >> int (*set_bfd)(struct ofport *ofport, const struct smap *cfg); >> >> /* Populates 'smap' with the status of BFD on 'ofport'. Returns 0 on >> - * success, or a positive errno. EOPNOTSUPP as a return value >> indicates >> - * that this ofproto_class does not support BFD, as does a null >> pointer. */ >> + * success. Returns a negative number if there is no status change >> since >> + * last update. 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); >> >> /* Configures spanning tree protocol (STP) on 'ofproto' using the >> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c >> index 436a745..e3e0444 100644 >> --- a/ofproto/ofproto.c >> +++ b/ofproto/ofproto.c >> @@ -1016,10 +1016,12 @@ ofproto_port_set_bfd(struct ofproto *ofproto, >> ofp_port_t ofp_port, >> } >> } >> >> -/* Populates 'status' with key value pairs indicating the status of the >> BFD >> - * session on 'ofp_port'. This information is intended to be populated >> in the >> - * OVS database. Has no effect if 'ofp_port' is not na OpenFlow port in >> - * 'ofproto'. */ >> +/* 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'. >> + * >> + * The caller must provide and own '*status'. */ >> int >> ofproto_port_get_bfd_status(struct ofproto *ofproto, ofp_port_t ofp_port, >> struct smap *status) >> @@ -3699,20 +3701,22 @@ 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 >> - * 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. >> +/* 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. >> * >> - * The caller must provide and owns '*status', and must free >> 'status->rmps'. */ >> -bool >> + * 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 ofport *ofport = ofproto_get_port(ofproto, ofp_port); >> - return (ofport >> - && ofproto->ofproto_class->get_cfm_status >> - && ofproto->ofproto_class->get_cfm_status(ofport, status)); >> + return (ofport && ofproto->ofproto_class->get_cfm_status >> + ? ofproto->ofproto_class->get_cfm_status(ofport, status) >> + : EOPNOTSUPP); >> } >> >> static enum ofperr >> diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h >> index ab51365..9ba6354 100644 >> --- a/ofproto/ofproto.h >> +++ b/ofproto/ofproto.h >> @@ -419,9 +419,9 @@ struct ofproto_cfm_status { >> size_t n_rmps; >> }; >> >> -bool ofproto_port_get_cfm_status(const struct ofproto *, >> - ofp_port_t ofp_port, >> - struct ofproto_cfm_status *); >> +int ofproto_port_get_cfm_status(const struct ofproto *, >> + ofp_port_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 f46d002..295e1be 100644 >> --- a/vswitchd/bridge.c >> +++ b/vswitchd/bridge.c >> @@ -1836,9 +1836,13 @@ iface_refresh_cfm_stats(struct iface *iface) >> { >> const struct ovsrec_interface *cfg = iface->cfg; >> struct ofproto_cfm_status status; >> + int error; >> >> - if (!ofproto_port_get_cfm_status(iface->port->bridge->ofproto, >> - iface->ofp_port, &status)) { >> + error = ofproto_port_get_cfm_status(iface->port->bridge->ofproto, >> + iface->ofp_port, &status); >> + if (error < 0) { >> + /* Do nothing if there is no status change since last update. */ >> + } else if (error > 0) { >> 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); >> @@ -2246,9 +2250,11 @@ instant_stats_run(void) >> iface_refresh_cfm_stats(iface); >> >> smap_init(&smap); >> - ofproto_port_get_bfd_status(br->ofproto, iface->ofp_port, >> - &smap); >> - ovsrec_interface_set_bfd_status(iface->cfg, &smap); >> + error = ofproto_port_get_bfd_status(br->ofproto, >> iface->ofp_port, >> + &smap); >> + if (error >= 0) { >> + ovsrec_interface_set_bfd_status(iface->cfg, &smap); >> + } >> smap_destroy(&smap); >> } >> } >> -- >> 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