NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
devemu_vfs_list_devices_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 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 <signal.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include <time.h>
31 
32 #include <doca_ctx.h>
33 #include <doca_devemu_pci.h>
34 #include <doca_devemu_pci_type.h>
35 #include <doca_dev.h>
36 #include <doca_error.h>
37 #include <doca_log.h>
38 
39 #include <doca_devemu_vfs.h>
40 #include <doca_devemu_vfs_type.h>
41 
42 DOCA_LOG_REGISTER(DPU_DEVEMU_VFS_DEVICE_LIST);
43 
44 struct program_state {
45  struct doca_dev *dev;
46  struct doca_devemu_vfs_type *vfs_type;
47 };
48 
49 /*
50  * Cleanup state of the sample
51  *
52  * @state [in]: The state of the sample
53  */
54 static void state_cleanup(struct program_state *state)
55 {
56  doca_error_t res;
57 
58  if (state->dev != NULL) {
59  res = doca_dev_close(state->dev);
60  if (res != DOCA_SUCCESS)
61  DOCA_LOG_ERR("Failed to close DOCA device: %s", doca_error_get_descr(res));
62 
63  state->dev = NULL;
64  }
65 }
66 
67 /*
68  * Check if the device's PCI address matches the provided PCI address
69  * Supports both formats DOMAIN:BUS:DEVICE.FUNCTION or BUS:DEVICE.FUNCTION
70  *
71  * @devinfo [in]: The DOCA device information
72  * @pci_address [in]: The PCI address to compare against
73  * @return: true in case matches, false otherwise
74  */
75 static bool device_match_pci_addr(const struct doca_devinfo *devinfo, const char *pci_address)
76 {
77  uint8_t is_equal = 0;
78 
79  (void)doca_devinfo_is_equal_pci_addr(devinfo, pci_address, &is_equal);
80 
81  return is_equal == 1;
82 }
83 
84 /*
85  * Open a DOCA device according to a given PCI address
86  * Picks device that has given PCI address and supports hotplug of the PCI type
87  *
88  * @pci_address [in]: PCI address
89  * @dev [out]: pointer to doca_dev struct, NULL if not found
90  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
91  */
92 static doca_error_t find_doca_device(const char *pci_address, struct doca_dev **dev)
93 {
94  struct doca_devinfo **dev_list;
95  uint32_t nb_devs;
96  doca_error_t res;
97  size_t i;
98 
99  /* Set default return value */
100  *dev = NULL;
101 
102  res = doca_devinfo_create_list(&dev_list, &nb_devs);
103  if (res != DOCA_SUCCESS) {
104  DOCA_LOG_ERR("Failed to load doca devices list: %s", doca_error_get_descr(res));
105  return res;
106  }
107 
108  /* Search */
109  for (i = 0; i < nb_devs; i++) {
110  if (!device_match_pci_addr(dev_list[i], pci_address))
111  continue;
112 
113  res = doca_dev_open(dev_list[i], dev);
114  if (res == DOCA_SUCCESS) {
115  doca_devinfo_destroy_list(dev_list);
116  return res;
117  }
118  }
119 
120  DOCA_LOG_WARN("Matching device not found");
121 
122  doca_devinfo_destroy_list(dev_list);
123  return DOCA_ERROR_NOT_FOUND;
124 }
125 
126 /*
127  * Convert PCI function type to string
128  *
129  * @pci_func_type [in]: PCI Function Type
130  * @return: String for function type
131  */
132 static const char *rep_func_type_to_string(enum doca_pci_func_type pci_func_type)
133 {
134  switch (pci_func_type) {
136  return "PF";
138  return "VF";
140  return "SF";
141  default:
142  break;
143  }
144 
145  return "Invalid pci function type";
146 }
147 
148 /*
149  * List the static and hotplug VirtioFS devices in system
150  *
151  * @vfs_type [in]: VFS Type to get the devices
152  * @return: DOCA_SUCCESS on success and doca_error_t otherwise
153  */
154 static doca_error_t list_emulated_devices(struct doca_devemu_vfs_type *vfs_type)
155 {
157  uint32_t num_devices = 0;
158  struct doca_devinfo_rep **dev_list_rep = NULL;
159  char buf[DOCA_DEVINFO_REP_VUID_SIZE] = {};
160  char pci_buf[DOCA_DEVINFO_REP_PCI_ADDR_SIZE] = {};
161  enum doca_pci_func_type pci_func_type;
162  uint32_t i;
163 
165  &dev_list_rep,
166  &num_devices);
167  if (result != DOCA_SUCCESS) {
168  DOCA_LOG_ERR("Failed to get list: %s", doca_error_get_descr(result));
169  return result;
170  }
171 
172  DOCA_LOG_INFO("Total Emulated Devices : %d\n", num_devices);
173  for (i = 0; i < num_devices; i++) {
175  if (result != DOCA_SUCCESS) {
176  DOCA_LOG_ERR("Failed to get vuid: %s", doca_error_get_descr(result));
177  return result;
178  }
179  result = doca_devinfo_rep_get_pci_addr_str(dev_list_rep[i], pci_buf);
180  if (result != DOCA_SUCCESS) {
181  DOCA_LOG_ERR("Failed to get pci addr: %s", doca_error_get_descr(result));
182  return result;
183  }
184 
185  result = doca_devinfo_rep_get_pci_func_type(dev_list_rep[i], &pci_func_type);
186  if (result != DOCA_SUCCESS) {
187  DOCA_LOG_ERR("Failed to get pci func type: %s", doca_error_get_descr(result));
188  return result;
189  }
190 
191  DOCA_LOG_INFO("Idx:%d, vuid:%s pci_addr:%s pci_func_type:%s",
192  i,
193  buf,
194  pci_buf,
195  rep_func_type_to_string(pci_func_type));
196  }
197 
198  doca_devinfo_rep_destroy_list(dev_list_rep);
199 
200  return DOCA_SUCCESS;
201 }
202 
203 /*
204  * Sample program to list VirtioFS Static and Hotplug devices
205  *
206  * @pci_address [in]: Device PCI address
207  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
208  */
209 doca_error_t devemu_vfs_device_list(const char *pci_address)
210 {
212  struct program_state state = {0};
213 
214  result = find_doca_device(pci_address, &state.dev);
215  if (result != DOCA_SUCCESS) {
216  state_cleanup(&state);
217  return result;
218  }
219 
221  if (result != DOCA_SUCCESS) {
222  state_cleanup(&state);
223  return result;
224  }
225 
226  DOCA_LOG_INFO("List Static VirtioFS Devices\n");
227 
229  if (result != DOCA_SUCCESS)
230  DOCA_LOG_ERR("Failed to get list of emulated devices: %s", doca_error_get_descr(result));
231 
232  state_cleanup(&state);
233 
234  return result;
235 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
static void state_cleanup(struct program_state *state)
doca_error_t devemu_vfs_device_list(const char *pci_address)
static const char * rep_func_type_to_string(enum doca_pci_func_type pci_func_type)
static bool device_match_pci_addr(const struct doca_devinfo *devinfo, const char *pci_address)
static doca_error_t list_emulated_devices(struct doca_devemu_vfs_type *vfs_type)
DOCA_LOG_REGISTER(DPU_DEVEMU_VFS_DEVICE_LIST)
static doca_error_t find_doca_device(const char *pci_address, struct doca_dev **dev)
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_type_create_rep_list(struct doca_devemu_pci_type *pci_type, struct doca_devinfo_rep ***dev_list_rep, uint32_t *nb_devs_rep)
Create list of available representor devices for a given DOCA devemu PCI type.
DOCA_EXPERIMENTAL struct doca_devemu_pci_type * doca_devemu_vfs_type_as_pci_type(struct doca_devemu_vfs_type *vfs_type)
Convert DOCA Virtio FS type instance into DOCA PCI type.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_vfs_find_default_vfs_type_by_dev(struct doca_dev *dev, struct doca_devemu_vfs_type **vfs_type)
Find the default DOCA Virtio FS type associated with the device.
DOCA_STABLE doca_error_t doca_devinfo_is_equal_pci_addr(const struct doca_devinfo *devinfo, const char *pci_addr_str, uint8_t *is_equal)
Check if a PCI address belongs to a DOCA devinfo.
DOCA_STABLE doca_error_t doca_devinfo_rep_destroy_list(struct doca_devinfo_rep **dev_list_rep)
Destroy list of representor device info structures.
DOCA_STABLE doca_error_t doca_devinfo_create_list(struct doca_devinfo ***dev_list, uint32_t *nb_devs)
Creates list of all available local devices.
#define DOCA_DEVINFO_REP_PCI_ADDR_SIZE
Buffer size to hold PCI BDF format: "XXXX:XX:XX.X". Including a null terminator.
Definition: doca_dev.h:665
DOCA_STABLE doca_error_t doca_devinfo_rep_get_vuid(const struct doca_devinfo_rep *devinfo_rep, char *rep_vuid, uint32_t size)
Get the Vendor Unique ID of a representor DOCA devinfo.
DOCA_STABLE doca_error_t doca_devinfo_rep_get_pci_addr_str(const struct doca_devinfo_rep *devinfo_rep, char *pci_addr_str)
Get the PCI address of a DOCA devinfo_rep.
DOCA_STABLE doca_error_t doca_devinfo_rep_get_pci_func_type(const struct doca_devinfo_rep *devinfo_rep, enum doca_pci_func_type *pci_func_type)
Get the PCI function type of a DOCA devinfo_rep.
#define DOCA_DEVINFO_REP_VUID_SIZE
Buffer size to hold VUID. Including a null terminator.
Definition: doca_dev.h:661
DOCA_STABLE doca_error_t doca_devinfo_destroy_list(struct doca_devinfo **dev_list)
Destroy list of local device info structures.
DOCA_STABLE doca_error_t doca_dev_open(struct doca_devinfo *devinfo, struct doca_dev **dev)
Initialize local device for use.
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_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_NOT_FOUND
Definition: doca_error.h:54
@ DOCA_SUCCESS
Definition: doca_error.h:38
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
doca_pci_func_type
Specifies the PCI function type for DOCA representor device.
Definition: doca_types.h:105
@ DOCA_PCI_FUNC_TYPE_PF
Definition: doca_types.h:106
@ DOCA_PCI_FUNC_TYPE_VF
Definition: doca_types.h:107
@ DOCA_PCI_FUNC_TYPE_SF
Definition: doca_types.h:108
struct doca_devemu_vfs_type * vfs_type