NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
nvmf_rpc.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 "spdk/log.h"
27 #include "spdk/rpc.h"
28 #include "spdk/util.h"
29 
30 #include <doca_dev.h>
31 
32 #include <doca_ctx.h>
33 #include <doca_devemu_pci.h>
34 #include <doca_devemu_pci_type.h>
35 #include <doca_error.h>
36 #include <doca_log.h>
37 
38 #include "nvme_pci_common.h"
39 #include "nvme_pci_type_config.h"
40 
41 /*
42  * List all DOCA devices that are emulation manager
43  *
44  * Implements the nvmf_doca_get_managers SPDK RPC call
45  *
46  * @request [in]: The RPC request json object
47  * @params [in]: The RPC parameters json object
48  */
49 static void rpc_nvmf_doca_get_managers(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
50 {
51  (void)params;
52 
53  struct doca_devinfo **dev_list;
54  uint32_t nb_devs;
56  uint8_t is_hotplug_manager;
57  doca_error_t ret;
58  struct spdk_json_write_ctx *w;
59 
60  ret = doca_devinfo_create_list(&dev_list, &nb_devs);
61  if (ret != DOCA_SUCCESS) {
62  spdk_jsonrpc_send_error_response(request,
63  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
64  "doca_devinfo_create_list failed\n");
65  return;
66  }
67 
68  w = spdk_jsonrpc_begin_result(request);
69  spdk_json_write_array_begin(w);
70  for (uint32_t idx = 0; idx < nb_devs; idx++) {
71  ret = doca_devinfo_cap_is_hotplug_manager_supported(dev_list[idx], &is_hotplug_manager);
72  if (ret == DOCA_SUCCESS && is_hotplug_manager) {
73  ret = doca_devinfo_get_ibdev_name(dev_list[idx], name, 64);
74  if (ret == DOCA_SUCCESS) {
75  spdk_json_write_object_begin(w);
76  spdk_json_write_named_string(w, "name", name);
77  spdk_json_write_object_end(w);
78  } else
79  SPDK_ERRLOG("failed to get ibdev name %d\n", ret);
80  }
81  }
82  spdk_json_write_array_end(w);
83  doca_devinfo_destroy_list(dev_list);
84  spdk_jsonrpc_end_result(request, w);
85 }
86 SPDK_RPC_REGISTER("nvmf_doca_get_managers", rpc_nvmf_doca_get_managers, SPDK_RPC_RUNTIME);
87 
92  char *dev_name;
93 };
94 
96 {
97  free(in->dev_name);
98 }
99 
100 static const struct spdk_json_object_decoder nvmf_doca_create_function_decoder[] = {
101  {"dev-name", offsetof(struct nvmf_doca_create_function_in, dev_name), spdk_json_decode_string, true},
102 };
103 
104 /*
105  * Creates an emulated function
106  *
107  * Implements the nvmf_doca_create_function SPDK RPC call
108  *
109  * @request [in]: The RPC request json object
110  * @params [in]: The RPC parameters json object
111  */
112 static void rpc_nvmf_doca_create_function(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
113 {
114  struct nvmf_doca_create_function_in attr = {0};
115  struct doca_dev_rep *dev_rep;
116  char buf[DOCA_DEVINFO_REP_VUID_SIZE];
117  struct spdk_json_write_ctx *w;
118  struct doca_devemu_pci_type *pci_type = {0};
119  struct doca_dev *dev = {0};
120  doca_error_t ret;
121 
122  if (params == NULL || spdk_json_decode_object(params,
124  SPDK_COUNTOF(nvmf_doca_create_function_decoder),
125  &attr)) {
126  spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
127  goto cleanup;
128  }
129 
130  ret = create_find_start_pci_type(attr.dev_name, &pci_type, &dev);
131  if (ret != DOCA_SUCCESS) {
132  spdk_jsonrpc_send_error_response(request,
133  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
134  "Couldn't find supported devices");
135  goto cleanup;
136  }
137 
138  ret = doca_devemu_pci_dev_create_rep(pci_type, &dev_rep);
139  if (ret != DOCA_SUCCESS) {
140  spdk_jsonrpc_send_error_response(request,
141  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
142  "Couldn't create the device representor\n");
143  goto destroy_pci_resources;
144  }
145 
147  if (ret != DOCA_SUCCESS) {
148  spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Couldnt get device VUID");
149  goto destroy_dev_rep;
150  }
151 
152  ret = doca_dev_rep_close(dev_rep);
153  if (ret != DOCA_SUCCESS) {
154  spdk_jsonrpc_send_error_response(request,
155  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
156  "Unable to cloes the device");
157  goto destroy_dev_rep;
158  }
159 
160  w = spdk_jsonrpc_begin_result(request);
161 
162  spdk_json_write_object_begin(w);
163  spdk_json_write_named_string(w, "Created a function with vuid", buf);
164  spdk_json_write_object_end(w);
165 
166  spdk_jsonrpc_end_result(request, w);
167 
168  goto destroy_pci_resources;
169 
170 destroy_dev_rep:
172 destroy_pci_resources:
173  cleanup_pci_resources(pci_type, dev);
174 cleanup:
176 }
177 SPDK_RPC_REGISTER("nvmf_doca_create_function", rpc_nvmf_doca_create_function, SPDK_RPC_RUNTIME);
178 
183  char *dev_name;
184  char *vuid;
185 };
186 
188 {
189  free(in->dev_name);
190  free(in->vuid);
191 }
192 
193 static const struct spdk_json_object_decoder nvmf_doca_destroy_function_decoder[] = {
194  {"dev-name", offsetof(struct nvmf_doca_destroy_function_in, dev_name), spdk_json_decode_string, true},
195  {"vuid", offsetof(struct nvmf_doca_destroy_function_in, vuid), spdk_json_decode_string, true},
196 };
197 
198 /*
199  * Destroys an emulated function
200  *
201  * Implements the nvmf_doca_destroy_function SPDK RPC call
202  *
203  * @request [in]: The RPC request json object
204  * @params [in]: The RPC parameters json object
205  */
206 static void rpc_nvmf_doca_destroy_function(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
207 {
208  struct nvmf_doca_destroy_function_in attr = {0};
209  struct doca_devinfo_rep **devinfo_rep_list;
210  uint32_t nb_devs_reps;
211  struct doca_dev_rep *dev_rep;
212  char buf[DOCA_DEVINFO_REP_VUID_SIZE];
213  doca_error_t ret;
214  struct doca_devemu_pci_type *pci_type = {0};
215  struct doca_dev *dev = {0};
216 
217  if (params == NULL || spdk_json_decode_object(params,
220  &attr)) {
221  spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
222  goto cleanup;
223  }
224 
225  ret = create_find_start_pci_type(attr.dev_name, &pci_type, &dev);
226  if (ret != DOCA_SUCCESS) {
227  spdk_jsonrpc_send_error_response(request,
228  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
229  "Couldn't find supported devices");
230  goto cleanup;
231  }
232 
233  ret = doca_devemu_pci_type_create_rep_list(pci_type, &devinfo_rep_list, &nb_devs_reps);
234  if (ret != DOCA_SUCCESS) {
235  spdk_jsonrpc_send_error_response(request,
236  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
237  "Couldn't create the device representors list\n");
238  cleanup_pci_resources(pci_type, dev);
239  goto cleanup;
240  }
241 
242  for (uint32_t i = 0; i < nb_devs_reps; i++) {
243  ret = doca_devinfo_rep_get_vuid(devinfo_rep_list[i], buf, DOCA_DEVINFO_REP_VUID_SIZE);
244  if (ret == DOCA_SUCCESS && (strncmp(buf, attr.vuid, DOCA_DEVINFO_REP_VUID_SIZE) == 0)) {
245  ret = doca_dev_rep_open(devinfo_rep_list[i], &dev_rep);
246  if (ret != DOCA_SUCCESS) {
247  spdk_jsonrpc_send_error_response(request,
248  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
249  "Couldn't open the device representor");
250  cleanup_pci_resources(pci_type, dev);
251  }
252 
253  ret = doca_devemu_pci_dev_destroy_rep(dev_rep);
254  if (ret != DOCA_SUCCESS) {
255  spdk_jsonrpc_send_error_response(request,
256  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
257  "Couldn't destroy device representor");
258  doca_dev_rep_close(dev_rep);
259  cleanup_pci_resources(pci_type, dev);
260  }
261  doca_devinfo_rep_destroy_list(devinfo_rep_list);
262  cleanup_pci_resources(pci_type, dev);
263  spdk_jsonrpc_send_bool_response(request, true);
264  goto cleanup;
265  }
266  }
267 
268  doca_devinfo_rep_destroy_list(devinfo_rep_list);
269  cleanup_pci_resources(pci_type, dev);
270  spdk_jsonrpc_send_error_response(request,
271  SPDK_JSONRPC_ERROR_INVALID_PARAMS,
272  "device representor with requested vuid doesn't exist");
273 
274 cleanup:
276 }
277 SPDK_RPC_REGISTER("nvmf_doca_destroy_function", rpc_nvmf_doca_destroy_function, SPDK_RPC_RUNTIME);
278 
283  char *dev_name;
284 };
285 
287 {
288  free(in->dev_name);
289 }
290 
291 static const struct spdk_json_object_decoder nvmf_doca_list_functions_decoder[] = {
292  {"dev-name", offsetof(struct nvmf_doca_list_functions_in, dev_name), spdk_json_decode_string, true},
293 };
294 
295 /*
296  * Lists the emulated functions
297  *
298  * Implements the nvmf_doca_list_functions SPDK RPC call
299  *
300  * @request [in]: The RPC request json object
301  * @params [in]: The RPC parameters json object
302  */
303 static void rpc_nvmf_doca_list_functions(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
304 {
305  struct nvmf_doca_list_functions_in attr = {0};
306  struct doca_devinfo_rep **devinfo_rep_list;
307  struct spdk_json_write_ctx *w;
308  uint32_t nb_devs_reps;
309  struct doca_devemu_pci_type *pci_type = {0};
310  struct doca_dev *dev = {0};
311  doca_error_t ret;
312  char buf[DOCA_DEVINFO_REP_VUID_SIZE];
313 
314  if (params == NULL || spdk_json_decode_object(params,
316  SPDK_COUNTOF(nvmf_doca_list_functions_decoder),
317  &attr)) {
318  spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
319  goto cleanup;
320  }
321 
322  ret = create_find_start_pci_type(attr.dev_name, &pci_type, &dev);
323  if (ret != DOCA_SUCCESS) {
324  spdk_jsonrpc_send_error_response(request,
325  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
326  "Couldn't find supported devices");
327  goto cleanup;
328  }
329 
330  ret = doca_devemu_pci_type_create_rep_list(pci_type, &devinfo_rep_list, &nb_devs_reps);
331  if (ret != DOCA_SUCCESS) {
332  spdk_jsonrpc_send_error_response(request,
333  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
334  "Couldn't create the device representors list\n");
335  cleanup_pci_resources(pci_type, dev);
336  goto cleanup;
337  }
338 
339  w = spdk_jsonrpc_begin_result(request);
340  spdk_json_write_array_begin(w);
341 
342  for (uint32_t i = 0; i < nb_devs_reps; i++) {
343  char rep_pci[DOCA_DEVINFO_REP_PCI_ADDR_SIZE];
344 
345  spdk_json_write_object_begin(w);
346 
347  ret = doca_devinfo_rep_get_vuid(devinfo_rep_list[i], buf, DOCA_DEVINFO_REP_VUID_SIZE);
348  if (ret != DOCA_SUCCESS) {
349  spdk_jsonrpc_send_error_response(request,
350  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
351  "Couldnt get device VUID");
352  doca_devinfo_rep_destroy_list(devinfo_rep_list);
353  cleanup_pci_resources(pci_type, dev);
354  goto cleanup;
355  }
356  ret = doca_devinfo_rep_get_pci_addr_str(devinfo_rep_list[i], rep_pci);
357  if (ret != DOCA_SUCCESS) {
358  spdk_jsonrpc_send_error_response(request,
359  SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
360  "Couldnt get PCI address");
361  doca_devinfo_rep_destroy_list(devinfo_rep_list);
362  cleanup_pci_resources(pci_type, dev);
363  goto cleanup;
364  }
365 
366  spdk_json_write_named_string(w, "Function VUID: ", buf);
367  spdk_json_write_named_string(w, "PCI Address: ", rep_pci);
368  spdk_json_write_object_end(w);
369  }
370 
371  spdk_json_write_array_end(w);
372  doca_devinfo_rep_destroy_list(devinfo_rep_list);
373  cleanup_pci_resources(pci_type, dev);
374  spdk_jsonrpc_end_result(request, w);
375 
376 cleanup:
378 }
379 SPDK_RPC_REGISTER("nvmf_doca_list_functions", rpc_nvmf_doca_list_functions, SPDK_RPC_RUNTIME);
#define NULL
Definition: __stddef_null.h:26
#define offsetof(t, d)
static void cleanup(struct cache_invalidate_sample_state *state)
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 doca_error_t doca_devemu_pci_dev_create_rep(const struct doca_devemu_pci_type *pci_type, struct doca_dev_rep **dev_rep)
Create a new representor device for a given DOCA devemu PCI type.
DOCA_EXPERIMENTAL doca_error_t doca_devemu_pci_dev_destroy_rep(struct doca_dev_rep *rep_dev)
Destroy a representor device created by doca_devemu_pci_dev_create_rep().
DOCA_STABLE doca_error_t doca_dev_rep_open(struct doca_devinfo_rep *devinfo, struct doca_dev_rep **dev_rep)
Initialize representor device for use.
DOCA_STABLE doca_error_t doca_devinfo_cap_is_hotplug_manager_supported(const struct doca_devinfo *devinfo, uint8_t *is_hotplug_manager)
Get the hotplug manager capability of 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_dev_rep_close(struct doca_dev_rep *dev)
Destroy allocated representor device instance.
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_get_ibdev_name(const struct doca_devinfo *devinfo, char *ibdev_name, uint32_t size)
Get the name of the IB device represented by a DOCA devinfo.
#define DOCA_DEVINFO_IBDEV_NAME_SIZE
Buffer size to hold Infiniband/RoCE device name. Including a null terminator.
Definition: doca_dev.h:309
#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 struct doca_devinfo_rep * doca_dev_rep_as_devinfo(struct doca_dev_rep *dev_rep)
Get representor device info from device. This should be useful when wanting to query information abou...
enum doca_error doca_error_t
DOCA API return codes.
@ DOCA_SUCCESS
Definition: doca_error.h:38
void cleanup_pci_resources(struct doca_devemu_pci_type *pci_type, struct doca_dev *dev)
doca_error_t create_find_start_pci_type(char *dev_name, struct doca_devemu_pci_type **pci_type, struct doca_dev **dev)
static void rpc_nvmf_doca_get_managers(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
Definition: nvmf_rpc.c:49
static void free_rpc_nvmf_doca_create_function(struct nvmf_doca_create_function_in *in)
Definition: nvmf_rpc.c:95
static void rpc_nvmf_doca_destroy_function(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
Definition: nvmf_rpc.c:206
static void rpc_nvmf_doca_list_functions(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
Definition: nvmf_rpc.c:303
static const struct spdk_json_object_decoder nvmf_doca_destroy_function_decoder[]
Definition: nvmf_rpc.c:193
static void free_rpc_nvmf_doca_destroy_function(struct nvmf_doca_destroy_function_in *in)
Definition: nvmf_rpc.c:187
static const struct spdk_json_object_decoder nvmf_doca_create_function_decoder[]
Definition: nvmf_rpc.c:100
static void free_rpc_nvmf_doca_list_functions(struct nvmf_doca_list_functions_in *in)
Definition: nvmf_rpc.c:286
static const struct spdk_json_object_decoder nvmf_doca_list_functions_decoder[]
Definition: nvmf_rpc.c:291
SPDK_RPC_REGISTER("nvmf_doca_get_managers", rpc_nvmf_doca_get_managers, SPDK_RPC_RUNTIME)
static void rpc_nvmf_doca_create_function(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
Definition: nvmf_rpc.c:112