X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vlib%2Fvlib%2Fcounter.h;h=a79032065d97b83bcdcff384dc90cfe8b19668ba;hb=20d1232532e6f6c94c77a125b6c17680e14785b5;hp=8db999c3a94ea057cb13be96c8cf0a39f2eb726c;hpb=cfb2d804ce4a9262577c63b9c0245d45b2335e64;p=vpp.git diff --git a/vlib/vlib/counter.h b/vlib/vlib/counter.h index 8db999c3a94..a79032065d9 100644 --- a/vlib/vlib/counter.h +++ b/vlib/vlib/counter.h @@ -40,40 +40,46 @@ #ifndef included_vlib_counter_h #define included_vlib_counter_h -/* - * Annoyingly enough, counters are created long before - * the CPU configuration is available, so we have to - * preallocate the mini-counter per-cpu vectors - */ - -typedef struct { - /* Compact counters that (rarely) can overflow. */ - u16 ** minis; +/** \file - /* Counters to hold overflow. */ - u64 * maxi; + Optimized thread-safe counters. - /* Counter values as of last clear. */ - u64 * value_at_last_clear; + Each vlib_[simple|combined]_counter_main_t consists of a single + vector of thread-safe / atomically-updated u64 counters [the + "maxi" vector], and a (u16 **) per-thread vector [the "minis" + vector] of narrow, per-thread counters. - /* Values as of last serialize. */ - u64 * value_at_last_serialize; + The idea is to drastically reduce the number of atomic operations. + In the case of packet counts, we divide the number of atomic ops + by 2**16, etc. +*/ - /* Last counter index serialized incrementally. */ - u32 last_incremental_serialize_index; +/** A collection of simple counters */ - /* Counter name. */ - char * name; +typedef struct +{ + u16 **minis; /**< Per-thread u16 non-atomic counters */ + u64 *maxi; /**< Shared wide counters */ + u64 *value_at_last_clear; /**< Counter values as of last clear. */ + u64 *value_at_last_serialize; /**< Values as of last serialize. */ + u32 last_incremental_serialize_index; /**< Last counter index + serialized incrementally. */ + + char *name; /**< The counter collection's name. */ } vlib_simple_counter_main_t; +/** Increment a simple counter + @param cm - (vlib_simple_counter_main_t *) simple counter main pointer + @param cpu_index - (u32) the current cpu index + @param index - (u32) index of the counter to increment + @param increment - (u32) quantitiy to add to the counter +*/ always_inline void vlib_increment_simple_counter (vlib_simple_counter_main_t * cm, - u32 cpu_index, - u32 index, - u32 increment) + u32 cpu_index, u32 index, u32 increment) { - u16 * my_minis; - u16 * mini; + u16 *my_minis; + u16 *mini; u32 old, new; my_minis = cm->minis[cpu_index]; @@ -89,6 +95,15 @@ vlib_increment_simple_counter (vlib_simple_counter_main_t * cm, } } +/** Get the value of a simple counter + Scrapes the entire set of mini counters. Innacurate unless + worker threads which might increment the counter are + barrier-synchronized + + @param cm - (vlib_simple_counter_main_t *) simple counter main pointer + @param index - (u32) index of the counter to fetch + @returns - (u64) current counter value +*/ always_inline u64 vlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index) { @@ -100,7 +115,7 @@ vlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index) v = 0; - for (i = 0; i < vec_len(cm->minis); i++) + for (i = 0; i < vec_len (cm->minis); i++) { my_minis = cm->minis[i]; mini = vec_elt_at_index (my_minis, index); @@ -118,15 +133,21 @@ vlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index) return v; } +/** Clear a simple counter + Clears the set of per-thread u16 counters, and the u64 counter + + @param cm - (vlib_simple_counter_main_t *) simple counter main pointer + @param index - (u32) index of the counter to clear +*/ always_inline void vlib_zero_simple_counter (vlib_simple_counter_main_t * cm, u32 index) { - u16 * my_minis; + u16 *my_minis; int i; ASSERT (index < vec_len (cm->maxi)); - for (i = 0; i < vec_len(cm->minis); i++) + for (i = 0; i < vec_len (cm->minis); i++) { my_minis = cm->minis[i]; my_minis[index] = 0; @@ -138,12 +159,19 @@ vlib_zero_simple_counter (vlib_simple_counter_main_t * cm, u32 index) cm->value_at_last_clear[index] = 0; } -/* Combined counters hold both packets and byte differences. */ -/* Maxi-packet/byte counter. */ -typedef struct { - u64 packets, bytes; +/** Combined counter to hold both packets and byte differences. + */ +typedef struct +{ + u64 packets; /**< packet counter */ + u64 bytes; /**< byte counter */ } vlib_counter_t; +/** Add two combined counters, results in the first counter + @param [in,out] a - (vlib_counter_t *) dst counter + @param b - (vlib_counter_t *) src counter +*/ + always_inline void vlib_counter_add (vlib_counter_t * a, vlib_counter_t * b) { @@ -151,6 +179,10 @@ vlib_counter_add (vlib_counter_t * a, vlib_counter_t * b) a->bytes += b->bytes; } +/** Subtract combined counters, results in the first counter + @param [in,out] a - (vlib_counter_t *) dst counter + @param b - (vlib_counter_t *) src counter +*/ always_inline void vlib_counter_sub (vlib_counter_t * a, vlib_counter_t * b) { @@ -160,60 +192,58 @@ vlib_counter_sub (vlib_counter_t * a, vlib_counter_t * b) a->bytes -= b->bytes; } +/** Clear a combined counter + @param a - (vlib_counter_t *) counter to clear +*/ always_inline void vlib_counter_zero (vlib_counter_t * a) -{ a->packets = a->bytes = 0; } - -/* Micro-counter: 16 bits of packets and 16 bits of byte difference. */ -typedef struct { - /* Packet count. */ - u16 packets; +{ + a->packets = a->bytes = 0; +} - /* The average packet size hack doesn't work in a multi-core config */ - i16 bytes; +/** Mini combined counter */ +typedef struct +{ + u16 packets; /**< Packet count */ + i16 bytes; /**< Byte count */ } vlib_mini_counter_t; -typedef struct { - /* Compact counters that (rarely) can overflow. */ - vlib_mini_counter_t ** minis; - - /* Counters to hold overflow. */ - vlib_counter_t * maxi; - - /* Debug counters for testing. */ - vlib_counter_t * debug; - - /* Counter values as of last clear. */ - vlib_counter_t * value_at_last_clear; - - /* Counter values as of last serialize. */ - vlib_counter_t * value_at_last_serialize; - - /* Last counter index serialized incrementally. */ - u32 last_incremental_serialize_index; - - /* Average packet sizes used in mini-counter byte differences. */ - u32 ave_packet_size; - - /* Current summed packets and bytes for average computation. */ - u32 ave_packets, ave_bytes; - - /* Counter name. */ - char * name; - +/** A collection of combined counters */ +typedef struct +{ + vlib_mini_counter_t **minis; /**< Per-thread u16 non-atomic counter pairs */ + vlib_counter_t *maxi; /**< Shared wide counter pairs */ + vlib_counter_t *value_at_last_clear; /**< Counter values as of last clear. */ + vlib_counter_t *value_at_last_serialize; /**< Counter values as of last serialize. */ + u32 last_incremental_serialize_index; /**< Last counter index serialized incrementally. */ + char *name; /**< The counter collection's name. */ } vlib_combined_counter_main_t; +/** Clear a collection of simple counters + @param cm - (vlib_simple_counter_main_t *) collection to clear +*/ void vlib_clear_simple_counters (vlib_simple_counter_main_t * cm); + +/** Clear a collection of combined counters + @param cm - (vlib_combined_counter_main_t *) collection to clear +*/ void vlib_clear_combined_counters (vlib_combined_counter_main_t * cm); +/** Increment a combined counter + @param cm - (vlib_combined_counter_main_t *) comined counter main pointer + @param cpu_index - (u32) the current cpu index + @param index - (u32) index of the counter to increment + @param packet_increment - (u32) number of packets to add to the counter + @param byte_increment - (u32) number of bytes to add to the counter +*/ + always_inline void vlib_increment_combined_counter (vlib_combined_counter_main_t * cm, - u32 cpu_index, + u32 cpu_index, u32 index, - u32 packet_increment, - u32 byte_increment) + u32 packet_increment, u32 byte_increment) { - vlib_mini_counter_t * my_minis, * mini; + vlib_mini_counter_t *my_minis, *mini; u32 old_packets, new_packets; i32 old_bytes, new_bytes; @@ -233,7 +263,7 @@ vlib_increment_combined_counter (vlib_combined_counter_main_t * cm, /* Bytes always overflow before packets.. */ if (PREDICT_FALSE (mini->bytes != new_bytes)) { - vlib_counter_t * maxi = vec_elt_at_index (cm->maxi, index); + vlib_counter_t *maxi = vec_elt_at_index (cm->maxi, index); __sync_fetch_and_add (&maxi->packets, new_packets); __sync_fetch_and_add (&maxi->bytes, new_bytes); @@ -243,20 +273,28 @@ vlib_increment_combined_counter (vlib_combined_counter_main_t * cm, } } -/* This is never done in the speed path */ +/** Get the value of a combined counter, never called in the speed path + Scrapes the entire set of mini counters. Innacurate unless + worker threads which might increment the counter are + barrier-synchronized + + @param cm - (vlib_combined_counter_main_t *) combined counter main pointer + @param index - (u32) index of the combined counter to fetch + @param result [out] - (vlib_counter_t *) result stored here +*/ + static inline void vlib_get_combined_counter (vlib_combined_counter_main_t * cm, - u32 index, - vlib_counter_t * result) + u32 index, vlib_counter_t * result) { - vlib_mini_counter_t * my_minis, * mini; - vlib_counter_t * maxi; + vlib_mini_counter_t *my_minis, *mini; + vlib_counter_t *maxi; int i; result->packets = 0; result->bytes = 0; - for (i = 0; i < vec_len(cm->minis); i++) + for (i = 0; i < vec_len (cm->minis); i++) { my_minis = cm->minis[i]; @@ -273,14 +311,19 @@ vlib_get_combined_counter (vlib_combined_counter_main_t * cm, vlib_counter_sub (result, &cm->value_at_last_clear[index]); } +/** Clear a combined counter + Clears the set of per-thread u16 counters, and the shared vlib_counter_t + + @param cm - (vlib_combined_counter_main_t *) combined counter main pointer + @param index - (u32) index of the counter to clear +*/ always_inline void -vlib_zero_combined_counter (vlib_combined_counter_main_t * cm, - u32 index) +vlib_zero_combined_counter (vlib_combined_counter_main_t * cm, u32 index) { - vlib_mini_counter_t * mini, * my_minis; + vlib_mini_counter_t *mini, *my_minis; int i; - for (i = 0; i < vec_len(cm->minis); i++) + for (i = 0; i < vec_len (cm->minis); i++) { my_minis = cm->minis[i]; @@ -294,13 +337,43 @@ vlib_zero_combined_counter (vlib_combined_counter_main_t * cm, vlib_counter_zero (&cm->value_at_last_clear[index]); } -void vlib_validate_simple_counter (vlib_simple_counter_main_t *cm, u32 index); -void vlib_validate_combined_counter (vlib_combined_counter_main_t *cm, u32 index); - -/* Number of simple/combined counters allocated. */ +/** validate a simple counter + @param cm - (vlib_simple_counter_main_t *) pointer to the counter collection + @param index - (u32) index of the counter to validate +*/ + +void vlib_validate_simple_counter (vlib_simple_counter_main_t * cm, + u32 index); +/** validate a combined counter + @param cm - (vlib_combined_counter_main_t *) pointer to the counter + collection + @param index - (u32) index of the counter to validate +*/ + +void vlib_validate_combined_counter (vlib_combined_counter_main_t * cm, + u32 index); + +/** Obtain the number of simple or combined counters allocated. + A macro which reduces to to vec_len(cm->maxi), the answer in either + case. + + @param cm - (vlib_simple_counter_main_t) or + (vlib_combined_counter_main_t) the counter collection to interrogate + @returns vec_len(cm->maxi) +*/ #define vlib_counter_len(cm) vec_len((cm)->maxi) -serialize_function_t serialize_vlib_simple_counter_main, unserialize_vlib_simple_counter_main; -serialize_function_t serialize_vlib_combined_counter_main, unserialize_vlib_combined_counter_main; +serialize_function_t serialize_vlib_simple_counter_main, + unserialize_vlib_simple_counter_main; +serialize_function_t serialize_vlib_combined_counter_main, + unserialize_vlib_combined_counter_main; #endif /* included_vlib_counter_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */