When --format json is passed to ovs-appctl, pmd-stats-show returns a
JSON array with one object per PMD thread (plus an object for the main
thread, identified by "type":"main"). Each object contains packet
counts, cache hit counters, cycle usage and their derived percentages.
All floating-point fields are always present even when the divisor is
zero (they are reported as 0.0 in that case).
Example output (abbreviated):
[{"type":"pmd","numa_id":0,"core_id":3,
"packets_received":1000,"emc_hits":500,
"megaflow_hits":400,"miss_with_success_upcall":100,
"idle_cycles_pct":90.0,"processing_cycles_pct":10.0,...}]
Signed-off-by: Timothy Redaelli <[email protected]>
---
lib/dpif-netdev.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++-
tests/pmd.at | 10 +++++
2 files changed, 104 insertions(+), 2 deletions(-)
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 46c1c73dc..e7b5fdf4f 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -724,6 +724,91 @@ pmd_info_show_stats(struct ds *reply,
stats[PMD_CYCLES_ITER_BUSY], total_packets);
}
+static struct json *
+pmd_info_show_stats_json(struct dp_netdev_pmd_thread *pmd)
+{
+ uint64_t stats[PMD_N_STATS];
+ uint64_t total_cycles, total_packets;
+ double passes_per_pkt = 0;
+ double lookups_per_hit = 0;
+ double packets_per_batch = 0;
+ const char *type_str;
+ struct json *json;
+
+ pmd_perf_read_counters(&pmd->perf_stats, stats);
+ total_cycles = stats[PMD_CYCLES_ITER_IDLE] + stats[PMD_CYCLES_ITER_BUSY];
+ total_packets = stats[PMD_STAT_RECV];
+
+ if (total_packets > 0) {
+ passes_per_pkt = (total_packets + stats[PMD_STAT_RECIRC])
+ / (double) total_packets;
+ }
+ if (stats[PMD_STAT_MASKED_HIT] > 0) {
+ lookups_per_hit = stats[PMD_STAT_MASKED_LOOKUP]
+ / (double) stats[PMD_STAT_MASKED_HIT];
+ }
+ if (stats[PMD_STAT_SENT_BATCHES] > 0) {
+ packets_per_batch = stats[PMD_STAT_SENT_PKTS]
+ / (double) stats[PMD_STAT_SENT_BATCHES];
+ }
+
+ json = json_object_create();
+ type_str = (pmd->core_id == NON_PMD_CORE_ID) ? "main" : "pmd";
+ json_object_put_string(json, "type", type_str);
+ if (pmd->numa_id != OVS_NUMA_UNSPEC) {
+ json_object_put(json, "numa_id", json_integer_create(pmd->numa_id));
+ }
+ if (pmd->core_id != OVS_CORE_UNSPEC && pmd->core_id != NON_PMD_CORE_ID) {
+ json_object_put(json, "core_id", json_integer_create(pmd->core_id));
+ }
+ json_object_put(json, "packets_received",
+ json_integer_create(total_packets));
+ json_object_put(json, "packet_recirculations",
+ json_integer_create(stats[PMD_STAT_RECIRC]));
+ json_object_put(json, "avg_datapath_passes_per_packet",
+ json_real_create(passes_per_pkt));
+ json_object_put(json, "phwol_hits",
+ json_integer_create(stats[PMD_STAT_PHWOL_HIT]));
+ json_object_put(json, "mfex_opt_hits",
+ json_integer_create(stats[PMD_STAT_MFEX_OPT_HIT]));
+ json_object_put(json, "simple_match_hits",
+ json_integer_create(stats[PMD_STAT_SIMPLE_HIT]));
+ json_object_put(json, "emc_hits",
+ json_integer_create(stats[PMD_STAT_EXACT_HIT]));
+ json_object_put(json, "smc_hits",
+ json_integer_create(stats[PMD_STAT_SMC_HIT]));
+ json_object_put(json, "megaflow_hits",
+ json_integer_create(stats[PMD_STAT_MASKED_HIT]));
+ json_object_put(json, "avg_subtable_lookups_per_megaflow_hit",
+ json_real_create(lookups_per_hit));
+ json_object_put(json, "miss_with_success_upcall",
+ json_integer_create(stats[PMD_STAT_MISS]));
+ json_object_put(json, "miss_with_failed_upcall",
+ json_integer_create(stats[PMD_STAT_LOST]));
+ json_object_put(json, "avg_packets_per_output_batch",
+ json_real_create(packets_per_batch));
+ json_object_put(json, "idle_cycles",
+ json_integer_create(stats[PMD_CYCLES_ITER_IDLE]));
+ json_object_put(json, "idle_cycles_pct",
+ json_real_create(total_cycles > 0
+ ? stats[PMD_CYCLES_ITER_IDLE]
+ / (double) total_cycles * 100 : 0.0));
+ json_object_put(json, "processing_cycles",
+ json_integer_create(stats[PMD_CYCLES_ITER_BUSY]));
+ json_object_put(json, "processing_cycles_pct",
+ json_real_create(total_cycles > 0
+ ? stats[PMD_CYCLES_ITER_BUSY]
+ / (double) total_cycles * 100 : 0.0));
+ json_object_put(json, "avg_cycles_per_packet",
+ json_real_create((total_cycles > 0 && total_packets > 0)
+ ? total_cycles / (double) total_packets : 0.0));
+ json_object_put(json, "avg_processing_cycles_per_packet",
+ json_real_create((total_cycles > 0 && total_packets > 0)
+ ? stats[PMD_CYCLES_ITER_BUSY]
+ / (double) total_packets : 0.0));
+ return json;
+}
+
static void
pmd_info_show_perf(struct ds *reply,
struct dp_netdev_pmd_thread *pmd,
@@ -1424,7 +1509,10 @@ dpif_netdev_pmd_info(struct unixctl_conn *conn, int
argc, const char *argv[],
}
if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) {
- if (type == PMD_INFO_SLEEP_SHOW) {
+ if (type == PMD_INFO_SHOW_STATS) {
+ json_output = true;
+ json_result = json_array_create_empty();
+ } else if (type == PMD_INFO_SLEEP_SHOW) {
json_output = true;
json_result = json_object_create();
json_object_put(json_result, "default_max_sleep_us",
@@ -1458,7 +1546,11 @@ dpif_netdev_pmd_info(struct unixctl_conn *conn, int
argc, const char *argv[],
} else if (type == PMD_INFO_CLEAR_STATS) {
pmd_perf_stats_clear(&pmd->perf_stats);
} else if (type == PMD_INFO_SHOW_STATS) {
- pmd_info_show_stats(&reply, pmd);
+ if (json_output) {
+ json_array_add(json_result, pmd_info_show_stats_json(pmd));
+ } else {
+ pmd_info_show_stats(&reply, pmd);
+ }
} else if (type == PMD_INFO_PERF_SHOW) {
pmd_info_show_perf(&reply, pmd, (struct pmd_perf_params *)aux);
} else if (type == PMD_INFO_SLEEP_SHOW) {
diff --git a/tests/pmd.at b/tests/pmd.at
index 5266fb696..2b3a4be3e 100644
--- a/tests/pmd.at
+++ b/tests/pmd.at
@@ -490,6 +490,16 @@ pmd thread numa_id <cleared> core_id <cleared>:
miss with failed upcall: 0
])
+dnl Check JSON output.
+AT_CHECK([ovs-appctl --format json dpif-netdev/pmd-stats-show | dnl
+ grep '"packets_received":20'], [0], [ignore])
+AT_CHECK([ovs-appctl --format json dpif-netdev/pmd-stats-show | dnl
+ grep '"emc_hits":19'], [0], [ignore])
+AT_CHECK([ovs-appctl --format json dpif-netdev/pmd-stats-show | dnl
+ grep '"miss_with_success_upcall":1'], [0], [ignore])
+AT_CHECK([ovs-appctl --format json dpif-netdev/pmd-stats-show | dnl
+ grep '"miss_with_failed_upcall":0'], [0], [ignore])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
--
2.53.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev