ibv_read_counters(3) — Linux manual page

NAME | SYNOPSIS | DESCRIPTION | ARGUMENTS | RETURN VALUE | EXAMPLE | SEE ALSO | AUTHORS | COLOPHON

ibv_read_counters(3)  Libibverbs Programmer’s Manual ibv_read_counters(3)

NAME         top

       ibv_read_counters - Read counter values

SYNOPSIS         top

              #include <infiniband/verbs.h>

              int ibv_read_counters(struct ibv_counters *counters,
                                    uint64_t *counters_value,
                                    uint32_t ncounters,
                                    uint32_t flags);

DESCRIPTION         top

       ibv_read_counters() returns the values of the chosen counters into
       counters_value array of which can accumulate ncounters.  The
       values are filled according to the configuration defined by the
       user in the ibv_attach_counters_point_xxx functions.

ARGUMENTS         top

       counters
              Counters object to read.

       counters_value
              Input buffer to hold read result.

       ncounters
              Number of counters to fill.

       flags  Use enum ibv_read_counters_flags.

   flags Argument
       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.

RETURN VALUE         top

       ibv_read_counters() returns 0 on success, or the value of errno on
       failure (which indicates the failure reason)

EXAMPLE         top

       Example: Statically attach counters to a new flow

       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.

              /* create counters object and define its counters points        */
              /* create simple L2 flow with hardcoded MAC, and a count action */
              /* read counters periodically, every 1sec, until loop ends      */
              /* assumes user prepared a RAW_PACKET QP as input               */
              /* only limited error checking in run time for code simplicity  */

              #include <inttypes.h>
              #include <infiniband/verbs.h>

              /* the below MAC should be replaced by user */
              #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(struct ibv_qp *qp) {
                  int idx = 0;
                  int loop = 10;
                  struct ibv_flow *flow = NULL;
                  struct ibv_counters *counters = NULL;
                  struct ibv_counters_init_attr init_attr = {0};
                  struct ibv_counter_attach_attr attach_attr = {0};

                  /* create single counters handle */
                  counters = ibv_create_counters(qp->context, &init_attr);

                  /* define counters points */
                  attach_attr.counter_desc = IBV_COUNTER_PACKETS;
                  attach_attr.index = idx++;
                  ret = ibv_attach_counters_point_flow(counters, &attach_attr, NULL);
                  if (ret == ENOTSUP) {
                      fprintf(stderr, "Attaching IBV_COUNTER_PACKETS to flow is not \
              supported");
                      exit(1);
                  }
                  attach_attr.counter_desc = IBV_COUNTER_BYTES;
                  attach_attr.index = idx++;
                  ibv_attach_counters_point_flow(counters, &attach_attr, NULL);
                  if (ret == ENOTSUP) {
                      fprintf(stderr, "Attaching IBV_COUNTER_BYTES to flow is not \
              supported");
                      exit(1);
                  }

                  /* define a new flow attr that includes the counters handle */
                  struct raw_eth_flow_attr {
                      struct ibv_flow_attr              attr;
                      struct ibv_flow_spec_eth          spec_eth;
                      struct ibv_flow_spec_counter_action spec_count;
                  } flow_attr = {
                      .attr = {
                              .comp_mask  = 0,
                              .type       = IBV_FLOW_ATTR_NORMAL,
                              .size       = sizeof(flow_attr),
                              .priority   = 0,
                              .num_of_specs = 2, /* ETH + COUNT */
                              .port       = 1,
                              .flags      = 0,
                          },
                      .spec_eth = {
                              .type = IBV_EXP_FLOW_SPEC_ETH,
                              .size = sizeof(struct 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   = sizeof(struct ibv_flow_spec_counter_action),
                              .counters = counters, /* attached this counters handle
              to the newly created ibv_flow */ } };

                  /* create the flow */
                  flow = ibv_create_flow(qp, &flow_attr.attr);

                  /* allocate array for counters value reading */
                  uint64_t *counters_value = malloc(sizeof(uint64_t) * idx);

                  /* periodical read and print of flow counters */
                  while (--loop) {
                      sleep(1);

                      /* read hardware counters values */
                      ibv_read_counters(counters, counters_value, idx,
                                IBV_READ_COUNTERS_ATTR_PREFER_CACHED);

                      printf("PACKETS = %"PRIu64", BYTES = %"PRIu64 \n",
                          counters_value[0], counters_value[1] );
                  }

                  /* all done, release all */
                  free(counters_value);

                  /* destroy flow and detach counters */
                  ibv_destroy_flow(flow);

                  /* destroy counters handle */
                  ibv_destroy_counters(counters);

                  return;
              }

SEE ALSO         top

       ibv_create_counters, ibv_destroy_counters,
       ibv_attach_counters_point_flow, ibv_create_flow

AUTHORS         top

       Raed Salem ⟨raeds@mellanox.com⟩

       Alex Rosenbaum ⟨alexr@mellanox.com⟩

COLOPHON         top

       This page is part of the rdma-core (RDMA Core Userspace Libraries
       and Daemons) project.  Information about the project can be found
       at ⟨https://github.com/linux-rdma/rdma-core⟩.  If you have a bug
       report for this manual page, send it to
       linux-rdma@vger.kernel.org.  This page was obtained from the
       project's upstream Git repository
       ⟨https://github.com/linux-rdma/rdma-core.git⟩ on 2025-08-11.  (At
       that time, the date of the most recent commit that was found in
       the repository was 2025-08-04.)  If you discover any rendering
       problems in this HTML version of the page, or you believe there is
       a better or more up-to-date source for the page, or you have
       corrections or improvements to the information in this COLOPHON
       (which is not part of the original manual page), send a mail to
       man-pages@man7.org

libibverbs                      2018-04-02           ibv_read_counters(3)