1*349950ddSRemy Horton.. BSD LICENSE 2*349950ddSRemy Horton Copyright(c) 2017 Intel Corporation. All rights reserved. 3*349950ddSRemy Horton All rights reserved. 4*349950ddSRemy Horton 5*349950ddSRemy Horton Redistribution and use in source and binary forms, with or without 6*349950ddSRemy Horton modification, are permitted provided that the following conditions 7*349950ddSRemy Horton are met: 8*349950ddSRemy Horton 9*349950ddSRemy Horton * Redistributions of source code must retain the above copyright 10*349950ddSRemy Horton notice, this list of conditions and the following disclaimer. 11*349950ddSRemy Horton * Redistributions in binary form must reproduce the above copyright 12*349950ddSRemy Horton notice, this list of conditions and the following disclaimer in 13*349950ddSRemy Horton the documentation and/or other materials provided with the 14*349950ddSRemy Horton distribution. 15*349950ddSRemy Horton * Neither the name of Intel Corporation nor the names of its 16*349950ddSRemy Horton contributors may be used to endorse or promote products derived 17*349950ddSRemy Horton from this software without specific prior written permission. 18*349950ddSRemy Horton 19*349950ddSRemy Horton THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*349950ddSRemy Horton "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*349950ddSRemy Horton LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*349950ddSRemy Horton A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*349950ddSRemy Horton OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*349950ddSRemy Horton SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*349950ddSRemy Horton LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*349950ddSRemy Horton DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*349950ddSRemy Horton THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*349950ddSRemy Horton (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*349950ddSRemy Horton OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*349950ddSRemy Horton 31*349950ddSRemy Horton.. _Metrics_Library: 32*349950ddSRemy Horton 33*349950ddSRemy HortonMetrics Library 34*349950ddSRemy Horton=============== 35*349950ddSRemy Horton 36*349950ddSRemy HortonThe Metrics library implements a mechanism by which *producers* can 37*349950ddSRemy Hortonpublish numeric information for later querying by *consumers*. In 38*349950ddSRemy Hortonpractice producers will typically be other libraries or primary 39*349950ddSRemy Hortonprocesses, whereas consumers will typically be applications. 40*349950ddSRemy Horton 41*349950ddSRemy HortonMetrics themselves are statistics that are not generated by PMDs. Metric 42*349950ddSRemy Hortoninformation is populated using a push model, where producers update the 43*349950ddSRemy Hortonvalues contained within the metric library by calling an update function 44*349950ddSRemy Hortonon the relevant metrics. Consumers receive metric information by querying 45*349950ddSRemy Hortonthe central metric data, which is held in shared memory. 46*349950ddSRemy Horton 47*349950ddSRemy HortonFor each metric, a separate value is maintained for each port id, and 48*349950ddSRemy Hortonwhen publishing metric values the producers need to specify which port is 49*349950ddSRemy Hortonbeing updated. In addition there is a special id ``RTE_METRICS_GLOBAL`` 50*349950ddSRemy Hortonthat is intended for global statistics that are not associated with any 51*349950ddSRemy Hortonindividual device. Since the metrics library is self-contained, the only 52*349950ddSRemy Hortonrestriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS`` 53*349950ddSRemy Horton- there is no requirement for the ports to actually exist. 54*349950ddSRemy Horton 55*349950ddSRemy HortonInitialising the library 56*349950ddSRemy Horton------------------------ 57*349950ddSRemy Horton 58*349950ddSRemy HortonBefore the library can be used, it has to be initialized by calling 59*349950ddSRemy Horton``rte_metrics_init()`` which sets up the metric store in shared memory. 60*349950ddSRemy HortonThis is where producers will publish metric information to, and where 61*349950ddSRemy Hortonconsumers will query it from. 62*349950ddSRemy Horton 63*349950ddSRemy Horton.. code-block:: c 64*349950ddSRemy Horton 65*349950ddSRemy Horton rte_metrics_init(rte_socket_id()); 66*349950ddSRemy Horton 67*349950ddSRemy HortonThis function **must** be called from a primary process, but otherwise 68*349950ddSRemy Hortonproducers and consumers can be in either primary or secondary processes. 69*349950ddSRemy Horton 70*349950ddSRemy HortonRegistering metrics 71*349950ddSRemy Horton------------------- 72*349950ddSRemy Horton 73*349950ddSRemy HortonMetrics must first be *registered*, which is the way producers declare 74*349950ddSRemy Hortonthe names of the metrics they will be publishing. Registration can either 75*349950ddSRemy Hortonbe done individually, or a set of metrics can be registered as a group. 76*349950ddSRemy HortonIndividual registration is done using ``rte_metrics_reg_name()``: 77*349950ddSRemy Horton 78*349950ddSRemy Horton.. code-block:: c 79*349950ddSRemy Horton 80*349950ddSRemy Horton id_1 = rte_metrics_reg_name("mean_bits_in"); 81*349950ddSRemy Horton id_2 = rte_metrics_reg_name("mean_bits_out"); 82*349950ddSRemy Horton id_3 = rte_metrics_reg_name("peak_bits_in"); 83*349950ddSRemy Horton id_4 = rte_metrics_reg_name("peak_bits_out"); 84*349950ddSRemy Horton 85*349950ddSRemy Hortonor alternatively, a set of metrics can be registered together using 86*349950ddSRemy Horton``rte_metrics_reg_names()``: 87*349950ddSRemy Horton 88*349950ddSRemy Horton.. code-block:: c 89*349950ddSRemy Horton 90*349950ddSRemy Horton const char * const names[] = { 91*349950ddSRemy Horton "mean_bits_in", "mean_bits_out", 92*349950ddSRemy Horton "peak_bits_in", "peak_bits_out", 93*349950ddSRemy Horton }; 94*349950ddSRemy Horton id_set = rte_metrics_reg_names(&names[0], 4); 95*349950ddSRemy Horton 96*349950ddSRemy HortonIf the return value is negative, it means registration failed. Otherwise 97*349950ddSRemy Hortonthe return value is the *key* for the metric, which is used when updating 98*349950ddSRemy Hortonvalues. A table mapping together these key values and the metrics' names 99*349950ddSRemy Hortoncan be obtained using ``rte_metrics_get_names()``. 100*349950ddSRemy Horton 101*349950ddSRemy HortonUpdating metric values 102*349950ddSRemy Horton---------------------- 103*349950ddSRemy Horton 104*349950ddSRemy HortonOnce registered, producers can update the metric for a given port using 105*349950ddSRemy Hortonthe ``rte_metrics_update_value()`` function. This uses the metric key 106*349950ddSRemy Hortonthat is returned when registering the metric, and can also be looked up 107*349950ddSRemy Hortonusing ``rte_metrics_get_names()``. 108*349950ddSRemy Horton 109*349950ddSRemy Horton.. code-block:: c 110*349950ddSRemy Horton 111*349950ddSRemy Horton rte_metrics_update_value(port_id, id_1, values[0]); 112*349950ddSRemy Horton rte_metrics_update_value(port_id, id_2, values[1]); 113*349950ddSRemy Horton rte_metrics_update_value(port_id, id_3, values[2]); 114*349950ddSRemy Horton rte_metrics_update_value(port_id, id_4, values[3]); 115*349950ddSRemy Horton 116*349950ddSRemy Hortonif metrics were registered as a single set, they can either be updated 117*349950ddSRemy Hortonindividually using ``rte_metrics_update_value()``, or updated together 118*349950ddSRemy Hortonusing the ``rte_metrics_update_values()`` function: 119*349950ddSRemy Horton 120*349950ddSRemy Horton.. code-block:: c 121*349950ddSRemy Horton 122*349950ddSRemy Horton rte_metrics_update_value(port_id, id_set, values[0]); 123*349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 1, values[1]); 124*349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 2, values[2]); 125*349950ddSRemy Horton rte_metrics_update_value(port_id, id_set + 3, values[3]); 126*349950ddSRemy Horton 127*349950ddSRemy Horton rte_metrics_update_values(port_id, id_set, values, 4); 128*349950ddSRemy Horton 129*349950ddSRemy HortonNote that ``rte_metrics_update_values()`` cannot be used to update 130*349950ddSRemy Hortonmetric values from *multiple* *sets*, as there is no guarantee two 131*349950ddSRemy Hortonsets registered one after the other have contiguous id values. 132*349950ddSRemy Horton 133*349950ddSRemy HortonQuerying metrics 134*349950ddSRemy Horton---------------- 135*349950ddSRemy Horton 136*349950ddSRemy HortonConsumers can obtain metric values by querying the metrics library using 137*349950ddSRemy Hortonthe ``rte_metrics_get_values()`` function that return an array of 138*349950ddSRemy Horton``struct rte_metric_value``. Each entry within this array contains a metric 139*349950ddSRemy Hortonvalue and its associated key. A key-name mapping can be obtained using the 140*349950ddSRemy Horton``rte_metrics_get_names()`` function that returns an array of 141*349950ddSRemy Horton``struct rte_metric_name`` that is indexed by the key. The following will 142*349950ddSRemy Hortonprint out all metrics for a given port: 143*349950ddSRemy Horton 144*349950ddSRemy Horton.. code-block:: c 145*349950ddSRemy Horton 146*349950ddSRemy Horton void print_metrics() { 147*349950ddSRemy Horton struct rte_metric_name *names; 148*349950ddSRemy Horton int len; 149*349950ddSRemy Horton 150*349950ddSRemy Horton len = rte_metrics_get_names(NULL, 0); 151*349950ddSRemy Horton if (len < 0) { 152*349950ddSRemy Horton printf("Cannot get metrics count\n"); 153*349950ddSRemy Horton return; 154*349950ddSRemy Horton } 155*349950ddSRemy Horton if (len == 0) { 156*349950ddSRemy Horton printf("No metrics to display (none have been registered)\n"); 157*349950ddSRemy Horton return; 158*349950ddSRemy Horton } 159*349950ddSRemy Horton metrics = malloc(sizeof(struct rte_metric_value) * len); 160*349950ddSRemy Horton names = malloc(sizeof(struct rte_metric_name) * len); 161*349950ddSRemy Horton if (metrics == NULL || names == NULL) { 162*349950ddSRemy Horton printf("Cannot allocate memory\n"); 163*349950ddSRemy Horton free(metrics); 164*349950ddSRemy Horton free(names); 165*349950ddSRemy Horton return; 166*349950ddSRemy Horton } 167*349950ddSRemy Horton ret = rte_metrics_get_values(port_id, metrics, len); 168*349950ddSRemy Horton if (ret < 0 || ret > len) { 169*349950ddSRemy Horton printf("Cannot get metrics values\n"); 170*349950ddSRemy Horton free(metrics); 171*349950ddSRemy Horton free(names); 172*349950ddSRemy Horton return; 173*349950ddSRemy Horton } 174*349950ddSRemy Horton printf("Metrics for port %i:\n", port_id); 175*349950ddSRemy Horton for (i = 0; i < len; i++) 176*349950ddSRemy Horton printf(" %s: %"PRIu64"\n", 177*349950ddSRemy Horton names[metrics[i].key].name, metrics[i].value); 178*349950ddSRemy Horton free(metrics); 179*349950ddSRemy Horton free(names); 180*349950ddSRemy Horton } 181