#include #include /** * @brief Round up a value to the nearest multiple of 8. * Note: This function is not thread-safe. * * @param value The value to round up. * @return The rounded up value. */ uint16_t round_up_to_multiple_of_8(uint16_t value) { return (value + 7) & ~7; } /** * @brief Create and initialize a new SC metrics handle. * * This function allocates and initializes a new SC metrics handle with the * specified capacity. It ensures that the capacity is rounded up to the * nearest multiple of 8. The handle includes memory for storing metrics * values based on the rounded capacity. * * @param capacity The number of metrics values that the handle should be able * to store. This value is rounded up to the nearest multiple * of 8. * * @return Pointer to the newly created SC metrics handle, or NULL if memory * allocation fails or if an invalid capacity is provided (0). */ struct sc_metrics_handle * sc_metrics_handle_create(uint16_t capacity) { if (capacity == 0) { MR_ERROR("Error allocating stats handle: invalid input parameters."); return NULL; } else if (capacity > SC_METRICS_MAX_CAPACITY) { MR_ERROR("Error allocating stats handle: capacity exceeds maximum limit."); return NULL; } struct sc_metrics_handle * metrics_handle = (struct sc_metrics_handle *)ZMALLOC(sizeof(struct sc_metrics_handle)); MR_VERIFY_MALLOC(metrics_handle); metrics_handle->capacity = round_up_to_multiple_of_8(capacity); metrics_handle->values = (volatile uint64_t *)ZMALLOC(sizeof(uint64_t) * metrics_handle->capacity); MR_VERIFY_MALLOC(metrics_handle->values); return metrics_handle; } /** * @brief Delete and free an SC metrics handle. * * This function deallocates the memory associated with an SC metrics handle, * including its values array. After freeing the memory, it sets the pointers * to NULL to avoid dangling pointers. * * @param metrics_handle Pointer to the SC metrics handle to be deleted. * If this pointer is NULL, no action is taken. * * @return Return value indicating success or failure: * - RT_SUCCESS (0) if the handle is successfully deleted. * - RT_ERR (-1) if the handle is NULL and cannot be deleted. */ int sc_metrics_handle_delete(struct sc_metrics_handle * metrics_handle) { if (metrics_handle == NULL) { MR_ERROR("Error deleting stats handle: invalid input parameters."); return RT_ERR; } FREE((void *)metrics_handle->values); metrics_handle->values = NULL; FREE((void *)metrics_handle); return RT_SUCCESS; } /** * @brief Set the values for the SC metrics handle. * * This function copies an array of metric values into the SC metrics handle. * It ensures that the provided capacity does not exceed the handle's allocated * capacity. The function uses `rte_memcpy` to perform the copy operation. * * @param metrics_handle Pointer to the SC metrics handle where the values will * be set. This handle must be valid and initialized. * @param stats Array of metric values to be copied into the handle. * @param capacity Number of metric values to copy from the `stats` array. * This should not exceed the handle's allocated capacity. * * @return Return value indicating success: * - RT_SUCCESS (0) if the values are successfully copied. */ int sc_metrics_values_set(struct sc_metrics_handle * metrics_handle, uint64_t values[], uint16_t capacity) { assert(metrics_handle != NULL); assert(metrics_handle->values != NULL); assert(capacity <= metrics_handle->capacity); rte_memcpy((void *)metrics_handle->values, values, sizeof(uint64_t) * capacity); return RT_SUCCESS; } /** * @brief Get the values from the SC metrics handle. * * This function copies the metric values from the SC metrics handle into the * provided array. It ensures that the provided capacity does not exceed the * handle's allocated capacity. The function uses `rte_memcpy` to perform the * copy operation. * * @param metrics_handle Pointer to the SC metrics handle from which the values * will be retrieved. This handle must be valid and initialized. * @param values Array where the metric values will be copied. * @param capacity Number of metric values to copy into the `values` array. * This should not exceed the handle's allocated capacity. * * @return Return value indicating success: * - RT_SUCCESS (0) if the values are successfully copied. */ int sc_metrics_values_get(struct sc_metrics_handle * metrics_handle, uint64_t values[], uint16_t capacity) { assert(metrics_handle != NULL); assert(metrics_handle->values != NULL); assert(capacity <= metrics_handle->capacity); rte_memcpy(values, (void *)metrics_handle->values, sizeof(uint64_t) * capacity); return RT_SUCCESS; } /** * @brief Get a single value from the SC metrics handle. * * This function retrieves a single metric value from the SC metrics handle at * the specified key. The function ensures that the key is within the handle's * allocated capacity. The value is directly read from the handle's values array * at the specified key. * * @param metrics_handle Pointer to the SC metrics handle from which the value * will be retrieved. This handle must be valid and initialized. * @param value Pointer to the variable where the metric value will be stored. * @param key The key from which to retrieve the metric value. This key must be * within the handle's allocated capacity. * * @return Return value indicating success: * - RT_SUCCESS (0) if the value is successfully retrieved. */ int sc_metrics_value_get(struct sc_metrics_handle * metrics_handle, uint64_t * value, uint16_t key) { assert(value != NULL); assert(metrics_handle != NULL); assert(metrics_handle->values != NULL); assert(key < metrics_handle->capacity); *value = metrics_handle->values[key]; return RT_SUCCESS; } /** * @brief Reset all values in the SC metrics handle to zero. * * This function sets all values in the SC metrics handle to zero. It uses * `memset` to overwrite the entire allocated space for metric values with zeros. * This operation effectively resets the metrics handle to its initial state. * * @param metrics_handle Pointer to the SC metrics handle to be reset. * This handle must be valid and initialized. * * @return Return value indicating success: * - RT_SUCCESS (0) if the values are successfully reset. */ int sc_metrics_values_reset(struct sc_metrics_handle * metrics_handle) { assert(metrics_handle != NULL); assert(metrics_handle->values != NULL); memset((void *)metrics_handle->values, 0, sizeof(uint64_t) * metrics_handle->capacity); return RT_SUCCESS; } /** * @brief Accumulate values into the SC metrics handle. * * This function adds values from the `inc_values` array to the existing values * in the SC metrics handle. The accumulation is performed element-wise for * the specified `capacity`. The function ensures that the provided capacity * does not exceed the handle's allocated capacity. * * @param metrics_handle Pointer to the SC metrics handle where the values * will be accumulated. This handle must be valid and * initialized. * @param inc_values Array of values to be added to the current values in * the handle. * @param capacity Number of values to accumulate. This should not exceed * the handle's allocated capacity. * * @return Return value indicating success: * - RT_SUCCESS (0) if the values are successfully accumulated. */ int sc_metrics_accumulate(struct sc_metrics_handle * metrics_handle, uint64_t inc_values[], uint16_t capacity) { assert(metrics_handle != NULL); assert(metrics_handle->values != NULL); assert(capacity <= metrics_handle->capacity); volatile uint64_t * values = metrics_handle->values; for (uint16_t i = 0; i < capacity; i++) { values[i] += inc_values[i]; } return RT_SUCCESS; }