1cb9cadadSEd Warnicke/*
2cb9cadadSEd Warnicke * Copyright (c) 2015 Cisco and/or its affiliates.
3cb9cadadSEd Warnicke * Licensed under the Apache License, Version 2.0 (the "License");
4cb9cadadSEd Warnicke * you may not use this file except in compliance with the License.
5cb9cadadSEd Warnicke * You may obtain a copy of the License at:
6cb9cadadSEd Warnicke *
7cb9cadadSEd Warnicke *     http://www.apache.org/licenses/LICENSE-2.0
8cb9cadadSEd Warnicke *
9cb9cadadSEd Warnicke * Unless required by applicable law or agreed to in writing, software
10cb9cadadSEd Warnicke * distributed under the License is distributed on an "AS IS" BASIS,
11cb9cadadSEd Warnicke * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb9cadadSEd Warnicke * See the License for the specific language governing permissions and
13cb9cadadSEd Warnicke * limitations under the License.
14cb9cadadSEd Warnicke */
15cb9cadadSEd Warnicke/*
16cb9cadadSEd Warnicke * counter.h: simple and packet/byte counters
17cb9cadadSEd Warnicke *
18cb9cadadSEd Warnicke * Copyright (c) 2008 Eliot Dresselhaus
19cb9cadadSEd Warnicke *
20cb9cadadSEd Warnicke * Permission is hereby granted, free of charge, to any person obtaining
21cb9cadadSEd Warnicke * a copy of this software and associated documentation files (the
22cb9cadadSEd Warnicke * "Software"), to deal in the Software without restriction, including
23cb9cadadSEd Warnicke * without limitation the rights to use, copy, modify, merge, publish,
24cb9cadadSEd Warnicke * distribute, sublicense, and/or sell copies of the Software, and to
25cb9cadadSEd Warnicke * permit persons to whom the Software is furnished to do so, subject to
26cb9cadadSEd Warnicke * the following conditions:
27cb9cadadSEd Warnicke *
28cb9cadadSEd Warnicke * The above copyright notice and this permission notice shall be
29cb9cadadSEd Warnicke * included in all copies or substantial portions of the Software.
30cb9cadadSEd Warnicke *
31cb9cadadSEd Warnicke *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32cb9cadadSEd Warnicke *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33cb9cadadSEd Warnicke *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34cb9cadadSEd Warnicke *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35cb9cadadSEd Warnicke *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36cb9cadadSEd Warnicke *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37cb9cadadSEd Warnicke *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38cb9cadadSEd Warnicke */
39cb9cadadSEd Warnicke
40cb9cadadSEd Warnicke#ifndef included_vlib_counter_h
41cb9cadadSEd Warnicke#define included_vlib_counter_h
42cb9cadadSEd Warnicke
4358492a83SOle Troan#include <vlib/counter_types.h>
4458492a83SOle Troan
456353920eSDave Barach/** \file
46cb9cadadSEd Warnicke
476353920eSDave Barach    Optimized thread-safe counters.
48cb9cadadSEd Warnicke
491bd01099SNeale Ranns    Each vlib_[simple|combined]_counter_main_t consists of a per-thread
501bd01099SNeale Ranns    vector of per-object counters.
511bd01099SNeale Ranns
521bd01099SNeale Ranns    The idea is to drastically eliminate atomic operations.
536353920eSDave Barach*/
54cb9cadadSEd Warnicke
556353920eSDave Barach/** A collection of simple counters */
56cb9cadadSEd Warnicke
576353920eSDave Barachtypedef struct
586353920eSDave Barach{
591bd01099SNeale Ranns  counter_t **counters;	 /**< Per-thread u64 non-atomic counters */
601bd01099SNeale Ranns  counter_t *value_at_last_serialize;	/**< Values as of last serialize. */
616353920eSDave Barach  u32 last_incremental_serialize_index;	/**< Last counter index
626353920eSDave Barach                                           serialized incrementally. */
636353920eSDave Barach
646353920eSDave Barach  char *name;			/**< The counter collection's name. */
65048a4e5aSDave Barach  char *stat_segment_name;    /**< Name in stat segment directory */
66cb9cadadSEd Warnicke} vlib_simple_counter_main_t;
67cb9cadadSEd Warnicke
681bd01099SNeale Ranns/** The number of counters (not the number of per-thread counters) */
691bd01099SNeale Rannsu32 vlib_simple_counter_n_counters (const vlib_simple_counter_main_t * cm);
701bd01099SNeale Ranns
716353920eSDave Barach/** Increment a simple counter
726353920eSDave Barach    @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
73586afd76SDamjan Marion    @param thread_index - (u32) the current cpu index
746353920eSDave Barach    @param index - (u32) index of the counter to increment
751bd01099SNeale Ranns    @param increment - (u64) quantitiy to add to the counter
766353920eSDave Barach*/
77cb9cadadSEd Warnickealways_inline void
78cb9cadadSEd Warnickevlib_increment_simple_counter (vlib_simple_counter_main_t * cm,
79586afd76SDamjan Marion			       u32 thread_index, u32 index, u64 increment)
80cb9cadadSEd Warnicke{
811bd01099SNeale Ranns  counter_t *my_counters;
82cb9cadadSEd Warnicke
83586afd76SDamjan Marion  my_counters = cm->counters[thread_index];
841bd01099SNeale Ranns  my_counters[index] += increment;
85cb9cadadSEd Warnicke}
86cb9cadadSEd Warnicke
87b0055c81SMatus Fabian/** Set a simple counter
88b0055c81SMatus Fabian    @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
89b0055c81SMatus Fabian    @param thread_index - (u32) the current cpu index
90b0055c81SMatus Fabian    @param index - (u32) index of the counter to increment
91b0055c81SMatus Fabian    @param value - (u64) quantitiy to set to the counter
92b0055c81SMatus Fabian*/
93b0055c81SMatus Fabianalways_inline void
94b0055c81SMatus Fabianvlib_set_simple_counter (vlib_simple_counter_main_t * cm,
95b0055c81SMatus Fabian			 u32 thread_index, u32 index, u64 value)
96b0055c81SMatus Fabian{
97b0055c81SMatus Fabian  counter_t *my_counters;
98b0055c81SMatus Fabian
99b0055c81SMatus Fabian  my_counters = cm->counters[thread_index];
100b0055c81SMatus Fabian  my_counters[index] = value;
101b0055c81SMatus Fabian}
102b0055c81SMatus Fabian
1036353920eSDave Barach/** Get the value of a simple counter
1041bd01099SNeale Ranns    Scrapes the entire set of per-thread counters. Innacurate unless
1056353920eSDave Barach    worker threads which might increment the counter are
1066353920eSDave Barach    barrier-synchronized
1076353920eSDave Barach
1086353920eSDave Barach    @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
1096353920eSDave Barach    @param index - (u32) index of the counter to fetch
1106353920eSDave Barach    @returns - (u64) current counter value
1116353920eSDave Barach*/
1121bd01099SNeale Rannsalways_inline counter_t
113cb9cadadSEd Warnickevlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
114cb9cadadSEd Warnicke{
1151bd01099SNeale Ranns  counter_t *my_counters;
1161bd01099SNeale Ranns  counter_t v;
117cb9cadadSEd Warnicke  int i;
118cb9cadadSEd Warnicke
1191bd01099SNeale Ranns  ASSERT (index < vlib_simple_counter_n_counters (cm));
120cb9cadadSEd Warnicke
121cb9cadadSEd Warnicke  v = 0;
122cb9cadadSEd Warnicke
1231bd01099SNeale Ranns  for (i = 0; i < vec_len (cm->counters); i++)
124cb9cadadSEd Warnicke    {
1251bd01099SNeale Ranns      my_counters = cm->counters[i];
1261bd01099SNeale Ranns      v += my_counters[index];
127cb9cadadSEd Warnicke    }
128cb9cadadSEd Warnicke
129cb9cadadSEd Warnicke  return v;
130cb9cadadSEd Warnicke}
131cb9cadadSEd Warnicke
1326353920eSDave Barach/** Clear a simple counter
1336353920eSDave Barach    Clears the set of per-thread u16 counters, and the u64 counter
1346353920eSDave Barach
1356353920eSDave Barach    @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
1366353920eSDave Barach    @param index - (u32) index of the counter to clear
1376353920eSDave Barach*/
138cb9cadadSEd Warnickealways_inline void
139cb9cadadSEd Warnickevlib_zero_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
140cb9cadadSEd Warnicke{
1411bd01099SNeale Ranns  counter_t *my_counters;
142cb9cadadSEd Warnicke  int i;
143cb9cadadSEd Warnicke
1441bd01099SNeale Ranns  ASSERT (index < vlib_simple_counter_n_counters (cm));
145cb9cadadSEd Warnicke
1461bd01099SNeale Ranns  for (i = 0; i < vec_len (cm->counters); i++)
147cb9cadadSEd Warnicke    {
1481bd01099SNeale Ranns      my_counters = cm->counters[i];
1491bd01099SNeale Ranns      my_counters[index] = 0;
150cb9cadadSEd Warnicke    }
151cb9cadadSEd Warnicke}
152cb9cadadSEd Warnicke
1536353920eSDave Barach/** Add two combined counters, results in the first counter
154d4024f58SChris Luke    @param [in,out] a - (vlib_counter_t *) dst counter
1556353920eSDave Barach    @param b - (vlib_counter_t *) src counter
1566353920eSDave Barach*/
1576353920eSDave Barach
158cb9cadadSEd Warnickealways_inline void
159cb9cadadSEd Warnickevlib_counter_add (vlib_counter_t * a, vlib_counter_t * b)
160cb9cadadSEd Warnicke{
161cb9cadadSEd Warnicke  a->packets += b->packets;
162cb9cadadSEd Warnicke  a->bytes += b->bytes;
163cb9cadadSEd Warnicke}
164cb9cadadSEd Warnicke
1656353920eSDave Barach/** Subtract combined counters, results in the first counter
166d4024f58SChris Luke    @param [in,out] a - (vlib_counter_t *) dst counter
1676353920eSDave Barach    @param b - (vlib_counter_t *) src counter
1686353920eSDave Barach*/
169cb9cadadSEd Warnickealways_inline void
170cb9cadadSEd Warnickevlib_counter_sub (vlib_counter_t * a, vlib_counter_t * b)
171cb9cadadSEd Warnicke{
172cb9cadadSEd Warnicke  ASSERT (a->packets >= b->packets);
173cb9cadadSEd Warnicke  ASSERT (a->bytes >= b->bytes);
174cb9cadadSEd Warnicke  a->packets -= b->packets;
175cb9cadadSEd Warnicke  a->bytes -= b->bytes;
176cb9cadadSEd Warnicke}
177cb9cadadSEd Warnicke
1786353920eSDave Barach/** Clear a combined counter
1796353920eSDave Barach    @param a - (vlib_counter_t *) counter to clear
1806353920eSDave Barach*/
181cb9cadadSEd Warnickealways_inline void
182cb9cadadSEd Warnickevlib_counter_zero (vlib_counter_t * a)
1839b8ffd99SDave Barach{
1849b8ffd99SDave Barach  a->packets = a->bytes = 0;
1859b8ffd99SDave Barach}
186cb9cadadSEd Warnicke
1876353920eSDave Barach/** A collection of combined counters */
1889b8ffd99SDave Barachtypedef struct
1899b8ffd99SDave Barach{
1901bd01099SNeale Ranns  vlib_counter_t **counters;	/**< Per-thread u64 non-atomic counter pairs */
1916353920eSDave Barach  vlib_counter_t *value_at_last_serialize; /**< Counter values as of last serialize. */
1926353920eSDave Barach  u32 last_incremental_serialize_index;	/**< Last counter index serialized incrementally. */
1936353920eSDave Barach  char *name; /**< The counter collection's name. */
194048a4e5aSDave Barach  char *stat_segment_name;	/**< Name in stat segment directory */
195cb9cadadSEd Warnicke} vlib_combined_counter_main_t;
196cb9cadadSEd Warnicke
1971bd01099SNeale Ranns/** The number of counters (not the number of per-thread counters) */
1981bd01099SNeale Rannsu32 vlib_combined_counter_n_counters (const vlib_combined_counter_main_t *
1991bd01099SNeale Ranns				      cm);
2001bd01099SNeale Ranns
2016353920eSDave Barach/** Clear a collection of simple counters
2026353920eSDave Barach    @param cm - (vlib_simple_counter_main_t *) collection to clear
2036353920eSDave Barach*/
204cb9cadadSEd Warnickevoid vlib_clear_simple_counters (vlib_simple_counter_main_t * cm);
2056353920eSDave Barach
2066353920eSDave Barach/** Clear a collection of combined counters
2076353920eSDave Barach    @param cm - (vlib_combined_counter_main_t *) collection to clear
2086353920eSDave Barach*/
209cb9cadadSEd Warnickevoid vlib_clear_combined_counters (vlib_combined_counter_main_t * cm);
210cb9cadadSEd Warnicke
2116353920eSDave Barach/** Increment a combined counter
2126353920eSDave Barach    @param cm - (vlib_combined_counter_main_t *) comined counter main pointer
213586afd76SDamjan Marion    @param thread_index - (u32) the current cpu index
2146353920eSDave Barach    @param index - (u32) index of the counter to increment
2151bd01099SNeale Ranns    @param packet_increment - (u64) number of packets to add to the counter
2161bd01099SNeale Ranns    @param byte_increment - (u64) number of bytes to add to the counter
2176353920eSDave Barach*/
2186353920eSDave Barach
219cb9cadadSEd Warnickealways_inline void
220cb9cadadSEd Warnickevlib_increment_combined_counter (vlib_combined_counter_main_t * cm,
221586afd76SDamjan Marion				 u32 thread_index,
2221bd01099SNeale Ranns				 u32 index, u64 n_packets, u64 n_bytes)
223cb9cadadSEd Warnicke{
2241bd01099SNeale Ranns  vlib_counter_t *my_counters;
225cb9cadadSEd Warnicke
2261bd01099SNeale Ranns  /* Use this CPU's counter array */
227586afd76SDamjan Marion  my_counters = cm->counters[thread_index];
228cb9cadadSEd Warnicke
2291bd01099SNeale Ranns  my_counters[index].packets += n_packets;
2301bd01099SNeale Ranns  my_counters[index].bytes += n_bytes;
231cb9cadadSEd Warnicke}
232cb9cadadSEd Warnicke
2331bd01099SNeale Ranns/** Pre-fetch a per-thread combined counter for the given object index */
2341bd01099SNeale Rannsalways_inline void
2351bd01099SNeale Rannsvlib_prefetch_combined_counter (const vlib_combined_counter_main_t * cm,
236586afd76SDamjan Marion				u32 thread_index, u32 index)
2371bd01099SNeale Ranns{
2381bd01099SNeale Ranns  vlib_counter_t *cpu_counters;
2391bd01099SNeale Ranns
2401bd01099SNeale Ranns  /*
2411bd01099SNeale Ranns   * This CPU's index is assumed to already be in cache
2421bd01099SNeale Ranns   */
243586afd76SDamjan Marion  cpu_counters = cm->counters[thread_index];
2441bd01099SNeale Ranns  CLIB_PREFETCH (cpu_counters + index, CLIB_CACHE_LINE_BYTES, STORE);
245044183faSNeale Ranns}
246044183faSNeale Ranns
247044183faSNeale Ranns
2486353920eSDave Barach/** Get the value of a combined counter, never called in the speed path
2491bd01099SNeale Ranns    Scrapes the entire set of per-thread counters. Innacurate unless
2506353920eSDave Barach    worker threads which might increment the counter are
2516353920eSDave Barach    barrier-synchronized
2526353920eSDave Barach
2536353920eSDave Barach    @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
2546353920eSDave Barach    @param index - (u32) index of the combined counter to fetch
2556353920eSDave Barach    @param result [out] - (vlib_counter_t *) result stored here
2566353920eSDave Barach*/
2576353920eSDave Barach
258cb9cadadSEd Warnickestatic inline void
2591bd01099SNeale Rannsvlib_get_combined_counter (const vlib_combined_counter_main_t * cm,
2609b8ffd99SDave Barach			   u32 index, vlib_counter_t * result)
261cb9cadadSEd Warnicke{
2621bd01099SNeale Ranns  vlib_counter_t *my_counters, *counter;
263cb9cadadSEd Warnicke  int i;
264cb9cadadSEd Warnicke
265cb9cadadSEd Warnicke  result->packets = 0;
266cb9cadadSEd Warnicke  result->bytes = 0;
267cb9cadadSEd Warnicke
2681bd01099SNeale Ranns  for (i = 0; i < vec_len (cm->counters); i++)
269cb9cadadSEd Warnicke    {
2701bd01099SNeale Ranns      my_counters = cm->counters[i];
271cb9cadadSEd Warnicke
2721bd01099SNeale Ranns      counter = vec_elt_at_index (my_counters, index);
2731bd01099SNeale Ranns      result->packets += counter->packets;
2741bd01099SNeale Ranns      result->bytes += counter->bytes;
275cb9cadadSEd Warnicke    }
276cb9cadadSEd Warnicke}
277cb9cadadSEd Warnicke
2786353920eSDave Barach/** Clear a combined counter
2791bd01099SNeale Ranns    Clears the set of per-thread counters.
2806353920eSDave Barach
2816353920eSDave Barach    @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
2826353920eSDave Barach    @param index - (u32) index of the counter to clear
2836353920eSDave Barach*/
284cb9cadadSEd Warnickealways_inline void
2859b8ffd99SDave Barachvlib_zero_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
286cb9cadadSEd Warnicke{
2871bd01099SNeale Ranns  vlib_counter_t *my_counters, *counter;
288cb9cadadSEd Warnicke  int i;
289cb9cadadSEd Warnicke
2901bd01099SNeale Ranns  for (i = 0; i < vec_len (cm->counters); i++)
291cb9cadadSEd Warnicke    {
2921bd01099SNeale Ranns      my_counters = cm->counters[i];
293cb9cadadSEd Warnicke
2941bd01099SNeale Ranns      counter = vec_elt_at_index (my_counters, index);
2951bd01099SNeale Ranns      counter->packets = 0;
2961bd01099SNeale Ranns      counter->bytes = 0;
297cb9cadadSEd Warnicke    }
298cb9cadadSEd Warnicke}
299cb9cadadSEd Warnicke
3006353920eSDave Barach/** validate a simple counter
3016353920eSDave Barach    @param cm - (vlib_simple_counter_main_t *) pointer to the counter collection
3026353920eSDave Barach    @param index - (u32) index of the counter to validate
3036353920eSDave Barach*/
3046353920eSDave Barach
3059b8ffd99SDave Barachvoid vlib_validate_simple_counter (vlib_simple_counter_main_t * cm,
3069b8ffd99SDave Barach				   u32 index);
307a568a19bSOle Troanvoid vlib_free_simple_counter (vlib_simple_counter_main_t * cm);
308a568a19bSOle Troan
3096353920eSDave Barach/** validate a combined counter
3106353920eSDave Barach    @param cm - (vlib_combined_counter_main_t *) pointer to the counter
3116353920eSDave Barach    collection
3126353920eSDave Barach    @param index - (u32) index of the counter to validate
3136353920eSDave Barach*/
3146353920eSDave Barach
3159b8ffd99SDave Barachvoid vlib_validate_combined_counter (vlib_combined_counter_main_t * cm,
3169b8ffd99SDave Barach				     u32 index);
317a568a19bSOle Troanvoid vlib_free_combined_counter (vlib_combined_counter_main_t * cm);
318cb9cadadSEd Warnicke
3196353920eSDave Barach/** Obtain the number of simple or combined counters allocated.
3206353920eSDave Barach    A macro which reduces to to vec_len(cm->maxi), the answer in either
3216353920eSDave Barach    case.
3226353920eSDave Barach
3236353920eSDave Barach    @param cm - (vlib_simple_counter_main_t) or
3246353920eSDave Barach    (vlib_combined_counter_main_t) the counter collection to interrogate
3256353920eSDave Barach    @returns vec_len(cm->maxi)
3266353920eSDave Barach*/
327cb9cadadSEd Warnicke#define vlib_counter_len(cm) vec_len((cm)->maxi)
328cb9cadadSEd Warnicke
329cb9cadadSEd Warnicke#endif /* included_vlib_counter_h */
3309b8ffd99SDave Barach
3319b8ffd99SDave Barach/*
3329b8ffd99SDave Barach * fd.io coding-style-patch-verification: ON
3339b8ffd99SDave Barach *
3349b8ffd99SDave Barach * Local Variables:
3359b8ffd99SDave Barach * eval: (c-set-style "gnu")
3369b8ffd99SDave Barach * End:
3379b8ffd99SDave Barach */
338