.\" Automatically generated by Pandoc 3.8.2.1
.\"
.TH "ibv_read_counters" "3" "2018\-04\-02" "libibverbs" "Libibverbs Programmer\(cqs Manual"
.SH NAME
\f[B]ibv_read_counters\f[R] \- Read counter values
.SH SYNOPSIS
.IP
.EX
#include \f[B]<infiniband/verbs.h>\f[R]

int ibv_read_counters(\f[B]struct\f[R] ibv_counters *counters,
                      uint64_t *counters_value,
                      uint32_t ncounters,
                      uint32_t flags);
.EE
.SH DESCRIPTION
\f[B]ibv_read_counters\f[R]() returns the values of the chosen counters
into \f[I]counters_value\f[R] array of which can accumulate
\f[I]ncounters\f[R].
The values are filled according to the configuration defined by the user
in the \f[B]ibv_attach_counters_point_xxx\f[R] functions.
.SH ARGUMENTS
.TP
\f[I]counters\f[R]
Counters object to read.
.TP
\f[I]counters_value\f[R]
Input buffer to hold read result.
.TP
\f[I]ncounters\f[R]
Number of counters to fill.
.TP
\f[I]flags\f[R]
Use enum ibv_read_counters_flags.
.SS \f[I]flags\f[R] Argument
.TP
IBV_READ_COUNTERS_ATTR_PREFER_CACHED
Will prefer reading the values from driver cache, else it will do
volatile hardware access which is the default.
.SH RETURN VALUE
\f[B]ibv_read_counters\f[R]() returns 0 on success, or the value of
errno on failure (which indicates the failure reason)
.SH EXAMPLE
Example: Statically attach counters to a new flow
.PP
This example demonstrates the use of counters which are attached
statically with the creation of a new flow.
The counters are read from hardware periodically, and finally all
resources are released.
.IP
.EX
\f[I]/* create counters object and define its counters points        */\f[R]
\f[I]/* create simple L2 flow with hardcoded MAC, and a count action */\f[R]
\f[I]/* read counters periodically, every 1sec, until loop ends      */\f[R]
\f[I]/* assumes user prepared a RAW_PACKET QP as input               */\f[R]
\f[I]/* only limited error checking in run time for code simplicity  */\f[R]

#include \f[B]<inttypes.h>\f[R]
#include \f[B]<infiniband/verbs.h>\f[R]

\f[I]/* the below MAC should be replaced by user */\f[R]
#define FLOW_SPEC_ETH_MAC_VAL {
    .dst_mac = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05},
    .src_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    .ether_type = 0, .vlan_tag = 0, }
#define FLOW_SPEC_ETH_MAC_MASK {
    .dst_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
    .src_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
    .ether_type = 0, .vlan_tag = 0, }

void example_create_flow_with_counters_on_raw_qp(\f[B]struct\f[R] ibv_qp *qp) {
    int idx = 0;
    int loop = 10;
    \f[B]struct\f[R] ibv_flow *flow = NULL;
    \f[B]struct\f[R] ibv_counters *counters = NULL;
    \f[B]struct\f[R] ibv_counters_init_attr init_attr = {0};
    \f[B]struct\f[R] ibv_counter_attach_attr attach_attr = {0};

    \f[I]/* create single counters handle */\f[R]
    counters = ibv_create_counters(qp\->context, &init_attr);

    \f[I]/* define counters points */\f[R]
    attach_attr.counter_desc = IBV_COUNTER_PACKETS;
    attach_attr.index = idx++;
    ret = ibv_attach_counters_point_flow(counters, &attach_attr, NULL);
    \f[B]if\f[R] (ret == ENOTSUP) {
        fprintf(stderr, \(dqAttaching IBV_COUNTER_PACKETS to flow is not \(rs
supported\(dq);
        exit(1);
    }
    attach_attr.counter_desc = IBV_COUNTER_BYTES;
    attach_attr.index = idx++;
    ibv_attach_counters_point_flow(counters, &attach_attr, NULL);
    \f[B]if\f[R] (ret == ENOTSUP) {
        fprintf(stderr, \(dqAttaching IBV_COUNTER_BYTES to flow is not \(rs
supported\(dq);
        exit(1);
    }

    \f[I]/* define a new flow attr that includes the counters handle */\f[R]
    \f[B]struct\f[R] raw_eth_flow_attr {
        \f[B]struct\f[R] ibv_flow_attr              attr;
        \f[B]struct\f[R] ibv_flow_spec_eth          spec_eth;
        \f[B]struct\f[R] ibv_flow_spec_counter_action spec_count;
    } flow_attr = {
        .attr = {
                .comp_mask  = 0,
                .type       = IBV_FLOW_ATTR_NORMAL,
                .size       = \f[B]sizeof\f[R](flow_attr),
                .priority   = 0,
                .num_of_specs = 2, \f[I]/* ETH + COUNT */\f[R]
                .port       = 1,
                .flags      = 0,
            },
        .spec_eth = {
                .type = IBV_EXP_FLOW_SPEC_ETH,
                .size = \f[B]sizeof\f[R](\f[B]struct\f[R] ibv_flow_spec_eth),
                .val  = FLOW_SPEC_ETH_MAC_VAL,
                .mask = FLOW_SPEC_ETH_MAC_MASK,
            },
        .spec_count = {
                .type   = IBV_FLOW_SPEC_ACTION_COUNT,
                .size   = \f[B]sizeof\f[R](\f[B]struct\f[R] ibv_flow_spec_counter_action),
                .counters = counters, \f[I]/* attached this counters handle\f[R]
\f[I]to the newly created ibv_flow */\f[R] } };

    \f[I]/* create the flow */\f[R]
    flow = ibv_create_flow(qp, &flow_attr.attr);

    \f[I]/* allocate array for counters value reading */\f[R]
    uint64_t *counters_value = malloc(\f[B]sizeof\f[R](uint64_t) * idx);

    \f[I]/* periodical read and print of flow counters */\f[R]
    \f[B]while\f[R] (\-\-loop) {
        sleep(1);

        \f[I]/* read hardware counters values */\f[R]
        ibv_read_counters(counters, counters_value, idx,
                  IBV_READ_COUNTERS_ATTR_PREFER_CACHED);

        printf(\(dqPACKETS = %\(dqPRIu64\(dq, BYTES = %\(dqPRIu64 \(rsn\(dq,
            counters_value[0], counters_value[1] );
    }

    \f[I]/* all done, release all */\f[R]
    free(counters_value);

    \f[I]/* destroy flow and detach counters */\f[R]
    ibv_destroy_flow(flow);

    \f[I]/* destroy counters handle */\f[R]
    ibv_destroy_counters(counters);

    \f[B]return\f[R];
}
.EE
.SH SEE ALSO
\f[B]ibv_create_counters\f[R], \f[B]ibv_destroy_counters\f[R],
\f[B]ibv_attach_counters_point_flow\f[R], \f[B]ibv_create_flow\f[R]
.SH AUTHORS
Raed Salem \c
.MT raeds@mellanox.com
.ME \c
.PP
Alex Rosenbaum \c
.MT alexr@mellanox.com
.ME \c
