FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
dispatch_wrapper.c
Go to the documentation of this file.
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 
29 perfmon_mmap_read_pmc1 (const struct perf_event_mmap_page *mmap_page)
30 {
31  u64 count;
32  u32 seq;
33 
34  /* See documentation in /usr/include/linux/perf_event.h, for more details
35  * but the 2 main important things are:
36  * 1) if seq != mmap_page->lock, it means the kernel is currently updating
37  * the user page and we need to read it again
38  * 2) if idx == 0, it means the perf event is currently turned off and we
39  * just need to read the kernel-updated 'offset', otherwise we must also
40  * add the current hw value (hence rdmpc) */
41  do
42  {
43  u32 idx;
44 
45  seq = mmap_page->lock;
47 
48  idx = mmap_page->index;
49  count = mmap_page->offset;
50  if (idx)
51  count += _rdpmc (idx - 1);
52 
54  }
55  while (mmap_page->lock != seq);
56 
57  return count;
58 }
59 
62  struct perf_event_mmap_page **mmap_pages,
63  u8 n_counters)
64 {
65  switch (n_counters)
66  {
67  default:
68  case 7:
69  counters[6] = perfmon_mmap_read_pmc1 (mmap_pages[6]);
70  case 6:
71  counters[5] = perfmon_mmap_read_pmc1 (mmap_pages[5]);
72  case 5:
73  counters[4] = perfmon_mmap_read_pmc1 (mmap_pages[4]);
74  case 4:
75  counters[3] = perfmon_mmap_read_pmc1 (mmap_pages[3]);
76  case 3:
77  counters[2] = perfmon_mmap_read_pmc1 (mmap_pages[2]);
78  case 2:
79  counters[1] = perfmon_mmap_read_pmc1 (mmap_pages[1]);
80  case 1:
81  counters[0] = perfmon_mmap_read_pmc1 (mmap_pages[0]);
82  break;
83  }
84 }
85 
86 uword
89 {
94  vec_elt_at_index (rt->node_stats, node->node_index);
95 
96  u8 n_events = rt->n_events;
97 
98  u64 before[PERF_MAX_EVENTS];
99  u64 after[PERF_MAX_EVENTS];
100  uword rv;
101 
102  clib_prefetch_load (s);
103 
104  perfmon_mmap_read_pmcs (&before[0], rt->mmap_pages, n_events);
105  rv = node->function (vm, node, frame);
106  perfmon_mmap_read_pmcs (&after[0], rt->mmap_pages, n_events);
107 
108  if (rv == 0)
109  return rv;
110 
111  s->n_calls += 1;
112  s->n_packets += rv;
113 
114  for (int i = 0; i < n_events; i++)
115  s->value[i] += after[i] - before[i];
116 
117  return rv;
118 }
119 
121 perfmon_metric_read_pmcs (u64 *counters, int *pmc_index, u8 n_counters)
122 {
123  switch (n_counters)
124  {
125  default:
126  case 7:
127  counters[6] = _rdpmc (pmc_index[6]);
128  case 6:
129  counters[5] = _rdpmc (pmc_index[5]);
130  case 5:
131  counters[4] = _rdpmc (pmc_index[4]);
132  case 4:
133  counters[3] = _rdpmc (pmc_index[3]);
134  case 3:
135  counters[2] = _rdpmc (pmc_index[2]);
136  case 2:
137  counters[1] = _rdpmc (pmc_index[1]);
138  case 1:
139  counters[0] = _rdpmc (pmc_index[0]);
140  break;
141  }
142 }
143 
146 {
147  return (int) (b->metrics[i]);
148 }
149 
150 uword
153 {
158  vec_elt_at_index (rt->node_stats, node->node_index);
159 
160  u8 n_events = rt->n_events;
161 
162  u64 before[PERF_MAX_EVENTS];
163  int pmc_index[PERF_MAX_EVENTS];
164  uword rv;
165 
166  clib_prefetch_load (s);
167 
168  switch (n_events)
169  {
170  default:
171  case 7:
172  pmc_index[6] = perfmon_metric_index (rt->bundle, 6);
173  case 6:
174  pmc_index[5] = perfmon_metric_index (rt->bundle, 5);
175  case 5:
176  pmc_index[4] = perfmon_metric_index (rt->bundle, 4);
177  case 4:
178  pmc_index[3] = perfmon_metric_index (rt->bundle, 3);
179  case 3:
180  pmc_index[2] = perfmon_metric_index (rt->bundle, 2);
181  case 2:
182  pmc_index[1] = perfmon_metric_index (rt->bundle, 1);
183  case 1:
184  pmc_index[0] = perfmon_metric_index (rt->bundle, 0);
185  break;
186  }
187 
188  perfmon_metric_read_pmcs (&before[0], pmc_index, n_events);
189  rv = node->function (vm, node, frame);
190 
191  clib_memcpy_fast (&s->t[0].value[0], &before, sizeof (before));
192  perfmon_metric_read_pmcs (&s->t[1].value[0], pmc_index, n_events);
193 
194  if (rv == 0)
195  return rv;
196 
197  s->n_calls += 1;
198  s->n_packets += rv;
199 
200  return rv;
201 }
perfmon_node_stats_t
Definition: perfmon.h:140
perfmon_node_stats_t::n_packets
u64 n_packets
Definition: perfmon.h:144
api.h
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
perfmon_main_t
Definition: perfmon.h:164
perfmon_node_stats_t::n_calls
u64 n_calls
Definition: perfmon.h:143
string.h
perfmon_main
perfmon_main_t perfmon_main
Definition: perfmon.c:27
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
perfmon_bundle
Definition: perfmon.h:105
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
api.h
vlib_frame_t
Definition: node.h:372
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
perfmon_main_t::thread_runtimes
perfmon_thread_runtime_t * thread_runtimes
Definition: perfmon.h:166
perfmon_node_stats_t::t
struct perfmon_node_stats_t::@769::@771 t[2]
CLIB_COMPILER_BARRIER
#define CLIB_COMPILER_BARRIER()
Definition: clib.h:134
count
u8 count
Definition: dhcp.api:208
perfmon_metric_index
static_always_inline int perfmon_metric_index(perfmon_bundle_t *b, u8 i)
Definition: dispatch_wrapper.c:145
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
static_always_inline
#define static_always_inline
Definition: clib.h:112
uword
u64 uword
Definition: types.h:112
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
perfmon_dispatch_wrapper_metrics
uword perfmon_dispatch_wrapper_metrics(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: dispatch_wrapper.c:151
plugin.h
PERF_MAX_EVENTS
#define PERF_MAX_EVENTS
Definition: perfmon.h:26
u64
unsigned long u64
Definition: types.h:89
u32
unsigned int u32
Definition: types.h:88
clib_prefetch_load
static_always_inline void clib_prefetch_load(void *p)
Definition: cache.h:92
perfmon_thread_runtime_t
Definition: perfmon.h:155
perfmon_mmap_read_pmcs
static_always_inline void perfmon_mmap_read_pmcs(u64 *counters, struct perf_event_mmap_page **mmap_pages, u8 n_counters)
Definition: dispatch_wrapper.c:61
vlib_main_t
Definition: main.h:102
perfmon_dispatch_wrapper_mmap
uword perfmon_dispatch_wrapper_mmap(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: dispatch_wrapper.c:87
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:419
perfmon_metric_read_pmcs
static_always_inline void perfmon_metric_read_pmcs(u64 *counters, int *pmc_index, u8 n_counters)
Definition: dispatch_wrapper.c:121
perfmon_node_stats_t::value
u64 value[PERF_MAX_EVENTS]
Definition: perfmon.h:149
i
int i
Definition: flowhash_template.h:376
rv
int __clib_unused rv
Definition: application.c:491
perfmon_mmap_read_pmc1
static_always_inline u64 perfmon_mmap_read_pmc1(const struct perf_event_mmap_page *mmap_page)
Definition: dispatch_wrapper.c:29
vnet.h
vlib_node_runtime_t
Definition: node.h:454