Looks good.
Acked-by: Andy Zhou <az...@nicira.com>

Is it worth while to add a unit test for this?

On Wed, Dec 17, 2014 at 10:34 AM, Joe Stringer <joestrin...@nicira.com> wrote:
> 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
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to