1*5630257fSFerruh Yigit.. SPDX-License-Identifier: BSD-3-Clause 2*5630257fSFerruh Yigit Copyright(c) 2017 Intel Corporation. 3349950ddSRemy Horton 4349950ddSRemy Horton.. _Metrics_Library: 5349950ddSRemy Horton 6349950ddSRemy HortonMetrics Library 7349950ddSRemy Horton=============== 8349950ddSRemy Horton 9349950ddSRemy HortonThe Metrics library implements a mechanism by which *producers* can 10349950ddSRemy Hortonpublish numeric information for later querying by *consumers*. In 11349950ddSRemy Hortonpractice producers will typically be other libraries or primary 12349950ddSRemy Hortonprocesses, whereas consumers will typically be applications. 13349950ddSRemy Horton 14349950ddSRemy HortonMetrics themselves are statistics that are not generated by PMDs. Metric 15349950ddSRemy Hortoninformation is populated using a push model, where producers update the 16349950ddSRemy Hortonvalues contained within the metric library by calling an update function 17349950ddSRemy Hortonon the relevant metrics. Consumers receive metric information by querying 18349950ddSRemy Hortonthe central metric data, which is held in shared memory. 19349950ddSRemy Horton 20349950ddSRemy HortonFor each metric, a separate value is maintained for each port id, and 21349950ddSRemy Hortonwhen publishing metric values the producers need to specify which port is 22349950ddSRemy Hortonbeing updated. In addition there is a special id ``RTE_METRICS_GLOBAL`` 23349950ddSRemy Hortonthat is intended for global statistics that are not associated with any 24349950ddSRemy Hortonindividual device. Since the metrics library is self-contained, the only 25349950ddSRemy Hortonrestriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS`` 26349950ddSRemy Horton- there is no requirement for the ports to actually exist. 27349950ddSRemy Horton 28349950ddSRemy HortonInitialising the library 29349950ddSRemy Horton------------------------ 30349950ddSRemy Horton 31349950ddSRemy HortonBefore the library can be used, it has to be initialized by calling 32349950ddSRemy Horton``rte_metrics_init()`` which sets up the metric store in shared memory. 33349950ddSRemy HortonThis is where producers will publish metric information to, and where 34349950ddSRemy Hortonconsumers will query it from. 35349950ddSRemy Horton 36349950ddSRemy Horton.. code-block:: c 37349950ddSRemy Horton 38349950ddSRemy Horton rte_metrics_init(rte_socket_id()); 39349950ddSRemy Horton 40349950ddSRemy HortonThis function **must** be called from a primary process, but otherwise 41349950ddSRemy Hortonproducers and consumers can be in either primary or secondary processes. 42349950ddSRemy Horton 43349950ddSRemy HortonRegistering metrics 44349950ddSRemy Horton------------------- 45349950ddSRemy Horton 46349950ddSRemy HortonMetrics must first be *registered*, which is the way producers declare 47349950ddSRemy Hortonthe names of the metrics they will be publishing. Registration can either 48349950ddSRemy Hortonbe done individually, or a set of metrics can be registered as a group. 49349950ddSRemy HortonIndividual registration is done using ``rte_metrics_reg_name()``: 50349950ddSRemy Horton 51349950ddSRemy Horton.. code-block:: c 52349950ddSRemy Horton 53349950ddSRemy Horton id_1 = rte_metrics_reg_name("mean_bits_in"); 54349950ddSRemy Horton id_2 = rte_metrics_reg_name("mean_bits_out"); 55349950ddSRemy Horton id_3 = rte_metrics_reg_name("peak_bits_in"); 56349950ddSRemy Horton id_4 = rte_metrics_reg_name("peak_bits_out"); 57349950ddSRemy Horton 58349950ddSRemy Hortonor alternatively, a set of metrics can be registered together using 59349950ddSRemy Horton``rte_metrics_reg_names()``: 60349950ddSRemy Horton 61349950ddSRemy Horton.. code-block:: c 62349950ddSRemy Horton 63349950ddSRemy Horton const char * const names[] = { 64349950ddSRemy Horton "mean_bits_in", "mean_bits_out", 65349950ddSRemy Horton "peak_bits_in", "peak_bits_out", 66349950ddSRemy Horton }; 67349950ddSRemy Horton id_set = rte_metrics_reg_names(&names[0], 4); 68349950ddSRemy Horton 69349950ddSRemy HortonIf the return value is negative, it means registration failed. Otherwise 70349950ddSRemy Hortonthe return value is the *key* for the metric, which is used when updating 71349950ddSRemy Hortonvalues. A table mapping together these key values and the metrics' names 72349950ddSRemy Hortoncan be obtained using ``rte_metrics_get_names()``. 73349950ddSRemy Horton 74349950ddSRemy HortonUpdating metric values 75349950ddSRemy Horton---------------------- 76349950ddSRemy Horton 77349950ddSRemy HortonOnce registered, producers can update the metric for a given port using 78349950ddSRemy Hortonthe ``rte_metrics_update_value()`` function. This uses the metric key 79349950ddSRemy Hortonthat is returned when registering the metric, and can also be looked up 80349950ddSRemy Hortonusing ``rte_metrics_get_names()``. 81349950ddSRemy Horton 82349950ddSRemy Horton.. code-block:: c 83349950ddSRemy Horton 84349950ddSRemy Horton rte_metrics_update_value(port_id, id_1, values[0]); 85349950ddSRemy Horton rte_metrics_update_value(port_id, id_2, values[1]); 86349950ddSRemy Horton rte_metrics_update_value(port_id, id_3, values[2]); 87349950ddSRemy Horton rte_metrics_update_value(port_id, id_4, values[3]); 88349950ddSRemy Horton 89349950ddSRemy Hortonif metrics were registered as a single set, they can either be updated 90349950ddSRemy Hortonindividually using ``rte_metrics_update_value()``, or updated together 91349950ddSRemy Hortonusing the ``rte_metrics_update_values()`` function: 92349950ddSRemy Horton 93349950ddSRemy Horton.. code-block:: c 94349950ddSRemy Horton 95349950ddSRemy Horton rte_metrics_update_value(port_id, id_set, values[0]); 96349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 1, values[1]); 97349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 2, values[2]); 98349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 3, values[3]); 99349950ddSRemy Horton 100349950ddSRemy Horton rte_metrics_update_values(port_id, id_set, values, 4); 101349950ddSRemy Horton 102349950ddSRemy HortonNote that ``rte_metrics_update_values()`` cannot be used to update 103349950ddSRemy Hortonmetric values from *multiple* *sets*, as there is no guarantee two 104349950ddSRemy Hortonsets registered one after the other have contiguous id values. 105349950ddSRemy Horton 106349950ddSRemy HortonQuerying metrics 107349950ddSRemy Horton---------------- 108349950ddSRemy Horton 109349950ddSRemy HortonConsumers can obtain metric values by querying the metrics library using 110349950ddSRemy Hortonthe ``rte_metrics_get_values()`` function that return an array of 111349950ddSRemy Horton``struct rte_metric_value``. Each entry within this array contains a metric 112349950ddSRemy Hortonvalue and its associated key. A key-name mapping can be obtained using the 113349950ddSRemy Horton``rte_metrics_get_names()`` function that returns an array of 114349950ddSRemy Horton``struct rte_metric_name`` that is indexed by the key. The following will 115349950ddSRemy Hortonprint out all metrics for a given port: 116349950ddSRemy Horton 117349950ddSRemy Horton.. code-block:: c 118349950ddSRemy Horton 119349950ddSRemy Horton void print_metrics() { 120c17c27e8SYong Wang struct rte_metric_value *metrics; 121349950ddSRemy Horton struct rte_metric_name *names; 122349950ddSRemy Horton int len; 123349950ddSRemy Horton 124349950ddSRemy Horton len = rte_metrics_get_names(NULL, 0); 125349950ddSRemy Horton if (len < 0) { 126349950ddSRemy Horton printf("Cannot get metrics count\n"); 127349950ddSRemy Horton return; 128349950ddSRemy Horton } 129349950ddSRemy Horton if (len == 0) { 130349950ddSRemy Horton printf("No metrics to display (none have been registered)\n"); 131349950ddSRemy Horton return; 132349950ddSRemy Horton } 133349950ddSRemy Horton metrics = malloc(sizeof(struct rte_metric_value) * len); 134349950ddSRemy Horton names = malloc(sizeof(struct rte_metric_name) * len); 135349950ddSRemy Horton if (metrics == NULL || names == NULL) { 136349950ddSRemy Horton printf("Cannot allocate memory\n"); 137349950ddSRemy Horton free(metrics); 138349950ddSRemy Horton free(names); 139349950ddSRemy Horton return; 140349950ddSRemy Horton } 141349950ddSRemy Horton ret = rte_metrics_get_values(port_id, metrics, len); 142349950ddSRemy Horton if (ret < 0 || ret > len) { 143349950ddSRemy Horton printf("Cannot get metrics values\n"); 144349950ddSRemy Horton free(metrics); 145349950ddSRemy Horton free(names); 146349950ddSRemy Horton return; 147349950ddSRemy Horton } 148349950ddSRemy Horton printf("Metrics for port %i:\n", port_id); 149349950ddSRemy Horton for (i = 0; i < len; i++) 150349950ddSRemy Horton printf(" %s: %"PRIu64"\n", 151349950ddSRemy Horton names[metrics[i].key].name, metrics[i].value); 152349950ddSRemy Horton free(metrics); 153349950ddSRemy Horton free(names); 154349950ddSRemy Horton } 1552ad7ba9aSRemy Horton 1562ad7ba9aSRemy Horton 1572ad7ba9aSRemy HortonBit-rate statistics library 1582ad7ba9aSRemy Horton--------------------------- 1592ad7ba9aSRemy Horton 1602ad7ba9aSRemy HortonThe bit-rate library calculates the exponentially-weighted moving 1612ad7ba9aSRemy Hortonaverage and peak bit-rates for each active port (i.e. network device). 1622ad7ba9aSRemy HortonThese statistics are reported via the metrics library using the 1632ad7ba9aSRemy Hortonfollowing names: 1642ad7ba9aSRemy Horton 1652ad7ba9aSRemy Horton - ``mean_bits_in``: Average inbound bit-rate 1662ad7ba9aSRemy Horton - ``mean_bits_out``: Average outbound bit-rate 1672ad7ba9aSRemy Horton - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed) 1682ad7ba9aSRemy Horton - ``ewma_bits_out``: Average outbound bit-rate (EWMA smoothed) 1692ad7ba9aSRemy Horton - ``peak_bits_in``: Peak inbound bit-rate 1702ad7ba9aSRemy Horton - ``peak_bits_out``: Peak outbound bit-rate 1712ad7ba9aSRemy Horton 1722ad7ba9aSRemy HortonOnce initialised and clocked at the appropriate frequency, these 1732ad7ba9aSRemy Hortonstatistics can be obtained by querying the metrics library. 1742ad7ba9aSRemy Horton 1752ad7ba9aSRemy HortonInitialization 1762ad7ba9aSRemy Horton~~~~~~~~~~~~~~ 1772ad7ba9aSRemy Horton 1782ad7ba9aSRemy HortonBefore the library can be used, it has to be initialised by calling 1792ad7ba9aSRemy Horton``rte_stats_bitrate_create()``, which will return a bit-rate 1802ad7ba9aSRemy Hortoncalculation object. Since the bit-rate library uses the metrics library 1812ad7ba9aSRemy Hortonto report the calculated statistics, the bit-rate library then needs to 1822ad7ba9aSRemy Hortonregister the calculated statistics with the metrics library. This is 1832ad7ba9aSRemy Hortondone using the helper function ``rte_stats_bitrate_reg()``. 1842ad7ba9aSRemy Horton 1852ad7ba9aSRemy Horton.. code-block:: c 1862ad7ba9aSRemy Horton 1872ad7ba9aSRemy Horton struct rte_stats_bitrates *bitrate_data; 1882ad7ba9aSRemy Horton 1892ad7ba9aSRemy Horton bitrate_data = rte_stats_bitrate_create(); 1902ad7ba9aSRemy Horton if (bitrate_data == NULL) 1912ad7ba9aSRemy Horton rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n"); 1922ad7ba9aSRemy Horton rte_stats_bitrate_reg(bitrate_data); 1932ad7ba9aSRemy Horton 1942ad7ba9aSRemy HortonControlling the sampling rate 1952ad7ba9aSRemy Horton~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1962ad7ba9aSRemy Horton 1972ad7ba9aSRemy HortonSince the library works by periodic sampling but does not use an 1982ad7ba9aSRemy Hortoninternal thread, the application has to periodically call 1992ad7ba9aSRemy Horton``rte_stats_bitrate_calc()``. The frequency at which this function 2002ad7ba9aSRemy Hortonis called should be the intended sampling rate required for the 2012ad7ba9aSRemy Hortoncalculated statistics. For instance if per-second statistics are 2022ad7ba9aSRemy Hortondesired, this function should be called once a second. 2032ad7ba9aSRemy Horton 2042ad7ba9aSRemy Horton.. code-block:: c 2052ad7ba9aSRemy Horton 2062ad7ba9aSRemy Horton tics_datum = rte_rdtsc(); 2072ad7ba9aSRemy Horton tics_per_1sec = rte_get_timer_hz(); 2082ad7ba9aSRemy Horton 2092ad7ba9aSRemy Horton while( 1 ) { 2102ad7ba9aSRemy Horton /* ... */ 2112ad7ba9aSRemy Horton tics_current = rte_rdtsc(); 2122ad7ba9aSRemy Horton if (tics_current - tics_datum >= tics_per_1sec) { 2132ad7ba9aSRemy Horton /* Periodic bitrate calculation */ 2142ad7ba9aSRemy Horton for (idx_port = 0; idx_port < cnt_ports; idx_port++) 2152ad7ba9aSRemy Horton rte_stats_bitrate_calc(bitrate_data, idx_port); 2162ad7ba9aSRemy Horton tics_datum = tics_current; 2172ad7ba9aSRemy Horton } 2182ad7ba9aSRemy Horton /* ... */ 2192ad7ba9aSRemy Horton } 2205cd3cac9SReshma Pattan 2215cd3cac9SReshma Pattan 2225cd3cac9SReshma PattanLatency statistics library 2235cd3cac9SReshma Pattan-------------------------- 2245cd3cac9SReshma Pattan 2255cd3cac9SReshma PattanThe latency statistics library calculates the latency of packet 2265cd3cac9SReshma Pattanprocessing by a DPDK application, reporting the minimum, average, 2275cd3cac9SReshma Pattanand maximum nano-seconds that packet processing takes, as well as 2285cd3cac9SReshma Pattanthe jitter in processing delay. These statistics are then reported 2295cd3cac9SReshma Pattanvia the metrics library using the following names: 2305cd3cac9SReshma Pattan 2315cd3cac9SReshma Pattan - ``min_latency_ns``: Minimum processing latency (nano-seconds) 2325cd3cac9SReshma Pattan - ``avg_latency_ns``: Average processing latency (nano-seconds) 2335cd3cac9SReshma Pattan - ``mac_latency_ns``: Maximum processing latency (nano-seconds) 2345cd3cac9SReshma Pattan - ``jitter_ns``: Variance in processing latency (nano-seconds) 2355cd3cac9SReshma Pattan 2365cd3cac9SReshma PattanOnce initialised and clocked at the appropriate frequency, these 2375cd3cac9SReshma Pattanstatistics can be obtained by querying the metrics library. 2385cd3cac9SReshma Pattan 2395cd3cac9SReshma PattanInitialization 2405cd3cac9SReshma Pattan~~~~~~~~~~~~~~ 2415cd3cac9SReshma Pattan 2425cd3cac9SReshma PattanBefore the library can be used, it has to be initialised by calling 2435cd3cac9SReshma Pattan``rte_latencystats_init()``. 2445cd3cac9SReshma Pattan 2455cd3cac9SReshma Pattan.. code-block:: c 2465cd3cac9SReshma Pattan 2475cd3cac9SReshma Pattan lcoreid_t latencystats_lcore_id = -1; 2485cd3cac9SReshma Pattan 2495cd3cac9SReshma Pattan int ret = rte_latencystats_init(1, NULL); 2505cd3cac9SReshma Pattan if (ret) 2515cd3cac9SReshma Pattan rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n"); 2525cd3cac9SReshma Pattan 2535cd3cac9SReshma Pattan 2545cd3cac9SReshma PattanTriggering statistic updates 2555cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2565cd3cac9SReshma Pattan 2575cd3cac9SReshma PattanThe ``rte_latencystats_update()`` function needs to be called 2585cd3cac9SReshma Pattanperiodically so that latency statistics can be updated. 2595cd3cac9SReshma Pattan 2605cd3cac9SReshma Pattan.. code-block:: c 2615cd3cac9SReshma Pattan 2625cd3cac9SReshma Pattan if (latencystats_lcore_id == rte_lcore_id()) 2635cd3cac9SReshma Pattan rte_latencystats_update(); 2645cd3cac9SReshma Pattan 2655cd3cac9SReshma PattanLibrary shutdown 2665cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~ 2675cd3cac9SReshma Pattan 2685cd3cac9SReshma PattanWhen finished, ``rte_latencystats_uninit()`` needs to be called to 2695cd3cac9SReshma Pattande-initialise the latency library. 2705cd3cac9SReshma Pattan 2715cd3cac9SReshma Pattan.. code-block:: c 2725cd3cac9SReshma Pattan 2735cd3cac9SReshma Pattan rte_latencystats_uninit(); 274