LCOV - code coverage report
Current view: top level - lib/metrics - rte_metrics.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 100 105 95.2 %
Date: 2025-03-01 20:23:48 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 55 68 80.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2017 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdlib.h>
       6                 :            : #include <string.h>
       7                 :            : 
       8                 :            : #include <rte_errno.h>
       9                 :            : #include <rte_common.h>
      10                 :            : #include <rte_string_fns.h>
      11                 :            : #include <rte_metrics.h>
      12                 :            : #include <rte_memzone.h>
      13                 :            : #include <rte_spinlock.h>
      14                 :            : 
      15                 :            : int metrics_initialized;
      16                 :            : 
      17                 :            : #define RTE_METRICS_MEMZONE_NAME "RTE_METRICS"
      18                 :            : 
      19                 :            : /**
      20                 :            :  * Internal stats metadata and value entry.
      21                 :            :  *
      22                 :            :  * @internal
      23                 :            :  */
      24                 :            : struct rte_metrics_meta_s {
      25                 :            :         /** Name of metric */
      26                 :            :         char name[RTE_METRICS_MAX_NAME_LEN];
      27                 :            :         /** Current value for metric */
      28                 :            :         uint64_t value[RTE_MAX_ETHPORTS];
      29                 :            :         /** Used for global metrics */
      30                 :            :         uint64_t global_value;
      31                 :            :         /** Index of next root element (zero for none) */
      32                 :            :         uint16_t idx_next_set;
      33                 :            :         /** Index of next metric in set (zero for none) */
      34                 :            :         uint16_t idx_next_stat;
      35                 :            : };
      36                 :            : 
      37                 :            : /**
      38                 :            :  * Internal stats info structure.
      39                 :            :  *
      40                 :            :  * @internal
      41                 :            :  * Offsets into metadata are used instead of pointers because ASLR
      42                 :            :  * means that having the same physical addresses in different
      43                 :            :  * processes is not guaranteed.
      44                 :            :  */
      45                 :            : struct rte_metrics_data_s {
      46                 :            :         /**   Index of last metadata entry with valid data.
      47                 :            :          * This value is not valid if cnt_stats is zero.
      48                 :            :          */
      49                 :            :         uint16_t idx_last_set;
      50                 :            :         /**   Number of metrics. */
      51                 :            :         uint16_t cnt_stats;
      52                 :            :         /** Metric data memory block. */
      53                 :            :         struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS];
      54                 :            :         /** Metric data access lock */
      55                 :            :         rte_spinlock_t lock;
      56                 :            : };
      57                 :            : 
      58                 :            : int
      59                 :          3 : rte_metrics_init(int socket_id)
      60                 :            : {
      61                 :            :         struct rte_metrics_data_s *stats;
      62                 :            :         const struct rte_memzone *memzone;
      63                 :            : 
      64         [ +  - ]:          3 :         if (metrics_initialized)
      65                 :            :                 return 0;
      66         [ +  - ]:          3 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
      67                 :            :                 return -E_RTE_SECONDARY;
      68                 :            : 
      69                 :          3 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
      70         [ +  - ]:          3 :         if (memzone != NULL)
      71                 :            :                 return -EEXIST;
      72                 :          3 :         memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME,
      73                 :            :                 sizeof(struct rte_metrics_data_s), socket_id, 0);
      74         [ +  - ]:          3 :         if (memzone == NULL)
      75                 :            :                 return -ENOMEM;
      76                 :          3 :         stats = memzone->addr;
      77                 :            :         memset(stats, 0, sizeof(struct rte_metrics_data_s));
      78                 :            :         rte_spinlock_init(&stats->lock);
      79                 :          3 :         metrics_initialized = 1;
      80                 :          3 :         return 0;
      81                 :            : }
      82                 :            : 
      83                 :            : int
      84                 :          3 : rte_metrics_deinit(void)
      85                 :            : {
      86                 :            :         struct rte_metrics_data_s *stats;
      87                 :            :         const struct rte_memzone *memzone;
      88                 :            :         int ret;
      89                 :            : 
      90         [ +  - ]:          3 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
      91                 :            :                 return -EINVAL;
      92                 :            : 
      93                 :          3 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
      94         [ +  - ]:          3 :         if (memzone == NULL)
      95                 :            :                 return -EIO;
      96                 :            : 
      97                 :          3 :         stats = memzone->addr;
      98                 :            :         memset(stats, 0, sizeof(struct rte_metrics_data_s));
      99                 :            : 
     100                 :          3 :         ret = rte_memzone_free(memzone);
     101         [ +  - ]:          3 :         if (ret == 0)
     102                 :          3 :                 metrics_initialized = 0;
     103                 :            :         return ret;
     104                 :            : }
     105                 :            : 
     106                 :            : int
     107                 :          4 : rte_metrics_reg_name(const char *name)
     108                 :            : {
     109                 :          4 :         const char * const list_names[] = {name};
     110                 :            : 
     111                 :          4 :         return rte_metrics_reg_names(list_names, 1);
     112                 :            : }
     113                 :            : 
     114                 :            : int
     115                 :          9 : rte_metrics_reg_names(const char * const *names, uint16_t cnt_names)
     116                 :            : {
     117                 :            :         struct rte_metrics_meta_s *entry = NULL;
     118                 :            :         struct rte_metrics_data_s *stats;
     119                 :            :         const struct rte_memzone *memzone;
     120                 :            :         uint16_t idx_name;
     121                 :            :         uint16_t idx_base;
     122                 :            : 
     123                 :            :         /* Some sanity checks */
     124         [ +  - ]:          9 :         if (cnt_names < 1 || names == NULL)
     125                 :            :                 return -EINVAL;
     126         [ +  + ]:         33 :         for (idx_name = 0; idx_name < cnt_names; idx_name++)
     127         [ +  + ]:         25 :                 if (names[idx_name] == NULL)
     128                 :            :                         return -EINVAL;
     129                 :            : 
     130                 :          8 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
     131         [ +  + ]:          8 :         if (memzone == NULL)
     132                 :            :                 return -EIO;
     133                 :          5 :         stats = memzone->addr;
     134                 :            : 
     135         [ +  - ]:          5 :         if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS)
     136                 :            :                 return -ENOMEM;
     137                 :            : 
     138                 :          5 :         rte_spinlock_lock(&stats->lock);
     139                 :            : 
     140                 :            :         /* Overwritten later if this is actually first set.. */
     141                 :          5 :         stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats;
     142                 :            : 
     143                 :          5 :         stats->idx_last_set = idx_base = stats->cnt_stats;
     144                 :            : 
     145         [ +  + ]:         21 :         for (idx_name = 0; idx_name < cnt_names; idx_name++) {
     146                 :         16 :                 entry = &stats->metadata[idx_name + stats->cnt_stats];
     147                 :         16 :                 strlcpy(entry->name, names[idx_name], RTE_METRICS_MAX_NAME_LEN);
     148                 :         16 :                 memset(entry->value, 0, sizeof(entry->value));
     149                 :         16 :                 entry->idx_next_stat = idx_name + stats->cnt_stats + 1;
     150                 :            :         }
     151                 :          5 :         entry->idx_next_stat = 0;
     152                 :          5 :         entry->idx_next_set = 0;
     153                 :          5 :         stats->cnt_stats += cnt_names;
     154                 :            : 
     155                 :            :         rte_spinlock_unlock(&stats->lock);
     156                 :            : 
     157                 :          5 :         return idx_base;
     158                 :            : }
     159                 :            : 
     160                 :            : int
     161                 :          6 : rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value)
     162                 :            : {
     163                 :          6 :         return rte_metrics_update_values(port_id, key, &value, 1);
     164                 :            : }
     165                 :            : 
     166                 :            : int
     167                 :         16 : rte_metrics_update_values(int port_id,
     168                 :            :         uint16_t key,
     169                 :            :         const uint64_t *values,
     170                 :            :         uint32_t count)
     171                 :            : {
     172                 :            :         struct rte_metrics_meta_s *entry;
     173                 :            :         struct rte_metrics_data_s *stats;
     174                 :            :         const struct rte_memzone *memzone;
     175                 :            :         uint16_t idx_metric;
     176                 :            :         uint16_t idx_value;
     177                 :            :         uint16_t cnt_setsize;
     178                 :            : 
     179         [ +  + ]:         16 :         if (port_id != RTE_METRICS_GLOBAL &&
     180                 :            :                         (port_id < 0 || port_id >= RTE_MAX_ETHPORTS))
     181                 :            :                 return -EINVAL;
     182                 :            : 
     183         [ +  + ]:         12 :         if (values == NULL)
     184                 :            :                 return -EINVAL;
     185                 :            : 
     186                 :         11 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
     187         [ +  + ]:         11 :         if (memzone == NULL)
     188                 :            :                 return -EIO;
     189                 :          9 :         stats = memzone->addr;
     190                 :            : 
     191                 :          9 :         rte_spinlock_lock(&stats->lock);
     192                 :            : 
     193         [ +  + ]:          9 :         if (key >= stats->cnt_stats) {
     194                 :            :                 rte_spinlock_unlock(&stats->lock);
     195                 :          1 :                 return -EINVAL;
     196                 :            :         }
     197                 :            :         idx_metric = key;
     198                 :            :         cnt_setsize = 1;
     199         [ +  - ]:         19 :         while (idx_metric < stats->cnt_stats) {
     200                 :         19 :                 entry = &stats->metadata[idx_metric];
     201         [ +  + ]:         19 :                 if (entry->idx_next_stat == 0)
     202                 :            :                         break;
     203                 :         11 :                 cnt_setsize++;
     204                 :         11 :                 idx_metric++;
     205                 :            :         }
     206                 :            :         /* Check update does not cross set border */
     207         [ +  + ]:          8 :         if (count > cnt_setsize) {
     208                 :            :                 rte_spinlock_unlock(&stats->lock);
     209                 :          1 :                 return -ERANGE;
     210                 :            :         }
     211                 :            : 
     212         [ +  + ]:          7 :         if (port_id == RTE_METRICS_GLOBAL)
     213         [ +  + ]:         16 :                 for (idx_value = 0; idx_value < count; idx_value++) {
     214                 :         11 :                         idx_metric = key + idx_value;
     215                 :         11 :                         stats->metadata[idx_metric].global_value =
     216                 :         11 :                                 values[idx_value];
     217                 :            :                 }
     218                 :            :         else
     219         [ +  + ]:          9 :                 for (idx_value = 0; idx_value < count; idx_value++) {
     220                 :          7 :                         idx_metric = key + idx_value;
     221                 :          7 :                         stats->metadata[idx_metric].value[port_id] =
     222                 :          7 :                                 values[idx_value];
     223                 :            :                 }
     224                 :            :         rte_spinlock_unlock(&stats->lock);
     225                 :          7 :         return 0;
     226                 :            : }
     227                 :            : 
     228                 :            : int
     229                 :          5 : rte_metrics_get_names(struct rte_metric_name *names,
     230                 :            :         uint16_t capacity)
     231                 :            : {
     232                 :            :         struct rte_metrics_data_s *stats;
     233                 :            :         const struct rte_memzone *memzone;
     234                 :            :         uint16_t idx_name;
     235                 :            :         int return_value;
     236                 :            : 
     237                 :          5 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
     238         [ +  + ]:          5 :         if (memzone == NULL)
     239                 :            :                 return -EIO;
     240                 :            : 
     241                 :          4 :         stats = memzone->addr;
     242                 :          4 :         rte_spinlock_lock(&stats->lock);
     243         [ +  + ]:          4 :         if (names != NULL) {
     244         [ +  + ]:          3 :                 if (capacity < stats->cnt_stats) {
     245                 :          1 :                         return_value = stats->cnt_stats;
     246                 :            :                         rte_spinlock_unlock(&stats->lock);
     247                 :          1 :                         return return_value;
     248                 :            :                 }
     249         [ +  + ]:         14 :                 for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++)
     250                 :         12 :                         strlcpy(names[idx_name].name,
     251                 :            :                                 stats->metadata[idx_name].name,
     252                 :            :                                 RTE_METRICS_MAX_NAME_LEN);
     253                 :            :         }
     254                 :          3 :         return_value = stats->cnt_stats;
     255                 :            :         rte_spinlock_unlock(&stats->lock);
     256                 :          3 :         return return_value;
     257                 :            : }
     258                 :            : 
     259                 :            : int
     260                 :          7 : rte_metrics_get_values(int port_id,
     261                 :            :         struct rte_metric_value *values,
     262                 :            :         uint16_t capacity)
     263                 :            : {
     264                 :            :         struct rte_metrics_meta_s *entry;
     265                 :            :         struct rte_metrics_data_s *stats;
     266                 :            :         const struct rte_memzone *memzone;
     267                 :            :         uint16_t idx_name;
     268                 :            :         int return_value;
     269                 :            : 
     270         [ +  + ]:          7 :         if (port_id != RTE_METRICS_GLOBAL &&
     271                 :            :                         (port_id < 0 || port_id >= RTE_MAX_ETHPORTS))
     272                 :            :                 return -EINVAL;
     273                 :            : 
     274                 :          5 :         memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME);
     275         [ +  + ]:          5 :         if (memzone == NULL)
     276                 :            :                 return -EIO;
     277                 :            : 
     278                 :          4 :         stats = memzone->addr;
     279                 :          4 :         rte_spinlock_lock(&stats->lock);
     280                 :            : 
     281         [ +  + ]:          4 :         if (values != NULL) {
     282         [ +  + ]:          3 :                 if (capacity < stats->cnt_stats) {
     283                 :          1 :                         return_value = stats->cnt_stats;
     284                 :            :                         rte_spinlock_unlock(&stats->lock);
     285                 :          1 :                         return return_value;
     286                 :            :                 }
     287         [ +  - ]:          2 :                 if (port_id == RTE_METRICS_GLOBAL)
     288                 :            :                         for (idx_name = 0;
     289         [ +  + ]:         14 :                                         idx_name < stats->cnt_stats;
     290                 :         12 :                                         idx_name++) {
     291                 :         12 :                                 entry = &stats->metadata[idx_name];
     292                 :         12 :                                 values[idx_name].key = idx_name;
     293                 :         12 :                                 values[idx_name].value = entry->global_value;
     294                 :            :                         }
     295                 :            :                 else
     296                 :            :                         for (idx_name = 0;
     297         [ #  # ]:          0 :                                         idx_name < stats->cnt_stats;
     298                 :          0 :                                         idx_name++) {
     299                 :          0 :                                 entry = &stats->metadata[idx_name];
     300                 :          0 :                                 values[idx_name].key = idx_name;
     301                 :          0 :                                 values[idx_name].value = entry->value[port_id];
     302                 :            :                         }
     303                 :            :         }
     304                 :          3 :         return_value = stats->cnt_stats;
     305                 :            :         rte_spinlock_unlock(&stats->lock);
     306                 :          3 :         return return_value;
     307                 :            : }

Generated by: LCOV version 1.14