This allows users to fetch a flow by giving a particular UFID. Usage: 'ovs-dpctl get-flow ufid:<ufid>'
Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- lib/dpctl.c | 96 +++++++++++++++++++++++++++++++++++++++++-------- lib/dpctl.man | 4 +++ utilities/ovs-dpctl.c | 1 + 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/lib/dpctl.c b/lib/dpctl.c index d3d4b7f..8eec944 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -689,6 +689,27 @@ dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, return lasterror; } +static void +format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports, + struct dpctl_params *dpctl_p) +{ + if (dpctl_p->verbosity) { + if (f->ufid_present) { + odp_format_ufid(&f->ufid, ds); + ds_put_cstr(ds, ", "); + } else { + ds_put_cstr(ds, "ufid:<empty>, "); + } + } + odp_flow_format(f->key, f->key_len, f->mask, f->mask_len, ports, ds, + dpctl_p->verbosity); + ds_put_cstr(ds, ", "); + + dpif_flow_stats_format(&f->stats, ds); + ds_put_cstr(ds, ", actions:"); + format_odp_actions(ds, f->actions, f->actions_len); +} + static int dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) { @@ -771,21 +792,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) minimatch_destroy(&minimatch); } ds_clear(&ds); - if (dpctl_p->verbosity) { - if (f.ufid_present) { - odp_format_ufid(&f.ufid, &ds); - ds_put_cstr(&ds, ", "); - } else { - ds_put_cstr(&ds, "ufid:<empty>, "); - } - } - odp_flow_format(f.key, f.key_len, f.mask, f.mask_len, - &portno_names, &ds, dpctl_p->verbosity); - ds_put_cstr(&ds, ", "); - - dpif_flow_stats_format(&f.stats, &ds); - ds_put_cstr(&ds, ", actions:"); - format_odp_actions(&ds, f.actions, f.actions_len); + format_dpif_flow(&ds, &f, &portno_names, dpctl_p); dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds)); } dpif_flow_dump_thread_destroy(flow_dump_thread); @@ -919,6 +926,64 @@ dpctl_mod_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p) } static int +dpctl_get_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p) +{ + const char *key_s = argv[argc - 1]; + struct dpif_flow flow; + struct dpif_port dpif_port; + struct dpif_port_dump port_dump; + struct dpif *dpif; + char *dp_name; + struct hmap portno_names; + ovs_u128 ufid; + struct ofpbuf buf; + uint64_t stub[DPIF_FLOW_BUFSIZE / 8]; + struct ds ds; + int n, error; + + dp_name = argc == 3 ? xstrdup(argv[1]) : get_one_dp(dpctl_p); + if (!dp_name) { + return EINVAL; + } + error = parsed_dpif_open(dp_name, false, &dpif); + free(dp_name); + if (error) { + dpctl_error(dpctl_p, error, "opening datapath"); + return error; + } + + ofpbuf_use_stub(&buf, &stub, sizeof stub); + hmap_init(&portno_names); + DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) { + odp_portno_names_set(&portno_names, dpif_port.port_no, dpif_port.name); + } + + n = odp_ufid_from_string(key_s, &ufid); + if (n <= 0) { + dpctl_error(dpctl_p, -n, "parsing flow ufid"); + goto out; + } + + error = dpif_flow_get(dpif, NULL, 0, &ufid, &buf, &flow); + if (error) { + dpctl_error(dpctl_p, error, "getting flow"); + goto out; + } + + ds_init(&ds); + format_dpif_flow(&ds, &flow, &portno_names, dpctl_p); + dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds)); + ds_destroy(&ds); + +out: + odp_portno_names_destroy(&portno_names); + hmap_destroy(&portno_names); + ofpbuf_uninit(&buf); + dpif_close(dpif); + return error; +} + +static int dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p) { const char *key_s = argv[argc - 1]; @@ -1339,6 +1404,7 @@ static const struct dpctl_command all_commands[] = { { "dump-flows", "[dp]", 0, 2, dpctl_dump_flows }, { "add-flow", "add-flow [dp] flow actions", 2, 3, dpctl_add_flow }, { "mod-flow", "mod-flow [dp] flow actions", 2, 3, dpctl_mod_flow }, + { "get-flow", "get-flow [dp] ufid", 1, 2, dpctl_get_flow }, { "del-flow", "del-flow [dp] flow", 1, 2, dpctl_del_flow }, { "del-flows", "[dp]", 0, 1, dpctl_del_flows }, { "help", "", 0, INT_MAX, dpctl_help }, diff --git a/lib/dpctl.man b/lib/dpctl.man index c678576..4e34630 100644 --- a/lib/dpctl.man +++ b/lib/dpctl.man @@ -143,5 +143,9 @@ Deletes the flow from \fIdp\fR's flow table that matches \fIflow\fR. If \fB\-s\fR or \fB\-\-statistics\fR is specified, then \fBmod\-flows\fR prints the deleted flow's statistics. . +.IP "\*(DX\fBget\-flow\fR [\fIdp\fR] ufid:\fIufid\fR" +Fetches the flow from \fIdp\fR's flow table with unique identifier \fIufid\fR. +\fIufid\fR must be specified as a string of hexadecimal characters. +. .IP "\*(DX\fBdel\-flows\fR [\fIdp\fR]" Deletes all flow entries from datapath \fIdp\fR's flow table. diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 404a428..9d279f0 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -168,6 +168,7 @@ usage(void *userdata OVS_UNUSED) " dump-flows [DP] display flows in DP\n" " add-flow [DP] FLOW ACTIONS add FLOW with ACTIONS to DP\n" " mod-flow [DP] FLOW ACTIONS change FLOW actions to ACTIONS in DP\n" + " get-flow [DP] ufid:UFID fetch flow corresponding to UFID\n" " del-flow [DP] FLOW delete FLOW from DP\n" " del-flows [DP] delete all flows from DP\n" "Each IFACE on add-dp, add-if, and set-if may be followed by\n" -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev