LCOV - code coverage report
Current view: top level - vlib/stats - collector.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 72 72 100.0 %
Date: 2023-10-26 01:39:38 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: Apache-2.0
       2             :  * Copyright(c) 2022 Cisco Systems, Inc.
       3             :  */
       4             : 
       5             : #include <vlib/vlib.h>
       6             : #include <vlib/unix/unix.h>
       7             : #include <vlib/stats/stats.h>
       8             : 
       9             : enum
      10             : {
      11             :   NODE_CLOCKS,
      12             :   NODE_VECTORS,
      13             :   NODE_CALLS,
      14             :   NODE_SUSPENDS,
      15             :   N_NODE_COUNTERS
      16             : };
      17             : 
      18             : struct
      19             : {
      20             :   u32 entry_index;
      21             :   char *name;
      22             : } node_counters[] = {
      23             :   [NODE_CLOCKS] = { .name = "clocks" },
      24             :   [NODE_VECTORS] = { .name = "vectors" },
      25             :   [NODE_CALLS] = { .name = "calls" },
      26             :   [NODE_SUSPENDS] = { .name = "suspends" },
      27             : };
      28             : 
      29             : static struct
      30             : {
      31             :   u8 *name;
      32             :   u32 symlinks[N_NODE_COUNTERS];
      33             : } *node_data = 0;
      34             : 
      35             : static vlib_stats_string_vector_t node_names = 0;
      36             : 
      37             : static inline void
      38         149 : update_node_counters (vlib_stats_segment_t *sm)
      39             : {
      40         149 :   clib_bitmap_t *bmp = 0;
      41         149 :   vlib_main_t **stat_vms = 0;
      42         149 :   vlib_node_t ***node_dups = 0;
      43             :   u32 n_nodes;
      44             :   int i, j;
      45             : 
      46         149 :   vlib_node_get_nodes (0 /* vm, for barrier sync */,
      47             :                        (u32) ~0 /* all threads */, 1 /* include stats */,
      48             :                        0 /* barrier sync */, &node_dups, &stat_vms);
      49             : 
      50         149 :   n_nodes = vec_len (node_dups[0]);
      51             : 
      52         149 :   vec_validate (node_data, n_nodes - 1);
      53             : 
      54      109004 :   for (i = 0; i < n_nodes; i++)
      55      108855 :     if (vec_is_equal (node_data[i].name, node_dups[0][i]->name) == 0)
      56         759 :       bmp = clib_bitmap_set (bmp, i, 1);
      57             : 
      58         149 :   if (bmp)
      59             :     {
      60           4 :       u32 last_thread = vlib_get_n_threads ();
      61           4 :       vlib_stats_segment_lock ();
      62         763 :       clib_bitmap_foreach (i, bmp)
      63             :         {
      64         759 :           if (node_data[i].name)
      65             :             {
      66          24 :               vec_free (node_data[i].name);
      67         120 :               for (j = 0; j < ARRAY_LEN (node_data->symlinks); j++)
      68          96 :                 vlib_stats_remove_entry (node_data[i].symlinks[j]);
      69             :             }
      70             :         }
      71             :       /* We can't merge the loops because a node index corresponding to a given
      72             :        * node name can change between 2 updates. Otherwise, we could add
      73             :        * already existing symlinks or delete valid ones.
      74             :        */
      75         763 :       clib_bitmap_foreach (i, bmp)
      76             :         {
      77         759 :           vlib_node_t *n = node_dups[0][i];
      78         759 :           node_data[i].name = vec_dup (n->name);
      79         759 :           vlib_stats_set_string_vector (&node_names, n->index, "%v", n->name);
      80             : 
      81        3795 :           for (int j = 0; j < ARRAY_LEN (node_counters); j++)
      82             :             {
      83        3036 :               vlib_stats_validate (node_counters[j].entry_index, last_thread,
      84             :                                    n_nodes - 1);
      85        3036 :               node_data[i].symlinks[j] = vlib_stats_add_symlink (
      86             :                 node_counters[j].entry_index, n->index, "/nodes/%U/%s",
      87             :                 format_vlib_stats_symlink, n->name, node_counters[j].name);
      88        3036 :               ASSERT (node_data[i].symlinks[j] != CLIB_U32_MAX);
      89             :             }
      90             :         }
      91           4 :       vlib_stats_segment_unlock ();
      92           4 :       vec_free (bmp);
      93             :     }
      94             : 
      95         298 :   for (j = 0; j < vec_len (node_dups); j++)
      96             :     {
      97         149 :       vlib_node_t **nodes = node_dups[j];
      98             : 
      99      109004 :       for (i = 0; i < vec_len (nodes); i++)
     100             :         {
     101             :           counter_t **counters;
     102             :           counter_t *c;
     103      108855 :           vlib_node_t *n = nodes[i];
     104             : 
     105      108855 :           counters = vlib_stats_get_entry_data_pointer (
     106             :             node_counters[NODE_CLOCKS].entry_index);
     107      108855 :           c = counters[j];
     108      108855 :           c[n->index] = n->stats_total.clocks - n->stats_last_clear.clocks;
     109             : 
     110      108855 :           counters = vlib_stats_get_entry_data_pointer (
     111             :             node_counters[NODE_VECTORS].entry_index);
     112      108855 :           c = counters[j];
     113      108855 :           c[n->index] = n->stats_total.vectors - n->stats_last_clear.vectors;
     114             : 
     115      108855 :           counters = vlib_stats_get_entry_data_pointer (
     116             :             node_counters[NODE_CALLS].entry_index);
     117      108855 :           c = counters[j];
     118      108855 :           c[n->index] = n->stats_total.calls - n->stats_last_clear.calls;
     119             : 
     120      108855 :           counters = vlib_stats_get_entry_data_pointer (
     121             :             node_counters[NODE_SUSPENDS].entry_index);
     122      108855 :           c = counters[j];
     123      108855 :           c[n->index] = n->stats_total.suspends - n->stats_last_clear.suspends;
     124             :         }
     125         149 :       vec_free (node_dups[j]);
     126             :     }
     127         149 :   vec_free (node_dups);
     128         149 :   vec_free (stat_vms);
     129         149 : }
     130             : 
     131             : static void
     132        1256 : do_stat_segment_updates (vlib_main_t *vm, vlib_stats_segment_t *sm)
     133             : {
     134        1256 :   if (sm->node_counters_enabled)
     135         149 :     update_node_counters (sm);
     136             : 
     137             :   vlib_stats_collector_t *c;
     138       10098 :   pool_foreach (c, sm->collectors)
     139             :     {
     140        8842 :       vlib_stats_collector_data_t data = {
     141        8842 :         .entry_index = c->entry_index,
     142        8842 :         .vector_index = c->vector_index,
     143        8842 :         .private_data = c->private_data,
     144        8842 :         .entry = sm->directory_vector + c->entry_index,
     145             :       };
     146        8842 :       c->fn (&data);
     147             :     }
     148             : 
     149             :   /* Heartbeat, so clients detect we're still here */
     150        1256 :   sm->directory_vector[STAT_COUNTER_HEARTBEAT].value++;
     151        1256 : }
     152             : 
     153             : static uword
     154         575 : stat_segment_collector_process (vlib_main_t *vm, vlib_node_runtime_t *rt,
     155             :                                 vlib_frame_t *f)
     156             : {
     157         575 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     158             : 
     159         575 :   if (sm->node_counters_enabled)
     160             :     {
     161           1 :       node_names = vlib_stats_add_string_vector ("/sys/node/names");
     162           1 :       ASSERT (node_names);
     163             : 
     164           5 :       for (int x = 0; x < ARRAY_LEN (node_counters); x++)
     165             :         {
     166           4 :           node_counters[x].entry_index = vlib_stats_add_counter_vector (
     167             :             "/sys/node/%s", node_counters[x].name);
     168           4 :           ASSERT (node_counters[x].entry_index != CLIB_U32_MAX);
     169             :         }
     170             :     }
     171             : 
     172         575 :   sm->directory_vector[STAT_COUNTER_BOOTTIME].value = unix_time_now ();
     173             : 
     174             :   while (1)
     175             :     {
     176        1256 :       do_stat_segment_updates (vm, sm);
     177        1256 :       vlib_process_suspend (vm, sm->update_interval);
     178             :     }
     179             :   return 0; /* or not */
     180             : }
     181             : 
     182      183788 : VLIB_REGISTER_NODE (stat_segment_collector, static) = {
     183             :   .function = stat_segment_collector_process,
     184             :   .name = "statseg-collector-process",
     185             :   .type = VLIB_NODE_TYPE_PROCESS,
     186             : };

Generated by: LCOV version 1.14