Flows that are offloaded via DPDK can be partially offloaded (matches only) or fully offloaded (matches and actions). Set partially offloaded display to (offloaded=partial, dp:ovs), and fully offloaded to (offloaded=yes, dp:dpdk). Also support filter types "dpdk" and "partially-offloaded".
Signed-off-by: Eli Britstein <[email protected]> --- NEWS | 3 ++ lib/dpctl.c | 97 ++++++++++++++++++++++++++++++++++++++++++++--------------- lib/dpctl.man | 2 ++ 3 files changed, 78 insertions(+), 24 deletions(-) diff --git a/NEWS b/NEWS index 2acde3fe8..85c4a4812 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,9 @@ Post-v2.12.0 * DPDK ring ports (dpdkr) are deprecated and will be removed in next releases. * Add support for DPDK 19.11. + - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for + partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and + type filter supports new filters: "dpdk" and "partially-offloaded". v2.12.0 - 03 Sep 2019 --------------------- diff --git a/lib/dpctl.c b/lib/dpctl.c index 0ee64718c..387f61ed4 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -818,7 +818,11 @@ format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports, dpif_flow_stats_format(&f->stats, ds); if (dpctl_p->verbosity && f->attrs.offloaded) { - ds_put_cstr(ds, ", offloaded:yes"); + if (f->attrs.dp_layer && !strcmp(f->attrs.dp_layer, "ovs")) { + ds_put_cstr(ds, ", offloaded:partial"); + } else { + ds_put_cstr(ds, ", offloaded:yes"); + } } if (dpctl_p->verbosity && f->attrs.dp_layer) { ds_put_format(ds, ", dp:%s", f->attrs.dp_layer); @@ -827,20 +831,30 @@ format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports, format_odp_actions(ds, f->actions, f->actions_len, ports); } +enum dp_type { + DP_TYPE_ANY, + DP_TYPE_OVS, + DP_TYPE_TC, + DP_TYPE_DPDK, +}; + +enum ol_type { + OL_TYPE_ANY, + OL_TYPE_NO, + OL_TYPE_YES, + OL_TYPE_PARTIAL, +}; + struct dump_types { - bool ovs; - bool tc; - bool offloaded; - bool non_offloaded; + enum dp_type dp_type; + enum ol_type ol_type; }; static void enable_all_dump_types(struct dump_types *dump_types) { - dump_types->ovs = true; - dump_types->tc = true; - dump_types->offloaded = true; - dump_types->non_offloaded = true; + dump_types->dp_type = DP_TYPE_ANY; + dump_types->ol_type = OL_TYPE_ANY; } static int @@ -862,13 +876,17 @@ populate_dump_types(char *types_list, struct dump_types *dump_types, current_type[type_len] = '\0'; if (!strcmp(current_type, "ovs")) { - dump_types->ovs = true; + dump_types->dp_type = DP_TYPE_OVS; } else if (!strcmp(current_type, "tc")) { - dump_types->tc = true; + dump_types->dp_type = DP_TYPE_TC; + } else if (!strcmp(current_type, "dpdk")) { + dump_types->dp_type = DP_TYPE_DPDK; } else if (!strcmp(current_type, "offloaded")) { - dump_types->offloaded = true; + dump_types->ol_type = OL_TYPE_YES; } else if (!strcmp(current_type, "non-offloaded")) { - dump_types->non_offloaded = true; + dump_types->ol_type = OL_TYPE_NO; + } else if (!strcmp(current_type, "partially-offloaded")) { + dump_types->ol_type = OL_TYPE_PARTIAL; } else if (!strcmp(current_type, "all")) { enable_all_dump_types(dump_types); } else { @@ -884,30 +902,61 @@ static void determine_dpif_flow_dump_types(struct dump_types *dump_types, struct dpif_flow_dump_types *dpif_dump_types) { - dpif_dump_types->ovs_flows = dump_types->ovs || dump_types->non_offloaded; - dpif_dump_types->netdev_flows = dump_types->tc || dump_types->offloaded - || dump_types->non_offloaded; + dpif_dump_types->ovs_flows = dump_types->dp_type == DP_TYPE_OVS; + dpif_dump_types->netdev_flows = (dump_types->dp_type == DP_TYPE_TC || + dump_types->dp_type == DP_TYPE_DPDK); } static bool -flow_passes_type_filter(const struct dpif_flow *f, - struct dump_types *dump_types) +flow_passes_dp_filter(const struct dpif_flow *f, + struct dump_types *dump_types) { - if (dump_types->ovs && !strcmp(f->attrs.dp_layer, "ovs")) { + if (dump_types->dp_type == DP_TYPE_ANY) { return true; } - if (dump_types->tc && !strcmp(f->attrs.dp_layer, "tc")) { - return true; + if (dump_types->dp_type == DP_TYPE_OVS) { + return !strcmp(f->attrs.dp_layer, "ovs"); } - if (dump_types->offloaded && f->attrs.offloaded) { - return true; + if (dump_types->dp_type == DP_TYPE_TC) { + return !strcmp(f->attrs.dp_layer, "tc"); } - if (dump_types->non_offloaded && !(f->attrs.offloaded)) { + if (dump_types->dp_type == DP_TYPE_DPDK) { + return !strcmp(f->attrs.dp_layer, "dpdk"); + } + /* should never get here. */ + return false; +} + +static bool +flow_passes_ol_filter(const struct dpif_flow *f, + struct dump_types *dump_types) +{ + if (dump_types->ol_type == OL_TYPE_ANY) { return true; } + if (dump_types->ol_type == OL_TYPE_NO) { + return !f->attrs.offloaded; + } + if (dump_types->ol_type == OL_TYPE_YES && + strcmp(f->attrs.dp_layer, "ovs")) { + return f->attrs.offloaded; + } + if (dump_types->ol_type == OL_TYPE_PARTIAL && + !strcmp(f->attrs.dp_layer, "ovs")) { + return f->attrs.offloaded; + } + /* should never get here. */ return false; } +static bool +flow_passes_type_filter(const struct dpif_flow *f, + struct dump_types *dump_types) +{ + return flow_passes_dp_filter(f, dump_types) && + flow_passes_ol_filter(f, dump_types); +} + static struct hmap * dpctl_get_portno_names(struct dpif *dpif, const struct dpctl_params *dpctl_p) { diff --git a/lib/dpctl.man b/lib/dpctl.man index 090c3b960..727d1f7be 100644 --- a/lib/dpctl.man +++ b/lib/dpctl.man @@ -124,8 +124,10 @@ This option supported only for \fBovs\-appctl dpctl/dump\-flows\fR. . \fBovs\fR - displays flows handled in the ovs dp \fBtc\fR - displays flows handled in the tc dp + \fBdpdk\fR - displays flows fully offloaded by dpdk \fBoffloaded\fR - displays flows offloaded to the HW \fBnon-offloaded\fR - displays flows not offloaded to the HW + \fBpartially-offloaded\fR - displays flows where only part of their proccessing is done in HW \fBall\fR - displays all the types of flows .IP By default all the types of flows are displayed. -- 2.14.5 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
