xref: /dpdk/doc/guides/prog_guide/metrics_lib.rst (revision 5cd3cac9ed228f35e10fc322483f10897ae44c86)
1349950ddSRemy Horton..  BSD LICENSE
2349950ddSRemy Horton    Copyright(c) 2017 Intel Corporation. All rights reserved.
3349950ddSRemy Horton    All rights reserved.
4349950ddSRemy Horton
5349950ddSRemy Horton    Redistribution and use in source and binary forms, with or without
6349950ddSRemy Horton    modification, are permitted provided that the following conditions
7349950ddSRemy Horton    are met:
8349950ddSRemy Horton
9349950ddSRemy Horton    * Redistributions of source code must retain the above copyright
10349950ddSRemy Horton    notice, this list of conditions and the following disclaimer.
11349950ddSRemy Horton    * Redistributions in binary form must reproduce the above copyright
12349950ddSRemy Horton    notice, this list of conditions and the following disclaimer in
13349950ddSRemy Horton    the documentation and/or other materials provided with the
14349950ddSRemy Horton    distribution.
15349950ddSRemy Horton    * Neither the name of Intel Corporation nor the names of its
16349950ddSRemy Horton    contributors may be used to endorse or promote products derived
17349950ddSRemy Horton    from this software without specific prior written permission.
18349950ddSRemy Horton
19349950ddSRemy Horton    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20349950ddSRemy Horton    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21349950ddSRemy Horton    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22349950ddSRemy Horton    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23349950ddSRemy Horton    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24349950ddSRemy Horton    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25349950ddSRemy Horton    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26349950ddSRemy Horton    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27349950ddSRemy Horton    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28349950ddSRemy Horton    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29349950ddSRemy Horton    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30349950ddSRemy Horton
31349950ddSRemy Horton.. _Metrics_Library:
32349950ddSRemy Horton
33349950ddSRemy HortonMetrics Library
34349950ddSRemy Horton===============
35349950ddSRemy Horton
36349950ddSRemy HortonThe Metrics library implements a mechanism by which *producers* can
37349950ddSRemy Hortonpublish numeric information for later querying by *consumers*. In
38349950ddSRemy Hortonpractice producers will typically be other libraries or primary
39349950ddSRemy Hortonprocesses, whereas consumers will typically be applications.
40349950ddSRemy Horton
41349950ddSRemy HortonMetrics themselves are statistics that are not generated by PMDs. Metric
42349950ddSRemy Hortoninformation is populated using a push model, where producers update the
43349950ddSRemy Hortonvalues contained within the metric library by calling an update function
44349950ddSRemy Hortonon the relevant metrics. Consumers receive metric information by querying
45349950ddSRemy Hortonthe central metric data, which is held in shared memory.
46349950ddSRemy Horton
47349950ddSRemy HortonFor each metric, a separate value is maintained for each port id, and
48349950ddSRemy Hortonwhen publishing metric values the producers need to specify which port is
49349950ddSRemy Hortonbeing updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
50349950ddSRemy Hortonthat is intended for global statistics that are not associated with any
51349950ddSRemy Hortonindividual device. Since the metrics library is self-contained, the only
52349950ddSRemy Hortonrestriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
53349950ddSRemy Horton- there is no requirement for the ports to actually exist.
54349950ddSRemy Horton
55349950ddSRemy HortonInitialising the library
56349950ddSRemy Horton------------------------
57349950ddSRemy Horton
58349950ddSRemy HortonBefore the library can be used, it has to be initialized by calling
59349950ddSRemy Horton``rte_metrics_init()`` which sets up the metric store in shared memory.
60349950ddSRemy HortonThis is where producers will publish metric information to, and where
61349950ddSRemy Hortonconsumers will query it from.
62349950ddSRemy Horton
63349950ddSRemy Horton.. code-block:: c
64349950ddSRemy Horton
65349950ddSRemy Horton    rte_metrics_init(rte_socket_id());
66349950ddSRemy Horton
67349950ddSRemy HortonThis function **must** be called from a primary process, but otherwise
68349950ddSRemy Hortonproducers and consumers can be in either primary or secondary processes.
69349950ddSRemy Horton
70349950ddSRemy HortonRegistering metrics
71349950ddSRemy Horton-------------------
72349950ddSRemy Horton
73349950ddSRemy HortonMetrics must first be *registered*, which is the way producers declare
74349950ddSRemy Hortonthe names of the metrics they will be publishing. Registration can either
75349950ddSRemy Hortonbe done individually, or a set of metrics can be registered as a group.
76349950ddSRemy HortonIndividual registration is done using ``rte_metrics_reg_name()``:
77349950ddSRemy Horton
78349950ddSRemy Horton.. code-block:: c
79349950ddSRemy Horton
80349950ddSRemy Horton    id_1 = rte_metrics_reg_name("mean_bits_in");
81349950ddSRemy Horton    id_2 = rte_metrics_reg_name("mean_bits_out");
82349950ddSRemy Horton    id_3 = rte_metrics_reg_name("peak_bits_in");
83349950ddSRemy Horton    id_4 = rte_metrics_reg_name("peak_bits_out");
84349950ddSRemy Horton
85349950ddSRemy Hortonor alternatively, a set of metrics can be registered together using
86349950ddSRemy Horton``rte_metrics_reg_names()``:
87349950ddSRemy Horton
88349950ddSRemy Horton.. code-block:: c
89349950ddSRemy Horton
90349950ddSRemy Horton    const char * const names[] = {
91349950ddSRemy Horton        "mean_bits_in", "mean_bits_out",
92349950ddSRemy Horton        "peak_bits_in", "peak_bits_out",
93349950ddSRemy Horton    };
94349950ddSRemy Horton    id_set = rte_metrics_reg_names(&names[0], 4);
95349950ddSRemy Horton
96349950ddSRemy HortonIf the return value is negative, it means registration failed. Otherwise
97349950ddSRemy Hortonthe return value is the *key* for the metric, which is used when updating
98349950ddSRemy Hortonvalues. A table mapping together these key values and the metrics' names
99349950ddSRemy Hortoncan be obtained using ``rte_metrics_get_names()``.
100349950ddSRemy Horton
101349950ddSRemy HortonUpdating metric values
102349950ddSRemy Horton----------------------
103349950ddSRemy Horton
104349950ddSRemy HortonOnce registered, producers can update the metric for a given port using
105349950ddSRemy Hortonthe ``rte_metrics_update_value()`` function. This uses the metric key
106349950ddSRemy Hortonthat is returned when registering the metric, and can also be looked up
107349950ddSRemy Hortonusing ``rte_metrics_get_names()``.
108349950ddSRemy Horton
109349950ddSRemy Horton.. code-block:: c
110349950ddSRemy Horton
111349950ddSRemy Horton    rte_metrics_update_value(port_id, id_1, values[0]);
112349950ddSRemy Horton    rte_metrics_update_value(port_id, id_2, values[1]);
113349950ddSRemy Horton    rte_metrics_update_value(port_id, id_3, values[2]);
114349950ddSRemy Horton    rte_metrics_update_value(port_id, id_4, values[3]);
115349950ddSRemy Horton
116349950ddSRemy Hortonif metrics were registered as a single set, they can either be updated
117349950ddSRemy Hortonindividually using ``rte_metrics_update_value()``, or updated together
118349950ddSRemy Hortonusing the ``rte_metrics_update_values()`` function:
119349950ddSRemy Horton
120349950ddSRemy Horton.. code-block:: c
121349950ddSRemy Horton
122349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set, values[0]);
123349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 1, values[1]);
124349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 2, values[2]);
125349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 3, values[3]);
126349950ddSRemy Horton
127349950ddSRemy Horton    rte_metrics_update_values(port_id, id_set, values, 4);
128349950ddSRemy Horton
129349950ddSRemy HortonNote that ``rte_metrics_update_values()`` cannot be used to update
130349950ddSRemy Hortonmetric values from *multiple* *sets*, as there is no guarantee two
131349950ddSRemy Hortonsets registered one after the other have contiguous id values.
132349950ddSRemy Horton
133349950ddSRemy HortonQuerying metrics
134349950ddSRemy Horton----------------
135349950ddSRemy Horton
136349950ddSRemy HortonConsumers can obtain metric values by querying the metrics library using
137349950ddSRemy Hortonthe ``rte_metrics_get_values()`` function that return an array of
138349950ddSRemy Horton``struct rte_metric_value``. Each entry within this array contains a metric
139349950ddSRemy Hortonvalue and its associated key. A key-name mapping can be obtained using the
140349950ddSRemy Horton``rte_metrics_get_names()`` function that returns an array of
141349950ddSRemy Horton``struct rte_metric_name`` that is indexed by the key. The following will
142349950ddSRemy Hortonprint out all metrics for a given port:
143349950ddSRemy Horton
144349950ddSRemy Horton.. code-block:: c
145349950ddSRemy Horton
146349950ddSRemy Horton    void print_metrics() {
147349950ddSRemy Horton        struct rte_metric_name *names;
148349950ddSRemy Horton        int len;
149349950ddSRemy Horton
150349950ddSRemy Horton        len = rte_metrics_get_names(NULL, 0);
151349950ddSRemy Horton        if (len < 0) {
152349950ddSRemy Horton            printf("Cannot get metrics count\n");
153349950ddSRemy Horton            return;
154349950ddSRemy Horton        }
155349950ddSRemy Horton        if (len == 0) {
156349950ddSRemy Horton            printf("No metrics to display (none have been registered)\n");
157349950ddSRemy Horton            return;
158349950ddSRemy Horton        }
159349950ddSRemy Horton        metrics = malloc(sizeof(struct rte_metric_value) * len);
160349950ddSRemy Horton        names =  malloc(sizeof(struct rte_metric_name) * len);
161349950ddSRemy Horton        if (metrics == NULL || names == NULL) {
162349950ddSRemy Horton            printf("Cannot allocate memory\n");
163349950ddSRemy Horton            free(metrics);
164349950ddSRemy Horton            free(names);
165349950ddSRemy Horton            return;
166349950ddSRemy Horton        }
167349950ddSRemy Horton        ret = rte_metrics_get_values(port_id, metrics, len);
168349950ddSRemy Horton        if (ret < 0 || ret > len) {
169349950ddSRemy Horton            printf("Cannot get metrics values\n");
170349950ddSRemy Horton            free(metrics);
171349950ddSRemy Horton            free(names);
172349950ddSRemy Horton            return;
173349950ddSRemy Horton        }
174349950ddSRemy Horton        printf("Metrics for port %i:\n", port_id);
175349950ddSRemy Horton        for (i = 0; i < len; i++)
176349950ddSRemy Horton            printf("  %s: %"PRIu64"\n",
177349950ddSRemy Horton                names[metrics[i].key].name, metrics[i].value);
178349950ddSRemy Horton        free(metrics);
179349950ddSRemy Horton        free(names);
180349950ddSRemy Horton    }
1812ad7ba9aSRemy Horton
1822ad7ba9aSRemy Horton
1832ad7ba9aSRemy HortonBit-rate statistics library
1842ad7ba9aSRemy Horton---------------------------
1852ad7ba9aSRemy Horton
1862ad7ba9aSRemy HortonThe bit-rate library calculates the exponentially-weighted moving
1872ad7ba9aSRemy Hortonaverage and peak bit-rates for each active port (i.e. network device).
1882ad7ba9aSRemy HortonThese statistics are reported via the metrics library using the
1892ad7ba9aSRemy Hortonfollowing names:
1902ad7ba9aSRemy Horton
1912ad7ba9aSRemy Horton    - ``mean_bits_in``: Average inbound bit-rate
1922ad7ba9aSRemy Horton    - ``mean_bits_out``:  Average outbound bit-rate
1932ad7ba9aSRemy Horton    - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed)
1942ad7ba9aSRemy Horton    - ``ewma_bits_out``:  Average outbound bit-rate (EWMA smoothed)
1952ad7ba9aSRemy Horton    - ``peak_bits_in``:  Peak inbound bit-rate
1962ad7ba9aSRemy Horton    - ``peak_bits_out``:  Peak outbound bit-rate
1972ad7ba9aSRemy Horton
1982ad7ba9aSRemy HortonOnce initialised and clocked at the appropriate frequency, these
1992ad7ba9aSRemy Hortonstatistics can be obtained by querying the metrics library.
2002ad7ba9aSRemy Horton
2012ad7ba9aSRemy HortonInitialization
2022ad7ba9aSRemy Horton~~~~~~~~~~~~~~
2032ad7ba9aSRemy Horton
2042ad7ba9aSRemy HortonBefore the library can be used, it has to be initialised by calling
2052ad7ba9aSRemy Horton``rte_stats_bitrate_create()``, which will return a bit-rate
2062ad7ba9aSRemy Hortoncalculation object. Since the bit-rate library uses the metrics library
2072ad7ba9aSRemy Hortonto report the calculated statistics, the bit-rate library then needs to
2082ad7ba9aSRemy Hortonregister the calculated statistics with the metrics library. This is
2092ad7ba9aSRemy Hortondone using the helper function ``rte_stats_bitrate_reg()``.
2102ad7ba9aSRemy Horton
2112ad7ba9aSRemy Horton.. code-block:: c
2122ad7ba9aSRemy Horton
2132ad7ba9aSRemy Horton    struct rte_stats_bitrates *bitrate_data;
2142ad7ba9aSRemy Horton
2152ad7ba9aSRemy Horton    bitrate_data = rte_stats_bitrate_create();
2162ad7ba9aSRemy Horton    if (bitrate_data == NULL)
2172ad7ba9aSRemy Horton        rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
2182ad7ba9aSRemy Horton    rte_stats_bitrate_reg(bitrate_data);
2192ad7ba9aSRemy Horton
2202ad7ba9aSRemy HortonControlling the sampling rate
2212ad7ba9aSRemy Horton~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2222ad7ba9aSRemy Horton
2232ad7ba9aSRemy HortonSince the library works by periodic sampling but does not use an
2242ad7ba9aSRemy Hortoninternal thread, the application has to periodically call
2252ad7ba9aSRemy Horton``rte_stats_bitrate_calc()``. The frequency at which this function
2262ad7ba9aSRemy Hortonis called should be the intended sampling rate required for the
2272ad7ba9aSRemy Hortoncalculated statistics. For instance if per-second statistics are
2282ad7ba9aSRemy Hortondesired, this function should be called once a second.
2292ad7ba9aSRemy Horton
2302ad7ba9aSRemy Horton.. code-block:: c
2312ad7ba9aSRemy Horton
2322ad7ba9aSRemy Horton    tics_datum = rte_rdtsc();
2332ad7ba9aSRemy Horton    tics_per_1sec = rte_get_timer_hz();
2342ad7ba9aSRemy Horton
2352ad7ba9aSRemy Horton    while( 1 ) {
2362ad7ba9aSRemy Horton        /* ... */
2372ad7ba9aSRemy Horton        tics_current = rte_rdtsc();
2382ad7ba9aSRemy Horton	if (tics_current - tics_datum >= tics_per_1sec) {
2392ad7ba9aSRemy Horton	    /* Periodic bitrate calculation */
2402ad7ba9aSRemy Horton	    for (idx_port = 0; idx_port < cnt_ports; idx_port++)
2412ad7ba9aSRemy Horton	            rte_stats_bitrate_calc(bitrate_data, idx_port);
2422ad7ba9aSRemy Horton		tics_datum = tics_current;
2432ad7ba9aSRemy Horton	    }
2442ad7ba9aSRemy Horton        /* ... */
2452ad7ba9aSRemy Horton    }
246*5cd3cac9SReshma Pattan
247*5cd3cac9SReshma Pattan
248*5cd3cac9SReshma PattanLatency statistics library
249*5cd3cac9SReshma Pattan--------------------------
250*5cd3cac9SReshma Pattan
251*5cd3cac9SReshma PattanThe latency statistics library calculates the latency of packet
252*5cd3cac9SReshma Pattanprocessing by a DPDK application, reporting the minimum, average,
253*5cd3cac9SReshma Pattanand maximum nano-seconds that packet processing takes, as well as
254*5cd3cac9SReshma Pattanthe jitter in processing delay. These statistics are then reported
255*5cd3cac9SReshma Pattanvia the metrics library using the following names:
256*5cd3cac9SReshma Pattan
257*5cd3cac9SReshma Pattan    - ``min_latency_ns``: Minimum processing latency (nano-seconds)
258*5cd3cac9SReshma Pattan    - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
259*5cd3cac9SReshma Pattan    - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
260*5cd3cac9SReshma Pattan    - ``jitter_ns``: Variance in processing latency (nano-seconds)
261*5cd3cac9SReshma Pattan
262*5cd3cac9SReshma PattanOnce initialised and clocked at the appropriate frequency, these
263*5cd3cac9SReshma Pattanstatistics can be obtained by querying the metrics library.
264*5cd3cac9SReshma Pattan
265*5cd3cac9SReshma PattanInitialization
266*5cd3cac9SReshma Pattan~~~~~~~~~~~~~~
267*5cd3cac9SReshma Pattan
268*5cd3cac9SReshma PattanBefore the library can be used, it has to be initialised by calling
269*5cd3cac9SReshma Pattan``rte_latencystats_init()``.
270*5cd3cac9SReshma Pattan
271*5cd3cac9SReshma Pattan.. code-block:: c
272*5cd3cac9SReshma Pattan
273*5cd3cac9SReshma Pattan    lcoreid_t latencystats_lcore_id = -1;
274*5cd3cac9SReshma Pattan
275*5cd3cac9SReshma Pattan    int ret = rte_latencystats_init(1, NULL);
276*5cd3cac9SReshma Pattan    if (ret)
277*5cd3cac9SReshma Pattan        rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
278*5cd3cac9SReshma Pattan
279*5cd3cac9SReshma Pattan
280*5cd3cac9SReshma PattanTriggering statistic updates
281*5cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282*5cd3cac9SReshma Pattan
283*5cd3cac9SReshma PattanThe ``rte_latencystats_update()`` function needs to be called
284*5cd3cac9SReshma Pattanperiodically so that latency statistics can be updated.
285*5cd3cac9SReshma Pattan
286*5cd3cac9SReshma Pattan.. code-block:: c
287*5cd3cac9SReshma Pattan
288*5cd3cac9SReshma Pattan    if (latencystats_lcore_id == rte_lcore_id())
289*5cd3cac9SReshma Pattan        rte_latencystats_update();
290*5cd3cac9SReshma Pattan
291*5cd3cac9SReshma PattanLibrary shutdown
292*5cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~
293*5cd3cac9SReshma Pattan
294*5cd3cac9SReshma PattanWhen finished, ``rte_latencystats_uninit()`` needs to be called to
295*5cd3cac9SReshma Pattande-initialise the latency library.
296*5cd3cac9SReshma Pattan
297*5cd3cac9SReshma Pattan.. code-block:: c
298*5cd3cac9SReshma Pattan
299*5cd3cac9SReshma Pattan    rte_latencystats_uninit();
300