---
date: 2018-04-02
footer: libibverbs
header: "Libibverbs Programmer's Manual"
layout: page
license: 'Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md'
section: 3
title: ibv_read_counters
---

# NAME

**ibv_read_counters** - Read counter values

# SYNOPSIS

```c
#include <infiniband/verbs.h>

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

# DESCRIPTION

**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

*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

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

# EXAMPLE

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.
```c
/* 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 coutners 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

**ibv_create_counters**, **ibv_destroy_counters**,
**ibv_attach_counters_point_flow**, **ibv_create_flow**

# AUTHORS

Raed Salem <raeds@mellanox.com>

Alex Rosenbaum <alexr@mellanox.com>
