NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
telemetry_pcc_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <doca_error.h>
27 #include <doca_log.h>
28 #include <doca_dev.h>
29 #include <doca_telemetry_pcc.h>
30 #include <errno.h>
31 #include <unistd.h>
32 
33 #include "common.h"
34 #include "telemetry_pcc_sample.h"
35 
36 DOCA_LOG_REGISTER(TELEMETRY_PCC::SAMPLE);
37 
38 /*
39  * Get and print algo information for each slot from the telemetry context
40  *
41  * @pcc [in]: pcc telemetry context
42  * @dev [in]: doca_device in use
43  * @slots_populated [out]: bitmap of slots populated
44  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
45  */
46 static doca_error_t get_algo_information(struct doca_telemetry_pcc *pcc,
47  struct doca_dev *dev,
48  uint32_t *slots_populated)
49 {
50  uint32_t max_slot_info_len, max_slots, id, major, minor, i;
51  char *algo_info;
53 
55  if (result != DOCA_SUCCESS) {
56  DOCA_LOG_ERR("Failed to get number of slots: error=%s", doca_error_get_name(result));
57  return result;
58  }
59 
60  printf("\n*************************************\n");
61  printf("%u slots detected on card:\n", max_slots);
62 
64  if (result != DOCA_SUCCESS) {
65  DOCA_LOG_ERR("Failed to get max algo info from device: error=%s", doca_error_get_name(result));
66  return result;
67  }
68 
69  algo_info = (char *)malloc(sizeof(char) * max_slot_info_len);
70  if (algo_info == NULL) {
71  DOCA_LOG_ERR("Failed to allocate array for algo info");
72  return DOCA_ERROR_NO_MEMORY;
73  }
74 
75  for (i = 0; i < max_slots; i++) {
77  /* Bad state indicates an empty slot */
79  printf("Slot %u: Empty\n", i);
80  continue;
81  } else if (result != DOCA_SUCCESS) {
82  DOCA_LOG_ERR("Failed to get algo id: Error=%s", doca_error_get_name(result));
83  goto free_algo_info;
84  }
85 
87  if (result != DOCA_SUCCESS) {
88  DOCA_LOG_ERR("Failed to get algo major version: Error=%s", doca_error_get_name(result));
89  goto free_algo_info;
90  }
91 
93  if (result != DOCA_SUCCESS) {
94  DOCA_LOG_ERR("Failed to get algo minor version: Error=%s", doca_error_get_name(result));
95  goto free_algo_info;
96  }
97 
98  result = doca_telemetry_pcc_get_algo_info(pcc, i, algo_info);
99  if (result != DOCA_SUCCESS) {
100  DOCA_LOG_ERR("Failed get algo info on slot %u: error=%s", i, doca_error_get_name(result));
101  goto free_algo_info;
102  }
103 
104  printf("Slot %u: ID %04x, version %u.%02u - %s\n", i, id, major, minor, algo_info);
105  *slots_populated |= (1 << i);
106  }
107  printf("*************************************\n");
108 
109  /* At this point the function has completed successfully even if result says BAD STATE */
111 
112 free_algo_info:
113  free(algo_info);
114 
115  return result;
116 }
117 
118 /*
119  * Get and print counters from an algo slot
120  *
121  * @pcc [in]: pcc telemetry context
122  * @dev [in]: doca_device in use
123  * @slot [in]: algo slot to parse
124  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
125  */
126 static doca_error_t get_counter_information(struct doca_telemetry_pcc *pcc, struct doca_dev *dev, uint8_t slot)
127 {
128  uint32_t max_info, max_counters, counters_populated, i;
129  char *counter_info;
130  uint32_t *counters;
132 
133  printf("-------------------------------------\n");
134 
136  if (result != DOCA_SUCCESS) {
137  DOCA_LOG_ERR("Failed to get max num counters: Error=%s", doca_error_get_name(result));
138  return result;
139  }
140 
141  counters = (uint32_t *)malloc(sizeof(uint32_t) * max_counters);
142  if (counters == NULL) {
143  DOCA_LOG_ERR("Failed to allocate array for counters");
144  return DOCA_ERROR_NO_MEMORY;
145  }
146 
147  result = doca_telemetry_pcc_get_counters(pcc, slot, &counters_populated, counters);
148  if (result != DOCA_SUCCESS) {
149  DOCA_LOG_ERR("Failed to get counters: Error=%s", doca_error_get_name(result));
150  goto free_counters;
151  }
152 
153  printf("Number of counters found is %u\n", counters_populated);
154 
156  if (result != DOCA_SUCCESS) {
157  DOCA_LOG_ERR("Failed to get max counter info: Error=%s", doca_error_get_name(result));
158  return result;
159  }
160 
161  counter_info = (char *)malloc(sizeof(char) * max_info);
162  if (counter_info == NULL) {
163  DOCA_LOG_ERR("Failed to allocate array for counter info");
165  goto free_counters;
166  }
167 
168  for (i = 0; i < counters_populated; i++) {
169  result = doca_telemetry_pcc_get_counter_info(pcc, slot, i, counter_info);
170  if (result != DOCA_SUCCESS) {
171  DOCA_LOG_ERR("Failed to get counter info: Error=%s", doca_error_get_name(result));
172  goto free_counter_info;
173  }
174 
175  printf("Counter %u: %u - %s\n", i, counters[i], counter_info);
176  }
177  printf("-------------------------------------\n");
178 
179 free_counter_info:
180  free(counter_info);
181 free_counters:
182  free(counters);
183 
184  return result;
185 }
186 
188 {
189  uint32_t slots_populated, slot, i;
190  struct doca_telemetry_pcc *pcc;
191  uint8_t algo_en, counters_en;
192  struct doca_dev *dev;
194 
195  /* Open DOCA device based on the given PCI address */
196  result = open_doca_device_with_pci(cfg->pci_addr, NULL, &dev);
197  if (result != DOCA_SUCCESS) {
198  DOCA_LOG_ERR("Failed to open device with error=%s", doca_error_get_name(result));
199  return result;
200  }
201 
202  /* Check for telemetry support */
204  if (result != DOCA_SUCCESS) {
205  DOCA_LOG_ERR("Device does not have PCC telemetry support. Error=%s", doca_error_get_name(result));
206  goto close_dev;
207  }
208 
209  /* Create telemetry context */
210  result = doca_telemetry_pcc_create(dev, &pcc);
211  if (result != DOCA_SUCCESS) {
212  DOCA_LOG_ERR("Failed to create telemetry pcc context. Error=%s", doca_error_get_name(result));
213  goto close_dev;
214  }
215 
216  /* Parse all the slots on the card for PCC algos */
217  slots_populated = 0;
218  result = get_algo_information(pcc, dev, &slots_populated);
219  if (result != DOCA_SUCCESS) {
220  DOCA_LOG_ERR("Failed getting algo information. Error=%s", doca_error_get_name(result));
221  goto destroy_pcc;
222  }
223 
224  /* Start the context for counter extraction */
226  if (result != DOCA_SUCCESS) {
227  DOCA_LOG_ERR("Failed to start telemetry pcc context. Error=%s", doca_error_get_name(result));
228  goto destroy_pcc;
229  }
230 
231  printf("\nContext is running. Parsing for counters...\n\n");
232 
233  while ((i = ffs(slots_populated))) {
234  /* FFS returns bit position but slot index starts at 0 so need to subtract 1 */
235  slot = i - 1;
236 
237  result = doca_telemetry_pcc_get_algo_enable_status(pcc, slot, &algo_en, &counters_en);
238  if (result != DOCA_SUCCESS) {
239  DOCA_LOG_ERR("Failed getting Enabled status of slot %u: Error=%s",
240  slot,
242  goto stop_pcc;
243  }
244 
245  printf("Slot %u: algo %s, counters %s\n",
246  slot,
247  algo_en ? "ENABLED" : "DISABLED",
248  counters_en ? "ENABLED" : "DISABLED");
249 
250  /* Mark slot as parsed */
251  slots_populated &= ~(1 << slot);
252 
253  if (counters_en == 0)
254  continue;
255 
256  result = get_counter_information(pcc, dev, (uint8_t)slot);
257  if (result != DOCA_SUCCESS) {
258  DOCA_LOG_ERR("Failed get get counters on slot %u: Error=%s", slot, doca_error_get_name(result));
259  goto stop_pcc;
260  }
261  }
262  printf("\n");
263 
264 stop_pcc:
265  (void)doca_telemetry_pcc_stop(pcc);
266 destroy_pcc:
267  (void)doca_telemetry_pcc_destroy(pcc);
268 close_dev:
269  doca_dev_close(dev);
270 
271  return result;
272 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
DOCA_STABLE struct doca_devinfo * doca_dev_as_devinfo(const struct doca_dev *dev)
Get local device info from device. This should be useful when wanting to query information about devi...
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_name(doca_error_t error)
Returns the string representation of an error code name.
@ DOCA_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_stop(struct doca_telemetry_pcc *pcc)
Stop pcc counter extraction context.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_cap_get_max_algo_info_len(const struct doca_devinfo *devinfo, uint32_t *max_algo_info_len)
Get the maximum number of characters that be returned by an algo_info request.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_create(struct doca_dev *dev, struct doca_telemetry_pcc **pcc)
Create a DOCA Telemetry PCC instance.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_cap_get_max_algo_slots(const struct doca_devinfo *devinfo, uint32_t *max_algo_slots)
Get the maximum number of algo slots that may be populated.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_algo_minor_version(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint32_t *minor_ver)
Get the minor version number of algo on a specific slot.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_algo_info(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, char *algo_info)
Get information on a given algorithm.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_cap_is_supported(const struct doca_devinfo *devinfo)
Check if given device is capable of executing telemetry PCC operations.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_algo_enable_status(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint8_t *algo_enabled, uint8_t *counters_enabled)
Get the enable status for a given algo slot.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_destroy(struct doca_telemetry_pcc *pcc)
Destroy doca_telemetry_pcc previously created by doca_telemetry_pcc_create().
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_algo_id(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint32_t *algo_id)
Get the id of algo on a specific slot.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_cap_get_max_counter_info_len(const struct doca_devinfo *devinfo, uint32_t *max_counter_info_len)
Get the maximum number of characters that be returned by a counter_info request.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_algo_major_version(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint32_t *major_ver)
Get the major version number of algo on a specific slot.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_counter_info(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint8_t counter_id, char *counter_info)
Get information on a given counter.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_cap_get_max_num_counters(const struct doca_devinfo *devinfo, uint32_t *max_num_counters)
Get the maximum number of counters that may be returned.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_get_counters(struct doca_telemetry_pcc *pcc, uint8_t algo_slot, uint32_t *counters_populated, uint32_t *counters)
Get counters for PCC algo slot.
DOCA_EXPERIMENTAL doca_error_t doca_telemetry_pcc_start(struct doca_telemetry_pcc *pcc)
Start context for pcc counter extraction.
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
static doca_error_t get_algo_information(struct doca_telemetry_pcc *pcc, struct doca_dev *dev, uint32_t *slots_populated)
DOCA_LOG_REGISTER(TELEMETRY_PCC::SAMPLE)
static doca_error_t get_counter_information(struct doca_telemetry_pcc *pcc, struct doca_dev *dev, uint8_t slot)
doca_error_t telemetry_pcc_sample_run(const struct telemetry_pcc_sample_cfg *cfg)