X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fperfmon%2Fperfmon.h;h=967b92e0e4a6664c879427bc0a2878f10d42c811;hb=c3cb2075d;hp=000e3c2849cf575ff52b4eaef25a28804675916e;hpb=47d165e4c1a5f571995d39b0ce142c06f17dea47;p=vpp.git diff --git a/src/plugins/perfmon/perfmon.h b/src/plugins/perfmon/perfmon.h index 000e3c2849c..967b92e0e4a 100644 --- a/src/plugins/perfmon/perfmon.h +++ b/src/plugins/perfmon/perfmon.h @@ -1,7 +1,5 @@ /* - * perfmon.h - performance monitor - * - * Copyright (c) 2018 Cisco Systems and/or its affiliates + * Copyright (c) 2020 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,138 +12,218 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef __included_perfmon_h__ -#define __included_perfmon_h__ -#include -#include -#include -#include +#ifndef __perfmon_perfmon_h +#define __perfmon_perfmon_h -#include +#include +#include +#include #include +#include +#include -#include -#include - -#define foreach_perfmon_event \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES, "cpu-cycles") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, "instructions") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, \ - "cache-references") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, "cache-misses") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "branches") \ - _(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES, "bus-cycles") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, \ - "stall-frontend") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, \ - "stall-backend") \ -_(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES, "ref-cpu-cycles") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS, "page-faults") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES, "context-switches") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS, "cpu-migrations") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN, "minor-pagefaults") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ, "major-pagefaults") \ -_(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS, "emulation-faults") +#define PERF_MAX_EVENTS 7 /* 3 fixed and 4 programmable */ -typedef struct +typedef enum { - char *name; - int pe_type; - int pe_config; -} perfmon_event_config_t; + PERFMON_BUNDLE_TYPE_UNKNOWN, + PERFMON_BUNDLE_TYPE_NODE, + PERFMON_BUNDLE_TYPE_THREAD, + PERFMON_BUNDLE_TYPE_SYSTEM, + PERFMON_BUNDLE_TYPE_MAX, +} perfmon_bundle_type_t; typedef enum { - PERFMON_STATE_OFF = 0, - PERFMON_STATE_RUNNING, -} perfmon_state_t; + PERFMON_OFFSET_TYPE_MMAP, + PERFMON_OFFSET_TYPE_METRICS, + PERFMON_OFFSET_TYPE_MAX, +} perfmon_offset_type_t; typedef struct { - u8 *thread_and_node_name; - u8 **counter_names; - u64 *counter_values; - u64 *vectors_this_counter; -} perfmon_capture_t; + u32 type_from_instance : 1; + u32 exclude_kernel : 1; + union + { + u32 type; + u32 instance_type; + }; + u64 config; + char *name; + char *description; +} perfmon_event_t; typedef struct { - u8 *name; - u8 *value; -} name_value_pair_t; + u32 type; + int cpu; + pid_t pid; + char *name; +} perfmon_instance_t; typedef struct { - /* API message ID base */ - u16 msg_id_base; - - /* on/off switch for the periodic function */ - volatile u8 state; + char *name; + perfmon_instance_t *instances; +} perfmon_instance_type_t; - /* capture pool, hash table */ - perfmon_capture_t *capture_pool; - uword *capture_by_thread_and_node_name; +struct perfmon_source; +vlib_node_function_t perfmon_dispatch_wrapper_mmap; +vlib_node_function_t perfmon_dispatch_wrapper_metrics; - /* vector of registered perfmon tables */ - perfmon_intel_pmc_registration_t *perfmon_tables; +#define foreach_permon_offset_type \ + _ (PERFMON_OFFSET_TYPE_MMAP, perfmon_dispatch_wrapper_mmap) \ + _ (PERFMON_OFFSET_TYPE_METRICS, perfmon_dispatch_wrapper_metrics) - /* active table */ - perfmon_intel_pmc_event_t *perfmon_table; +typedef clib_error_t *(perfmon_source_init_fn_t) (vlib_main_t *vm, + struct perfmon_source *); +typedef struct perfmon_source +{ + char *name; + char *description; + struct perfmon_source *next; + perfmon_event_t *events; + u32 n_events; + perfmon_instance_type_t *instances_by_type; + format_function_t *format_config; + perfmon_source_init_fn_t *init_fn; +} perfmon_source_t; - uword *pmc_event_by_name; +struct perfmon_bundle; - /* vector of single events to collect */ - perfmon_event_config_t *single_events_to_collect; +typedef clib_error_t *(perfmon_bundle_init_fn_t) (vlib_main_t *vm, + struct perfmon_bundle *); - /* vector of paired events to collect */ - perfmon_event_config_t *paired_events_to_collect; +typedef struct +{ + clib_cpu_supports_func_t cpu_supports; + perfmon_bundle_type_t bundle_type; +} perfmon_cpu_supports_t; - /* Base indices of synthetic event tuples */ - u32 ipc_event_index; - u32 mispredict_event_index; +typedef struct perfmon_bundle +{ + char *name; + char *description; + char *source; + char *footer; + perfmon_bundle_type_t type; + perfmon_offset_type_t offset_type; + u32 events[PERF_MAX_EVENTS]; + u32 n_events; - /* Length of time to capture a single event */ - f64 timeout_interval; + u32 metrics[PERF_MAX_EVENTS]; + u32 n_metrics; - /* Current event (index) being collected */ - u32 current_event; - int n_active; - u32 **rdpmc_indices; - /* mmap base / size of (mapped) struct perf_event_mmap_page */ - u8 ***perf_event_pages; - u32 page_size; + perfmon_cpu_supports_t *cpu_supports; + u32 n_cpu_supports; - /* Current perf_event file descriptors, per thread */ - int **pm_fds; + perfmon_bundle_init_fn_t *init_fn; - /* thread bitmap */ - uword *thread_bitmap; + char **column_headers; + format_function_t *format_fn; - /* Logging */ - vlib_log_class_t log_class; + /* do not set manually */ + perfmon_source_t *src; + struct perfmon_bundle *next; +} perfmon_bundle_t; - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - ethernet_main_t *ethernet_main; -} perfmon_main_t; +typedef struct +{ + u64 nr; + u64 time_enabled; + u64 time_running; + u64 value[PERF_MAX_EVENTS]; +} perfmon_reading_t; -extern perfmon_main_t perfmon_main; +typedef struct +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + u64 n_calls; + u64 n_packets; + union + { + struct + { + u64 value[PERF_MAX_EVENTS]; + } t[2]; + u64 value[PERF_MAX_EVENTS * 2]; + }; +} perfmon_node_stats_t; -extern vlib_node_registration_t perfmon_periodic_node; -uword *perfmon_parse_table (perfmon_main_t * pm, char *path, char *filename); +typedef struct +{ + u8 n_events; + u16 n_nodes; + perfmon_node_stats_t *node_stats; + perfmon_bundle_t *bundle; + struct perf_event_mmap_page *mmap_pages[PERF_MAX_EVENTS]; +} perfmon_thread_runtime_t; -/* Periodic function events */ -#define PERFMON_START 1 +typedef struct +{ + perfmon_thread_runtime_t *thread_runtimes; + perfmon_bundle_t *bundles; + uword *bundle_by_name; + perfmon_source_t *sources; + uword *source_by_name; + perfmon_bundle_t *active_bundle; + int is_running; + f64 sample_time; + int *group_fds; + int *fds_to_close; + perfmon_instance_type_t *default_instance_type; + perfmon_instance_type_t *active_instance_type; +} perfmon_main_t; -#endif /* __included_perfmon_h__ */ +extern perfmon_main_t perfmon_main; -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ +always_inline uword +perfmon_cpu_supported_bundle_type (perfmon_bundle_t *b) +{ + perfmon_cpu_supports_t *supports = b->cpu_supports; + uword type = 0; + + /* if nothing specific for this bundle, go with the default */ + if (!supports) + return b->type; + + /* the last specified type, will always win */ + for (int i = 0; i < b->n_cpu_supports; ++i) + if (supports[i].cpu_supports ()) + type = supports[i].bundle_type; + + return type; +} + +#define PERFMON_REGISTER_SOURCE(x) \ + perfmon_source_t __perfmon_source_##x; \ + static void __clib_constructor __perfmon_source_registration_##x (void) \ + { \ + perfmon_main_t *pm = &perfmon_main; \ + __perfmon_source_##x.next = pm->sources; \ + pm->sources = &__perfmon_source_##x; \ + } \ + perfmon_source_t __perfmon_source_##x + +#define PERFMON_REGISTER_BUNDLE(x) \ + perfmon_bundle_t __perfmon_bundle_##x; \ + static void __clib_constructor __perfmon_bundle_registration_##x (void) \ + { \ + perfmon_main_t *pm = &perfmon_main; \ + __perfmon_bundle_##x.next = pm->bundles; \ + __perfmon_bundle_##x.type = \ + perfmon_cpu_supported_bundle_type (&__perfmon_bundle_##x); \ + pm->bundles = &__perfmon_bundle_##x; \ + } \ + perfmon_bundle_t __perfmon_bundle_##x + +void perfmon_reset (vlib_main_t *vm); +clib_error_t *perfmon_start (vlib_main_t *vm, perfmon_bundle_t *); +clib_error_t *perfmon_stop (vlib_main_t *vm); + +#define PERFMON_STRINGS(...) \ + (char *[]) { __VA_ARGS__, 0 } + +#endif