--- 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 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 #include /* 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 **ibv_create_counters**, **ibv_destroy_counters**, **ibv_attach_counters_point_flow**, **ibv_create_flow** # AUTHORS Raed Salem Alex Rosenbaum