FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
counter.h
Go to the documentation of this file.
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 /** \file
44 
45  Optimized thread-safe counters.
46 
47  Each vlib_[simple|combined]_counter_main_t consists of a single
48  vector of thread-safe / atomically-updated u64 counters [the
49  "maxi" vector], and a (u16 **) per-thread vector [the "minis"
50  vector] of narrow, per-thread counters.
51 
52  The idea is to drastically reduce the number of atomic operations.
53  In the case of packet counts, we divide the number of atomic ops
54  by 2**16, etc.
55 */
56 
57 /** A collection of simple counters */
58 
59 typedef struct
60 {
61  u16 **minis; /**< Per-thread u16 non-atomic counters */
62  u64 *maxi; /**< Shared wide counters */
63  u64 *value_at_last_clear; /**< Counter values as of last clear. */
64  u64 *value_at_last_serialize; /**< Values as of last serialize. */
65  u32 last_incremental_serialize_index; /**< Last counter index
66  serialized incrementally. */
67 
68  char *name; /**< The counter collection's name. */
70 
71 /** Increment a simple counter
72  @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
73  @param cpu_index - (u32) the current cpu index
74  @param index - (u32) index of the counter to increment
75  @param increment - (u32) quantitiy to add to the counter
76 */
77 always_inline void
79  u32 cpu_index, u32 index, u32 increment)
80 {
81  u16 *my_minis;
82  u16 *mini;
83  u32 old, new;
84 
85  my_minis = cm->minis[cpu_index];
86  mini = vec_elt_at_index (my_minis, index);
87  old = mini[0];
88  new = old + increment;
89  mini[0] = new;
90 
91  if (PREDICT_FALSE (mini[0] != new))
92  {
93  __sync_fetch_and_add (&cm->maxi[index], new);
94  my_minis[index] = 0;
95  }
96 }
97 
98 /** Get the value of a simple counter
99  Scrapes the entire set of mini counters. Innacurate unless
100  worker threads which might increment the counter are
101  barrier-synchronized
102 
103  @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
104  @param index - (u32) index of the counter to fetch
105  @returns - (u64) current counter value
106 */
109 {
110  u16 *my_minis, *mini;
111  u64 v;
112  int i;
113 
114  ASSERT (index < vec_len (cm->maxi));
115 
116  v = 0;
117 
118  for (i = 0; i < vec_len (cm->minis); i++)
119  {
120  my_minis = cm->minis[i];
121  mini = vec_elt_at_index (my_minis, index);
122  v += mini[0];
123  }
124 
125  v += cm->maxi[index];
126 
127  if (index < vec_len (cm->value_at_last_clear))
128  {
129  ASSERT (v >= cm->value_at_last_clear[index]);
130  v -= cm->value_at_last_clear[index];
131  }
132 
133  return v;
134 }
135 
136 /** Clear a simple counter
137  Clears the set of per-thread u16 counters, and the u64 counter
138 
139  @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
140  @param index - (u32) index of the counter to clear
141 */
142 always_inline void
144 {
145  u16 *my_minis;
146  int i;
147 
148  ASSERT (index < vec_len (cm->maxi));
149 
150  for (i = 0; i < vec_len (cm->minis); i++)
151  {
152  my_minis = cm->minis[i];
153  my_minis[index] = 0;
154  }
155 
156  cm->maxi[index] = 0;
157 
158  if (index < vec_len (cm->value_at_last_clear))
159  cm->value_at_last_clear[index] = 0;
160 }
161 
162 /** Combined counter to hold both packets and byte differences.
163  */
164 typedef struct
165 {
166  u64 packets; /**< packet counter */
167  u64 bytes; /**< byte counter */
169 
170 /** Add two combined counters, results in the first counter
171  @param [in,out] a - (vlib_counter_t *) dst counter
172  @param b - (vlib_counter_t *) src counter
173 */
174 
175 always_inline void
177 {
178  a->packets += b->packets;
179  a->bytes += b->bytes;
180 }
181 
182 /** Subtract combined counters, results in the first counter
183  @param [in,out] a - (vlib_counter_t *) dst counter
184  @param b - (vlib_counter_t *) src counter
185 */
186 always_inline void
188 {
189  ASSERT (a->packets >= b->packets);
190  ASSERT (a->bytes >= b->bytes);
191  a->packets -= b->packets;
192  a->bytes -= b->bytes;
193 }
194 
195 /** Clear a combined counter
196  @param a - (vlib_counter_t *) counter to clear
197 */
198 always_inline void
200 {
201  a->packets = a->bytes = 0;
202 }
203 
204 /** Mini combined counter */
205 typedef struct
206 {
207  u16 packets; /**< Packet count */
208  i16 bytes; /**< Byte count */
210 
211 /** A collection of combined counters */
212 typedef struct
213 {
214  vlib_mini_counter_t **minis; /**< Per-thread u16 non-atomic counter pairs */
215  vlib_counter_t *maxi; /**< Shared wide counter pairs */
216  vlib_counter_t *value_at_last_clear; /**< Counter values as of last clear. */
217  vlib_counter_t *value_at_last_serialize; /**< Counter values as of last serialize. */
218  u32 last_incremental_serialize_index; /**< Last counter index serialized incrementally. */
219  char *name; /**< The counter collection's name. */
221 
222 /** Clear a collection of simple counters
223  @param cm - (vlib_simple_counter_main_t *) collection to clear
224 */
226 
227 /** Clear a collection of combined counters
228  @param cm - (vlib_combined_counter_main_t *) collection to clear
229 */
231 
232 /** Increment a combined counter
233  @param cm - (vlib_combined_counter_main_t *) comined counter main pointer
234  @param cpu_index - (u32) the current cpu index
235  @param index - (u32) index of the counter to increment
236  @param packet_increment - (u32) number of packets to add to the counter
237  @param byte_increment - (u32) number of bytes to add to the counter
238 */
239 
240 always_inline void
242  u32 cpu_index,
243  u32 index,
244  u32 packet_increment, u32 byte_increment)
245 {
246  vlib_mini_counter_t *my_minis, *mini;
247  u32 old_packets, new_packets;
248  i32 old_bytes, new_bytes;
249 
250  /* Use this CPU's mini counter array */
251  my_minis = cm->minis[cpu_index];
252 
253  mini = vec_elt_at_index (my_minis, index);
254  old_packets = mini->packets;
255  old_bytes = mini->bytes;
256 
257  new_packets = old_packets + packet_increment;
258  new_bytes = old_bytes + byte_increment;
259 
260  mini->packets = new_packets;
261  mini->bytes = new_bytes;
262 
263  /* Bytes always overflow before packets.. */
264  if (PREDICT_FALSE (mini->bytes != new_bytes))
265  {
266  vlib_counter_t *maxi = vec_elt_at_index (cm->maxi, index);
267 
268  __sync_fetch_and_add (&maxi->packets, new_packets);
269  __sync_fetch_and_add (&maxi->bytes, new_bytes);
270 
271  mini->packets = 0;
272  mini->bytes = 0;
273  }
274 }
275 
276 /** Get the value of a combined counter, never called in the speed path
277  Scrapes the entire set of mini counters. Innacurate unless
278  worker threads which might increment the counter are
279  barrier-synchronized
280 
281  @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
282  @param index - (u32) index of the combined counter to fetch
283  @param result [out] - (vlib_counter_t *) result stored here
284 */
285 
286 static inline void
288  u32 index, vlib_counter_t * result)
289 {
290  vlib_mini_counter_t *my_minis, *mini;
291  vlib_counter_t *maxi;
292  int i;
293 
294  result->packets = 0;
295  result->bytes = 0;
296 
297  for (i = 0; i < vec_len (cm->minis); i++)
298  {
299  my_minis = cm->minis[i];
300 
301  mini = vec_elt_at_index (my_minis, index);
302  result->packets += mini->packets;
303  result->bytes += mini->bytes;
304  }
305 
306  maxi = vec_elt_at_index (cm->maxi, index);
307  result->packets += maxi->packets;
308  result->bytes += maxi->bytes;
309 
310  if (index < vec_len (cm->value_at_last_clear))
311  vlib_counter_sub (result, &cm->value_at_last_clear[index]);
312 }
313 
314 /** Clear a combined counter
315  Clears the set of per-thread u16 counters, and the shared vlib_counter_t
316 
317  @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
318  @param index - (u32) index of the counter to clear
319 */
320 always_inline void
322 {
323  vlib_mini_counter_t *mini, *my_minis;
324  int i;
325 
326  for (i = 0; i < vec_len (cm->minis); i++)
327  {
328  my_minis = cm->minis[i];
329 
330  mini = vec_elt_at_index (my_minis, index);
331  mini->packets = 0;
332  mini->bytes = 0;
333  }
334 
335  vlib_counter_zero (&cm->maxi[index]);
336  if (index < vec_len (cm->value_at_last_clear))
338 }
339 
340 /** validate a simple counter
341  @param cm - (vlib_simple_counter_main_t *) pointer to the counter collection
342  @param index - (u32) index of the counter to validate
343 */
344 
346  u32 index);
347 /** validate a combined counter
348  @param cm - (vlib_combined_counter_main_t *) pointer to the counter
349  collection
350  @param index - (u32) index of the counter to validate
351 */
352 
354  u32 index);
355 
356 /** Obtain the number of simple or combined counters allocated.
357  A macro which reduces to to vec_len(cm->maxi), the answer in either
358  case.
359 
360  @param cm - (vlib_simple_counter_main_t) or
361  (vlib_combined_counter_main_t) the counter collection to interrogate
362  @returns vec_len(cm->maxi)
363 */
364 #define vlib_counter_len(cm) vec_len((cm)->maxi)
365 
370 
371 #endif /* included_vlib_counter_h */
372 
373 /*
374  * fd.io coding-style-patch-verification: ON
375  *
376  * Local Variables:
377  * eval: (c-set-style "gnu")
378  * End:
379  */
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
Increment a simple counter.
Definition: counter.h:78
u64 * value_at_last_serialize
Values as of last serialize.
Definition: counter.h:64
u64 packets
packet counter
Definition: counter.h:166
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u64 * maxi
Shared wide counters.
Definition: counter.h:62
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Clear a collection of combined counters.
Definition: counter.c:67
a
Definition: bitmap.h:516
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:98
vlib_counter_t * value_at_last_serialize
Counter values as of last serialize.
Definition: counter.h:217
vlib_counter_t * maxi
Shared wide counter pairs.
Definition: counter.h:215
Combined counter to hold both packets and byte differences.
Definition: counter.h:164
static void vlib_counter_zero(vlib_counter_t *a)
Clear a combined counter.
Definition: counter.h:199
Mini combined counter.
Definition: counter.h:205
u64 * value_at_last_clear
Counter values as of last clear.
Definition: counter.h:63
#define always_inline
Definition: clib.h:84
int i32
Definition: types.h:81
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned long u64
Definition: types.h:89
static void vlib_counter_sub(vlib_counter_t *a, vlib_counter_t *b)
Subtract combined counters, results in the first counter.
Definition: counter.h:187
A collection of simple counters.
Definition: counter.h:59
static void vlib_counter_add(vlib_counter_t *a, vlib_counter_t *b)
Add two combined counters, results in the first counter.
Definition: counter.h:176
i16 bytes
Byte count.
Definition: counter.h:208
char * name
The counter collection&#39;s name.
Definition: counter.h:68
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread u16 counters, and the shared vlib_counter_t...
Definition: counter.h:321
serialize_function_t unserialize_vlib_simple_counter_main
Definition: counter.h:366
u16 ** minis
Per-thread u16 non-atomic counters.
Definition: counter.h:61
static void vlib_get_combined_counter(vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of mini co...
Definition: counter.h:287
#define PREDICT_FALSE(x)
Definition: clib.h:97
u32 last_incremental_serialize_index
Last counter index serialized incrementally.
Definition: counter.h:218
serialize_function_t serialize_vlib_combined_counter_main
Definition: counter.h:368
u32 last_incremental_serialize_index
Last counter index serialized incrementally.
Definition: counter.h:65
u64 bytes
byte counter
Definition: counter.h:167
u16 packets
Packet count.
Definition: counter.h:207
vlib_mini_counter_t ** minis
Per-thread u16 non-atomic counter pairs.
Definition: counter.h:214
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:110
serialize_function_t serialize_vlib_simple_counter_main
Definition: counter.h:366
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
Definition: counter.h:241
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
serialize_function_t unserialize_vlib_combined_counter_main
Definition: counter.h:368
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:143
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
void( serialize_function_t)(serialize_main_t *m, va_list *va)
Definition: serialize.h:168
char * name
The counter collection&#39;s name.
Definition: counter.h:219
A collection of combined counters.
Definition: counter.h:212
static u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of mini counters.
Definition: counter.h:108
short i16
Definition: types.h:46
vlib_counter_t * value_at_last_clear
Counter values as of last clear.
Definition: counter.h:216
void vlib_clear_simple_counters(vlib_simple_counter_main_t *cm)
Clear a collection of simple counters.
Definition: counter.c:43