@@ -23,6 +23,8 @@ Post-v2.13.0
* New configuration knob 'other_config:lb-output-action' for bond ports
that enables new datapath action 'lb_output' to avoid recirculation
in balance-tcp mode. Disabled by default.
+ * Command "ovs-appctl dpctl/dump-flows" added option "pmd" which allow
+ user to dump pmd specified.
- Tunnels: TC Flower offload
* Tunnel Local endpoint address masked match are supported.
* Tunnel Romte endpoint address masked match are supported.
@@ -979,6 +979,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
struct dpif_flow_dump_thread *flow_dump_thread;
struct dpif_flow_dump *flow_dump;
struct dpif_flow f;
+ int pmd_id_filter = PMD_ID_NULL;
int pmd_id = PMD_ID_NULL;
int lastargc = 0;
int error;
@@ -996,6 +997,12 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
goto out_free;
}
types_list = xstrdup(argv[--argc] + 5);
+ } else if (pmd_id_filter == PMD_ID_NULL &&
+ !strncmp(argv[argc - 1], "pmd=", 4)) {
+ if (!ovs_scan(argv[--argc], "pmd=%"SCNu32, &pmd_id_filter)) {
+ error = EINVAL;
+ goto out_free;
+ }
}
}
@@ -1044,7 +1051,13 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
ds_init(&ds);
memset(&f, 0, sizeof f);
flow_dump = dpif_flow_dump_create(dpif, false, &dpif_dump_types);
+ flow_dump->pmd_id = pmd_id_filter;
flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
+ if (!flow_dump_thread) {
+ error = ENOENT;
+ goto out_dump_destroy;
+ }
+
while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
if (filter) {
struct flow flow;
@@ -1085,11 +1098,16 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
}
}
dpif_flow_dump_thread_destroy(flow_dump_thread);
- error = dpif_flow_dump_destroy(flow_dump);
- if (error) {
- dpctl_error(dpctl_p, error, "Failed to dump flows from datapath");
+out_dump_destroy:
+ {
+ int ret = dpif_flow_dump_destroy(flow_dump);
+ if (ret) {
+ dpctl_error(dpctl_p, ret, "Failed to dump flows from datapath");
+ error = ret;
+ }
}
+
ds_destroy(&ds);
out_dpifclose:
@@ -2503,8 +2521,8 @@ static const struct dpctl_command all_commands[] = {
{ "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
{ "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
{ "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
- { "dump-flows", "[dp] [filter=..] [type=..]",
- 0, 3, dpctl_dump_flows, DP_RO },
+ { "dump-flows", "[dp] [filter=..] [type=..] [pmd=..]",
+ 0, 4, dpctl_dump_flows, DP_RO },
{ "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
{ "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
{ "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
@@ -3776,6 +3776,21 @@ dpif_netdev_flow_dump_thread_create(struct dpif_flow_dump *dump_)
struct dpif_netdev_flow_dump *dump = dpif_netdev_flow_dump_cast(dump_);
struct dpif_netdev_flow_dump_thread *thread;
+ dump->cur_pmd = NULL;
+ if (dump->up.pmd_id != PMD_ID_NULL) {
+ struct dp_netdev *dp = get_dp_netdev(dump->up.dpif);
+ struct dp_netdev_pmd_thread *pmd;
+
+ pmd = dp_netdev_get_pmd(dp, dump->up.pmd_id);
+ if (!pmd || !dp_netdev_pmd_try_ref(pmd)) {
+ VLOG_DBG("The PMD ID (%u) not found or ref.\n",
+ dump->up.pmd_id);
+ return NULL;
+ }
+
+ dump->cur_pmd = pmd;
+ }
+
thread = xmalloc(sizeof *thread);
dpif_flow_dump_thread_init(&thread->up, &dump->up);
thread->dump = dump;
@@ -3787,6 +3802,11 @@ dpif_netdev_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
{
struct dpif_netdev_flow_dump_thread *thread
= dpif_netdev_flow_dump_thread_cast(thread_);
+ struct dpif_netdev_flow_dump *dump = thread->dump;
+
+ if (dump->up.pmd_id != PMD_ID_NULL && dump->cur_pmd) {
+ dp_netdev_pmd_unref(dump->cur_pmd);
+ }
free(thread);
}
@@ -3832,6 +3852,11 @@ dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread *thread_,
struct dp_netdev_flow,
node);
}
+
+ if (dump->up.pmd_id != PMD_ID_NULL) {
+ break;
+ }
+
/* When finishing dumping the current pmd thread, moves to
* the next. */
if (n_flows < flow_limit) {
@@ -57,6 +57,7 @@ static inline void dpif_assert_class(const struct dpif *dpif,
struct dpif_flow_dump {
struct dpif *dpif;
+ unsigned pmd_id; /* As a filter for PMD flows. */
bool terse; /* If true, key/mask/actions may be omitted. */
};
@@ -64,6 +65,7 @@ static inline void
dpif_flow_dump_init(struct dpif_flow_dump *dump, const struct dpif *dpif)
{
dump->dpif = CONST_CAST(struct dpif *, dpif);
+ dump->pmd_id = PMD_ID_NULL;
}
struct dpif_flow_dump_thread {