FD.io VPP  v16.06
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 /*
44  * Annoyingly enough, counters are created long before
45  * the CPU configuration is available, so we have to
46  * preallocate the mini-counter per-cpu vectors
47  */
48 
49 typedef struct {
50  /* Compact counters that (rarely) can overflow. */
51  u16 ** minis;
52 
53  /* Counters to hold overflow. */
54  u64 * maxi;
55 
56  /* Counter values as of last clear. */
58 
59  /* Values as of last serialize. */
61 
62  /* Last counter index serialized incrementally. */
64 
65  /* Counter name. */
66  char * name;
68 
69 always_inline void
71  u32 cpu_index,
72  u32 index,
73  u32 increment)
74 {
75  u16 * my_minis;
76  u16 * mini;
77  u32 old, new;
78 
79  my_minis = cm->minis[cpu_index];
80  mini = vec_elt_at_index (my_minis, index);
81  old = mini[0];
82  new = old + increment;
83  mini[0] = new;
84 
85  if (PREDICT_FALSE (mini[0] != new))
86  {
87  __sync_fetch_and_add (&cm->maxi[index], new);
88  my_minis[index] = 0;
89  }
90 }
91 
94 {
95  u16 *my_minis, *mini;
96  u64 v;
97  int i;
98 
99  ASSERT (index < vec_len (cm->maxi));
100 
101  v = 0;
102 
103  for (i = 0; i < vec_len(cm->minis); i++)
104  {
105  my_minis = cm->minis[i];
106  mini = vec_elt_at_index (my_minis, index);
107  v += mini[0];
108  }
109 
110  v += cm->maxi[index];
111 
112  if (index < vec_len (cm->value_at_last_clear))
113  {
114  ASSERT (v >= cm->value_at_last_clear[index]);
115  v -= cm->value_at_last_clear[index];
116  }
117 
118  return v;
119 }
120 
121 always_inline void
123 {
124  u16 * my_minis;
125  int i;
126 
127  ASSERT (index < vec_len (cm->maxi));
128 
129  for (i = 0; i < vec_len(cm->minis); i++)
130  {
131  my_minis = cm->minis[i];
132  my_minis[index] = 0;
133  }
134 
135  cm->maxi[index] = 0;
136 
137  if (index < vec_len (cm->value_at_last_clear))
138  cm->value_at_last_clear[index] = 0;
139 }
140 
141 /* Combined counters hold both packets and byte differences. */
142 /* Maxi-packet/byte counter. */
143 typedef struct {
144  u64 packets, bytes;
146 
147 always_inline void
149 {
150  a->packets += b->packets;
151  a->bytes += b->bytes;
152 }
153 
154 always_inline void
156 {
157  ASSERT (a->packets >= b->packets);
158  ASSERT (a->bytes >= b->bytes);
159  a->packets -= b->packets;
160  a->bytes -= b->bytes;
161 }
162 
163 always_inline void
165 { a->packets = a->bytes = 0; }
166 
167 /* Micro-counter: 16 bits of packets and 16 bits of byte difference. */
168 typedef struct {
169  /* Packet count. */
171 
172  /* The average packet size hack doesn't work in a multi-core config */
175 
176 typedef struct {
177  /* Compact counters that (rarely) can overflow. */
179 
180  /* Counters to hold overflow. */
182 
183  /* Debug counters for testing. */
185 
186  /* Counter values as of last clear. */
188 
189  /* Counter values as of last serialize. */
191 
192  /* Last counter index serialized incrementally. */
194 
195  /* Average packet sizes used in mini-counter byte differences. */
197 
198  /* Current summed packets and bytes for average computation. */
199  u32 ave_packets, ave_bytes;
200 
201  /* Counter name. */
202  char * name;
203 
205 
208 
209 always_inline void
211  u32 cpu_index,
212  u32 index,
213  u32 packet_increment,
214  u32 byte_increment)
215 {
216  vlib_mini_counter_t * my_minis, * mini;
217  u32 old_packets, new_packets;
218  i32 old_bytes, new_bytes;
219 
220  /* Use this CPU's mini counter array */
221  my_minis = cm->minis[cpu_index];
222 
223  mini = vec_elt_at_index (my_minis, index);
224  old_packets = mini->packets;
225  old_bytes = mini->bytes;
226 
227  new_packets = old_packets + packet_increment;
228  new_bytes = old_bytes + byte_increment;
229 
230  mini->packets = new_packets;
231  mini->bytes = new_bytes;
232 
233  /* Bytes always overflow before packets.. */
234  if (PREDICT_FALSE (mini->bytes != new_bytes))
235  {
236  vlib_counter_t * maxi = vec_elt_at_index (cm->maxi, index);
237 
238  __sync_fetch_and_add (&maxi->packets, new_packets);
239  __sync_fetch_and_add (&maxi->bytes, new_bytes);
240 
241  mini->packets = 0;
242  mini->bytes = 0;
243  }
244 }
245 
246 /* This is never done in the speed path */
247 static inline void
249  u32 index,
250  vlib_counter_t * result)
251 {
252  vlib_mini_counter_t * my_minis, * mini;
253  vlib_counter_t * maxi;
254  int i;
255 
256  result->packets = 0;
257  result->bytes = 0;
258 
259  for (i = 0; i < vec_len(cm->minis); i++)
260  {
261  my_minis = cm->minis[i];
262 
263  mini = vec_elt_at_index (my_minis, index);
264  result->packets += mini->packets;
265  result->bytes += mini->bytes;
266  }
267 
268  maxi = vec_elt_at_index (cm->maxi, index);
269  result->packets += maxi->packets;
270  result->bytes += maxi->bytes;
271 
272  if (index < vec_len (cm->value_at_last_clear))
273  vlib_counter_sub (result, &cm->value_at_last_clear[index]);
274 }
275 
276 always_inline void
278  u32 index)
279 {
280  vlib_mini_counter_t * mini, * my_minis;
281  int i;
282 
283  for (i = 0; i < vec_len(cm->minis); i++)
284  {
285  my_minis = cm->minis[i];
286 
287  mini = vec_elt_at_index (my_minis, index);
288  mini->packets = 0;
289  mini->bytes = 0;
290  }
291 
292  vlib_counter_zero (&cm->maxi[index]);
293  if (index < vec_len (cm->value_at_last_clear))
295 }
296 
299 
300 /* Number of simple/combined counters allocated. */
301 #define vlib_counter_len(cm) vec_len((cm)->maxi)
302 
305 
306 #endif /* included_vlib_counter_h */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Definition: counter.c:65
a
Definition: bitmap.h:393
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.c:95
vlib_counter_t * value_at_last_serialize
Definition: counter.h:190
vlib_counter_t * maxi
Definition: counter.h:181
always_inline u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:93
always_inline void vlib_counter_add(vlib_counter_t *a, vlib_counter_t *b)
Definition: counter.h:148
#define always_inline
Definition: clib.h:84
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Definition: counter.h:210
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
vlib_counter_t * debug
Definition: counter.h:184
serialize_function_t unserialize_vlib_simple_counter_main
Definition: counter.h:303
always_inline void vlib_counter_zero(vlib_counter_t *a)
Definition: counter.h:164
always_inline void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
Definition: counter.h:70
static void vlib_get_combined_counter(vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Definition: counter.h:248
#define PREDICT_FALSE(x)
Definition: clib.h:97
always_inline void vlib_counter_sub(vlib_counter_t *a, vlib_counter_t *b)
Definition: counter.h:155
serialize_function_t serialize_vlib_combined_counter_main
Definition: counter.h:304
u32 last_incremental_serialize_index
Definition: counter.h:63
vlib_mini_counter_t ** minis
Definition: counter.h:178
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.c:106
serialize_function_t serialize_vlib_simple_counter_main
Definition: counter.h:303
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
serialize_function_t unserialize_vlib_combined_counter_main
Definition: counter.h:304
always_inline void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.h:277
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:154
short i16
Definition: types.h:46
always_inline void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:122
vlib_counter_t * value_at_last_clear
Definition: counter.h:187
void vlib_clear_simple_counters(vlib_simple_counter_main_t *cm)
Definition: counter.c:42