On Fri, Apr 07, 2017 at 04:13:08PM +0300, Roi Dayan wrote:
> From: Paul Blakey <[email protected]>
> 
> Usage:
>     # to dump all datapath flows (default):
>     ovs-dpctl dump-flows
> 
>     # to dump only flows that in kernel datapath:
>     ovs-dpctl dump-flows type=ovs
> 
>     # to dump only flows that are offloaded:
>     ovs-dpctl dump-flows type=offloaded


It should return an error if the type= is wrong/unavailable.

Flavio

> 
> Signed-off-by: Paul Blakey <[email protected]>
> Reviewed-by: Roi Dayan <[email protected]>
> Reviewed-by: Simon Horman <[email protected]>
> ---
>  lib/dpctl.c                   | 21 ++++++++++-----
>  lib/dpctl.man                 |  7 ++++-
>  lib/dpif-netdev.c             |  3 ++-
>  lib/dpif-netlink.c            | 62 
> ++++++++++++++++++++++++++++++++++---------
>  lib/dpif-provider.h           |  6 +++--
>  lib/dpif.c                    |  4 +--
>  lib/dpif.h                    |  3 ++-
>  ofproto/ofproto-dpif-upcall.c |  3 ++-
>  ofproto/ofproto-dpif.c        |  2 +-
>  9 files changed, 84 insertions(+), 27 deletions(-)
> 
> diff --git a/lib/dpctl.c b/lib/dpctl.c
> index 11be857..f534de2 100644
> --- a/lib/dpctl.c
> +++ b/lib/dpctl.c
> @@ -762,6 +762,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct 
> dpctl_params *dpctl_p)
>      char *name;
>  
>      char *filter = NULL;
> +    char *type = NULL;
>      struct flow flow_filter;
>      struct flow_wildcards wc_filter;
>  
> @@ -774,22 +775,29 @@ dpctl_dump_flows(int argc, const char *argv[], struct 
> dpctl_params *dpctl_p)
>      struct dpif_flow_dump *flow_dump;
>      struct dpif_flow f;
>      int pmd_id = PMD_ID_NULL;
> +    int lastargc = 0;
>      int error;
>  
> -    if (argc > 1 && !strncmp(argv[argc - 1], "filter=", 7)) {
> -        filter = xstrdup(argv[--argc] + 7);
> +    while (argc > 1 && lastargc != argc) {
> +        lastargc = argc;
> +        if (!strncmp(argv[argc - 1], "filter=", 7)) {
> +            filter = xstrdup(argv[--argc] + 7);
> +        } else if (!strncmp(argv[argc - 1], "type=", 5)) {
> +            type = xstrdup(argv[--argc] + 5);
> +        }
>      }
> +
>      name = (argc == 2) ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
>      if (!name) {
>          error = EINVAL;
> -        goto out_freefilter;
> +        goto out_free;
>      }
>  
>      error = parsed_dpif_open(name, false, &dpif);
>      free(name);
>      if (error) {
>          dpctl_error(dpctl_p, error, "opening datapath");
> -        goto out_freefilter;
> +        goto out_free;
>      }
>  
>  
> @@ -818,7 +826,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct 
> dpctl_params *dpctl_p)
>      BUILD_ASSERT(PMD_ID_NULL != NON_PMD_CORE_ID);
>  
>      ds_init(&ds);
> -    flow_dump = dpif_flow_dump_create(dpif, false);
> +    flow_dump = dpif_flow_dump_create(dpif, false, (type ? type : "dpctl"));
>      flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
>      while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
>          if (filter) {
> @@ -870,8 +878,9 @@ out_dpifclose:
>      simap_destroy(&names_portno);
>      hmap_destroy(&portno_names);
>      dpif_close(dpif);
> -out_freefilter:
> +out_free:
>      free(filter);
> +    free(type);
>      return error;
>  }
>  
> diff --git a/lib/dpctl.man b/lib/dpctl.man
> index 2fcbc94..efd459f 100644
> --- a/lib/dpctl.man
> +++ b/lib/dpctl.man
> @@ -99,7 +99,7 @@ default.  When multiple datapaths exist, then a datapath 
> name is
>  required.
>  .
>  .TP
> -.DO "[\fB\-m \fR| \fB\-\-more\fR]" \*(DX\fBdump\-flows\fR "[\fIdp\fR] 
> [\fBfilter=\fIfilter\fR]"
> +.DO "[\fB\-m \fR| \fB\-\-more\fR]" \*(DX\fBdump\-flows\fR "[\fIdp\fR] 
> [\fBfilter=\fIfilter\fR] [\fBtype=\fItype\fR]"
>  Prints to the console all flow entries in datapath \fIdp\fR's flow
>  table.  Without \fB\-m\fR or \fB\-\-more\fR, output omits match fields
>  that a flow wildcards entirely; with \fB\-m\fR or \fB\-\-more\fR,
> @@ -112,6 +112,11 @@ not an OpenFlow flow: besides other differences, it 
> never contains wildcards.)
>  The \fIfilter\fR is also useful to match wildcarded fields in the datapath
>  flow. As an example, \fBfilter='tcp,tp_src=100'\fR will match the
>  datapath flow containing '\fBtcp(src=80/0xff00,dst=8080/0xff)\fR'.
> +.IP
> +If \fBtype=\fItype\fR is specified, only displays flows of a specific type.
> +\fItype\fR can be \fBoffloaded\fR to display only offloaded rules or 
> \fBOVS\fR
> +to display only non-offloaded rules.
> +By default both offloaded and non-offloaded rules are displayed.
>  .
>  .IP "\*(DX\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR"
>  .TP
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index a14a2eb..a70e3e1 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -2612,7 +2612,8 @@ dpif_netdev_flow_dump_cast(struct dpif_flow_dump *dump)
>  }
>  
>  static struct dpif_flow_dump *
> -dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse)
> +dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse,
> +                             char *type OVS_UNUSED)
>  {
>      struct dpif_netdev_flow_dump *dump;
>  
> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
> index 5d1639b..acce90e 100644
> --- a/lib/dpif-netlink.c
> +++ b/lib/dpif-netlink.c
> @@ -1374,6 +1374,16 @@ dpif_netlink_init_flow_del(struct dpif_netlink *dpif,
>                                   del->ufid, del->terse, request);
>  }
>  
> +enum {
> +    DUMP_OVS_FLOWS_BIT       = 0,
> +    DUMP_OFFLOADED_FLOWS_BIT = 1,
> +};
> +
> +enum {
> +    DUMP_OVS_FLOWS       = (1 << DUMP_OVS_FLOWS_BIT),
> +    DUMP_OFFLOADED_FLOWS = (1 << DUMP_OFFLOADED_FLOWS_BIT),
> +};
> +
>  struct dpif_netlink_flow_dump {
>      struct dpif_flow_dump up;
>      struct nl_dump nl_dump;
> @@ -1382,6 +1392,7 @@ struct dpif_netlink_flow_dump {
>      int netdev_dumps_num;                    /* Number of netdev_flow_dumps 
> */
>      struct ovs_mutex netdev_lock;            /* Guards the following. */
>      int netdev_current_dump OVS_GUARDED;     /* Shared current dump */
> +    int type;                                /* Type of dump */
>  };
>  
>  static struct dpif_netlink_flow_dump *
> @@ -1396,7 +1407,7 @@ start_netdev_dump(const struct dpif *dpif_,
>  {
>      ovs_mutex_init(&dump->netdev_lock);
>  
> -    if (!netdev_flow_api_enabled) {
> +    if (!(dump->type & DUMP_OFFLOADED_FLOWS)) {
>          dump->netdev_dumps_num = 0;
>          dump->netdev_dumps = NULL;
>          return;
> @@ -1410,8 +1421,24 @@ start_netdev_dump(const struct dpif *dpif_,
>      ovs_mutex_unlock(&dump->netdev_lock);
>  }
>  
> +static int
> +dpif_netlink_get_dump_type(char *str) {
> +    int type = 0;
> +
> +    if (!str || !strcmp(str, "ovs") || !strcmp(str, "dpctl")) {
> +        type |= DUMP_OVS_FLOWS;
> +    }
> +    if ((netdev_flow_api_enabled && !str)
> +        || (str && (!strcmp(str, "offloaded") || !strcmp(str, "dpctl")))) {
> +        type |= DUMP_OFFLOADED_FLOWS;
> +    }
> +
> +    return type;
> +}
> +
>  static struct dpif_flow_dump *
> -dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse)
> +dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse,
> +                              char *type)
>  {
>      const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
>      struct dpif_netlink_flow_dump *dump;
> @@ -1421,16 +1448,20 @@ dpif_netlink_flow_dump_create(const struct dpif 
> *dpif_, bool terse)
>      dump = xmalloc(sizeof *dump);
>      dpif_flow_dump_init(&dump->up, dpif_);
>  
> -    dpif_netlink_flow_init(&request);
> -    request.cmd = OVS_FLOW_CMD_GET;
> -    request.dp_ifindex = dpif->dp_ifindex;
> -    request.ufid_present = false;
> -    request.ufid_terse = terse;
> +    dump->type = dpif_netlink_get_dump_type(type);
>  
> -    buf = ofpbuf_new(1024);
> -    dpif_netlink_flow_to_ofpbuf(&request, buf);
> -    nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
> -    ofpbuf_delete(buf);
> +    if (dump->type & DUMP_OVS_FLOWS) {
> +        dpif_netlink_flow_init(&request);
> +        request.cmd = OVS_FLOW_CMD_GET;
> +        request.dp_ifindex = dpif->dp_ifindex;
> +        request.ufid_present = false;
> +        request.ufid_terse = terse;
> +
> +        buf = ofpbuf_new(1024);
> +        dpif_netlink_flow_to_ofpbuf(&request, buf);
> +        nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
> +        ofpbuf_delete(buf);
> +    }
>      atomic_init(&dump->status, 0);
>      dump->up.terse = terse;
>  
> @@ -1443,9 +1474,12 @@ static int
>  dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_)
>  {
>      struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
> -    unsigned int nl_status = nl_dump_done(&dump->nl_dump);
> +    unsigned int nl_status = 0;
>      int dump_status;
>  
> +    if (dump->type & DUMP_OVS_FLOWS) {
> +        nl_status = nl_dump_done(&dump->nl_dump);
> +    }
>      for (int i = 0; i < dump->netdev_dumps_num; i++) {
>          int err = netdev_flow_dump_destroy(dump->netdev_dumps[i]);
>          if (err != 0 && err != EOPNOTSUPP) {
> @@ -1676,6 +1710,10 @@ dpif_netlink_flow_dump_next(struct 
> dpif_flow_dump_thread *thread_,
>          }
>      }
>  
> +    if (!(dump->type & DUMP_OVS_FLOWS)) {
> +        return n_flows;
> +    }
> +
>      while (!n_flows
>             || (n_flows < flow_limit && thread->nl_flows.size)) {
>          struct dpif_netlink_flow datapath_flow;
> diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
> index a4ed01a..64ac2e2 100644
> --- a/lib/dpif-provider.h
> +++ b/lib/dpif-provider.h
> @@ -281,9 +281,11 @@ struct dpif_class {
>       * dpif_flow_dump_thread_init(), respectively.
>       *
>       * If 'terse' is true, then only UID and statistics will
> -     * be returned in the dump. Otherwise, all fields will be returned. */
> +     * be returned in the dump. Otherwise, all fields will be returned.
> +     *
> +     * If 'type' isn't null, dumps only the flows of the given type. */
>      struct dpif_flow_dump *(*flow_dump_create)(const struct dpif *dpif,
> -                                               bool terse);
> +                                               bool terse, char *type);
>      int (*flow_dump_destroy)(struct dpif_flow_dump *dump);
>  
>      struct dpif_flow_dump_thread *(*flow_dump_thread_create)(
> diff --git a/lib/dpif.c b/lib/dpif.c
> index d45f21d..f5fcf47 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -1054,9 +1054,9 @@ dpif_flow_del(struct dpif *dpif,
>   * This function always successfully returns a dpif_flow_dump.  Error
>   * reporting is deferred to dpif_flow_dump_destroy(). */
>  struct dpif_flow_dump *
> -dpif_flow_dump_create(const struct dpif *dpif, bool terse)
> +dpif_flow_dump_create(const struct dpif *dpif, bool terse, char *type)
>  {
> -    return dpif->dpif_class->flow_dump_create(dpif, terse);
> +    return dpif->dpif_class->flow_dump_create(dpif, terse, type);
>  }
>  
>  /* Destroys 'dump', which must have been created with 
> dpif_flow_dump_create().
> diff --git a/lib/dpif.h b/lib/dpif.h
> index 81376c0..b1f516e 100644
> --- a/lib/dpif.h
> +++ b/lib/dpif.h
> @@ -569,7 +569,8 @@ int dpif_flow_get(struct dpif *,
>   *
>   * All error reporting is deferred to the call to dpif_flow_dump_destroy().
>   */
> -struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *, bool 
> terse);
> +struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *, bool terse,
> +                                             char *type);
>  int dpif_flow_dump_destroy(struct dpif_flow_dump *);
>  
>  struct dpif_flow_dump_thread *dpif_flow_dump_thread_create(
> diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
> index 3b28f9a..d6a4cf6 100644
> --- a/ofproto/ofproto-dpif-upcall.c
> +++ b/ofproto/ofproto-dpif-upcall.c
> @@ -885,7 +885,8 @@ udpif_revalidator(void *arg)
>                  bool terse_dump;
>  
>                  terse_dump = udpif_use_ufid(udpif);
> -                udpif->dump = dpif_flow_dump_create(udpif->dpif, terse_dump);
> +                udpif->dump = dpif_flow_dump_create(udpif->dpif, terse_dump,
> +                                                    NULL);
>              }
>          }
>  
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 523adad..fa0fb19 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -5107,7 +5107,7 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn 
> *conn,
>      }
>  
>      ds_init(&ds);
> -    flow_dump = dpif_flow_dump_create(ofproto->backer->dpif, false);
> +    flow_dump = dpif_flow_dump_create(ofproto->backer->dpif, false, NULL);
>      flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
>      while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
>          struct flow flow;
> -- 
> 2.7.4
> 
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

-- 
Flavio

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to