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