perfmon: refactor perf metric support
[vpp.git] / src / plugins / perfmon / dispatch_wrapper.c
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 #include "vppinfra/string.h"
17 #include <vnet/vnet.h>
18
19 #include <vlibapi/api.h>
20 #include <vlibmemory/api.h>
21 #include <vnet/plugin/plugin.h>
22 #include <vpp/app/version.h>
23 #include <linux/limits.h>
24 #include <sys/ioctl.h>
25
26 #include <perfmon/perfmon.h>
27
28 static_always_inline void
29 perfmon_read_pmcs (u64 *counters, u32 *indexes, u8 n_counters)
30 {
31   switch (n_counters)
32     {
33     case 12:
34       counters[11] = _rdpmc (indexes[11] - 1);
35     case 11:
36       counters[10] = _rdpmc (indexes[10] - 1);
37     case 10:
38       counters[9] = _rdpmc (indexes[9] - 1);
39     case 9:
40       counters[8] = _rdpmc (indexes[8] - 1);
41     case 8:
42       counters[7] = _rdpmc (indexes[7] - 1);
43     case 7:
44       counters[6] = _rdpmc (indexes[6] - 1);
45     case 6:
46       counters[5] = _rdpmc (indexes[5] - 1);
47     case 5:
48       counters[4] = _rdpmc (indexes[4] - 1);
49     case 4:
50       counters[3] = _rdpmc (indexes[3] - 1);
51     case 3:
52       counters[2] = _rdpmc (indexes[2] - 1);
53     case 2:
54       counters[1] = _rdpmc (indexes[1] - 1);
55     case 1:
56       counters[0] = _rdpmc (indexes[0] - 1);
57     }
58 }
59
60 uword
61 perfmon_dispatch_wrapper (vlib_main_t *vm, vlib_node_runtime_t *node,
62                           vlib_frame_t *frame)
63 {
64   perfmon_main_t *pm = &perfmon_main;
65   perfmon_thread_runtime_t *rt =
66     vec_elt_at_index (pm->thread_runtimes, vm->thread_index);
67   perfmon_node_stats_t *s =
68     vec_elt_at_index (rt->node_stats, node->node_index);
69
70   u8 n_events = rt->n_events;
71
72   struct
73   {
74     u64 t[2][PERF_MAX_EVENTS];
75   } samples;
76   uword rv;
77
78   clib_prefetch_load (s);
79
80   perfmon_read_pmcs (&samples.t[0][0], &rt->indexes[0], n_events);
81   rv = node->function (vm, node, frame);
82   perfmon_read_pmcs (&samples.t[1][0], &rt->indexes[0], n_events);
83
84   if (rv == 0)
85     return rv;
86
87   s->n_calls += 1;
88   s->n_packets += rv;
89
90   for (int i = 0; i < n_events; i++)
91     {
92       if (!(rt->preserve_samples & 1 << i))
93         {
94           s->value[i] += samples.t[1][i] - samples.t[0][i];
95         }
96       else
97         {
98           s->t[0].value[i] = samples.t[0][i];
99           s->t[1].value[i] = samples.t[1][i];
100         }
101     }
102
103   return rv;
104 }