Previously when dumping flows from the datapath, callers of dpif_flow_dump_next() could specify whether they wish to fetch the actions for a flow. Depending on the datapath implementation, these may be fetched at no performance cost or may require additional resources to fetch.
The most frequent caller of this function is the flow_dumper, which does not care about fetching actions. This patch removes the actions parameters from dpif_flow_dump_next(), to provide more consistent performance in this common use case. If callers wish to get the actions for a flow, they can make a separate call to flow_get(). Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- lib/dpif-linux.c | 24 ------------------------ lib/dpif-netdev.c | 20 +++----------------- lib/dpif-provider.h | 7 +------ lib/dpif.c | 13 ++----------- lib/dpif.h | 1 - ofproto/ofproto-dpif-upcall.c | 4 ++-- ofproto/ofproto-dpif.c | 16 +++++++++++----- utilities/ovs-dpctl.c | 15 ++++++++++----- 8 files changed, 29 insertions(+), 71 deletions(-) diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c index 45a2492..cac3f52 100644 --- a/lib/dpif-linux.c +++ b/lib/dpif-linux.c @@ -1024,7 +1024,6 @@ static int dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, - const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **stats) { struct dpif_linux_flow_state *state = state_; @@ -1040,31 +1039,8 @@ dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_, if (error) { return error; } - - if (actions && !state->flow.actions) { - struct ofpbuf *tmp_buf = NULL; - - error = dpif_linux_flow_get__(dpif_, state->flow.key, - state->flow.key_len, - &state->flow, &tmp_buf); - if (tmp_buf) { - ofpbuf_delete(state->buf); - state->buf = tmp_buf; - } - - if (error == ENOENT) { - VLOG_DBG("dumped flow disappeared on get"); - } else if (error) { - VLOG_WARN("error fetching dumped flow: %s", - ovs_strerror(error)); - } - } } while (error); - if (actions) { - *actions = state->flow.actions; - *actions_len = state->flow.actions_len; - } if (key) { *key = state->flow.key; *key_len = state->flow.key_len; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index fdea0a7..1c3869a 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1302,7 +1302,6 @@ dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del) struct dp_netdev_flow_state { uint32_t bucket; uint32_t offset; - struct dp_netdev_actions *actions; struct odputil_keybuf keybuf; struct odputil_keybuf maskbuf; struct dpif_flow_stats stats; @@ -1316,7 +1315,6 @@ dpif_netdev_flow_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep) *statep = state = xmalloc(sizeof *state); state->bucket = 0; state->offset = 0; - state->actions = NULL; return 0; } @@ -1324,7 +1322,6 @@ static int dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, - const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **stats) { struct dp_netdev_flow_state *state = state_; @@ -1367,20 +1364,10 @@ dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_, *mask_len = buf.size; } - if (actions || stats) { - dp_netdev_actions_unref(state->actions); - state->actions = NULL; - + if (stats) { ovs_mutex_lock(&netdev_flow->mutex); - if (actions) { - state->actions = dp_netdev_actions_ref(netdev_flow->actions); - *actions = state->actions->actions; - *actions_len = state->actions->size; - } - if (stats) { - get_dpif_flow_stats(netdev_flow, &state->stats); - *stats = &state->stats; - } + get_dpif_flow_stats(netdev_flow, &state->stats); + *stats = &state->stats; ovs_mutex_unlock(&netdev_flow->mutex); } @@ -1394,7 +1381,6 @@ dpif_netdev_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_) { struct dp_netdev_flow_state *state = state_; - dp_netdev_actions_unref(state->actions); free(state); return 0; } diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index adc5242..3323e16 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -285,12 +285,8 @@ struct dpif_class { * must be set to Netlink attributes with types of OVS_KEY_ATTR_* * representing the dumped flow's mask. * - * - If 'actions' and 'actions_len' are nonnull then they should be set - * to Netlink attributes with types OVS_ACTION_ATTR_* representing - * the dumped flow's actions. - * * - If 'stats' is nonnull then it should be set to the dumped flow's - * statistics. + * statistics. * * All of the returned data is owned by 'dpif', not by the caller, and the * caller must not modify or free it. 'dpif' must guarantee that it @@ -299,7 +295,6 @@ struct dpif_class { int (*flow_dump_next)(const struct dpif *dpif, void *state, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, - const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **stats); /* Releases resources from 'dpif' for 'state', which was initialized by a diff --git a/lib/dpif.c b/lib/dpif.c index 2b79a6e..ecaeb28 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -984,9 +984,7 @@ dpif_flow_dump_start(struct dpif_flow_dump *dump, const struct dpif *dpif) * * On success, if 'key' and 'key_len' are nonnull then '*key' and '*key_len' * will be set to Netlink attributes with types OVS_KEY_ATTR_* representing the - * dumped flow's key. If 'actions' and 'actions_len' are nonnull then they are - * set to Netlink attributes with types OVS_ACTION_ATTR_* representing the - * dumped flow's actions. If 'stats' is nonnull then it will be set to the + * dumped flow's key. If 'stats' is nonnull then it will be set to the * dumped flow's statistics. * * All of the returned data is owned by 'dpif', not by the caller, and the @@ -997,7 +995,6 @@ bool dpif_flow_dump_next(struct dpif_flow_dump *dump, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, - const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **stats) { const struct dpif *dpif = dump->dpif; @@ -1007,7 +1004,6 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, error = dpif->dpif_class->flow_dump_next(dpif, dump->state, key, key_len, mask, mask_len, - actions, actions_len, stats); if (error) { dpif->dpif_class->flow_dump_done(dpif, dump->state); @@ -1022,10 +1018,6 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, *mask = NULL; *mask_len = 0; } - if (actions) { - *actions = NULL; - *actions_len = 0; - } if (stats) { *stats = NULL; } @@ -1037,8 +1029,7 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, 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); + stats ? *stats : NULL, NULL, 0); } } dump->error = error; diff --git a/lib/dpif.h b/lib/dpif.h index 7f986f9..277c1f1 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -513,7 +513,6 @@ void dpif_flow_dump_start(struct dpif_flow_dump *, const struct dpif *); bool dpif_flow_dump_next(struct dpif_flow_dump *, const struct nlattr **key, size_t *key_len, const struct nlattr **mask, size_t *mask_len, - const struct nlattr **actions, size_t *actions_len, const struct dpif_flow_stats **); int dpif_flow_dump_done(struct dpif_flow_dump *); diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index dd24f5c..4789f43 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -534,8 +534,8 @@ udpif_flow_dumper(void *arg) start_time = time_msec(); dpif_flow_dump_start(&dump, udpif->dpif); - while (dpif_flow_dump_next(&dump, &key, &key_len, &mask, &mask_len, - NULL, NULL, &stats) + while (dpif_flow_dump_next(&dump, &key, &key_len, + &mask, &mask_len, &stats) && !latch_is_set(&udpif->exit_latch)) { struct udpif_flow_dump *udump = xmalloc(sizeof *udump); struct revalidator *revalidator; diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 62c1e4c..b70b66d 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4056,10 +4056,8 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, const struct dpif_flow_stats *stats; const struct ofproto_dpif *ofproto; struct dpif_flow_dump flow_dump; - const struct nlattr *actions; const struct nlattr *mask; const struct nlattr *key; - size_t actions_len; size_t mask_len; size_t key_len; bool verbosity = false; @@ -4084,18 +4082,26 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, ds_init(&ds); dpif_flow_dump_start(&flow_dump, ofproto->backer->dpif); - while (dpif_flow_dump_next(&flow_dump, &key, &key_len, &mask, &mask_len, - &actions, &actions_len, &stats)) { + while (dpif_flow_dump_next(&flow_dump, &key, &key_len, + &mask, &mask_len, &stats)) { + struct ofpbuf *actions; + if (!ofproto_dpif_contains_flow(ofproto, key, key_len)) { continue; } + if (dpif_flow_get(flow_dump.dpif, key, key_len, &actions, NULL)) { + VLOG_DBG("dpif/dump_flows: failed to retrieve actions"); + continue; + } + odp_flow_format(key, key_len, mask, mask_len, &portno_names, &ds, verbosity); ds_put_cstr(&ds, ", "); dpif_flow_stats_format(stats, &ds); ds_put_cstr(&ds, ", actions:"); - format_odp_actions(&ds, actions, actions_len); + format_odp_actions(&ds, actions->data, actions->size); + ofpbuf_delete(actions); ds_put_char(&ds, '\n'); } diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 09db084..0a7dd15 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -747,7 +747,6 @@ static void dpctl_dump_flows(int argc, char *argv[]) { const struct dpif_flow_stats *stats; - const struct nlattr *actions; struct dpif_flow_dump flow_dump; const struct nlattr *key; const struct nlattr *mask; @@ -755,7 +754,6 @@ dpctl_dump_flows(int argc, char *argv[]) struct dpif_port_dump port_dump; struct hmap portno_names; struct simap names_portno; - size_t actions_len; struct dpif *dpif; size_t key_len; size_t mask_len; @@ -791,8 +789,9 @@ dpctl_dump_flows(int argc, char *argv[]) ds_init(&ds); dpif_flow_dump_start(&flow_dump, dpif); while (dpif_flow_dump_next(&flow_dump, &key, &key_len, - &mask, &mask_len, - &actions, &actions_len, &stats)) { + &mask, &mask_len, &stats)) { + struct ofpbuf *actions; + if (filter) { struct flow flow; struct flow_wildcards wc; @@ -813,6 +812,11 @@ dpctl_dump_flows(int argc, char *argv[]) } minimatch_destroy(&minimatch); } + + if (dpif_flow_get(flow_dump.dpif, key, key_len, &actions, NULL)) { + continue; + } + ds_clear(&ds); odp_flow_format(key, key_len, mask, mask_len, &portno_names, &ds, verbosity); @@ -820,7 +824,8 @@ dpctl_dump_flows(int argc, char *argv[]) dpif_flow_stats_format(stats, &ds); ds_put_cstr(&ds, ", actions:"); - format_odp_actions(&ds, actions, actions_len); + format_odp_actions(&ds, actions->data, actions->size); + ofpbuf_delete(actions); printf("%s\n", ds_cstr(&ds)); } dpif_flow_dump_done(&flow_dump); -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev