LCOV - code coverage report
Current view: top level - vlib - counter.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 50 50 100.0 %
Date: 2023-10-26 01:39:38 Functions: 9 9 100.0 %

          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             :  */

Generated by: LCOV version 1.14