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
