1.. BSD LICENSE 2 Copyright(c) 2017 Intel Corporation. All rights reserved. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions 7 are met: 8 9 * Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in 13 the documentation and/or other materials provided with the 14 distribution. 15 * Neither the name of Intel Corporation nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31.. _Metrics_Library: 32 33Metrics Library 34=============== 35 36The Metrics library implements a mechanism by which *producers* can 37publish numeric information for later querying by *consumers*. In 38practice producers will typically be other libraries or primary 39processes, whereas consumers will typically be applications. 40 41Metrics themselves are statistics that are not generated by PMDs. Metric 42information is populated using a push model, where producers update the 43values contained within the metric library by calling an update function 44on the relevant metrics. Consumers receive metric information by querying 45the central metric data, which is held in shared memory. 46 47For each metric, a separate value is maintained for each port id, and 48when publishing metric values the producers need to specify which port is 49being updated. In addition there is a special id ``RTE_METRICS_GLOBAL`` 50that is intended for global statistics that are not associated with any 51individual device. Since the metrics library is self-contained, the only 52restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS`` 53- there is no requirement for the ports to actually exist. 54 55Initialising the library 56------------------------ 57 58Before the library can be used, it has to be initialized by calling 59``rte_metrics_init()`` which sets up the metric store in shared memory. 60This is where producers will publish metric information to, and where 61consumers will query it from. 62 63.. code-block:: c 64 65 rte_metrics_init(rte_socket_id()); 66 67This function **must** be called from a primary process, but otherwise 68producers and consumers can be in either primary or secondary processes. 69 70Registering metrics 71------------------- 72 73Metrics must first be *registered*, which is the way producers declare 74the names of the metrics they will be publishing. Registration can either 75be done individually, or a set of metrics can be registered as a group. 76Individual registration is done using ``rte_metrics_reg_name()``: 77 78.. code-block:: c 79 80 id_1 = rte_metrics_reg_name("mean_bits_in"); 81 id_2 = rte_metrics_reg_name("mean_bits_out"); 82 id_3 = rte_metrics_reg_name("peak_bits_in"); 83 id_4 = rte_metrics_reg_name("peak_bits_out"); 84 85or alternatively, a set of metrics can be registered together using 86``rte_metrics_reg_names()``: 87 88.. code-block:: c 89 90 const char * const names[] = { 91 "mean_bits_in", "mean_bits_out", 92 "peak_bits_in", "peak_bits_out", 93 }; 94 id_set = rte_metrics_reg_names(&names[0], 4); 95 96If the return value is negative, it means registration failed. Otherwise 97the return value is the *key* for the metric, which is used when updating 98values. A table mapping together these key values and the metrics' names 99can be obtained using ``rte_metrics_get_names()``. 100 101Updating metric values 102---------------------- 103 104Once registered, producers can update the metric for a given port using 105the ``rte_metrics_update_value()`` function. This uses the metric key 106that is returned when registering the metric, and can also be looked up 107using ``rte_metrics_get_names()``. 108 109.. code-block:: c 110 111 rte_metrics_update_value(port_id, id_1, values[0]); 112 rte_metrics_update_value(port_id, id_2, values[1]); 113 rte_metrics_update_value(port_id, id_3, values[2]); 114 rte_metrics_update_value(port_id, id_4, values[3]); 115 116if metrics were registered as a single set, they can either be updated 117individually using ``rte_metrics_update_value()``, or updated together 118using the ``rte_metrics_update_values()`` function: 119 120.. code-block:: c 121 122 rte_metrics_update_value(port_id, id_set, values[0]); 123 rte_metrics_update_value(port_id, id_set + 1, values[1]); 124 rte_metrics_update_value(port_id, id_set + 2, values[2]); 125 rte_metrics_update_value(port_id, id_set + 3, values[3]); 126 127 rte_metrics_update_values(port_id, id_set, values, 4); 128 129Note that ``rte_metrics_update_values()`` cannot be used to update 130metric values from *multiple* *sets*, as there is no guarantee two 131sets registered one after the other have contiguous id values. 132 133Querying metrics 134---------------- 135 136Consumers can obtain metric values by querying the metrics library using 137the ``rte_metrics_get_values()`` function that return an array of 138``struct rte_metric_value``. Each entry within this array contains a metric 139value and its associated key. A key-name mapping can be obtained using the 140``rte_metrics_get_names()`` function that returns an array of 141``struct rte_metric_name`` that is indexed by the key. The following will 142print out all metrics for a given port: 143 144.. code-block:: c 145 146 void print_metrics() { 147 struct rte_metric_value *metrics; 148 struct rte_metric_name *names; 149 int len; 150 151 len = rte_metrics_get_names(NULL, 0); 152 if (len < 0) { 153 printf("Cannot get metrics count\n"); 154 return; 155 } 156 if (len == 0) { 157 printf("No metrics to display (none have been registered)\n"); 158 return; 159 } 160 metrics = malloc(sizeof(struct rte_metric_value) * len); 161 names = malloc(sizeof(struct rte_metric_name) * len); 162 if (metrics == NULL || names == NULL) { 163 printf("Cannot allocate memory\n"); 164 free(metrics); 165 free(names); 166 return; 167 } 168 ret = rte_metrics_get_values(port_id, metrics, len); 169 if (ret < 0 || ret > len) { 170 printf("Cannot get metrics values\n"); 171 free(metrics); 172 free(names); 173 return; 174 } 175 printf("Metrics for port %i:\n", port_id); 176 for (i = 0; i < len; i++) 177 printf(" %s: %"PRIu64"\n", 178 names[metrics[i].key].name, metrics[i].value); 179 free(metrics); 180 free(names); 181 } 182 183 184Bit-rate statistics library 185--------------------------- 186 187The bit-rate library calculates the exponentially-weighted moving 188average and peak bit-rates for each active port (i.e. network device). 189These statistics are reported via the metrics library using the 190following names: 191 192 - ``mean_bits_in``: Average inbound bit-rate 193 - ``mean_bits_out``: Average outbound bit-rate 194 - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed) 195 - ``ewma_bits_out``: Average outbound bit-rate (EWMA smoothed) 196 - ``peak_bits_in``: Peak inbound bit-rate 197 - ``peak_bits_out``: Peak outbound bit-rate 198 199Once initialised and clocked at the appropriate frequency, these 200statistics can be obtained by querying the metrics library. 201 202Initialization 203~~~~~~~~~~~~~~ 204 205Before the library can be used, it has to be initialised by calling 206``rte_stats_bitrate_create()``, which will return a bit-rate 207calculation object. Since the bit-rate library uses the metrics library 208to report the calculated statistics, the bit-rate library then needs to 209register the calculated statistics with the metrics library. This is 210done using the helper function ``rte_stats_bitrate_reg()``. 211 212.. code-block:: c 213 214 struct rte_stats_bitrates *bitrate_data; 215 216 bitrate_data = rte_stats_bitrate_create(); 217 if (bitrate_data == NULL) 218 rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n"); 219 rte_stats_bitrate_reg(bitrate_data); 220 221Controlling the sampling rate 222~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 223 224Since the library works by periodic sampling but does not use an 225internal thread, the application has to periodically call 226``rte_stats_bitrate_calc()``. The frequency at which this function 227is called should be the intended sampling rate required for the 228calculated statistics. For instance if per-second statistics are 229desired, this function should be called once a second. 230 231.. code-block:: c 232 233 tics_datum = rte_rdtsc(); 234 tics_per_1sec = rte_get_timer_hz(); 235 236 while( 1 ) { 237 /* ... */ 238 tics_current = rte_rdtsc(); 239 if (tics_current - tics_datum >= tics_per_1sec) { 240 /* Periodic bitrate calculation */ 241 for (idx_port = 0; idx_port < cnt_ports; idx_port++) 242 rte_stats_bitrate_calc(bitrate_data, idx_port); 243 tics_datum = tics_current; 244 } 245 /* ... */ 246 } 247 248 249Latency statistics library 250-------------------------- 251 252The latency statistics library calculates the latency of packet 253processing by a DPDK application, reporting the minimum, average, 254and maximum nano-seconds that packet processing takes, as well as 255the jitter in processing delay. These statistics are then reported 256via the metrics library using the following names: 257 258 - ``min_latency_ns``: Minimum processing latency (nano-seconds) 259 - ``avg_latency_ns``: Average processing latency (nano-seconds) 260 - ``mac_latency_ns``: Maximum processing latency (nano-seconds) 261 - ``jitter_ns``: Variance in processing latency (nano-seconds) 262 263Once initialised and clocked at the appropriate frequency, these 264statistics can be obtained by querying the metrics library. 265 266Initialization 267~~~~~~~~~~~~~~ 268 269Before the library can be used, it has to be initialised by calling 270``rte_latencystats_init()``. 271 272.. code-block:: c 273 274 lcoreid_t latencystats_lcore_id = -1; 275 276 int ret = rte_latencystats_init(1, NULL); 277 if (ret) 278 rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n"); 279 280 281Triggering statistic updates 282~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 283 284The ``rte_latencystats_update()`` function needs to be called 285periodically so that latency statistics can be updated. 286 287.. code-block:: c 288 289 if (latencystats_lcore_id == rte_lcore_id()) 290 rte_latencystats_update(); 291 292Library shutdown 293~~~~~~~~~~~~~~~~ 294 295When finished, ``rte_latencystats_uninit()`` needs to be called to 296de-initialise the latency library. 297 298.. code-block:: c 299 300 rte_latencystats_uninit(); 301