Linux Perf Users
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
	 Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	 James Clark <james.clark@linaro.org>,
	Thomas Falcon <thomas.falcon@intel.com>,
	 Thomas Richter <tmricht@linux.ibm.com>,
	linux-perf-users@vger.kernel.org,  linux-kernel@vger.kernel.org
Cc: Andi Kleen <ak@linux.intel.com>
Subject: [PATCH v2 2/4] perf tool_pmu: Add network events
Date: Fri, 13 Nov 2026 15:37:37 -0800	[thread overview]
Message-ID: <20261113233739.3626499-3-irogers@google.com> (raw)
In-Reply-To: <20261113233739.3626499-1-irogers@google.com>

Add system-wide tool PMU events to report network statistics from
/proc/net/dev. Since /proc/pid/net/dev reports statistics for the entire
network namespace rather than an individual process, reject opening
these events in per-process or cgroup mode.

The following events are added for both RX (receive) and TX (transmit):
- bytes
- packets
- errors
- drop
- fifo
- frame (RX only) / colls (TX only)
- compressed
- multicast (RX only) / carrier (TX only)

Track initial and accumulated values across enable/disable transitions so
perf stat reports deltas over the measurement period rather than
cumulative totals since boot. Also honor the group leader's
attr.disabled state when opening grouped tool events and map CPU indices
safely in evsel__enable_cpu(), evsel__disable_cpu(), and tool_pmu xyarray
lookups when single-CPU tool events are grouped with per-CPU events.

Example output:

  $ perf stat -a -e net_rx_bytes,net_rx_packets,net_tx_bytes \
      -e net_tx_packets -- sleep 0.02

   Performance counter stats for 'system wide':

              16,971      net_rx_bytes
                  10      net_rx_packets
              17,214      net_tx_bytes
                  10      net_tx_packets

         0.017721776 seconds time elapsed

Signed-off-by: Ian Rogers <irogers@google.com>
---
 .../pmu-events/arch/common/common/tool.json   |  96 ++++++
 tools/perf/pmu-events/empty-pmu-events.c      | 286 +++++++++++-------
 tools/perf/util/evsel.c                       |  53 +++-
 tools/perf/util/tool_pmu.c                    | 263 ++++++++++++++--
 tools/perf/util/tool_pmu.h                    |  17 ++
 5 files changed, 571 insertions(+), 144 deletions(-)

diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json
index 9e0e89553847..a332cbf842f7 100644
--- a/tools/perf/pmu-events/arch/common/common/tool.json
+++ b/tools/perf/pmu-events/arch/common/common/tool.json
@@ -238,5 +238,101 @@
     "EventName": "memory_uss",
     "BriefDescription": "Unique Set Size (USS) in bytes",
     "ConfigCode": "40"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_bytes",
+    "BriefDescription": "System-wide network received bytes",
+    "ConfigCode": "41"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_packets",
+    "BriefDescription": "System-wide network received packets",
+    "ConfigCode": "42"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_errors",
+    "BriefDescription": "System-wide network received errors",
+    "ConfigCode": "43"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_drop",
+    "BriefDescription": "System-wide network received dropped packets",
+    "ConfigCode": "44"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_fifo",
+    "BriefDescription": "System-wide network received fifo overruns",
+    "ConfigCode": "45"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_frame",
+    "BriefDescription": "System-wide network received framing errors",
+    "ConfigCode": "46"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_compressed",
+    "BriefDescription": "System-wide network received compressed packets",
+    "ConfigCode": "47"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_rx_multicast",
+    "BriefDescription": "System-wide network received multicast packets",
+    "ConfigCode": "48"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_bytes",
+    "BriefDescription": "System-wide network transmitted bytes",
+    "ConfigCode": "49"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_packets",
+    "BriefDescription": "System-wide network transmitted packets",
+    "ConfigCode": "50"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_errors",
+    "BriefDescription": "System-wide network transmitted errors",
+    "ConfigCode": "51"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_drop",
+    "BriefDescription": "System-wide network transmitted dropped packets",
+    "ConfigCode": "52"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_fifo",
+    "BriefDescription": "System-wide network transmitted fifo overruns",
+    "ConfigCode": "53"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_colls",
+    "BriefDescription": "System-wide network transmitted collisions",
+    "ConfigCode": "54"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_carrier",
+    "BriefDescription": "System-wide network transmitted carrier losses",
+    "ConfigCode": "55"
+  },
+  {
+    "Unit": "tool",
+    "EventName": "net_tx_compressed",
+    "BriefDescription": "System-wide network transmitted compressed packets",
+    "ConfigCode": "56"
   }
 ]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 8d1b9e9b4f58..8705f32563a6 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -2596,116 +2596,148 @@ static const char *const big_c_string =
 /* offset=128716 */
 "memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\000\000\000\000\000"
 /* offset=128783 */
+"net_rx_bytes\000tool\000System-wide network received bytes\000config=0x29\000\00000\000\000\000\000\000"
+/* offset=128856 */
+"net_rx_packets\000tool\000System-wide network received packets\000config=0x2a\000\00000\000\000\000\000\000"
+/* offset=128933 */
+"net_rx_errors\000tool\000System-wide network received errors\000config=0x2b\000\00000\000\000\000\000\000"
+/* offset=129008 */
+"net_rx_drop\000tool\000System-wide network received dropped packets\000config=0x2c\000\00000\000\000\000\000\000"
+/* offset=129090 */
+"net_rx_fifo\000tool\000System-wide network received fifo overruns\000config=0x2d\000\00000\000\000\000\000\000"
+/* offset=129170 */
+"net_rx_frame\000tool\000System-wide network received framing errors\000config=0x2e\000\00000\000\000\000\000\000"
+/* offset=129252 */
+"net_rx_compressed\000tool\000System-wide network received compressed packets\000config=0x2f\000\00000\000\000\000\000\000"
+/* offset=129343 */
+"net_rx_multicast\000tool\000System-wide network received multicast packets\000config=0x30\000\00000\000\000\000\000\000"
+/* offset=129432 */
+"net_tx_bytes\000tool\000System-wide network transmitted bytes\000config=0x31\000\00000\000\000\000\000\000"
+/* offset=129508 */
+"net_tx_packets\000tool\000System-wide network transmitted packets\000config=0x32\000\00000\000\000\000\000\000"
+/* offset=129588 */
+"net_tx_errors\000tool\000System-wide network transmitted errors\000config=0x33\000\00000\000\000\000\000\000"
+/* offset=129666 */
+"net_tx_drop\000tool\000System-wide network transmitted dropped packets\000config=0x34\000\00000\000\000\000\000\000"
+/* offset=129751 */
+"net_tx_fifo\000tool\000System-wide network transmitted fifo overruns\000config=0x35\000\00000\000\000\000\000\000"
+/* offset=129834 */
+"net_tx_colls\000tool\000System-wide network transmitted collisions\000config=0x36\000\00000\000\000\000\000\000"
+/* offset=129915 */
+"net_tx_carrier\000tool\000System-wide network transmitted carrier losses\000config=0x37\000\00000\000\000\000\000\000"
+/* offset=130002 */
+"net_tx_compressed\000tool\000System-wide network transmitted compressed packets\000config=0x38\000\00000\000\000\000\000\000"
+/* offset=130096 */
 "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=128845 */
+/* offset=130158 */
 "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=128907 */
+/* offset=130220 */
 "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=129005 */
+/* offset=130318 */
 "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=129107 */
+/* offset=130420 */
 "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
-/* offset=129240 */
+/* offset=130553 */
 "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=129358 */
+/* offset=130671 */
 "hisi_sccl,ddrc\000"
-/* offset=129373 */
+/* offset=130686 */
 "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=129443 */
+/* offset=130756 */
 "uncore_cbox\000"
-/* offset=129455 */
+/* offset=130768 */
 "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
-/* offset=129609 */
+/* offset=130922 */
 "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=129663 */
+/* offset=130976 */
 "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=129721 */
+/* offset=131034 */
 "hisi_sccl,l3c\000"
-/* offset=129735 */
+/* offset=131048 */
 "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=129803 */
+/* offset=131116 */
 "uncore_imc_free_running\000"
-/* offset=129827 */
+/* offset=131140 */
 "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=129907 */
+/* offset=131220 */
 "uncore_imc\000"
-/* offset=129918 */
+/* offset=131231 */
 "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=129983 */
+/* offset=131296 */
 "uncore_sys_ddr_pmu\000"
-/* offset=130002 */
+/* offset=131315 */
 "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=130078 */
+/* offset=131391 */
 "uncore_sys_ccn_pmu\000"
-/* offset=130097 */
+/* offset=131410 */
 "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=130174 */
+/* offset=131487 */
 "uncore_sys_cmn_pmu\000"
-/* offset=130193 */
+/* offset=131506 */
 "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
-/* offset=130336 */
+/* offset=131649 */
 "CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011"
-/* offset=130522 */
+/* offset=131835 */
 "cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011"
-/* offset=130755 */
+/* offset=132068 */
 "migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011"
-/* offset=131015 */
+/* offset=132328 */
 "page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011"
-/* offset=131246 */
+/* offset=132559 */
 "insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001"
-/* offset=131359 */
+/* offset=132672 */
 "stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001"
-/* offset=131784 */
+/* offset=133097 */
 "frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001"
-/* offset=131963 */
+/* offset=133276 */
 "backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001"
-/* offset=132137 */
+/* offset=133450 */
 "cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011"
-/* offset=132313 */
+/* offset=133626 */
 "branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011"
-/* offset=132493 */
+/* offset=133806 */
 "branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001"
-/* offset=132597 */
+/* offset=133910 */
 "l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D  miss rate\000\000100%\000\000\000\000001"
-/* offset=132713 */
+/* offset=134026 */
 "llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001"
-/* offset=132814 */
+/* offset=134127 */
 "l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001"
-/* offset=132929 */
+/* offset=134242 */
 "dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=133035 */
+/* offset=134348 */
 "itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=133141 */
+/* offset=134454 */
 "l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001"
-/* offset=133289 */
+/* offset=134602 */
 "CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000"
-/* offset=133312 */
+/* offset=134625 */
 "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000"
-/* offset=133376 */
+/* offset=134689 */
 "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000"
-/* offset=133543 */
+/* offset=134856 */
 "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=133608 */
+/* offset=134921 */
 "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=133676 */
+/* offset=134989 */
 "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000"
-/* offset=133748 */
+/* offset=135061 */
 "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000"
-/* offset=133843 */
+/* offset=135156 */
 "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000"
-/* offset=133978 */
+/* offset=135291 */
 "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000"
-/* offset=134043 */
+/* offset=135356 */
 "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=134112 */
+/* offset=135425 */
 "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=134183 */
+/* offset=135496 */
 "M1\000\000ipc + M2\000\000\000\000\000\000\000\000000"
-/* offset=134206 */
+/* offset=135519 */
 "M2\000\000ipc + M1\000\000\000\000\000\000\000\000000"
-/* offset=134229 */
+/* offset=135542 */
 "M3\000\0001 / M3\000\000\000\000\000\000\000\000000"
-/* offset=134250 */
+/* offset=135563 */
 "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000"
 ;
 
@@ -5262,6 +5294,38 @@ static const struct compact_pmu_event pmu_events__common_tool[] = {
 	{ 128630 },
 	/* memory_uss\000tool\000Unique Set Size (USS) in bytes\000config=0x28\000\00000\00... */
 	{ 128716 },
+	/* net_rx_bytes\000tool\000System-wide network received bytes\000config=0x29\000\00... */
+	{ 128783 },
+	/* net_rx_compressed\000tool\000System-wide network received compressed packets\000... */
+	{ 129252 },
+	/* net_rx_drop\000tool\000System-wide network received dropped packets\000config=0x... */
+	{ 129008 },
+	/* net_rx_errors\000tool\000System-wide network received errors\000config=0x2b\000\... */
+	{ 128933 },
+	/* net_rx_fifo\000tool\000System-wide network received fifo overruns\000config=0x2d... */
+	{ 129090 },
+	/* net_rx_frame\000tool\000System-wide network received framing errors\000config=0x... */
+	{ 129170 },
+	/* net_rx_multicast\000tool\000System-wide network received multicast packets\000co... */
+	{ 129343 },
+	/* net_rx_packets\000tool\000System-wide network received packets\000config=0x2a\00... */
+	{ 128856 },
+	/* net_tx_bytes\000tool\000System-wide network transmitted bytes\000config=0x31\000... */
+	{ 129432 },
+	/* net_tx_carrier\000tool\000System-wide network transmitted carrier losses\000conf... */
+	{ 129915 },
+	/* net_tx_colls\000tool\000System-wide network transmitted collisions\000config=0x3... */
+	{ 129834 },
+	/* net_tx_compressed\000tool\000System-wide network transmitted compressed packets\... */
+	{ 130002 },
+	/* net_tx_drop\000tool\000System-wide network transmitted dropped packets\000config... */
+	{ 129666 },
+	/* net_tx_errors\000tool\000System-wide network transmitted errors\000config=0x33\0... */
+	{ 129588 },
+	/* net_tx_fifo\000tool\000System-wide network transmitted fifo overruns\000config=0... */
+	{ 129751 },
+	/* net_tx_packets\000tool\000System-wide network transmitted packets\000config=0x32... */
+	{ 129508 },
 	/* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with ... */
 	{ 125363 },
 	/* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPU... */
@@ -5307,39 +5371,39 @@ static const struct pmu_table_entry pmu_events__common[] = {
 
 static const struct compact_pmu_event pmu_metrics__common_default_core[] = {
 	/* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */
-	{ 130336 },
+	{ 131649 },
 	/* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */
-	{ 131963 },
+	{ 133276 },
 	/* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */
-	{ 132313 },
+	{ 133626 },
 	/* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */
-	{ 132493 },
+	{ 133806 },
 	/* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */
-	{ 130522 },
+	{ 131835 },
 	/* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */
-	{ 132137 },
+	{ 133450 },
 	/* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */
-	{ 132929 },
+	{ 134242 },
 	/* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */
-	{ 131784 },
+	{ 133097 },
 	/* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */
-	{ 131246 },
+	{ 132559 },
 	/* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */
-	{ 133035 },
+	{ 134348 },
 	/* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */
-	{ 133141 },
+	{ 134454 },
 	/* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */
-	{ 132597 },
+	{ 133910 },
 	/* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */
-	{ 132814 },
+	{ 134127 },
 	/* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */
-	{ 132713 },
+	{ 134026 },
 	/* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */
-	{ 130755 },
+	{ 132068 },
 	/* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */
-	{ 131015 },
+	{ 132328 },
 	/* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */
-	{ 131359 },
+	{ 132672 },
 
 };
 
@@ -5353,41 +5417,41 @@ static const struct pmu_table_entry pmu_metrics__common[] = {
 
 static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
 	/* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */
-	{ 128783 },
+	{ 130096 },
 	/* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */
-	{ 128845 },
+	{ 130158 },
 	/* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */
-	{ 129107 },
+	{ 130420 },
 	/* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */
-	{ 129240 },
+	{ 130553 },
 	/* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */
-	{ 128907 },
+	{ 130220 },
 	/* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */
-	{ 129005 },
+	{ 130318 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
 	/* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */
-	{ 129373 },
+	{ 130686 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
 	/* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */
-	{ 129735 },
+	{ 131048 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
 	/* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */
-	{ 129609 },
+	{ 130922 },
 	/* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */
-	{ 129663 },
+	{ 130976 },
 	/* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */
-	{ 129455 },
+	{ 130768 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
 	/* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */
-	{ 129918 },
+	{ 131231 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
 	/* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */
-	{ 129827 },
+	{ 131140 },
 
 };
 
@@ -5400,61 +5464,61 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
 	{
 		.entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
-		.pmu_name = { 129358 /* hisi_sccl,ddrc\000 */ },
+		.pmu_name = { 130671 /* hisi_sccl,ddrc\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
-		.pmu_name = { 129721 /* hisi_sccl,l3c\000 */ },
+		.pmu_name = { 131034 /* hisi_sccl,l3c\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_cpu_uncore_cbox,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
-		.pmu_name = { 129443 /* uncore_cbox\000 */ },
+		.pmu_name = { 130756 /* uncore_cbox\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_cpu_uncore_imc,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
-		.pmu_name = { 129907 /* uncore_imc\000 */ },
+		.pmu_name = { 131220 /* uncore_imc\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
-		.pmu_name = { 129803 /* uncore_imc_free_running\000 */ },
+		.pmu_name = { 131116 /* uncore_imc_free_running\000 */ },
 	},
 };
 
 static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
 	/* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */
-	{ 133289 },
+	{ 134602 },
 	/* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */
-	{ 133978 },
+	{ 135291 },
 	/* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */
-	{ 133748 },
+	{ 135061 },
 	/* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */
-	{ 133843 },
+	{ 135156 },
 	/* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */
-	{ 134043 },
+	{ 135356 },
 	/* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */
-	{ 134112 },
+	{ 135425 },
 	/* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */
-	{ 133376 },
+	{ 134689 },
 	/* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */
-	{ 133312 },
+	{ 134625 },
 	/* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */
-	{ 134250 },
+	{ 135563 },
 	/* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */
-	{ 134183 },
+	{ 135496 },
 	/* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */
-	{ 134206 },
+	{ 135519 },
 	/* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */
-	{ 134229 },
+	{ 135542 },
 	/* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */
-	{ 133676 },
+	{ 134989 },
 	/* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */
-	{ 133543 },
+	{ 134856 },
 	/* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */
-	{ 133608 },
+	{ 134921 },
 
 };
 
@@ -5468,15 +5532,15 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
 
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
 	/* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */
-	{ 130097 },
+	{ 131410 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
 	/* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */
-	{ 130193 },
+	{ 131506 },
 };
 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
 	/* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */
-	{ 130002 },
+	{ 131315 },
 
 };
 
@@ -5484,17 +5548,17 @@ static const struct pmu_table_entry pmu_events__test_soc_sys[] = {
 	{
 		.entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
-		.pmu_name = { 130078 /* uncore_sys_ccn_pmu\000 */ },
+		.pmu_name = { 131391 /* uncore_sys_ccn_pmu\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
-		.pmu_name = { 130174 /* uncore_sys_cmn_pmu\000 */ },
+		.pmu_name = { 131487 /* uncore_sys_cmn_pmu\000 */ },
 	},
 	{
 		.entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
 		.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
-		.pmu_name = { 129983 /* uncore_sys_ddr_pmu\000 */ },
+		.pmu_name = { 131296 /* uncore_sys_ddr_pmu\000 */ },
 	},
 };
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6d69f63b7fb1..a508e438bb03 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1899,6 +1899,46 @@ int evsel__append_addr_filter(struct evsel *evsel, const char *filter)
 	return evsel__append_filter(evsel, "%s,%s", filter);
 }
 
+static int evsel__group_member_cpu_action(struct evsel *leader, struct evsel *member,
+					  int cpu_map_idx, bool enable)
+{
+	struct perf_cpu cpu;
+	int m_idx;
+
+	if (perf_cpu_map__equal(leader->core.cpus, member->core.cpus))
+		return enable ? evsel__enable_cpu(member, cpu_map_idx)
+			      : evsel__disable_cpu(member, cpu_map_idx);
+
+	if (member->core.reads_only_on_cpu_idx0) {
+		if (cpu_map_idx == 0 && perf_cpu_map__nr(member->core.cpus) > 0)
+			return enable ? evsel__enable_cpu(member, 0)
+				      : evsel__disable_cpu(member, 0);
+		return 0;
+	}
+
+	if (leader->core.reads_only_on_cpu_idx0) {
+		if (cpu_map_idx == 0) {
+			int nr = perf_cpu_map__nr(member->core.cpus);
+
+			for (m_idx = 0; m_idx < nr; m_idx++) {
+				int err = enable ? evsel__enable_cpu(member, m_idx)
+						 : evsel__disable_cpu(member, m_idx);
+
+				if (err)
+					return err;
+			}
+		}
+		return 0;
+	}
+
+	cpu = perf_cpu_map__cpu(leader->core.cpus, cpu_map_idx);
+	m_idx = perf_cpu_map__idx(member->core.cpus, cpu);
+	if (m_idx >= 0)
+		return enable ? evsel__enable_cpu(member, m_idx)
+			      : evsel__disable_cpu(member, m_idx);
+	return 0;
+}
+
 /* Caller has to clear disabled after going through all CPUs. */
 int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx)
 {
@@ -1922,7 +1962,8 @@ int evsel__enable_cpu(struct evsel *evsel, int cpu_map_idx)
 				 * group leader. We must manually enable them in
 				 * userspace.
 				 */
-				int mem_err = evsel__enable_cpu(member, cpu_map_idx);
+				int mem_err = evsel__group_member_cpu_action(evsel, member,
+									     cpu_map_idx, true);
 
 				if (mem_err)
 					return mem_err;
@@ -1991,7 +2032,8 @@ int evsel__disable_cpu(struct evsel *evsel, int cpu_map_idx)
 				 * kernel when disabling the group leader. We must
 				 * manually disable them in userspace.
 				 */
-				int mem_err = evsel__disable_cpu(member, cpu_map_idx);
+				int mem_err = evsel__group_member_cpu_action(evsel, member,
+									     cpu_map_idx, false);
 
 				if (mem_err)
 					return mem_err;
@@ -2099,11 +2141,8 @@ static void evsel__exit(struct evsel *evsel)
 	if (evsel__priv_destructor)
 		evsel__priv_destructor(evsel->priv);
 	perf_evsel__object.fini(evsel);
-	if (evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME ||
-	    evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) {
-		xyarray__delete(evsel->process_time.start_times);
-		xyarray__delete(evsel->process_time.accumulated_times);
-	}
+	if (evsel__is_tool(evsel))
+		evsel__tool_pmu_exit(evsel);
 }
 
 void evsel__put(struct evsel *evsel)
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index 0ae08cd910bc..655b22104320 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -68,6 +68,22 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
 	"memory_swap_pss",
 	"memory_text",
 	"memory_uss",
+	"net_rx_bytes",
+	"net_rx_packets",
+	"net_rx_errors",
+	"net_rx_drop",
+	"net_rx_fifo",
+	"net_rx_frame",
+	"net_rx_compressed",
+	"net_rx_multicast",
+	"net_tx_bytes",
+	"net_tx_packets",
+	"net_tx_errors",
+	"net_tx_drop",
+	"net_tx_fifo",
+	"net_tx_colls",
+	"net_tx_carrier",
+	"net_tx_compressed",
 };
 
 bool tool_pmu__skip_event(const char *name __maybe_unused)
@@ -271,6 +287,22 @@ static const char *tool_pmu__memory_event_to_key(enum tool_pmu_event ev)
 	case TOOL_PMU__EVENT_MEMORY_SIZE:
 	case TOOL_PMU__EVENT_MEMORY_TEXT:
 	case TOOL_PMU__EVENT_MEMORY_USS:
+	case TOOL_PMU__EVENT_NET_RX_BYTES:
+	case TOOL_PMU__EVENT_NET_RX_PACKETS:
+	case TOOL_PMU__EVENT_NET_RX_ERRORS:
+	case TOOL_PMU__EVENT_NET_RX_DROP:
+	case TOOL_PMU__EVENT_NET_RX_FIFO:
+	case TOOL_PMU__EVENT_NET_RX_FRAME:
+	case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+	case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+	case TOOL_PMU__EVENT_NET_TX_BYTES:
+	case TOOL_PMU__EVENT_NET_TX_PACKETS:
+	case TOOL_PMU__EVENT_NET_TX_ERRORS:
+	case TOOL_PMU__EVENT_NET_TX_DROP:
+	case TOOL_PMU__EVENT_NET_TX_FIFO:
+	case TOOL_PMU__EVENT_NET_TX_COLLS:
+	case TOOL_PMU__EVENT_NET_TX_CARRIER:
+	case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
 	case TOOL_PMU__EVENT_DURATION_TIME:
 	case TOOL_PMU__EVENT_USER_TIME:
 	case TOOL_PMU__EVENT_SYSTEM_TIME:
@@ -435,13 +467,110 @@ static int read_statm(int fd, enum tool_pmu_event ev, u64 *val)
 	return -EINVAL;
 }
 
+static bool tool_pmu__is_net_event(enum tool_pmu_event ev)
+{
+	return ev >= TOOL_PMU__EVENT_NET_RX_BYTES &&
+	       ev <= TOOL_PMU__EVENT_NET_TX_COMPRESSED;
+}
+
+static bool tool_pmu__has_start_times(enum tool_pmu_event ev)
+{
+	return ev == TOOL_PMU__EVENT_USER_TIME ||
+	       ev == TOOL_PMU__EVENT_SYSTEM_TIME ||
+	       tool_pmu__is_net_event(ev);
+}
+
+static int read_net_dev_col(struct io *io, __u64 *val, int *term)
+{
+	int ch;
+
+	do {
+		ch = io__get_char(io);
+		if (ch == -1 || ch == '\n') {
+			*term = ch;
+			return -EINVAL;
+		}
+	} while (ch == ' ' || ch == '\t');
+
+	if (ch < '0' || ch > '9') {
+		*term = ch;
+		return -EINVAL;
+	}
+
+	*val = ch - '0';
+	while (true) {
+		ch = io__get_char(io);
+		if (ch >= '0' && ch <= '9') {
+			*val = (*val * 10) + (ch - '0');
+		} else {
+			*term = ch;
+			return 0;
+		}
+	}
+}
+
+static int read_net_dev(int fd, enum tool_pmu_event ev, __u64 *val)
+{
+	struct io io;
+	char buf[4096];
+	int index = ev - TOOL_PMU__EVENT_NET_RX_BYTES;
+
+	io__init(&io, fd, buf, sizeof(buf));
+	lseek(fd, 0, SEEK_SET);
+
+	/*
+	 * Drop two header lines:
+	 * Inter-|   Receive                                                |  Transmit
+	 *  face |bytes    packets errs drop fifo frame compressed multicast|bytes ...
+	 */
+	if (!read_until_char(&io, '\n'))
+		return -EINVAL;
+	if (!read_until_char(&io, '\n'))
+		return -EINVAL;
+
+	*val = 0;
+	while (true) {
+		int ch = io__get_char(&io);
+		int i, term = 0;
+		__u64 v;
+
+		if (ch == -1)
+			break;
+		while (ch == ' ' || ch == '\t')
+			ch = io__get_char(&io);
+		if (ch == -1)
+			break;
+		while (ch != ':' && ch != -1 && ch != '\n')
+			ch = io__get_char(&io);
+		if (ch != ':') {
+			if (ch == '\n')
+				continue;
+			if (ch == -1)
+				break;
+			read_until_char(&io, '\n');
+			continue;
+		}
+		for (i = 0; i < index; i++) {
+			if (read_net_dev_col(&io, &v, &term))
+				break;
+		}
+		if (i == index && !read_net_dev_col(&io, &v, &term))
+			*val += v;
+		if (term != '\n' && term != -1)
+			read_until_char(&io, '\n');
+		if (term == -1)
+			break;
+	}
+	return 0;
+}
+
 int evsel__tool_pmu_prepare_open(struct evsel *evsel,
 				 struct perf_cpu_map *cpus,
 				 int nthreads)
 {
 	enum tool_pmu_event ev = evsel__tool_event(evsel);
 
-	if (ev == TOOL_PMU__EVENT_SYSTEM_TIME || ev == TOOL_PMU__EVENT_USER_TIME) {
+	if (tool_pmu__has_start_times(ev)) {
 		if (!evsel->process_time.start_times) {
 			evsel->process_time.start_times =
 				xyarray__new(perf_cpu_map__nr(cpus), nthreads, sizeof(__u64));
@@ -464,7 +593,8 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
 {
 	enum tool_pmu_event ev = evsel__tool_event(evsel);
 	bool system = ev == TOOL_PMU__EVENT_SYSTEM_TIME;
-	int fd = FD(evsel, cpu_map_idx, thread);
+	int *fd_ptr = evsel->core.fd ? xyarray__entry(evsel->core.fd, cpu_map_idx, thread) : NULL;
+	int fd = fd_ptr ? *fd_ptr : -1;
 	int err = 0;
 
 	if (fd < 0) {
@@ -472,6 +602,13 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
 		return 0;
 	}
 
+	if (tool_pmu__is_net_event(ev)) {
+		if (cpu_map_idx == 0 && thread == 0)
+			return read_net_dev(fd, ev, val);
+		*val = 0;
+		return 0;
+	}
+
 	lseek(fd, 0, SEEK_SET);
 	if (evsel->pid_stat) {
 		if (cpu_map_idx == 0)
@@ -539,40 +676,58 @@ static int open_memory_pid_dir(enum tool_pmu_event ev, int pid,
 	return 0;
 }
 
+static bool tool_pmu__is_initially_disabled(const struct evsel *evsel)
+{
+	const struct evsel *leader = evsel__leader(evsel);
+
+	return evsel->core.attr.disabled || (leader && leader->core.attr.disabled);
+}
+
 static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
 				    int pid, int idx, int thread,
 				    int *seen_tgids, int *nr_seen_tgids)
 {
-	if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+	if (tool_pmu__has_start_times(ev)) {
 		__u64 *start_time = NULL;
 		__u64 *accumulated_time = NULL;
 		char buf[PATH_MAX];
-		int fd, err;
-
-		if (pid > -1) {
-			snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
-			evsel->pid_stat = true;
+		int fd = -1, err;
+
+		if (tool_pmu__is_net_event(ev)) {
+			if (pid > -1 || evsel->cgrp)
+				return -EINVAL;
+			if (idx == 0 && thread == 0) {
+				snprintf(buf, sizeof(buf), "%s/net/dev", procfs__mountpoint());
+				fd = open(buf, O_RDONLY);
+				if (fd < 0)
+					return -errno;
+			}
 		} else {
-			snprintf(buf, sizeof(buf), "%s/stat", procfs__mountpoint());
+			if (pid > -1) {
+				snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
+				evsel->pid_stat = true;
+			} else {
+				snprintf(buf, sizeof(buf), "%s/stat", procfs__mountpoint());
+			}
+			fd = open(buf, O_RDONLY);
+			if (fd < 0)
+				return -errno;
 		}
-		fd = open(buf, O_RDONLY);
 		FD(evsel, idx, thread) = fd;
-		if (fd < 0)
-			return -errno;
-
 		start_time = xyarray__entry(evsel->process_time.start_times, idx, thread);
 		accumulated_time = xyarray__entry(evsel->process_time.accumulated_times,
 						  idx, thread);
 		*accumulated_time = 0;
 
-		if (evsel->core.attr.disabled) {
+		if (tool_pmu__is_initially_disabled(evsel)) {
 			evsel->disabled = true;
 			*start_time = INVALID_START_TIME;
 		} else {
 			evsel->disabled = false;
 			err = tool_pmu__read_stat(evsel, idx, thread, start_time);
 			if (err) {
-				close(fd);
+				if (fd >= 0)
+					close(fd);
 				FD(evsel, idx, thread) = -1;
 				return err;
 			}
@@ -583,7 +738,7 @@ static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
 		if (evsel->cgrp)
 			return -EINVAL;
 
-		evsel->disabled = evsel->core.attr.disabled;
+		evsel->disabled = tool_pmu__is_initially_disabled(evsel);
 		if (pid > -1) {
 			evsel->pid_stat = true;
 			if (idx == 0) {
@@ -623,7 +778,7 @@ int evsel__tool_pmu_open(struct evsel *evsel,
 
 	if (ev == TOOL_PMU__EVENT_DURATION_TIME) {
 		evsel->duration_time.accumulated_time = 0;
-		if (evsel->core.attr.disabled) {
+		if (tool_pmu__is_initially_disabled(evsel)) {
 			evsel->disabled = true;
 			evsel->duration_time.start_time = INVALID_START_TIME;
 		} else {
@@ -834,6 +989,22 @@ bool tool_pmu__read_event(enum tool_pmu_event ev,
 	case TOOL_PMU__EVENT_MEMORY_LOCKED:
 	case TOOL_PMU__EVENT_MEMORY_DATA:
 	case TOOL_PMU__EVENT_MEMORY_TEXT:
+	case TOOL_PMU__EVENT_NET_RX_BYTES:
+	case TOOL_PMU__EVENT_NET_RX_PACKETS:
+	case TOOL_PMU__EVENT_NET_RX_ERRORS:
+	case TOOL_PMU__EVENT_NET_RX_DROP:
+	case TOOL_PMU__EVENT_NET_RX_FIFO:
+	case TOOL_PMU__EVENT_NET_RX_FRAME:
+	case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+	case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+	case TOOL_PMU__EVENT_NET_TX_BYTES:
+	case TOOL_PMU__EVENT_NET_TX_PACKETS:
+	case TOOL_PMU__EVENT_NET_TX_ERRORS:
+	case TOOL_PMU__EVENT_NET_TX_DROP:
+	case TOOL_PMU__EVENT_NET_TX_FIFO:
+	case TOOL_PMU__EVENT_NET_TX_COLLS:
+	case TOOL_PMU__EVENT_NET_TX_CARRIER:
+	case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
 	case TOOL_PMU__EVENT_NONE:
 	case TOOL_PMU__EVENT_DURATION_TIME:
 	case TOOL_PMU__EVENT_USER_TIME:
@@ -928,7 +1099,11 @@ int evsel__tool_pmu_enable_cpu(struct evsel *evsel, int cpu_map_idx)
 		return 0;
 	}
 
-	if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+	if (tool_pmu__has_start_times(ev)) {
+		if (!evsel->process_time.start_times || cpu_map_idx < 0 ||
+		    cpu_map_idx >= xyarray__max_x(evsel->process_time.start_times))
+			return 0;
+
 		nthreads = xyarray__max_y(evsel->process_time.start_times);
 		for (thread = 0; thread < nthreads; thread++) {
 			__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -979,7 +1154,12 @@ int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx)
 		return 0;
 	}
 
-	if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) {
+	if (tool_pmu__has_start_times(ev)) {
+		if (!evsel->process_time.start_times || !evsel->process_time.accumulated_times ||
+		    cpu_map_idx < 0 ||
+		    cpu_map_idx >= xyarray__max_x(evsel->process_time.start_times))
+			return 0;
+
 		nthreads = xyarray__max_y(evsel->process_time.start_times);
 		for (thread = 0; thread < nthreads; thread++) {
 			__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -1065,11 +1245,29 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
 		}
 		break;
 	case TOOL_PMU__EVENT_USER_TIME:
-	case TOOL_PMU__EVENT_SYSTEM_TIME: {
-		__u64 accumulated = *(__u64 *)xyarray__entry(evsel->process_time.accumulated_times,
-							     cpu_map_idx, thread);
-
-		if (evsel->disabled) {
+	case TOOL_PMU__EVENT_SYSTEM_TIME:
+	case TOOL_PMU__EVENT_NET_RX_BYTES:
+	case TOOL_PMU__EVENT_NET_RX_PACKETS:
+	case TOOL_PMU__EVENT_NET_RX_ERRORS:
+	case TOOL_PMU__EVENT_NET_RX_DROP:
+	case TOOL_PMU__EVENT_NET_RX_FIFO:
+	case TOOL_PMU__EVENT_NET_RX_FRAME:
+	case TOOL_PMU__EVENT_NET_RX_COMPRESSED:
+	case TOOL_PMU__EVENT_NET_RX_MULTICAST:
+	case TOOL_PMU__EVENT_NET_TX_BYTES:
+	case TOOL_PMU__EVENT_NET_TX_PACKETS:
+	case TOOL_PMU__EVENT_NET_TX_ERRORS:
+	case TOOL_PMU__EVENT_NET_TX_DROP:
+	case TOOL_PMU__EVENT_NET_TX_FIFO:
+	case TOOL_PMU__EVENT_NET_TX_COLLS:
+	case TOOL_PMU__EVENT_NET_TX_CARRIER:
+	case TOOL_PMU__EVENT_NET_TX_COMPRESSED: {
+		__u64 *accumulated_ptr = evsel->process_time.accumulated_times ?
+			xyarray__entry(evsel->process_time.accumulated_times, cpu_map_idx, thread) :
+			NULL;
+		__u64 accumulated = accumulated_ptr ? *accumulated_ptr : 0;
+
+		if (!accumulated_ptr || evsel->disabled) {
 			delta_start = accumulated;
 		} else {
 			__u64 *start_time = xyarray__entry(evsel->process_time.start_times,
@@ -1078,13 +1276,14 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
 
 			err = tool_pmu__read_stat(evsel, cpu_map_idx, thread, &cur_time);
 			if (!err) {
-				if (*start_time != INVALID_START_TIME && cur_time >= *start_time)
+				if (start_time && *start_time != INVALID_START_TIME &&
+				    cur_time >= *start_time)
 					delta_start = accumulated + (cur_time - *start_time);
 				else
 					delta_start = accumulated;
 			}
 		}
-		adjust = true;
+		adjust = (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME);
 		break;
 	}
 	case TOOL_PMU__EVENT_MEMORY_SIZE:
@@ -1163,6 +1362,18 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
 	return 0;
 }
 
+void evsel__tool_pmu_exit(struct evsel *evsel)
+{
+	enum tool_pmu_event ev = evsel__tool_event(evsel);
+
+	if (tool_pmu__has_start_times(ev)) {
+		xyarray__delete(evsel->process_time.start_times);
+		xyarray__delete(evsel->process_time.accumulated_times);
+		evsel->process_time.start_times = NULL;
+		evsel->process_time.accumulated_times = NULL;
+	}
+}
+
 struct perf_pmu *tool_pmu__new(void)
 {
 	struct perf_pmu *tool = zalloc(sizeof(struct perf_pmu));
diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h
index 99a2ea1548f8..f972995bb8ed 100644
--- a/tools/perf/util/tool_pmu.h
+++ b/tools/perf/util/tool_pmu.h
@@ -50,6 +50,22 @@ enum tool_pmu_event {
 	TOOL_PMU__EVENT_MEMORY_SWAP_PSS,
 	TOOL_PMU__EVENT_MEMORY_TEXT,
 	TOOL_PMU__EVENT_MEMORY_USS,
+	TOOL_PMU__EVENT_NET_RX_BYTES,
+	TOOL_PMU__EVENT_NET_RX_PACKETS,
+	TOOL_PMU__EVENT_NET_RX_ERRORS,
+	TOOL_PMU__EVENT_NET_RX_DROP,
+	TOOL_PMU__EVENT_NET_RX_FIFO,
+	TOOL_PMU__EVENT_NET_RX_FRAME,
+	TOOL_PMU__EVENT_NET_RX_COMPRESSED,
+	TOOL_PMU__EVENT_NET_RX_MULTICAST,
+	TOOL_PMU__EVENT_NET_TX_BYTES,
+	TOOL_PMU__EVENT_NET_TX_PACKETS,
+	TOOL_PMU__EVENT_NET_TX_ERRORS,
+	TOOL_PMU__EVENT_NET_TX_DROP,
+	TOOL_PMU__EVENT_NET_TX_FIFO,
+	TOOL_PMU__EVENT_NET_TX_COLLS,
+	TOOL_PMU__EVENT_NET_TX_CARRIER,
+	TOOL_PMU__EVENT_NET_TX_COMPRESSED,
 
 	TOOL_PMU__EVENT_MAX,
 };
@@ -87,6 +103,7 @@ int evsel__tool_pmu_enable(struct evsel *evsel);
 int evsel__tool_pmu_disable_cpu(struct evsel *evsel, int cpu_map_idx);
 int evsel__tool_pmu_disable(struct evsel *evsel);
 int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread);
+void evsel__tool_pmu_exit(struct evsel *evsel);
 
 struct perf_pmu *tool_pmu__new(void);
 
-- 
2.56.1.703.gf848ed807c-goog


  parent reply	other threads:[~2026-11-13 23:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and schedstat events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 1/4] perf tool_pmu: Add memory events Ian Rogers
2026-11-13 23:37 ` Ian Rogers [this message]
2026-11-13 23:37 ` [PATCH v2 3/4] perf tool_pmu: Add schedstat events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 4/4] perf test tool_pmu: Add memory, network and schedstat tests Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261113233739.3626499-3-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=thomas.falcon@intel.com \
    --cc=tmricht@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox