perfmon: bundles with multiple types
[vpp.git] / src / plugins / perfmon / perfmon.h
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef __perfmon_perfmon_h
17 #define __perfmon_perfmon_h
18
19 #include <linux/perf_event.h>
20 #include <vppinfra/clib.h>
21 #include <vppinfra/format.h>
22 #include <vppinfra/error.h>
23 #include <vppinfra/cpu.h>
24 #include <vlib/vlib.h>
25
26 #define PERF_MAX_EVENTS 8 /* 4 fixed and 8 programmable on ICX */
27
28 typedef enum
29 {
30   PERFMON_BUNDLE_TYPE_UNKNOWN,
31   PERFMON_BUNDLE_TYPE_NODE,
32   PERFMON_BUNDLE_TYPE_THREAD,
33   PERFMON_BUNDLE_TYPE_SYSTEM,
34   PERFMON_BUNDLE_TYPE_MAX,
35   PERFMON_BUNDLE_TYPE_NODE_OR_THREAD,
36 } perfmon_bundle_type_t;
37
38 #define foreach_perfmon_bundle_type                                           \
39   _ (PERFMON_BUNDLE_TYPE_UNKNOWN, "not supported")                            \
40   _ (PERFMON_BUNDLE_TYPE_NODE, "node")                                        \
41   _ (PERFMON_BUNDLE_TYPE_THREAD, "thread")                                    \
42   _ (PERFMON_BUNDLE_TYPE_SYSTEM, "system")
43
44 typedef enum
45 {
46 #define _(e, str) e##_FLAG = 1 << e,
47   foreach_perfmon_bundle_type
48 #undef _
49
50 } perfmon_bundle_type_flag_t;
51
52 typedef enum
53 {
54   PERFMON_OFFSET_TYPE_MMAP,
55   PERFMON_OFFSET_TYPE_METRICS,
56   PERFMON_OFFSET_TYPE_MAX,
57 } perfmon_offset_type_t;
58
59 typedef struct
60 {
61   u32 type_from_instance : 1;
62   u32 exclude_kernel : 1;
63   union
64   {
65     u32 type;
66     u32 instance_type;
67   };
68   u64 config;
69   char *name;
70   char *description;
71 } perfmon_event_t;
72
73 typedef struct
74 {
75   u32 type;
76   int cpu;
77   pid_t pid;
78   char *name;
79 } perfmon_instance_t;
80
81 typedef struct
82 {
83   char *name;
84   perfmon_instance_t *instances;
85 } perfmon_instance_type_t;
86
87 struct perfmon_source;
88 vlib_node_function_t perfmon_dispatch_wrapper_mmap;
89 vlib_node_function_t perfmon_dispatch_wrapper_metrics;
90
91 #define foreach_permon_offset_type                                            \
92   _ (PERFMON_OFFSET_TYPE_MMAP, perfmon_dispatch_wrapper_mmap)                 \
93   _ (PERFMON_OFFSET_TYPE_METRICS, perfmon_dispatch_wrapper_metrics)
94
95 typedef clib_error_t *(perfmon_source_init_fn_t) (vlib_main_t *vm,
96                                                   struct perfmon_source *);
97 typedef struct perfmon_source
98 {
99   char *name;
100   char *description;
101   struct perfmon_source *next;
102   perfmon_event_t *events;
103   u32 n_events;
104   perfmon_instance_type_t *instances_by_type;
105   format_function_t *format_config;
106   perfmon_source_init_fn_t *init_fn;
107 } perfmon_source_t;
108
109 struct perfmon_bundle;
110
111 typedef clib_error_t *(perfmon_bundle_init_fn_t) (vlib_main_t *vm,
112                                                   struct perfmon_bundle *);
113
114 typedef struct
115 {
116   clib_cpu_supports_func_t cpu_supports;
117   perfmon_bundle_type_t bundle_type;
118 } perfmon_cpu_supports_t;
119
120 typedef struct perfmon_bundle
121 {
122   char *name;
123   char *description;
124   char *source;
125   char *footer;
126
127   union
128   {
129     perfmon_bundle_type_flag_t type_flags;
130     perfmon_bundle_type_t type;
131   };
132   perfmon_bundle_type_t active_type;
133
134   perfmon_offset_type_t offset_type;
135   u32 events[PERF_MAX_EVENTS];
136   u32 n_events;
137
138   u32 metrics[PERF_MAX_EVENTS];
139   u32 n_metrics;
140
141   perfmon_cpu_supports_t *cpu_supports;
142   u32 n_cpu_supports;
143
144   perfmon_bundle_init_fn_t *init_fn;
145
146   char **column_headers;
147   format_function_t *format_fn;
148
149   /* do not set manually */
150   perfmon_source_t *src;
151   struct perfmon_bundle *next;
152 } perfmon_bundle_t;
153
154 typedef struct
155 {
156   u64 nr;
157   u64 time_enabled;
158   u64 time_running;
159   u64 value[PERF_MAX_EVENTS];
160 } perfmon_reading_t;
161
162 typedef struct
163 {
164   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
165   u64 n_calls;
166   u64 n_packets;
167   union
168   {
169     struct
170     {
171       u64 value[PERF_MAX_EVENTS];
172     } t[2];
173     u64 value[PERF_MAX_EVENTS * 2];
174   };
175 } perfmon_node_stats_t;
176
177 typedef struct
178 {
179   u8 n_events;
180   u16 n_nodes;
181   perfmon_node_stats_t *node_stats;
182   perfmon_bundle_t *bundle;
183   struct perf_event_mmap_page *mmap_pages[PERF_MAX_EVENTS];
184 } perfmon_thread_runtime_t;
185
186 typedef struct
187 {
188   perfmon_thread_runtime_t *thread_runtimes;
189   perfmon_bundle_t *bundles;
190   uword *bundle_by_name;
191   perfmon_source_t *sources;
192   uword *source_by_name;
193   perfmon_bundle_t *active_bundle;
194   int is_running;
195   f64 sample_time;
196   int *group_fds;
197   int *fds_to_close;
198   perfmon_instance_type_t *default_instance_type;
199   perfmon_instance_type_t *active_instance_type;
200 } perfmon_main_t;
201
202 extern perfmon_main_t perfmon_main;
203
204 #define PERFMON_BUNDLE_TYPE_TO_FLAGS(type)                                    \
205   ({                                                                          \
206     uword rtype = 0;                                                          \
207     if (type == PERFMON_BUNDLE_TYPE_NODE_OR_THREAD)                           \
208       rtype =                                                                 \
209         1 << PERFMON_BUNDLE_TYPE_THREAD | 1 << PERFMON_BUNDLE_TYPE_NODE;      \
210     else                                                                      \
211       rtype = 1 << type;                                                      \
212     rtype;                                                                    \
213   })
214
215 always_inline uword
216 perfmon_cpu_update_bundle_type (perfmon_bundle_t *b)
217 {
218   perfmon_cpu_supports_t *supports = b->cpu_supports;
219   uword type = 0;
220
221   /* either supports or b->type should be set, but not both */
222   ASSERT (!!supports ^ !!b->type);
223
224   /* if nothing specific for this bundle, go with the defaults */
225   if (!supports)
226     type = PERFMON_BUNDLE_TYPE_TO_FLAGS (b->type);
227   else
228     {
229       /* more than one type may be supported by a given bundle */
230       for (int i = 0; i < b->n_cpu_supports; ++i)
231         if (supports[i].cpu_supports ())
232           type |= PERFMON_BUNDLE_TYPE_TO_FLAGS (supports[i].bundle_type);
233     }
234
235   return type;
236 }
237 #undef PERFMON_BUNDLE_TYPE_TO_FLAGS
238
239 #define PERFMON_REGISTER_SOURCE(x)                                            \
240   perfmon_source_t __perfmon_source_##x;                                      \
241   static void __clib_constructor __perfmon_source_registration_##x (void)     \
242   {                                                                           \
243     perfmon_main_t *pm = &perfmon_main;                                       \
244     __perfmon_source_##x.next = pm->sources;                                  \
245     pm->sources = &__perfmon_source_##x;                                      \
246   }                                                                           \
247   perfmon_source_t __perfmon_source_##x
248
249 #define PERFMON_REGISTER_BUNDLE(x)                                            \
250   perfmon_bundle_t __perfmon_bundle_##x;                                      \
251   static void __clib_constructor __perfmon_bundle_registration_##x (void)     \
252   {                                                                           \
253     perfmon_main_t *pm = &perfmon_main;                                       \
254     __perfmon_bundle_##x.next = pm->bundles;                                  \
255     __perfmon_bundle_##x.type_flags =                                         \
256       perfmon_cpu_update_bundle_type (&__perfmon_bundle_##x);                 \
257     pm->bundles = &__perfmon_bundle_##x;                                      \
258   }                                                                           \
259   perfmon_bundle_t __perfmon_bundle_##x
260
261 void perfmon_reset (vlib_main_t *vm);
262 clib_error_t *perfmon_start (vlib_main_t *vm, perfmon_bundle_t *);
263 clib_error_t *perfmon_stop (vlib_main_t *vm);
264
265 #define PERFMON_STRINGS(...)                                                  \
266   (char *[]) { __VA_ARGS__, 0 }
267
268 #endif