Line data Source code
1 : /*
2 : * Copyright (c) 2015 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 : * counter.h: simple and packet/byte counters
17 : *
18 : * Copyright (c) 2008 Eliot Dresselhaus
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining
21 : * a copy of this software and associated documentation files (the
22 : * "Software"), to deal in the Software without restriction, including
23 : * without limitation the rights to use, copy, modify, merge, publish,
24 : * distribute, sublicense, and/or sell copies of the Software, and to
25 : * permit persons to whom the Software is furnished to do so, subject to
26 : * the following conditions:
27 : *
28 : * The above copyright notice and this permission notice shall be
29 : * included in all copies or substantial portions of the Software.
30 : *
31 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 : */
39 :
40 : #ifndef included_vlib_counter_h
41 : #define included_vlib_counter_h
42 :
43 : #include <vlib/counter_types.h>
44 :
45 : /** \file
46 :
47 : Optimized thread-safe counters.
48 :
49 : Each vlib_[simple|combined]_counter_main_t consists of a per-thread
50 : vector of per-object counters.
51 :
52 : The idea is to drastically eliminate atomic operations.
53 : */
54 :
55 : /** A collection of simple counters */
56 :
57 : typedef struct
58 : {
59 : counter_t **counters; /**< Per-thread u64 non-atomic counters */
60 : char *name; /**< The counter collection's name. */
61 : char *stat_segment_name; /**< Name in stat segment directory */
62 : u32 stats_entry_index;
63 : } vlib_simple_counter_main_t;
64 :
65 : /** The number of counters (not the number of per-thread counters) */
66 : u32 vlib_simple_counter_n_counters (const vlib_simple_counter_main_t * cm);
67 :
68 : /** Pre-fetch a per-thread simple counter for the given object index */
69 : always_inline void
70 244118 : vlib_prefetch_simple_counter (const vlib_simple_counter_main_t *cm,
71 : u32 thread_index, u32 index)
72 : {
73 : counter_t *my_counters;
74 :
75 : /*
76 : * This CPU's index is assumed to already be in cache
77 : */
78 244118 : my_counters = cm->counters[thread_index];
79 244118 : clib_prefetch_store (my_counters + index);
80 244118 : }
81 :
82 : /** Increment a simple counter
83 : @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
84 : @param thread_index - (u32) the current cpu index
85 : @param index - (u32) index of the counter to increment
86 : @param increment - (u64) quantitiy to add to the counter
87 : */
88 : always_inline void
89 10516667 : vlib_increment_simple_counter (vlib_simple_counter_main_t * cm,
90 : u32 thread_index, u32 index, u64 increment)
91 : {
92 : counter_t *my_counters;
93 :
94 10516667 : my_counters = cm->counters[thread_index];
95 10516667 : my_counters[index] += increment;
96 10516667 : }
97 :
98 : /** Decrement a simple counter
99 : @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
100 : @param thread_index - (u32) the current cpu index
101 : @param index - (u32) index of the counter to increment
102 : @param increment - (u64) quantitiy remove from the counter value
103 : */
104 : always_inline void
105 : vlib_decrement_simple_counter (vlib_simple_counter_main_t * cm,
106 : u32 thread_index, u32 index, u64 decrement)
107 : {
108 : counter_t *my_counters;
109 :
110 : my_counters = cm->counters[thread_index];
111 :
112 : ASSERT (my_counters[index] >= decrement);
113 :
114 : my_counters[index] -= decrement;
115 : }
116 :
117 : /** Set a simple counter
118 : @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
119 : @param thread_index - (u32) the current cpu index
120 : @param index - (u32) index of the counter to increment
121 : @param value - (u64) quantitiy to set to the counter
122 : */
123 : always_inline void
124 99053 : vlib_set_simple_counter (vlib_simple_counter_main_t * cm,
125 : u32 thread_index, u32 index, u64 value)
126 : {
127 : counter_t *my_counters;
128 :
129 99053 : my_counters = cm->counters[thread_index];
130 99053 : my_counters[index] = value;
131 99053 : }
132 :
133 : /** Get the value of a simple counter
134 : Scrapes the entire set of per-thread counters. Innacurate unless
135 : worker threads which might increment the counter are
136 : barrier-synchronized
137 :
138 : @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
139 : @param index - (u32) index of the counter to fetch
140 : @returns - (u64) current counter value
141 : */
142 : always_inline counter_t
143 127513 : vlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
144 : {
145 : counter_t *my_counters;
146 : counter_t v;
147 : int i;
148 :
149 127513 : ASSERT (index < vlib_simple_counter_n_counters (cm));
150 :
151 127513 : v = 0;
152 :
153 289244 : for (i = 0; i < vec_len (cm->counters); i++)
154 : {
155 161731 : my_counters = cm->counters[i];
156 161731 : v += my_counters[index];
157 : }
158 :
159 127513 : return v;
160 : }
161 :
162 : /** Clear a simple counter
163 : Clears the set of per-thread u16 counters, and the u64 counter
164 :
165 : @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
166 : @param index - (u32) index of the counter to clear
167 : */
168 : always_inline void
169 692019 : vlib_zero_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
170 : {
171 : counter_t *my_counters;
172 : int i;
173 :
174 692019 : ASSERT (index < vlib_simple_counter_n_counters (cm));
175 :
176 1408198 : for (i = 0; i < vec_len (cm->counters); i++)
177 : {
178 716179 : my_counters = cm->counters[i];
179 716179 : my_counters[index] = 0;
180 : }
181 692019 : }
182 :
183 : /** Add two combined counters, results in the first counter
184 : @param [in,out] a - (vlib_counter_t *) dst counter
185 : @param b - (vlib_counter_t *) src counter
186 : */
187 :
188 : always_inline void
189 : vlib_counter_add (vlib_counter_t * a, vlib_counter_t * b)
190 : {
191 : a->packets += b->packets;
192 : a->bytes += b->bytes;
193 : }
194 :
195 : /** Subtract combined counters, results in the first counter
196 : @param [in,out] a - (vlib_counter_t *) dst counter
197 : @param b - (vlib_counter_t *) src counter
198 : */
199 : always_inline void
200 : vlib_counter_sub (vlib_counter_t * a, vlib_counter_t * b)
201 : {
202 : ASSERT (a->packets >= b->packets);
203 : ASSERT (a->bytes >= b->bytes);
204 : a->packets -= b->packets;
205 : a->bytes -= b->bytes;
206 : }
207 :
208 : /** Clear a combined counter
209 : @param a - (vlib_counter_t *) counter to clear
210 : */
211 : always_inline void
212 : vlib_counter_zero (vlib_counter_t * a)
213 : {
214 : a->packets = a->bytes = 0;
215 : }
216 :
217 : /** A collection of combined counters */
218 : typedef struct
219 : {
220 : vlib_counter_t **counters; /**< Per-thread u64 non-atomic counter pairs */
221 : char *name; /**< The counter collection's name. */
222 : char *stat_segment_name; /**< Name in stat segment directory */
223 : u32 stats_entry_index;
224 : } vlib_combined_counter_main_t;
225 :
226 : /** The number of counters (not the number of per-thread counters) */
227 : u32 vlib_combined_counter_n_counters (const vlib_combined_counter_main_t *
228 : cm);
229 :
230 : /** Clear a collection of simple counters
231 : @param cm - (vlib_simple_counter_main_t *) collection to clear
232 : */
233 : void vlib_clear_simple_counters (vlib_simple_counter_main_t * cm);
234 :
235 : /** Clear a collection of combined counters
236 : @param cm - (vlib_combined_counter_main_t *) collection to clear
237 : */
238 : void vlib_clear_combined_counters (vlib_combined_counter_main_t * cm);
239 :
240 : /** Increment a combined counter
241 : @param cm - (vlib_combined_counter_main_t *) comined counter main pointer
242 : @param thread_index - (u32) the current cpu index
243 : @param index - (u32) index of the counter to increment
244 : @param packet_increment - (u64) number of packets to add to the counter
245 : @param byte_increment - (u64) number of bytes to add to the counter
246 : */
247 :
248 : always_inline void
249 31281105 : vlib_increment_combined_counter (vlib_combined_counter_main_t * cm,
250 : u32 thread_index,
251 : u32 index, u64 n_packets, u64 n_bytes)
252 : {
253 : vlib_counter_t *my_counters;
254 :
255 : /* Use this CPU's counter array */
256 31281105 : my_counters = cm->counters[thread_index];
257 :
258 31281105 : my_counters[index].packets += n_packets;
259 31281105 : my_counters[index].bytes += n_bytes;
260 31281105 : }
261 :
262 : /** Pre-fetch a per-thread combined counter for the given object index */
263 : always_inline void
264 326850 : vlib_prefetch_combined_counter (const vlib_combined_counter_main_t * cm,
265 : u32 thread_index, u32 index)
266 : {
267 : vlib_counter_t *cpu_counters;
268 :
269 : /*
270 : * This CPU's index is assumed to already be in cache
271 : */
272 326850 : cpu_counters = cm->counters[thread_index];
273 326850 : clib_prefetch_store (cpu_counters + index);
274 326850 : }
275 :
276 :
277 : /** Get the value of a combined counter, never called in the speed path
278 : Scrapes the entire set of per-thread counters. Innacurate unless
279 : worker threads which might increment the counter are
280 : barrier-synchronized
281 :
282 : @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
283 : @param index - (u32) index of the combined counter to fetch
284 : @param result [out] - (vlib_counter_t *) result stored here
285 : */
286 :
287 : static inline void
288 178951 : vlib_get_combined_counter (const vlib_combined_counter_main_t * cm,
289 : u32 index, vlib_counter_t * result)
290 : {
291 : vlib_counter_t *my_counters, *counter;
292 : int i;
293 :
294 178951 : result->packets = 0;
295 178951 : result->bytes = 0;
296 :
297 388668 : for (i = 0; i < vec_len (cm->counters); i++)
298 : {
299 209717 : my_counters = cm->counters[i];
300 :
301 209717 : counter = vec_elt_at_index (my_counters, index);
302 209717 : result->packets += counter->packets;
303 209717 : result->bytes += counter->bytes;
304 : }
305 178951 : }
306 :
307 : /** Clear a combined counter
308 : Clears the set of per-thread counters.
309 :
310 : @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
311 : @param index - (u32) index of the counter to clear
312 : */
313 : always_inline void
314 245515 : vlib_zero_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
315 : {
316 : vlib_counter_t *my_counters, *counter;
317 : int i;
318 :
319 502413 : for (i = 0; i < vec_len (cm->counters); i++)
320 : {
321 256898 : my_counters = cm->counters[i];
322 :
323 256898 : counter = vec_elt_at_index (my_counters, index);
324 256898 : counter->packets = 0;
325 256898 : counter->bytes = 0;
326 : }
327 245515 : }
328 :
329 : /** validate a simple counter
330 : @param cm - (vlib_simple_counter_main_t *) pointer to the counter collection
331 : @param index - (u32) index of the counter to validate
332 : */
333 :
334 : void vlib_validate_simple_counter (vlib_simple_counter_main_t * cm,
335 : u32 index);
336 : void vlib_free_simple_counter (vlib_simple_counter_main_t * cm);
337 :
338 : /** validate a combined counter
339 : @param cm - (vlib_combined_counter_main_t *) pointer to the counter
340 : collection
341 : @param index - (u32) index of the counter to validate
342 : */
343 :
344 : void vlib_validate_combined_counter (vlib_combined_counter_main_t * cm,
345 : u32 index);
346 : int vlib_validate_combined_counter_will_expand
347 : (vlib_combined_counter_main_t * cm, u32 index);
348 :
349 : void vlib_free_combined_counter (vlib_combined_counter_main_t * cm);
350 :
351 : /** Obtain the number of simple or combined counters allocated.
352 : A macro which reduces to to vec_len(cm->maxi), the answer in either
353 : case.
354 :
355 : @param cm - (vlib_simple_counter_main_t) or
356 : (vlib_combined_counter_main_t) the counter collection to interrogate
357 : @returns vec_len(cm->maxi)
358 : */
359 : #define vlib_counter_len(cm) vec_len((cm)->maxi)
360 :
361 : #endif /* included_vlib_counter_h */
362 :
363 : /*
364 : * fd.io coding-style-patch-verification: ON
365 : *
366 : * Local Variables:
367 : * eval: (c-set-style "gnu")
368 : * End:
369 : */
|