Recent changes to the flow_dump_next() interface have made it the responsibility of the dpif implementation to track error status over a flow dump operation.
This patch removes status tracking from 'struct dpif_flow_dump', allowing multiple threads to call dpif_flow_dump_next() and track their status independently. Even if one thread finishes processing flows for a given iterator and state, it will not prevent other callers from processing the remaining flows in their buffers. After this patch, the error code that dpif_flow_dump_next() returns is only significant for the current state and buffer. As before, the status of the entire flow dump operation can be obtained by calling dpif_flow_dump_done(). Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- v2: Completely remove dump->status --- lib/dpif.c | 68 +++++++++++++++++------------------------ lib/dpif.h | 3 +- ofproto/ofproto-dpif-upcall.c | 8 ++++- ofproto/ofproto-dpif.c | 10 ++++-- utilities/ovs-dpctl.c | 22 ++++++++----- 5 files changed, 59 insertions(+), 52 deletions(-) diff --git a/lib/dpif.c b/lib/dpif.c index f972011..117d720 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -978,23 +978,22 @@ dpif_flow_dump_state_uninit(const struct dpif *dpif, void *state) dpif->dpif_class->flow_dump_state_uninit(state); } -/* Initializes 'dump' to begin dumping the flows in a dpif. - * - * This function provides no status indication. An error status for the entire - * dump operation is provided when it is completed by calling - * dpif_flow_dump_done(). - */ -void +/* Initializes 'dump' to begin dumping the flows in a dpif. On sucess, + * initializes 'dump' with any data needed for iteration and returns 0. + * Otherwise, returns a positive errno value describing the problem. */ +int dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif) { + int error; dump->dpif = dpif; - dump->error = dpif->dpif_class->flow_dump_start(dpif, &dump->iter); - log_operation(dpif, "flow_dump_start", dump->error); + error = dpif->dpif_class->flow_dump_start(dpif, &dump->iter); + log_operation(dpif, "flow_dump_start", error); + return error; } /* Attempts to retrieve another flow from 'dump', using 'state' for - * thread-local storage. 'dump' must have been initialized with - * dpif_flow_dump_start(), and 'state' must have been initialized with + * thread-local storage. 'dump' must have been initialized with a successful + * call to dpif_flow_dump_start(), and 'state' must have been initialized with * dpif_flow_state_init(). * * On success, updates the output parameters as described below and returns @@ -1023,18 +1022,11 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, void *state, const struct dpif_flow_stats **stats) { const struct dpif *dpif = dump->dpif; - int error = dump->error; + int error; - if (!error) { - error = dpif->dpif_class->flow_dump_next(dpif, dump->iter, state, - key, key_len, - mask, mask_len, - actions, actions_len, - stats); - if (error) { - dpif->dpif_class->flow_dump_done(dpif, dump->iter); - } - } + error = dpif->dpif_class->flow_dump_next(dpif, dump->iter, state, + key, key_len, mask, mask_len, + actions, actions_len, stats); if (error) { if (key) { *key = NULL; @@ -1052,33 +1044,29 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, void *state, *stats = NULL; } } - if (!dump->error) { - if (error == EOF) { - VLOG_DBG_RL(&dpmsg_rl, "%s: dumped all flows", dpif_name(dpif)); - } else if (should_log_flow_message(error)) { - log_flow_message(dpif, error, "flow_dump", - key ? *key : NULL, key ? *key_len : 0, - mask ? *mask : NULL, mask ? *mask_len : 0, - stats ? *stats : NULL, actions ? *actions : NULL, - actions ? *actions_len : 0); - } + if (error == EOF) { + VLOG_DBG_RL(&dpmsg_rl, "%s: dumped all flows", dpif_name(dpif)); + } else if (should_log_flow_message(error)) { + log_flow_message(dpif, error, "flow_dump", + key ? *key : NULL, key ? *key_len : 0, + mask ? *mask : NULL, mask ? *mask_len : 0, + stats ? *stats : NULL, actions ? *actions : NULL, + actions ? *actions_len : 0); } - dump->error = error; return !error; } /* Completes flow table dump operation 'dump', which must have been initialized - * with dpif_flow_dump_start(). Returns 0 if the dump operation was - * error-free, otherwise a positive errno value describing the problem. */ + * with a successful call to dpif_flow_dump_start(). Returns 0 if the dump + * operation was error-free, otherwise a positive errno value describing the + * problem. */ int dpif_flow_dump_done(struct dpif_flow_dump *dump) { const struct dpif *dpif = dump->dpif; - if (!dump->error) { - dump->error = dpif->dpif_class->flow_dump_done(dpif, dump->iter); - log_operation(dpif, "flow_dump_done", dump->error); - } - return dump->error == EOF ? 0 : dump->error; + int error = dpif->dpif_class->flow_dump_done(dpif, dump->iter); + log_operation(dpif, "flow_dump_done", error); + return error == EOF ? 0 : error; } struct dpif_execute_helper_aux { diff --git a/lib/dpif.h b/lib/dpif.h index 65de686..0c763dc 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -514,11 +514,10 @@ int dpif_flow_get(const struct dpif *, struct dpif_flow_dump { const struct dpif *dpif; - int error; void *iter; }; void dpif_flow_dump_state_init(const struct dpif *, void **statep);; -void dpif_flow_dump_start(struct dpif_flow_dump *, const struct dpif *); +int dpif_flow_dump_start(struct dpif_flow_dump *, const struct dpif *); bool dpif_flow_dump_next(struct dpif_flow_dump *, void *state, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 81f2d36..da604b1 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -513,6 +513,7 @@ udpif_flow_dumper(void *arg) bool need_revalidate; uint64_t reval_seq; size_t n_flows, i; + int error; void *state = NULL; reval_seq = seq_read(udpif->reval_seq); @@ -536,7 +537,11 @@ udpif_flow_dumper(void *arg) atomic_store(&udpif->max_idle, max_idle); start_time = time_msec(); - dpif_flow_dump_start(&dump, udpif->dpif); + error = dpif_flow_dump_start(&dump, udpif->dpif); + if (error) { + VLOG_INFO("Failed to start flow dump (%s)", ovs_strerror(error)); + goto skip; + } dpif_flow_dump_state_init(udpif->dpif, &state); while (dpif_flow_dump_next(&dump, state, &key, &key_len, &mask, &mask_len, NULL, NULL, &stats) @@ -612,6 +617,7 @@ udpif_flow_dumper(void *arg) duration); } +skip: poll_timer_wait_until(start_time + MIN(max_idle, 500)); seq_wait(udpif->reval_seq, udpif->last_reval_seq); latch_wait(&udpif->exit_latch); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 25a8e4d..7bb1fc6 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4069,6 +4069,7 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, struct dpif_port_dump port_dump; struct hmap portno_names; void *state = NULL; + int error; ofproto = ofproto_dpif_lookup(argv[argc - 1]); if (!ofproto) { @@ -4086,7 +4087,10 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, } ds_init(&ds); - dpif_flow_dump_start(&flow_dump, ofproto->backer->dpif); + error = dpif_flow_dump_start(&flow_dump, ofproto->backer->dpif); + if (error) { + goto exit; + } dpif_flow_dump_state_init(ofproto->backer->dpif, &state); while (dpif_flow_dump_next(&flow_dump, state, &key, &key_len, &mask, &mask_len, &actions, &actions_len, @@ -4104,8 +4108,10 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, ds_put_char(&ds, '\n'); } dpif_flow_dump_state_uninit(ofproto->backer->dpif, state); + error = dpif_flow_dump_done(&flow_dump); - if (dpif_flow_dump_done(&flow_dump)) { +exit: + if (error) { ds_clear(&ds); ds_put_format(&ds, "dpif/dump_flows failed: %s", ovs_strerror(errno)); unixctl_command_reply_error(conn, ds_cstr(&ds)); diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 0126b23..ca49e70 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -760,10 +760,11 @@ dpctl_dump_flows(int argc, char *argv[]) size_t key_len; size_t mask_len; struct ds ds; - char *name, *error, *filter = NULL; + char *name, *filter = NULL; struct flow flow_filter; struct flow_wildcards wc_filter; void *state = NULL; + int error; if (argc > 1 && !strncmp(argv[argc - 1], "filter=", 7)) { filter = xstrdup(argv[--argc] + 7); @@ -782,15 +783,18 @@ dpctl_dump_flows(int argc, char *argv[]) } if (filter) { - error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter, - &names_portno); - if (error) { - ovs_fatal(0, "Failed to parse filter (%s)", error); + char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, + filter, &names_portno); + if (err) { + ovs_fatal(0, "Failed to parse filter (%s)", err); } } ds_init(&ds); - dpif_flow_dump_start(&flow_dump, dpif); + error = dpif_flow_dump_start(&flow_dump, dpif); + if (error) { + goto exit; + } dpif_flow_dump_state_init(dpif, &state); while (dpif_flow_dump_next(&flow_dump, state, &key, &key_len, &mask, &mask_len, &actions, &actions_len, @@ -826,8 +830,12 @@ dpctl_dump_flows(int argc, char *argv[]) printf("%s\n", ds_cstr(&ds)); } dpif_flow_dump_state_uninit(dpif, state); - dpif_flow_dump_done(&flow_dump); + error = dpif_flow_dump_done(&flow_dump); +exit: + if (error) { + ovs_fatal(error, "Failed to dump flows from datapath"); + } free(filter); odp_portno_names_destroy(&portno_names); hmap_destroy(&portno_names); -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev