> On Feb 25, 2015, at 8:43 AM, Daniele Di Proietto <diproiet...@vmware.com> > wrote: > >
(snip) > > +enum pmd_info_type { > + PMD_INFO_SHOW_STATS, /* show how cpu cycles are spent */ > + PMD_INFO_CLEAR_STATS /* set the cycles count to 0 */ > +}; > + > +static void > +dpif_netdev_pmd_info(struct unixctl_conn *conn, int argc, const char *argv[], > + void *aux) > +{ > + struct ds reply = DS_EMPTY_INITIALIZER; > + struct dp_netdev_pmd_thread *pmd; > + struct dp_netdev *dp = NULL; > + enum pmd_info_type type = (enum pmd_info_type) aux; > + > + ovs_mutex_lock(&dp_netdev_mutex); > + > + if (argc == 2) { > + dp = shash_find_data(&dp_netdevs, argv[1]); > + } else if (shash_count(&dp_netdevs) == 1) { > + /* There's only one datapath */ > + dp = shash_random_node(&dp_netdevs)->data; > + } > + > + if (!dp) { > + ovs_mutex_unlock(&dp_netdev_mutex); > + unixctl_command_reply_error(conn, > + "please specify an existing datapath"); > + return; > + } > + > + CMAP_FOR_EACH (pmd, node, &dp->poll_threads) { > + struct dp_netdev_pmd_stats s; > + struct dp_netdev_pmd_cycles t; > + unsigned long long total_packets = 0; > + uint64_t total_cycles = 0; > + int i; > + > + if (type == PMD_INFO_CLEAR_STATS) { > + /* We cannot write 'stats' and 'cycles' (because they're written > + * by other threads) and we shouldn't change 'stats' (because > + * ther're used to count datapath stats, which must not be > cleared > + * here). > + * Insted, we save the current values and subtract them from the “instead" > + * values to be displayed in the future */ > + pmd->cycles_zero = pmd->cycles; > + pmd->stats_zero = pmd->stats; It seems to me that this access should be protected with a similar mechanism we use in cmaps, as any concurrent write by the pmd thread may result the “zero” versions to be inconsistent, a mixture of the old and new. Or is it the case that this does not matter? I guess that the cycles and stats need not be consistent with each other, though. > + continue; > + } > + t = pmd->cycles; > + s = pmd->stats; > + > + for (i = 0; i < ARRAY_SIZE(t.n); i++) { > + t.n[i] -= pmd->cycles_zero.n[i]; > + total_cycles += t.n[i]; > + } > + for (i = 0; i < ARRAY_SIZE(s.n); i++) { > + s.n[i] -= pmd->stats_zero.n[i]; > + if (i != DP_STAT_LOST) { > + total_packets += s.n[i]; > + } > + } > + Similar concern up here. > + ds_put_cstr(&reply, (pmd->core_id == NON_PMD_CORE_ID) > + ?"main thread":"pmd thread"); > + > + if(pmd->numa_id != OVS_NUMA_UNSPEC) { > + ds_put_format(&reply, " numa_id %d", pmd->numa_id); > + } > + if(pmd->core_id != OVS_CORE_UNSPEC) { > + ds_put_format(&reply, " core_id %d", pmd->core_id); > + } > + ds_put_cstr(&reply, ":\n"); > + > + ds_put_format(&reply, > + "\temc hits:%llu\n" > + "\tmasked hits:%llu\n" > + "\tmiss:%llu\n" > + "\tlost:%llu\n", > + s.n[DP_STAT_EXACT_HIT], > + s.n[DP_STAT_MASKED_HIT], > + s.n[DP_STAT_MISS], > + s.n[DP_STAT_LOST]); > + > + if (total_cycles == 0) { > + ds_put_cstr(&reply, "\tcycles counters not supported\n"); > + continue; > + } > + > + ds_put_format(&reply, > + "\tpolling cycles:%"PRIu64" (%.02f%%)\n" > + "\tprocessing cycles:%"PRIu64" (%.02f%%)\n" > + "\tother cycles:%"PRIu64" (%.02f%%)\n", > + t.n[PMD_CYCLES_POLLING], > + t.n[PMD_CYCLES_POLLING]/(double)total_cycles*100, > + t.n[PMD_CYCLES_PROCESSING], > + t.n[PMD_CYCLES_PROCESSING]/(double)total_cycles*100, > + t.n[PMD_CYCLES_OTHER], > + t.n[PMD_CYCLES_OTHER]/(double)total_cycles*100); > + > + if (total_packets == 0) { > + ds_put_cstr(&reply, "\tno packets processed yet\n"); > + continue; > + } > + ds_put_format(&reply, > + "\tavg cycles per packet: %.02f (%"PRIu64"/%llu)\n", > + total_cycles/(double)total_packets, > + total_cycles, total_packets); > + > + ds_put_format(&reply, > + "\tavg processing cycles per packet: %.02f > (%"PRIu64"/%llu)\n", > + t.n[PMD_CYCLES_PROCESSING]/(double)total_packets, > + t.n[PMD_CYCLES_PROCESSING], total_packets); > + } > + > + ovs_mutex_unlock(&dp_netdev_mutex); > + > + unixctl_command_reply(conn, ds_cstr(&reply)); > + ds_destroy(&reply); > +} > + > +static int > +dpif_netdev_init(void) > +{ > + unixctl_command_register("dpif-netdev/pmd-stats-show", "[dp]", > + 0, 1, dpif_netdev_pmd_info, > + (void *)PMD_INFO_SHOW_STATS); > + unixctl_command_register("dpif-netdev/pmd-stats-clear", "[dp]", > + 0, 1, dpif_netdev_pmd_info, > + (void *)PMD_INFO_CLEAR_STATS); > + return 0; > +} > + > static int > dpif_netdev_enumerate(struct sset *all_dps, > const struct dpif_class *dpif_class) > @@ -2260,7 +2399,7 @@ pmd_cycles_counter_diff(struct dp_netdev_pmd_thread > *pmd) > { > uint64_t old_cycles = pmd->last_cycles, > #ifdef DPDK_NETDEV > - new_cycles = rte_get_tsc_cycles(); > + new_cycles = rte_get_timer_cycles(); > #else > new_cycles = 0; > #endif > @@ -3332,7 +3471,7 @@ dp_netdev_execute_actions(struct dp_netdev_pmd_thread > *pmd, > > const struct dpif_class dpif_netdev_class = { > "netdev", > - NULL, /* init */ > + dpif_netdev_init, > dpif_netdev_enumerate, > dpif_netdev_port_open_type, > dpif_netdev_open, > diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in > index 7f165ea..26b257b 100644 > --- a/vswitchd/ovs-vswitchd.8.in > +++ b/vswitchd/ovs-vswitchd.8.in > @@ -239,6 +239,24 @@ type). > .. > .so lib/dpctl.man > . > +.SS "DPIF-NETDEV COMMANDS" > +These commands are used to expose internal information (mostly statistics) > +about the ``dpif-netdev'' userspace datapath. If there is only one datapath > +(as is often the case, unless \fBdpctl/\fR commands are used), the \fIdp\fR > +argument can be omitted. > +.IP "\fBdpif-netdev/pmd-stats-show\fR [\fIdp\fR]" > +Shows performance statistics for each pmd thread of the datapath \fIdp\fR. > +The special thread ``main'' sums up the statistics of every other thread. > +The sum of ``emc hits'', ``masked hits'' and ``miss'' is the number of > +packets received by the datapath. Cycles are counted using the TSC or similar > +facilities (when available on the platform). To reset these counters use > +\fBdpif-netdev/pmd-stats-clear\fR. The duration of one cycle depends on the > +measuring infrastructure. > +.IP "\fBdpif-netdev/pmd-stats-clear\fR [\fIdp\fR]" > +Resets to zero the per pmd thread performance numbers shown by the > +\fBdpif-netdev/pmd-stats-show\fR command. It will NOT reset datapath or > +bridge statistics, only the values shown by the above command. > +. > .so ofproto/ofproto-dpif-unixctl.man > .so ofproto/ofproto-unixctl.man > .so lib/vlog-unixctl.man > -- > 2.1.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev