NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
dpa_all_to_all_core.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022-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 <stdlib.h>
27 #include <unistd.h>
28 #include <limits.h>
29 #include <math.h>
30 #include <time.h>
31 
32 #include <doca_ctx.h>
33 #include <doca_dev.h>
34 #include <doca_log.h>
35 
36 #include "dpa_all_to_all_core.h"
37 
38 #define MAX_MPI_WAIT_TIME (10) /* Maximum time to wait on MPI request */
39 #define SLEEP_IN_NANO_SEC (100000000) /* Sleeping interval for completion polling */
40 
41 DOCA_LOG_REGISTER(A2A::Core);
42 
43 /*
44  * A struct that includes all needed info on registered kernels and is initialized during linkage by DPACC.
45  * Variable name should be the token passed to DPACC with --app-name parameter.
46  */
47 extern struct doca_dpa_app *dpa_all2all_app;
48 
49 /* IB devices names */
54 
55 /* DOCA DPA all to all kernel function pointer */
57 
58 /*
59  * Calculate the width of the integers (according to the number of digits)
60  * Note that this functions wouldn't work for n = MIN_INT however in the usage of this function here is guaranteed not
61  * to use such values.
62  *
63  * @n [in]: An integer
64  * @return: The width of the integer on success and negative value otherwise
65  */
66 static int calc_width(int n)
67 {
68  if (n < 0)
69  n = -n;
70  if (n < 10)
71  return 1;
72  return floor(log10(n) + 1);
73 }
74 
75 /*
76  * Print buffer as a matrix
77  *
78  * @buff [in]: A buffer of integers
79  * @columns [in]: Number of columns
80  * @rows [in]: Number of rows
81  */
82 static void print_buff(const int *buff, size_t columns, size_t rows)
83 {
84  int max_wdt1 = 0;
85  int max_wdt2 = 0;
86  int tmp, wdt, i, j;
87  const int *tmp_buff = buff;
88 
89  for (i = 0; i < columns * rows; i++) {
90  tmp = calc_width(buff[i]);
91  max_wdt1 = (tmp > max_wdt1) ? tmp : max_wdt1;
92  }
93  max_wdt2 = calc_width(rows);
94  for (j = 0; j < rows; j++) {
95  printf("Rank %d", j);
96  wdt = calc_width(j);
97  for (; wdt < max_wdt2; wdt++)
98  printf(" ");
99  printf(" |");
100  for (i = 0; i < columns - 1; i++) {
101  wdt = calc_width(tmp_buff[i]);
102  printf("%d ", tmp_buff[i]);
103  for (; wdt < max_wdt1; wdt++)
104  printf(" ");
105  }
106  printf("%d", tmp_buff[columns - 1]);
107  wdt = calc_width(tmp_buff[columns - 1]);
108  for (; wdt < max_wdt1; wdt++)
109  printf(" ");
110  printf("|\n");
111  tmp_buff += columns;
112  }
113 }
114 
115 /*
116  * Generate a random integer between 0 and 10000
117  *
118  * @return: A random integer between 0 and 10000 on success and negative value otherwise
119  */
120 static int compute_random_int(void)
121 {
122  return (rand() % 10000);
123 }
124 
125 /*
126  * Wait for MPI request to finish or until timeout
127  *
128  * @req [in]: MPI request
129  * @timeout [in]: Maximum time to wait on request, in seconds
130  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
131  */
132 static doca_error_t mpi_request_wait_timeout(MPI_Request *req, size_t timeout)
133 {
134  time_t now = time(NULL);
135  int status;
136 
137  MPI_Test(req, &status, MPI_STATUS_IGNORE);
138  /* Wait until request returns true or timeout */
139  while (status == 0 && (time(NULL) < now + timeout))
140  MPI_Test(req, &status, MPI_STATUS_IGNORE);
141 
142  /* Return success if request finishes and error otherwise */
143  if (status)
144  return DOCA_SUCCESS;
145  else
146  return DOCA_ERROR_TIME_OUT;
147 }
148 
149 bool dpa_device_exists_check(const char *device_name)
150 {
151  struct doca_devinfo **dev_list;
152  uint32_t nb_devs = 0;
154  bool exists = false;
155  char ibdev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE] = {0};
156  int i = 0;
157 
158  /* If it's the default then return true */
159  if (strncmp(device_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) == 0)
160  return true;
161 
162  result = doca_devinfo_create_list(&dev_list, &nb_devs);
163  if (result != DOCA_SUCCESS) {
164  DOCA_LOG_ERR("Failed to load DOCA devices list: %s", doca_error_get_descr(result));
165  return false;
166  }
167 
168  /* Search device with same dev name*/
169  for (i = 0; i < nb_devs; i++) {
170  result = doca_dpa_cap_is_supported(dev_list[i]);
171  if (result != DOCA_SUCCESS)
172  continue;
173 
174  result = doca_devinfo_get_ibdev_name(dev_list[i], ibdev_name, sizeof(ibdev_name));
175  if (result != DOCA_SUCCESS)
176  continue;
177 
178  /* Check if we found the device with the wanted name */
179  if (strncmp(device_name, ibdev_name, MAX_IB_DEVICE_NAME_LEN) == 0) {
180  exists = true;
181  break;
182  }
183  }
184 
185  doca_devinfo_destroy_list(dev_list);
186 
187  return exists;
188 }
189 
190 bool rdma_device_exists_check(const char *device_name)
191 {
192  struct doca_devinfo **dev_list;
193  uint32_t nb_devs = 0;
195  bool exists = false;
196  char ibdev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE] = {0};
197  int i = 0;
198 
199  /* If it's the default then return true */
200  if (strncmp(device_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) == 0)
201  return true;
202 
203  result = doca_devinfo_create_list(&dev_list, &nb_devs);
204  if (result != DOCA_SUCCESS) {
205  DOCA_LOG_ERR("Failed to load DOCA devices list: %s", doca_error_get_descr(result));
206  return false;
207  }
208 
209  /* Search device with same dev name*/
210  for (i = 0; i < nb_devs; i++) {
212  if (result != DOCA_SUCCESS)
213  continue;
214 
215  result = doca_devinfo_get_ibdev_name(dev_list[i], ibdev_name, sizeof(ibdev_name));
216  if (result != DOCA_SUCCESS)
217  continue;
218 
219  /* Check if we found the device with the wanted name */
220  if (strncmp(device_name, ibdev_name, MAX_IB_DEVICE_NAME_LEN) == 0) {
221  exists = true;
222  break;
223  }
224  }
225 
226  doca_devinfo_destroy_list(dev_list);
227 
228  return exists;
229 }
230 
231 /*
232  * Open DPA DOCA devices
233  *
234  * When running from DPU, rdma_doca_device will be opened for SF DOCA device with RDMA capability.
235  * When running from Host, returned rdma_doca_device is equal to pf_doca_device.
236  *
237  * @pf_device_name [in]: Wanted PF device name, can be NOT_SET and then a random DPA supported device is chosen
238  * @rdma_device_name [in]: Relevant when running from DPU. Wanted RDMA device name, can be NOT_SET and then a random
239  * RDMA supported device is chosen
240  * @pf_doca_device [out]: An allocated PF DOCA device on success and NULL otherwise
241  * @rdma_doca_device [out]: An allocated RDMA DOCA device on success and NULL otherwise
242  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
243  */
244 static doca_error_t open_dpa_devices(const char *pf_device_name,
245  const char *rdma_device_name,
246  struct doca_dev **pf_doca_device,
247  struct doca_dev **rdma_doca_device)
248 {
249  struct doca_devinfo **dev_list;
250  uint32_t nb_devs = 0;
251  doca_error_t result, dpa_cap;
252  char ibdev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE] = {0};
253  char actual_base_ibdev_name[DOCA_DEVINFO_IBDEV_NAME_SIZE] = {0};
254  uint32_t i = 0;
255 
256  if (strcmp(pf_device_name, IB_DEVICE_DEFAULT_NAME) != 0 &&
257  strcmp(rdma_device_name, IB_DEVICE_DEFAULT_NAME) != 0 && strcmp(pf_device_name, rdma_device_name) == 0) {
258  DOCA_LOG_ERR("RDMA DOCA device must be different than PF DOCA device (%s)", pf_device_name);
260  }
261 
262  result = doca_devinfo_create_list(&dev_list, &nb_devs);
263  if (result != DOCA_SUCCESS) {
264  DOCA_LOG_ERR("Failed to load DOCA devices list: %s", doca_error_get_descr(result));
265  return result;
266  }
267 
268  for (i = 0; i < nb_devs; i++) {
269  result = doca_devinfo_get_ibdev_name(dev_list[i], ibdev_name, sizeof(ibdev_name));
270  if (result != DOCA_SUCCESS) {
271  continue;
272  }
273 
274 #ifdef DOCA_ARCH_DPU
275  doca_error_t rdma_cap = doca_rdma_cap_task_send_is_supported(dev_list[i]);
276  if (*rdma_doca_device == NULL && rdma_cap == DOCA_SUCCESS) {
277  /* to be able to extend rdma device later on (if needed), it must be a different device */
278  if (strcmp(ibdev_name, actual_base_ibdev_name) == 0) {
279  continue;
280  }
281  if (strncmp(rdma_device_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) == 0 ||
282  strncmp(rdma_device_name, ibdev_name, MAX_IB_DEVICE_NAME_LEN) == 0) {
283  result = doca_dev_open(dev_list[i], rdma_doca_device);
284  if (result != DOCA_SUCCESS) {
285  doca_devinfo_destroy_list(dev_list);
286  DOCA_LOG_ERR("Failed to open DOCA device %s: %s",
287  ibdev_name,
289  return result;
290  }
291  }
292  }
293 #endif
294 
295  dpa_cap = doca_dpa_cap_is_supported(dev_list[i]);
296  if (*pf_doca_device == NULL && dpa_cap == DOCA_SUCCESS) {
297  if (strncmp(pf_device_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) == 0 ||
298  strncmp(pf_device_name, ibdev_name, MAX_IB_DEVICE_NAME_LEN) == 0) {
299  result = doca_dev_open(dev_list[i], pf_doca_device);
300  if (result != DOCA_SUCCESS) {
301  doca_devinfo_destroy_list(dev_list);
302  DOCA_LOG_ERR("Failed to open DOCA device %s: %s",
303  ibdev_name,
305  return result;
306  }
307  strncpy(actual_base_ibdev_name, ibdev_name, DOCA_DEVINFO_IBDEV_NAME_SIZE);
308  }
309  }
310  }
311 
312  doca_devinfo_destroy_list(dev_list);
313 
314  if (*pf_doca_device == NULL) {
315  DOCA_LOG_ERR("Couldn't get PF DOCA device");
316  return DOCA_ERROR_NOT_FOUND;
317  }
318 
319 #ifdef DOCA_ARCH_DPU
320  if (*rdma_doca_device == NULL) {
321  DOCA_LOG_ERR("Couldn't get RDMA DOCA device");
322  return DOCA_ERROR_NOT_FOUND;
323  }
324 #else
325  *rdma_doca_device = *pf_doca_device;
326 #endif
327 
328  return result;
329 }
330 
331 /*
332  * Create DOCA DPA context
333  *
334  * @resources [in/out]: All to all resources
335  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
336  */
338 {
339  doca_error_t result, tmp_result;
340 
341  /* Open doca devices */
342  result = open_dpa_devices(resources->pf_device_name,
343  resources->rdma_device_name,
344  &(resources->pf_doca_device),
345  &(resources->rdma_doca_device));
346  if (result != DOCA_SUCCESS) {
347  DOCA_LOG_ERR("open_dpa_devices() failed");
348  return result;
349  }
350 
351  /* Create doca_dpa context */
352  result = doca_dpa_create(resources->pf_doca_device, &(resources->pf_doca_dpa));
353  if (result != DOCA_SUCCESS) {
354  DOCA_LOG_ERR("Failed to create DOCA DPA context: %s", doca_error_get_descr(result));
355  goto close_doca_dev;
356  }
357 
358  /* Set doca_dpa app */
360  if (result != DOCA_SUCCESS) {
361  DOCA_LOG_ERR("Failed to set DOCA DPA app: %s", doca_error_get_descr(result));
362  goto destroy_doca_dpa;
363  }
364 
365  /* Start doca_dpa context */
366  result = doca_dpa_start(resources->pf_doca_dpa);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to start DOCA DPA context: %s", doca_error_get_descr(result));
369  goto destroy_doca_dpa;
370  }
371 
372 #ifdef DOCA_ARCH_DPU
373  if (resources->rdma_doca_device != resources->pf_doca_device) {
374  result = doca_dpa_device_extend(resources->pf_doca_dpa,
375  resources->rdma_doca_device,
376  &resources->rdma_doca_dpa);
377  if (result != DOCA_SUCCESS) {
378  DOCA_LOG_ERR("Failed to extend DOCA DPA context: %s", doca_error_get_descr(result));
379  goto destroy_doca_dpa;
380  }
381 
382  result = doca_dpa_get_dpa_handle(resources->rdma_doca_dpa, &resources->rdma_doca_dpa_handle);
383  if (result != DOCA_SUCCESS) {
384  DOCA_LOG_ERR("Failed to get DOCA DPA context handle: %s", doca_error_get_descr(result));
385  goto destroy_rdma_doca_dpa;
386  }
387  } else {
388  resources->rdma_doca_dpa = resources->pf_doca_dpa;
389  }
390 #else
391  resources->rdma_doca_dpa = resources->pf_doca_dpa;
392 #endif
393 
394  return result;
395 
396 #ifdef DOCA_ARCH_DPU
397 destroy_rdma_doca_dpa:
398  tmp_result = doca_dpa_destroy(resources->rdma_doca_dpa);
399  if (tmp_result != DOCA_SUCCESS) {
400  DOCA_LOG_ERR("Failed to destroy DOCA DPA context: %s", doca_error_get_descr(tmp_result));
401  DOCA_ERROR_PROPAGATE(result, tmp_result);
402  }
403 #endif
404 destroy_doca_dpa:
405  tmp_result = doca_dpa_destroy(resources->pf_doca_dpa);
406  if (tmp_result != DOCA_SUCCESS) {
407  DOCA_LOG_ERR("Failed to destroy DOCA DPA context: %s", doca_error_get_descr(tmp_result));
408  DOCA_ERROR_PROPAGATE(result, tmp_result);
409  }
410 close_doca_dev:
411  tmp_result = doca_dev_close(resources->pf_doca_device);
412  if (tmp_result != DOCA_SUCCESS) {
413  DOCA_LOG_ERR("Failed to close DOCA DPA device: %s", doca_error_get_descr(tmp_result));
414  DOCA_ERROR_PROPAGATE(result, tmp_result);
415  }
416 #ifdef DOCA_ARCH_DPU
417  tmp_result = doca_dev_close(resources->rdma_doca_device);
418  if (tmp_result != DOCA_SUCCESS) {
419  DOCA_LOG_ERR("Failed to close DOCA DPA device: %s", doca_error_get_descr(tmp_result));
420  DOCA_ERROR_PROPAGATE(result, tmp_result);
421  }
422 #endif
423 
424  return result;
425 }
426 
427 /*
428  * Create DOCA mmap
429  *
430  * @doca_device [in]: device to associate to mmap context
431  * @mmap_permissions [in]: capabilities enabled on the mmap
432  * @memrange_addr [in]: memrange address to set on the mmap
433  * @memrange_len [in]: length of memrange to set on the mmap
434  * @mmap [out]: Created mmap
435  * @dpa_mmap_handle [out]: Created DPA mmap handle
436  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
437  */
438 static doca_error_t create_mmap(struct doca_dev *doca_device,
439  unsigned int mmap_permissions,
440  void *memrange_addr,
441  size_t memrange_len,
442  struct doca_mmap **mmap,
444 {
446  doca_error_t tmp_result;
447 
448  /* Creating DOCA mmap */
450  if (result != DOCA_SUCCESS) {
451  DOCA_LOG_ERR("Failed to create DOCA mmap: %s", doca_error_get_descr(result));
452  return result;
453  }
454 
455  /* Add DOCA device to DOCA mmap */
456  result = doca_mmap_add_dev(*mmap, doca_device);
457  if (result != DOCA_SUCCESS) {
458  DOCA_LOG_ERR("Failed to add DOCA device: %s", doca_error_get_descr(result));
459  goto destroy_mmap;
460  }
461 
462  /* Set permissions for DOCA mmap */
463  result = doca_mmap_set_permissions(*mmap, mmap_permissions);
464  if (result != DOCA_SUCCESS) {
465  DOCA_LOG_ERR("Failed to set permissions for DOCA mmap: %s", doca_error_get_descr(result));
466  goto destroy_mmap;
467  }
468 
469  /* Set memrange for DOCA mmap */
470  result = doca_mmap_set_memrange(*mmap, memrange_addr, memrange_len);
471  if (result != DOCA_SUCCESS) {
472  DOCA_LOG_ERR("Failed to set memrange for DOCA mmap: %s", doca_error_get_descr(result));
473  goto destroy_mmap;
474  }
475 
476  /* Start DOCA mmap */
478  if (result != DOCA_SUCCESS) {
479  DOCA_LOG_ERR("Failed to start DOCA mmap: %s", doca_error_get_descr(result));
480  goto destroy_mmap;
481  }
482 
483  /* Get DOCA mmap DPA handle */
485  if (result != DOCA_SUCCESS) {
486  DOCA_LOG_ERR("Failed to get DOCA mmap DPA handle: %s", doca_error_get_descr(result));
487  goto destroy_mmap;
488  }
489 
490  return result;
491 
492 destroy_mmap:
493  /* destroy DOCA mmap */
494  tmp_result = doca_mmap_destroy(*mmap);
495  if (tmp_result != DOCA_SUCCESS) {
496  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
497  DOCA_ERROR_PROPAGATE(result, tmp_result);
498  }
499  return result;
500 }
501 
502 /*
503  * Create DOCA sync event from remote net export and its DPA handle
504  *
505  * @doca_dpa [in]: DOCA DPA context
506  * @doca_device [in]: DOCA device
507  * @remote_event_export_data [in]: export data of the remote net DOCA sync event to create
508  * @remote_event_export_size [in]: export size of the remote net DOCA sync event to create
509  * @remote_event [out]: Created remote net DOCA sync event
510  * @remote_event_dpa_handle [out]: DPA handle for the created remote net DOCA sync event
511  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
512  */
513 static doca_error_t create_doca_dpa_sync_event_from_export(struct doca_dpa *doca_dpa,
514  struct doca_dev *doca_device,
515  const uint8_t *remote_event_export_data,
516  size_t remote_event_export_size,
517  struct doca_sync_event_remote_net **remote_event,
518  doca_dpa_dev_sync_event_remote_net_t *remote_event_dpa_handle)
519 {
520  doca_error_t result, tmp_result;
521 
523  remote_event_export_data,
524  remote_event_export_size,
525  remote_event);
526  if (result != DOCA_SUCCESS) {
527  DOCA_LOG_ERR("Failed to create remote net DOCA sync event: %s", doca_error_get_descr(result));
528  return result;
529  }
530 
531  result = doca_sync_event_remote_net_get_dpa_handle(*remote_event, doca_dpa, remote_event_dpa_handle);
532  if (result != DOCA_SUCCESS) {
533  DOCA_LOG_ERR("Failed to export remote net DOCA sync event to DPA: %s", doca_error_get_descr(result));
534  goto destroy_remote_event;
535  }
536 
537  return result;
538 
539 destroy_remote_event:
540  tmp_result = doca_sync_event_remote_net_destroy(*remote_event);
541  if (tmp_result != DOCA_SUCCESS) {
542  DOCA_LOG_ERR("Failed to destroy remote net DOCA sync event: %s", doca_error_get_descr(tmp_result));
543  DOCA_ERROR_PROPAGATE(result, tmp_result);
544  }
545  return result;
546 }
547 
548 /*
549  * Prepare the memory needed for the DOCA DPA all to all, including the sendbuf and recvbufs memory handlers and remote
550  * keys, and getting the remote recvbufs addresses from the remote processes.
551  *
552  * @resources [in/out]: All to all resources
553  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
554  */
556 {
557  /* DOCA mmap recvbuf rdma export */
558  const void *recv_mmap_export;
559  /* DOCA mmap recvbuf rdma export length */
560  size_t recv_mmap_export_len;
561  /* DOCA mmap exports of remote processes */
562  void **recvbufs_mmap_exports = NULL;
563  /* DOCA mmap exports lengths of remote processes */
564  size_t *recvbufs_mmap_exports_lens = NULL;
565  /* Host memory for all remote processes recvbufs */
566  uintptr_t *recvbufs = NULL;
567  /*
568  * Define DOCA DPA host memory access flags
569  * mem_access_read gives read access to the sendbuf
570  * mem_access_write gives write access to the recvbuf
571  */
572  const unsigned int mem_access_read = DOCA_ACCESS_FLAG_LOCAL_READ_ONLY | DOCA_ACCESS_FLAG_RDMA_READ;
573  const unsigned int mem_access_write = DOCA_ACCESS_FLAG_LOCAL_READ_WRITE | DOCA_ACCESS_FLAG_RDMA_WRITE;
574  /* Size of the buffers (send and receive) */
575  size_t buf_size;
576  MPI_Aint lb, extent;
577  MPI_Request reqs[5];
578  doca_error_t result, tmp_result;
579  int i, j;
580  doca_dpa_dev_mmap_t recvbuf_dpa_mmap_handle;
581 
582  /* Get the extent of the datatype and calculate the size of the buffers */
583  MPI_Type_get_extent(resources->msg_type, &lb, &extent);
584  buf_size = extent * resources->mesg_count * resources->num_ranks;
585  resources->extent = extent;
586 
587  /* create mmap for process send buff */
588  result = create_mmap(resources->rdma_doca_device,
589  mem_access_read,
590  resources->sendbuf,
591  buf_size,
592  &(resources->sendbuf_mmap),
593  &(resources->sendbuf_dpa_mmap_handle));
594  if (result != DOCA_SUCCESS) {
595  DOCA_LOG_ERR("Failed to create mmap for sendbuf: %s", doca_error_get_descr(result));
596  return result;
597  }
598 
599  /* create mmap for process receive buff */
600  result = create_mmap(resources->rdma_doca_device,
601  mem_access_write,
602  resources->recvbuf,
603  buf_size,
604  &(resources->recvbuf_mmap),
605  &recvbuf_dpa_mmap_handle);
606  if (result != DOCA_SUCCESS) {
607  DOCA_LOG_ERR("Failed to create mmap for recvbuf: %s", doca_error_get_descr(result));
608  goto destroy_sendbuf_mmap;
609  }
610 
611  /* create mmap export to the receive buffer for rdma operation */
612  result = doca_mmap_export_rdma(resources->recvbuf_mmap,
613  resources->rdma_doca_device,
614  &recv_mmap_export,
615  &recv_mmap_export_len);
616  if (result != DOCA_SUCCESS) {
617  DOCA_LOG_ERR("Failed to export mmap for recvbuf: %s", doca_error_get_descr(result));
618  goto destroy_recvbuf_mmap;
619  }
620 
621  /* Allocate memory to hold recvbufs mmap exports lengths of all the processes */
622  recvbufs_mmap_exports_lens = (size_t *)calloc(resources->num_ranks, sizeof(*recvbufs_mmap_exports_lens));
623  if (recvbufs_mmap_exports_lens == NULL) {
624  DOCA_LOG_ERR("Failed to allocate memory for recv mmap export lengths");
626  goto destroy_recvbuf_mmap;
627  }
628 
629  /* Allocate memory to hold recvbufs mmap exports of all the processes */
630  recvbufs_mmap_exports = (void **)calloc(resources->num_ranks, recv_mmap_export_len);
631  if (recvbufs_mmap_exports == NULL) {
632  DOCA_LOG_ERR("Failed to allocate memory for recv mmap exports");
634  goto free_mmap_exports_lens;
635  }
636 
637  /* Send the local recvbuf export length and receive all the remote recvbuf exports lengths using Allgather */
638  MPI_Iallgather(&recv_mmap_export_len,
639  sizeof(recv_mmap_export_len),
640  MPI_BYTE,
641  recvbufs_mmap_exports_lens,
642  sizeof(recv_mmap_export_len),
643  MPI_BYTE,
644  resources->comm,
645  &reqs[0]);
646 
648  if (result != DOCA_SUCCESS) {
649  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
650  goto free_mmap_exports;
651  }
652 
653  /* Send the local recvbuf mmap export and receive all the remote recvbuf mmap exports using Allgather */
654  MPI_Iallgather(recv_mmap_export,
655  recv_mmap_export_len,
656  MPI_BYTE,
657  recvbufs_mmap_exports,
658  recv_mmap_export_len,
659  MPI_BYTE,
660  resources->comm,
661  &reqs[1]);
662 
664  if (result != DOCA_SUCCESS) {
665  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
666  goto free_mmap_exports;
667  }
668 
669  resources->export_mmaps = calloc(resources->num_ranks, sizeof(*(resources->export_mmaps)));
670  if (resources->export_mmaps == NULL) {
671  DOCA_LOG_ERR("Failed to allocate memory for export mmaps");
673  goto free_mmap_exports;
674  }
675 
676  resources->export_mmaps_dpa_handle =
677  calloc(resources->num_ranks, sizeof(*(resources->export_mmaps_dpa_handle)));
678  if (resources->export_mmaps_dpa_handle == NULL) {
679  DOCA_LOG_ERR("Failed to allocate memory for export mmaps dpa handle");
681  goto free_export_mmaps;
682  }
683 
684  for (i = 0; i < resources->num_ranks; i++) {
685  /* skip to export index */
686  j = i * recv_mmap_export_len;
687  /* create mmap for process send buff */
689  (const void *)&(((char *)recvbufs_mmap_exports)[j]),
690  recvbufs_mmap_exports_lens[i],
691  resources->rdma_doca_device,
692  &(resources->export_mmaps[i]));
693  if (result != DOCA_SUCCESS) {
694  DOCA_LOG_ERR("Failed to create mmap from export: %s", doca_error_get_descr(result));
695  goto destroy_export_mmaps;
696  }
697 
698  /* Get DOCA mmap DPA handle */
699  result = doca_mmap_dev_get_dpa_handle(resources->export_mmaps[i],
700  resources->rdma_doca_device,
701  &(resources->export_mmaps_dpa_handle[i]));
702  if (result != DOCA_SUCCESS) {
703  DOCA_LOG_ERR("Failed to get DOCA mmap DPA handle: %s", doca_error_get_descr(result));
704  goto destroy_export_mmaps;
705  }
706  }
707 
708  /* Allocate memory to hold recvbufs of all the processes */
709  recvbufs = (uintptr_t *)calloc(resources->num_ranks, sizeof(*(recvbufs)));
710  if (recvbufs == NULL) {
711  DOCA_LOG_ERR("Failed to allocate memory for recvbufs of all the processes");
713  goto destroy_export_mmaps;
714  }
715 
716  /* Send the local recvbuf export length and receive all the remote recvbuf exports lengths using Allgather */
717  MPI_Iallgather(&(resources->recvbuf),
718  sizeof(uintptr_t),
719  MPI_BYTE,
720  (void *)recvbufs,
721  sizeof(uintptr_t),
722  MPI_BYTE,
723  resources->comm,
724  &reqs[2]);
726  if (result != DOCA_SUCCESS) {
727  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
728  goto free_recvbufs;
729  }
730 
731  /* Allocate DPA memory to hold the recvbufs addresses */
732  result = doca_dpa_mem_alloc(resources->rdma_doca_dpa,
733  (resources->num_ranks * sizeof(uintptr_t)),
734  &(resources->devptr_recvbufs));
735  if (result != DOCA_SUCCESS) {
736  DOCA_LOG_ERR("Failed to allocate DOCA DPA memory: %s", doca_error_get_descr(result));
737  goto free_recvbufs;
738  }
739 
740  /* Copy the recvbufs addresses array from the host memory to the device memory */
741  result = doca_dpa_h2d_memcpy(resources->rdma_doca_dpa,
742  resources->devptr_recvbufs,
743  (void *)recvbufs,
744  resources->num_ranks * sizeof(uintptr_t));
745  if (result != DOCA_SUCCESS) {
746  DOCA_LOG_ERR("Failed to copy DOCA DPA memory from host to device: %s", doca_error_get_descr(result));
747  goto free_devptr_recvbufs;
748  }
749 
750  /* Allocate DPA memory to hold the recvbufs mmap handles */
751  result = doca_dpa_mem_alloc(resources->rdma_doca_dpa,
752  (resources->num_ranks * sizeof(doca_dpa_dev_mmap_t)),
753  &(resources->devptr_recvbufs_mmap_handles));
754  if (result != DOCA_SUCCESS) {
755  DOCA_LOG_ERR("Failed to allocate DOCA DPA memory: %s", doca_error_get_descr(result));
756  goto free_devptr_recvbufs;
757  }
758 
759  /* Copy the recvbufs mmap handles array from the host memory to the device memory */
760  result = doca_dpa_h2d_memcpy(resources->rdma_doca_dpa,
761  resources->devptr_recvbufs_mmap_handles,
762  (void *)resources->export_mmaps_dpa_handle,
763  resources->num_ranks * sizeof(doca_dpa_dev_mmap_t));
764  if (result != DOCA_SUCCESS) {
765  DOCA_LOG_ERR("Failed to copy DOCA DPA memory from host to device: %s", doca_error_get_descr(result));
766  goto free_devptr_recvbufs_mmap_handles;
767  }
768 
769  resources->rp_remote_kernel_events_export_sizes =
770  calloc(resources->num_ranks, sizeof(*(resources->rp_remote_kernel_events_export_sizes)));
771  if (resources->rp_remote_kernel_events_export_sizes == NULL) {
772  DOCA_LOG_ERR("Failed to allocate memory for rp_remote_kernel_events_export_sizes");
774  goto free_devptr_recvbufs;
775  }
776 
777  /* Send the local process' remote kernel event and receive all the remote kernel events using Alltoall */
778  MPI_Ialltoall(resources->lp_remote_kernel_events_export_sizes,
779  sizeof(*(resources->lp_remote_kernel_events_export_sizes)),
780  MPI_BYTE,
781  resources->rp_remote_kernel_events_export_sizes,
782  sizeof(*(resources->rp_remote_kernel_events_export_sizes)),
783  MPI_BYTE,
784  resources->comm,
785  &reqs[3]);
786 
788  if (result != DOCA_SUCCESS) {
789  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
790  goto free_remote_kernel_events_exports;
791  }
792 
793  resources->rp_remote_kernel_events_export_data =
794  calloc(resources->num_ranks, resources->rp_remote_kernel_events_export_sizes[0]);
795  if (resources->rp_remote_kernel_events_export_data == NULL) {
796  DOCA_LOG_ERR("Failed to allocate memory for rp_remote_kernel_events_export_data");
798  goto free_remote_kernel_events_exports;
799  }
800 
801  /* Send the local process' remote kernel event and receive all the remote kernel events using Alltoall */
802  MPI_Ialltoall(resources->lp_remote_kernel_events_export_data,
803  resources->lp_remote_kernel_events_export_sizes[0],
804  MPI_BYTE,
805  resources->rp_remote_kernel_events_export_data,
806  resources->rp_remote_kernel_events_export_sizes[0],
807  MPI_BYTE,
808  resources->comm,
809  &reqs[4]);
810 
812  if (result != DOCA_SUCCESS) {
813  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
814  goto free_remote_kernel_events_exports;
815  }
816 
817  resources->rp_kernel_events = calloc(resources->num_ranks, sizeof(*(resources->rp_kernel_events)));
818  if (resources->rp_kernel_events == NULL) {
819  DOCA_LOG_ERR("Failed to allocate memory for rp_kernel_events");
821  goto free_remote_kernel_events_exports;
822  }
823 
824  resources->rp_kernel_events_dpa_handles =
825  calloc(resources->num_ranks, sizeof(*(resources->rp_kernel_events_dpa_handles)));
826  if (resources->rp_kernel_events_dpa_handles == NULL) {
827  DOCA_LOG_ERR("Failed to allocate memory for rp_kernel_events_dpa_handles");
829  goto free_remote_kernel_events;
830  }
831 
832  for (i = 0; i < resources->num_ranks; i++) {
833  /* skip to export index */
834  j = i * resources->rp_remote_kernel_events_export_sizes[i];
836  resources->rdma_doca_dpa,
837  resources->rdma_doca_device,
838  (const uint8_t *)&(((char *)resources->rp_remote_kernel_events_export_data)[j]),
839  resources->rp_remote_kernel_events_export_sizes[i],
840  &(resources->rp_kernel_events[i]),
841  &(resources->rp_kernel_events_dpa_handles[i]));
842  if (result != DOCA_SUCCESS) {
843  DOCA_LOG_ERR("Failed to create DOCA sync event from export: %s", doca_error_get_descr(result));
844  goto free_remote_kernel_events_dpa_handles;
845  }
846  }
847 
848  /* Allocate DPA memory to hold the remote kernel events */
849  result = doca_dpa_mem_alloc(resources->rdma_doca_dpa,
850  resources->num_ranks * sizeof(*(resources->rp_kernel_events_dpa_handles)),
851  &(resources->devptr_rp_remote_kernel_events));
852  if (result != DOCA_SUCCESS) {
853  DOCA_LOG_ERR("Failed to allocate DOCA DPA memory: %s", doca_error_get_descr(result));
854  goto destroy_kernel_events_from_export;
855  }
856 
857  /* Copy the remote kernel events from the host memory to the device memory */
858  result = doca_dpa_h2d_memcpy(resources->rdma_doca_dpa,
859  resources->devptr_rp_remote_kernel_events,
860  (void *)resources->rp_kernel_events_dpa_handles,
861  resources->num_ranks * sizeof(*(resources->rp_kernel_events_dpa_handles)));
862  if (result != DOCA_SUCCESS) {
863  DOCA_LOG_ERR("Failed to copy DOCA DPA memory from host to device: %s", doca_error_get_descr(result));
864  goto destroy_kernel_events_from_export;
865  }
866 
867  /* Allocate DPA memory to hold the local remote kernel events */
868  result = doca_dpa_mem_alloc(resources->rdma_doca_dpa,
869  resources->num_ranks * sizeof(*(resources->kernel_events_handle)),
870  &(resources->devptr_kernel_events_handle));
871  if (result != DOCA_SUCCESS) {
872  DOCA_LOG_ERR("Failed to allocate DOCA DPA memory: %s", doca_error_get_descr(result));
873  goto free_rp_remote_kernel_events_dpa;
874  }
875 
876  /* Copy the remote kernel events from the host memory to the device memory */
877  result = doca_dpa_h2d_memcpy(resources->rdma_doca_dpa,
878  resources->devptr_kernel_events_handle,
879  (void *)resources->kernel_events_handle,
880  resources->num_ranks * sizeof(*(resources->kernel_events_handle)));
881  if (result != DOCA_SUCCESS) {
882  DOCA_LOG_ERR("Failed to copy DOCA DPA memory from host to device: %s", doca_error_get_descr(result));
883  goto free_kernel_events_handle_dpa;
884  }
885 
886  free(recvbufs);
887 
888  /* free recv mmaps exports pointers since no longer needed after creating mmaps from exports */
889  free(recvbufs_mmap_exports);
890  free(recvbufs_mmap_exports_lens);
891 
892  /* Free the local process' remote kernel event exports since we don't need them anymore */
893  free(resources->lp_remote_kernel_events_export_sizes);
894  free(resources->lp_remote_kernel_events_export_data);
895 
896  /* free remote processes kernel event exports since we don't need them after creating the DPA handle */
897  free(resources->rp_remote_kernel_events_export_data);
898  free(resources->rp_remote_kernel_events_export_sizes);
899 
900  return result;
901 
902 free_kernel_events_handle_dpa:
903  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_kernel_events_handle);
904  if (tmp_result != DOCA_SUCCESS) {
905  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
906  DOCA_ERROR_PROPAGATE(result, tmp_result);
907  }
908 free_rp_remote_kernel_events_dpa:
909  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_rp_remote_kernel_events);
910  if (tmp_result != DOCA_SUCCESS) {
911  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
912  DOCA_ERROR_PROPAGATE(result, tmp_result);
913  }
914 destroy_kernel_events_from_export:
915  for (i = 0; i < resources->num_ranks; i++) {
916  if (resources->rp_kernel_events[i] != NULL) {
917  tmp_result = doca_sync_event_remote_net_destroy(resources->rp_kernel_events[i]);
918  if (tmp_result != DOCA_SUCCESS) {
919  DOCA_LOG_ERR("Failed to destroy remote net DOCA sync event: %s",
920  doca_error_get_descr(tmp_result));
921  DOCA_ERROR_PROPAGATE(result, tmp_result);
922  }
923  }
924  }
925 free_remote_kernel_events_dpa_handles:
926  free(resources->rp_kernel_events_dpa_handles);
927 free_remote_kernel_events:
928  free(resources->rp_kernel_events);
929 free_remote_kernel_events_exports:
930  free(resources->rp_remote_kernel_events_export_data);
931  free(resources->rp_remote_kernel_events_export_sizes);
932 free_devptr_recvbufs_mmap_handles:
933  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_recvbufs_mmap_handles);
934  if (tmp_result != DOCA_SUCCESS) {
935  DOCA_LOG_ERR("Failed to free DOCA DPA memory: %s", doca_error_get_descr(tmp_result));
936  DOCA_ERROR_PROPAGATE(result, tmp_result);
937  }
938 free_devptr_recvbufs:
939  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_recvbufs);
940  if (tmp_result != DOCA_SUCCESS) {
941  DOCA_LOG_ERR("Failed to free DOCA DPA memory: %s", doca_error_get_descr(tmp_result));
942  DOCA_ERROR_PROPAGATE(result, tmp_result);
943  }
944 free_recvbufs:
945  free(recvbufs);
946 destroy_export_mmaps:
947  for (j = 0; j < i; j++) {
948  if (resources->export_mmaps[j] != NULL) {
949  tmp_result = doca_mmap_destroy(resources->export_mmaps[j]);
950  if (tmp_result != DOCA_SUCCESS) {
951  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
952  DOCA_ERROR_PROPAGATE(result, tmp_result);
953  }
954  }
955  }
956 free_export_mmaps:
957  free(resources->export_mmaps);
958 free_mmap_exports:
959  free(recvbufs_mmap_exports);
960 free_mmap_exports_lens:
961  free(recvbufs_mmap_exports_lens);
962 destroy_recvbuf_mmap:
963  tmp_result = doca_mmap_destroy(resources->recvbuf_mmap);
964  if (tmp_result != DOCA_SUCCESS) {
965  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
966  DOCA_ERROR_PROPAGATE(result, tmp_result);
967  }
968 destroy_sendbuf_mmap:
969  tmp_result = doca_mmap_destroy(resources->sendbuf_mmap);
970  if (tmp_result != DOCA_SUCCESS) {
971  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
972  DOCA_ERROR_PROPAGATE(result, tmp_result);
973  }
974  return result;
975 }
976 
977 /*
978  * Connect the local process' DOCA RDMA contexts to the remote processes' DOCA DPA RDMAs.
979  * rdma number i in each process would be connected to an rdma in process rank i.
980  *
981  * @resources [in]: All to all resources
982  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
983  */
985 {
986  /* Local rdma connection details */
987  const void *local_connection_details = NULL;
988  /* Remote rdma connection details */
989  const void *remote_connection_details = NULL;
990  /* Length of addresses */
991  size_t local_connection_details_len, remote_connection_details_len;
992  /* rdma connection object */
993  struct doca_rdma_connection *connection = NULL;
994  /* Tags for the MPI send and recv for address and address length */
995  const int addr_tag = 1;
996  const int addr_len_tag = 2;
997  /* MPI request used for synchronization between processes */
998  MPI_Request reqs[4];
999  int i;
1001 
1002  for (i = 0; i < resources->num_ranks; i++) {
1003  /*
1004  * Get the local rdma connection details with the index
1005  * same as the rank of the process we are going to send to
1006  */
1007  result = doca_rdma_export(resources->rdmas[i],
1008  &local_connection_details,
1009  &local_connection_details_len,
1010  &connection);
1011  if (result != DOCA_SUCCESS) {
1012  DOCA_LOG_ERR("Failed to get DOCA rdma connection details: %s", doca_error_get_descr(result));
1013  return result;
1014  }
1015 
1016  /* Send and receive the addresses using MPI Isend and Recv */
1017  MPI_Isend(&local_connection_details_len, 1, MPI_INT64_T, i, addr_len_tag, resources->comm, &reqs[0]);
1018  MPI_Isend(local_connection_details,
1019  local_connection_details_len,
1020  MPI_CHAR,
1021  i,
1022  addr_tag,
1023  resources->comm,
1024  &reqs[1]);
1025 
1026  MPI_Irecv(&remote_connection_details_len, 1, MPI_INT64_T, i, addr_len_tag, resources->comm, &reqs[2]);
1027 
1029  if (result != DOCA_SUCCESS) {
1030  DOCA_LOG_ERR("Timed out waiting on receiving remote connection details length: %s",
1032  return result;
1033  }
1034 
1035  remote_connection_details = malloc(remote_connection_details_len);
1036  if (remote_connection_details == NULL) {
1037  DOCA_LOG_ERR("Failed to allocate memory for remote rdma connection details");
1038  return DOCA_ERROR_NO_MEMORY;
1039  }
1040  MPI_Irecv((void *)remote_connection_details,
1041  remote_connection_details_len,
1042  MPI_CHAR,
1043  i,
1044  addr_tag,
1045  resources->comm,
1046  &reqs[3]);
1047 
1049  if (result != DOCA_SUCCESS) {
1050  DOCA_LOG_ERR("Timed out waiting on receiving remote connection details: %s",
1052  free((void *)remote_connection_details);
1053  return result;
1054  }
1055 
1056  /*
1057  * Connect to the rdma of the remote process.
1058  * The local rdma of index i will be connected to an rdma of a remote process of rank i.
1059  */
1060  result = doca_rdma_connect(resources->rdmas[i],
1061  remote_connection_details,
1062  remote_connection_details_len,
1063  connection);
1064  if (result != DOCA_SUCCESS) {
1065  DOCA_LOG_ERR("Failed to connect DOCA rdma: %s", doca_error_get_descr(result));
1066  free((void *)remote_connection_details);
1067  return result;
1068  }
1069 
1071  if (result != DOCA_SUCCESS) {
1072  DOCA_LOG_ERR("Timed out waiting on sending local connection details length: %s",
1074  free((void *)remote_connection_details);
1075  return result;
1076  }
1077 
1079  if (result != DOCA_SUCCESS) {
1080  DOCA_LOG_ERR("Timed out waiting on sending local connection details: %s",
1082  free((void *)remote_connection_details);
1083  return result;
1084  }
1085 
1086  free((void *)remote_connection_details);
1087  }
1088 
1089  return result;
1090 }
1091 
1092 /*
1093  * Create DOCA rdma instance
1094  *
1095  * @doca_dpa [in]: DPA context to set datapath on
1096  * @doca_device [in]: device to associate to rdma context
1097  * @rdma_caps [in]: capabilities enabled on the rdma context
1098  * @dpa_completion [in]: DPA completion context to be attached for the rdma context
1099  * @rdma [out]: Created rdma
1100  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1101  */
1102 static doca_error_t create_rdma(struct doca_dpa *doca_dpa,
1103  struct doca_dev *doca_device,
1104  unsigned int rdma_caps,
1105  struct doca_dpa_completion *dpa_completion,
1106  struct doca_rdma **rdma)
1107 {
1108  struct doca_ctx *rdma_as_doca_ctx;
1109  doca_error_t result, tmp_result;
1110 
1111  /* Creating DOCA rdma instance */
1112  result = doca_rdma_create(doca_device, rdma);
1113  if (result != DOCA_SUCCESS) {
1114  DOCA_LOG_ERR("Failed to create DOCA rdma instance: %s", doca_error_get_descr(result));
1115  return result;
1116  }
1117 
1118  /* Setup DOCA rdma as DOCA context */
1119  rdma_as_doca_ctx = doca_rdma_as_ctx(*rdma);
1120 
1121  /* Set permissions for DOCA rdma */
1122  result = doca_rdma_set_permissions(*rdma, rdma_caps);
1123  if (result != DOCA_SUCCESS) {
1124  DOCA_LOG_ERR("Failed to set permissions for DOCA rdma: %s", doca_error_get_descr(result));
1125  goto destroy_rdma;
1126  }
1127 
1128  /* Set grh flag for DOCA rdma */
1129  result = doca_rdma_set_grh_enabled(*rdma, true);
1130  if (result != DOCA_SUCCESS) {
1131  DOCA_LOG_ERR("Failed to set grh for DOCA rdma: %s", doca_error_get_descr(result));
1132  goto destroy_rdma;
1133  }
1134 
1135  /* Set datapath of DOCA rdma context on DPA */
1136  result = doca_ctx_set_datapath_on_dpa(rdma_as_doca_ctx, doca_dpa);
1137  if (result != DOCA_SUCCESS) {
1138  DOCA_LOG_ERR("Failed to set datapath for DOCA rdma on DPA: %s", doca_error_get_descr(result));
1139  goto destroy_rdma;
1140  }
1141 
1142  /* Attach DPA completion context for DOCA rdma context */
1143  result = doca_rdma_dpa_completion_attach(*rdma, dpa_completion);
1144  if (result != DOCA_SUCCESS) {
1145  DOCA_LOG_ERR("Failed to attach DPA completion context for DOCA rdma: %s", doca_error_get_descr(result));
1146  goto destroy_rdma;
1147  }
1148 
1149  /* Start DOCA rdma context */
1150  result = doca_ctx_start(rdma_as_doca_ctx);
1151  if (result != DOCA_SUCCESS) {
1152  DOCA_LOG_ERR("Failed to start context for DOCA rdma: %s", doca_error_get_descr(result));
1153  goto destroy_rdma;
1154  }
1155 
1156  return result;
1157 
1158 destroy_rdma:
1159  tmp_result = doca_rdma_destroy(*rdma);
1160  if (tmp_result != DOCA_SUCCESS) {
1161  DOCA_LOG_ERR("Failed to destroy DOCA rdma instance: %s", doca_error_get_descr(tmp_result));
1162  DOCA_ERROR_PROPAGATE(result, tmp_result);
1163  }
1164  return result;
1165 }
1166 
1167 /*
1168  * Destroy DOCA rdma instance
1169  *
1170  * @rdma [in]: rdma context to destroy
1171  * @doca_device [in]: device associated to rdma context
1172  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1173  */
1174 static doca_error_t destroy_rdma(struct doca_rdma *rdma, struct doca_dev *doca_device)
1175 {
1176  doca_error_t result = DOCA_SUCCESS, tmp_result = DOCA_SUCCESS;
1177 
1178  tmp_result = doca_ctx_stop(doca_rdma_as_ctx(rdma));
1179  if (tmp_result != DOCA_SUCCESS) {
1180  DOCA_LOG_ERR("Failed to stop DOCA rdma context: %s", doca_error_get_descr(tmp_result));
1181  DOCA_ERROR_PROPAGATE(result, tmp_result);
1182  }
1183  tmp_result = doca_rdma_destroy(rdma);
1184  if (tmp_result != DOCA_SUCCESS) {
1185  DOCA_LOG_ERR("Failed to destroy DOCA rdma instance: %s", doca_error_get_descr(tmp_result));
1186  DOCA_ERROR_PROPAGATE(result, tmp_result);
1187  }
1188  return result;
1189 }
1190 
1191 /*
1192  * Prepare the DOCA DPA completion contexts
1193  *
1194  * @resources [in/out]: All to all resources
1195  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1196  */
1198 {
1199  int i, j;
1200  doca_error_t result, tmp_result;
1201 
1202  /* Create dpa completion contexts as number of the processes */
1203  resources->dpa_completions = calloc(resources->num_ranks, sizeof(*(resources->dpa_completions)));
1204  if (resources->dpa_completions == NULL) {
1205  DOCA_LOG_ERR("Failed to allocate memory for DOCA DPA completions");
1206  return DOCA_ERROR_NO_MEMORY;
1207  }
1208  for (i = 0; i < resources->num_ranks; i++) {
1209  result = doca_dpa_completion_create(resources->rdma_doca_dpa,
1210  resources->num_ranks,
1211  &(resources->dpa_completions[i]));
1212  if (result != DOCA_SUCCESS) {
1213  DOCA_LOG_ERR("Failed to create DOCA DPA completion: %s", doca_error_get_descr(result));
1214  goto destroy_dpa_completions;
1215  }
1216 
1217  result = doca_dpa_completion_start(resources->dpa_completions[i]);
1218  if (result != DOCA_SUCCESS) {
1219  DOCA_LOG_ERR("Failed to start DOCA DPA completion: %s", doca_error_get_descr(result));
1220  tmp_result = doca_dpa_completion_destroy(resources->dpa_completions[i]);
1221  if (tmp_result != DOCA_SUCCESS) {
1222  DOCA_LOG_ERR("Failed to destroy DOCA DPA completion instance: %s",
1223  doca_error_get_descr(tmp_result));
1224  DOCA_ERROR_PROPAGATE(result, tmp_result);
1225  }
1226  goto destroy_dpa_completions;
1227  }
1228  }
1229 
1230  return result;
1231 
1232 destroy_dpa_completions:
1233  for (j = 0; j < i; j++) {
1234  tmp_result = doca_dpa_completion_destroy(resources->dpa_completions[j]);
1235  if (tmp_result != DOCA_SUCCESS) {
1236  DOCA_LOG_ERR("Failed to destroy DOCA DPA completion instance: %s",
1237  doca_error_get_descr(tmp_result));
1238  DOCA_ERROR_PROPAGATE(result, tmp_result);
1239  }
1240  }
1241  free(resources->dpa_completions);
1242 
1243  return result;
1244 }
1245 
1246 /*
1247  * Prepare the DOCA rdma, which includes creating the RDMA contexts and their handlers, connecting them to
1248  * the remote processes' RDMA contexts and allocating DOCA DPA device memory to hold the handlers so that
1249  * they can be used in a DOCA DPA kernel function.
1250  *
1251  * @resources [in/out]: All to all resources
1252  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1253  */
1255 {
1256  /* Access flags for the rdma */
1257  const unsigned int rdma_access = DOCA_ACCESS_FLAG_LOCAL_READ_WRITE | DOCA_ACCESS_FLAG_RDMA_READ |
1259  /* DOCA DPA rdma handlers */
1260  doca_dpa_dev_rdma_t *rdma_handlers;
1261  int i, j;
1262  doca_error_t result, tmp_result;
1263 
1264  /* Create rdmas as number of the processes */
1265  resources->rdmas = calloc(resources->num_ranks, sizeof(*(resources->rdmas)));
1266  if (resources->rdmas == NULL) {
1267  DOCA_LOG_ERR("Failed to allocate memory for DOCA DPA RDMAs");
1268  return DOCA_ERROR_NO_MEMORY;
1269  }
1270  for (i = 0; i < resources->num_ranks; i++) {
1271  result = create_rdma(resources->rdma_doca_dpa,
1272  resources->rdma_doca_device,
1273  rdma_access,
1274  resources->dpa_completions[i],
1275  &(resources->rdmas[i]));
1276  if (result != DOCA_SUCCESS) {
1277  DOCA_LOG_ERR("Failed to create DOCA rdma: %s", doca_error_get_descr(result));
1278  goto destroy_rdmas;
1279  }
1280  }
1281 
1282  /* Connect local RDMA contexts to the remote RDMA contexts */
1284  if (result != DOCA_SUCCESS) {
1285  DOCA_LOG_ERR("Failed to connect DOCA rdma: %s", doca_error_get_descr(result));
1286  goto destroy_rdmas;
1287  }
1288 
1289  /* Create device handlers for the RDMA contexts */
1290  rdma_handlers = (doca_dpa_dev_rdma_t *)calloc(resources->num_ranks, sizeof(*rdma_handlers));
1291  if (rdma_handlers == NULL) {
1292  DOCA_LOG_ERR("Failed to allocate memory for DOCA DPA device rdma handlers");
1293  goto destroy_rdmas;
1294  }
1295  for (j = 0; j < resources->num_ranks; j++) {
1296  result = doca_rdma_get_dpa_handle(resources->rdmas[j], &(rdma_handlers[j]));
1297  if (result != DOCA_SUCCESS) {
1298  DOCA_LOG_ERR("Failed to get DOCA rdma DPA handler: %s", doca_error_get_descr(result));
1299  goto free_rdma_handlers;
1300  }
1301  }
1302 
1303  /* Allocate DPA memory to hold the RDMA handlers */
1304  result = doca_dpa_mem_alloc(resources->rdma_doca_dpa,
1305  sizeof(*rdma_handlers) * resources->num_ranks,
1306  &(resources->devptr_rdmas));
1307  if (result != DOCA_SUCCESS) {
1308  DOCA_LOG_ERR("Failed to allocate DOCA DPA memory: %s", doca_error_get_descr(result));
1309  goto free_rdma_handlers;
1310  }
1311 
1312  /* Copy the rdma handlers from the host memory to the device memory */
1313  result = doca_dpa_h2d_memcpy(resources->rdma_doca_dpa,
1314  resources->devptr_rdmas,
1315  (void *)rdma_handlers,
1316  sizeof(*rdma_handlers) * resources->num_ranks);
1317  if (result != DOCA_SUCCESS) {
1318  DOCA_LOG_ERR("Failed to copy DOCA DPA memory from host to device: %s", doca_error_get_descr(result));
1319  goto free_rdma_handlers_dpa;
1320  }
1321 
1322  /* Free the rdma handlers */
1323  free(rdma_handlers);
1324 
1325  return result;
1326 
1327 free_rdma_handlers_dpa:
1328  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_rdmas);
1329  if (tmp_result != DOCA_SUCCESS) {
1330  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1331  DOCA_ERROR_PROPAGATE(result, tmp_result);
1332  }
1333 free_rdma_handlers:
1334  free(rdma_handlers);
1335 destroy_rdmas:
1336  for (j = 0; j < i; j++) {
1337  tmp_result = destroy_rdma(resources->rdmas[j], resources->rdma_doca_device);
1338  if (tmp_result != DOCA_SUCCESS) {
1339  DOCA_LOG_ERR("Failed to destroy DOCA rdma instance: %s", doca_error_get_descr(tmp_result));
1340  DOCA_ERROR_PROPAGATE(result, tmp_result);
1341  }
1342  }
1343  free(resources->rdmas);
1344 
1345  return result;
1346 }
1347 
1348 /*
1349  * Create DOCA sync event to be published by the DPA and subscribed by the CPU
1350  *
1351  * @doca_dpa [in]: DOCA DPA context
1352  * @doca_device [in]: DOCA device
1353  * @comp_event [out]: Created DOCA sync event that is published by the DPA and subscribed by the CPU
1354  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1355  */
1356 static doca_error_t create_doca_dpa_completion_sync_event(struct doca_dpa *doca_dpa,
1357  struct doca_dev *doca_device,
1358  struct doca_sync_event **comp_event)
1359 {
1360  doca_error_t result, tmp_result;
1361 
1362  result = doca_sync_event_create(comp_event);
1363  if (result != DOCA_SUCCESS) {
1364  DOCA_LOG_ERR("Failed to create DOCA sync event: %s", doca_error_get_descr(result));
1365  return result;
1366  }
1367 
1368  result = doca_sync_event_add_publisher_location_dpa(*comp_event, doca_dpa);
1369  if (result != DOCA_SUCCESS) {
1370  DOCA_LOG_ERR("Failed to set DPA as publisher for DOCA sync event: %s", doca_error_get_descr(result));
1371  goto destroy_comp_event;
1372  }
1373 
1374  result = doca_sync_event_add_subscriber_location_cpu(*comp_event, doca_device);
1375  if (result != DOCA_SUCCESS) {
1376  DOCA_LOG_ERR("Failed to set CPU as subscriber for DOCA sync event: %s", doca_error_get_descr(result));
1377  goto destroy_comp_event;
1378  }
1379 
1380  result = doca_sync_event_start(*comp_event);
1381  if (result != DOCA_SUCCESS) {
1382  DOCA_LOG_ERR("Failed to start DOCA sync event: %s", doca_error_get_descr(result));
1383  goto destroy_comp_event;
1384  }
1385 
1386  return result;
1387 
1388 destroy_comp_event:
1389  tmp_result = doca_sync_event_destroy(*comp_event);
1390  if (tmp_result != DOCA_SUCCESS) {
1391  DOCA_LOG_ERR("Failed to destroy DOCA sync event: %s", doca_error_get_descr(tmp_result));
1392  DOCA_ERROR_PROPAGATE(result, tmp_result);
1393  }
1394  return result;
1395 }
1396 
1397 /*
1398  * Create DOCA sync event to be published by remote net and subscribed by the DPA
1399  *
1400  * @doca_dpa [in]: DOCA DPA context
1401  * @kernel_event [out]: Created DOCA sync event that is published by remote net and subscribed by the DPA
1402  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1403  */
1404 static doca_error_t create_doca_dpa_remote_net_sync_event(struct doca_dpa *doca_dpa,
1405  struct doca_sync_event **kernel_event)
1406 {
1407  doca_error_t result, tmp_result;
1408 
1409  result = doca_sync_event_create(kernel_event);
1410  if (result != DOCA_SUCCESS) {
1411  DOCA_LOG_ERR("Failed to create DOCA sync event: %s", doca_error_get_descr(result));
1412  return result;
1413  }
1414 
1416  if (result != DOCA_SUCCESS) {
1417  DOCA_LOG_ERR("Failed to set remote as publisher for DOCA sync event: %s", doca_error_get_descr(result));
1418  goto destroy_kernel_event;
1419  }
1420 
1421  result = doca_sync_event_add_subscriber_location_dpa(*kernel_event, doca_dpa);
1422  if (result != DOCA_SUCCESS) {
1423  DOCA_LOG_ERR("Failed to set DPA as subscriber for DOCA sync event: %s", doca_error_get_descr(result));
1424  goto destroy_kernel_event;
1425  }
1426 
1427  result = doca_sync_event_start(*kernel_event);
1428  if (result != DOCA_SUCCESS) {
1429  DOCA_LOG_ERR("Failed to start DOCA sync event: %s", doca_error_get_descr(result));
1430  goto destroy_kernel_event;
1431  }
1432 
1433  return result;
1434 
1435 destroy_kernel_event:
1436  tmp_result = doca_sync_event_destroy(*kernel_event);
1437  if (tmp_result != DOCA_SUCCESS) {
1438  DOCA_LOG_ERR("Failed to destroy DOCA sync event: %s", doca_error_get_descr(tmp_result));
1439  DOCA_ERROR_PROPAGATE(result, tmp_result);
1440  }
1441  return result;
1442 }
1443 
1444 /*
1445  * Create the needed DOCA sync events for the All to All:
1446  * One kernel completion event, the publisher is the DPA and the subscriber is the host.
1447  * Number of ranks kernel events, the publisher and subscriber is the DPA.
1448  *
1449  * @resources [in/out]: All to all resources
1450  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1451  */
1453 {
1454  int i, j;
1455  doca_error_t result, tmp_result;
1456  const uint8_t **lp_remote_kernel_events_export_data_arr = NULL;
1457 
1458  /* Create DOCA DPA kernel completion event*/
1460  resources->pf_doca_device,
1461  &(resources->comp_event));
1462  if (result != DOCA_SUCCESS) {
1463  DOCA_LOG_ERR("Failed to create host completion event: %s", doca_error_get_descr(result));
1464  return result;
1465  }
1466 
1467  /* Create DOCA DPA events to be used inside of the kernel */
1468  resources->kernel_events = calloc(resources->num_ranks, sizeof(*(resources->kernel_events)));
1469  if (resources->kernel_events == NULL) {
1470  DOCA_LOG_ERR("Failed to allocate memory for kernel events");
1472  goto destroy_comp_event;
1473  }
1474  for (i = 0; i < resources->num_ranks; i++) {
1475  result =
1476  create_doca_dpa_remote_net_sync_event(resources->rdma_doca_dpa, &(resources->kernel_events[i]));
1477  if (result != DOCA_SUCCESS) {
1478  DOCA_LOG_ERR("Failed to create kernel event: %s", doca_error_get_descr(result));
1479  goto destroy_kernel_events;
1480  }
1481  }
1482 
1483  /* Create DOCA DPA events handles */
1484  resources->kernel_events_handle = calloc(resources->num_ranks, sizeof(*(resources->kernel_events_handle)));
1485  if (resources->kernel_events_handle == NULL) {
1486  DOCA_LOG_ERR("Failed to allocate memory for kernel events handles");
1488  goto destroy_kernel_events_handles;
1489  }
1490 
1491  for (j = 0; j < resources->num_ranks; j++) {
1492  /* Export the kernel events */
1493  result = doca_sync_event_get_dpa_handle(resources->kernel_events[j],
1494  resources->rdma_doca_dpa,
1495  &(resources->kernel_events_handle[j]));
1496  if (result != DOCA_SUCCESS) {
1497  DOCA_LOG_ERR("Failed to export kernel event: %s", doca_error_get_descr(result));
1498  goto destroy_kernel_events_handles;
1499  }
1500  }
1501 
1502  /* Remote export the kernel events */
1503  resources->lp_remote_kernel_events_export_sizes =
1504  calloc(resources->num_ranks, sizeof(*(resources->lp_remote_kernel_events_export_sizes)));
1505  if (resources->lp_remote_kernel_events_export_sizes == NULL) {
1506  DOCA_LOG_ERR("Failed to allocate memory for kernel events export sizes");
1508  goto destroy_kernel_events_handles;
1509  }
1510 
1511  lp_remote_kernel_events_export_data_arr = calloc(resources->num_ranks, sizeof(const uint8_t *));
1512 
1513  for (j = 0; j < resources->num_ranks; j++) {
1514  /* Export the kernel events */
1516  &(lp_remote_kernel_events_export_data_arr[j]),
1517  &(resources->lp_remote_kernel_events_export_sizes[j]));
1518  if (result != DOCA_SUCCESS) {
1519  DOCA_LOG_ERR("Failed to remote export kernel event: %s", doca_error_get_descr(result));
1520  goto free_remote_kernel_events_export_data_arr;
1521  }
1522  }
1523 
1524  resources->lp_remote_kernel_events_export_data =
1525  calloc(resources->num_ranks, resources->lp_remote_kernel_events_export_sizes[0]);
1526  if (resources->lp_remote_kernel_events_export_data == NULL) {
1527  DOCA_LOG_ERR("Failed to allocate memory for kernel events export data");
1529  goto free_remote_kernel_events_export_data_arr;
1530  }
1531 
1532  for (j = 0; j < resources->num_ranks; j++) {
1533  /* skip to export index */
1534  i = j * resources->lp_remote_kernel_events_export_sizes[j];
1535  memcpy(&(resources->lp_remote_kernel_events_export_data[i]),
1536  lp_remote_kernel_events_export_data_arr[j],
1537  resources->lp_remote_kernel_events_export_sizes[j]);
1538  }
1539 
1540  free(lp_remote_kernel_events_export_data_arr);
1541 
1542  return result;
1543 
1544 free_remote_kernel_events_export_data_arr:
1545  free(lp_remote_kernel_events_export_data_arr);
1546 
1547  free(resources->lp_remote_kernel_events_export_sizes);
1548 destroy_kernel_events_handles:
1549  free(resources->kernel_events_handle);
1550 destroy_kernel_events:
1551  for (j = 0; j < i; j++) {
1552  tmp_result = doca_sync_event_destroy(resources->kernel_events[j]);
1553  if (tmp_result != DOCA_SUCCESS) {
1554  DOCA_LOG_ERR("Failed to destroy kernel_event: %s", doca_error_get_descr(tmp_result));
1555  DOCA_ERROR_PROPAGATE(result, tmp_result);
1556  }
1557  }
1558  free(resources->kernel_events);
1559 destroy_comp_event:
1560  tmp_result = doca_sync_event_destroy(resources->comp_event);
1561  if (tmp_result != DOCA_SUCCESS) {
1562  DOCA_LOG_ERR("Failed to destroy comp_event: %s", doca_error_get_descr(tmp_result));
1563  DOCA_ERROR_PROPAGATE(result, tmp_result);
1564  }
1565 
1566  return result;
1567 }
1568 
1570 {
1571  doca_error_t result, tmp_result;
1572  int i;
1573 
1574  /* divide the two devices (can be the same) on all processes equally */
1575  if (resources->my_rank >= ((double)resources->num_ranks / 2.0)) {
1576  strcpy(resources->pf_device_name, pf_device2_name);
1577  strcpy(resources->rdma_device_name, rdma_device2_name);
1578  } else {
1579  strcpy(resources->pf_device_name, pf_device1_name);
1580  strcpy(resources->rdma_device_name, rdma_device1_name);
1581  }
1582 
1583  /* Create DOCA DPA context*/
1585  if (result != DOCA_SUCCESS) {
1586  DOCA_LOG_ERR("Failed to create DOCA DPA device: %s", doca_error_get_descr(result));
1587  return result;
1588  }
1589 
1591  if (result != DOCA_SUCCESS) {
1592  DOCA_LOG_ERR("Failed to create DOCA DPA events: %s", doca_error_get_descr(result));
1593  goto destroy_dpa;
1594  }
1595 
1596  /* Prepare DOCA DPA completion contexts all to all resources */
1598  if (result != DOCA_SUCCESS) {
1599  DOCA_LOG_ERR("Failed to prepare DOCA DPA completion contexts resources: %s",
1601  goto destroy_events;
1602  }
1603 
1604  /* Prepare DOCA RDMA contexts all to all resources */
1606  if (result != DOCA_SUCCESS) {
1607  DOCA_LOG_ERR("Failed to prepare DOCA RDMA contexts resources: %s", doca_error_get_descr(result));
1608  goto destroy_dpa_completions;
1609  }
1610 
1611  /* Prepare DOCA DPA all to all memory */
1613  if (result != DOCA_SUCCESS) {
1614  DOCA_LOG_ERR("Failed to prepare DOCA DPA memory resources: %s", doca_error_get_descr(result));
1615  goto destroy_rdmas;
1616  }
1617 
1618  return result;
1619 
1620 destroy_rdmas:
1621  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_rdmas);
1622  if (tmp_result != DOCA_SUCCESS) {
1623  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1624  DOCA_ERROR_PROPAGATE(result, tmp_result);
1625  }
1626  /* Destroy DOCA RDMA contexts */
1627  for (i = 0; i < resources->num_ranks; i++) {
1628  tmp_result = destroy_rdma(resources->rdmas[i], resources->rdma_doca_device);
1629  if (tmp_result != DOCA_SUCCESS) {
1630  DOCA_LOG_ERR("Failed to destroy DOCA rdma instance: %s", doca_error_get_descr(tmp_result));
1631  DOCA_ERROR_PROPAGATE(result, tmp_result);
1632  }
1633  }
1634  free(resources->rdmas);
1635 destroy_dpa_completions:
1636  /* Destroy DOCA DPA completion contexts */
1637  for (i = 0; i < resources->num_ranks; i++) {
1638  tmp_result = doca_dpa_completion_destroy(resources->dpa_completions[i]);
1639  if (tmp_result != DOCA_SUCCESS) {
1640  DOCA_LOG_ERR("Failed to destroy DOCA DPA completion instance: %s",
1641  doca_error_get_descr(tmp_result));
1642  DOCA_ERROR_PROPAGATE(result, tmp_result);
1643  }
1644  }
1645  free(resources->dpa_completions);
1646 destroy_events:
1647  free(resources->lp_remote_kernel_events_export_data);
1648  free(resources->lp_remote_kernel_events_export_sizes);
1649  free(resources->kernel_events_handle);
1650  for (i = 0; i < resources->num_ranks; i++) {
1651  tmp_result = doca_sync_event_destroy(resources->kernel_events[i]);
1652  if (tmp_result != DOCA_SUCCESS) {
1653  DOCA_LOG_ERR("Failed to destroy kernel_event: %s", doca_error_get_descr(tmp_result));
1654  DOCA_ERROR_PROPAGATE(result, tmp_result);
1655  }
1656  }
1657  free(resources->kernel_events);
1658  tmp_result = doca_sync_event_destroy(resources->comp_event);
1659  if (tmp_result != DOCA_SUCCESS) {
1660  DOCA_LOG_ERR("Failed to destroy comp_event: %s", doca_error_get_descr(tmp_result));
1661  DOCA_ERROR_PROPAGATE(result, tmp_result);
1662  }
1663 destroy_dpa:
1664 #ifdef DOCA_ARCH_DPU
1665  tmp_result = doca_dpa_destroy(resources->rdma_doca_dpa);
1666  if (tmp_result != DOCA_SUCCESS) {
1667  DOCA_LOG_ERR("Failed to destroy extended DOCA DPA context: %s", doca_error_get_descr(tmp_result));
1668  DOCA_ERROR_PROPAGATE(result, tmp_result);
1669  }
1670 #endif
1671  tmp_result = doca_dpa_destroy(resources->pf_doca_dpa);
1672  if (tmp_result != DOCA_SUCCESS) {
1673  DOCA_LOG_ERR("Failed to destroy base DOCA DPA context: %s", doca_error_get_descr(tmp_result));
1674  DOCA_ERROR_PROPAGATE(result, tmp_result);
1675  }
1676  tmp_result = doca_dev_close(resources->pf_doca_device);
1677  if (tmp_result != DOCA_SUCCESS) {
1678  DOCA_LOG_ERR("Failed to close base DOCA DPA device: %s", doca_error_get_descr(tmp_result));
1679  DOCA_ERROR_PROPAGATE(result, tmp_result);
1680  }
1681 #ifdef DOCA_ARCH_DPU
1682  tmp_result = doca_dev_close(resources->rdma_doca_device);
1683  if (tmp_result != DOCA_SUCCESS) {
1684  DOCA_LOG_ERR("Failed to close extended DOCA DPA device: %s", doca_error_get_descr(tmp_result));
1685  DOCA_ERROR_PROPAGATE(result, tmp_result);
1686  }
1687 #endif
1688 
1689  return result;
1690 }
1691 
1693 {
1694  doca_error_t result = DOCA_SUCCESS, tmp_result = DOCA_SUCCESS;
1695  int i;
1696 
1697  /* Free DPA device memory*/
1698 
1699  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_kernel_events_handle);
1700  if (tmp_result != DOCA_SUCCESS) {
1701  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1702  DOCA_ERROR_PROPAGATE(result, tmp_result);
1703  }
1704  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_rp_remote_kernel_events);
1705  if (tmp_result != DOCA_SUCCESS) {
1706  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1707  DOCA_ERROR_PROPAGATE(result, tmp_result);
1708  }
1709  for (i = 0; i < resources->num_ranks; i++) {
1710  if (resources->rp_kernel_events[i] != NULL) {
1711  tmp_result = doca_sync_event_remote_net_destroy(resources->rp_kernel_events[i]);
1712  if (tmp_result != DOCA_SUCCESS) {
1713  DOCA_LOG_ERR("Failed to destroy remote net DOCA sync event: %s",
1714  doca_error_get_descr(tmp_result));
1715  DOCA_ERROR_PROPAGATE(result, tmp_result);
1716  }
1717  }
1718  }
1719  free(resources->rp_kernel_events_dpa_handles);
1720  free(resources->rp_kernel_events);
1721  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_recvbufs);
1722  if (tmp_result != DOCA_SUCCESS) {
1723  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1724  DOCA_ERROR_PROPAGATE(result, tmp_result);
1725  }
1726  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_recvbufs_mmap_handles);
1727  if (tmp_result != DOCA_SUCCESS) {
1728  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1729  DOCA_ERROR_PROPAGATE(result, tmp_result);
1730  }
1731  free(resources->export_mmaps_dpa_handle);
1732  for (i = 0; i < resources->num_ranks; i++) {
1733  if (resources->export_mmaps[i] != NULL) {
1734  tmp_result = doca_mmap_destroy(resources->export_mmaps[i]);
1735  if (tmp_result != DOCA_SUCCESS) {
1736  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
1737  DOCA_ERROR_PROPAGATE(result, tmp_result);
1738  }
1739  }
1740  }
1741  free(resources->export_mmaps);
1742  tmp_result = doca_mmap_destroy(resources->recvbuf_mmap);
1743  if (tmp_result != DOCA_SUCCESS) {
1744  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
1745  DOCA_ERROR_PROPAGATE(result, tmp_result);
1746  }
1747  tmp_result = doca_mmap_destroy(resources->sendbuf_mmap);
1748  if (tmp_result != DOCA_SUCCESS) {
1749  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
1750  DOCA_ERROR_PROPAGATE(result, tmp_result);
1751  }
1752 
1753  tmp_result = doca_dpa_mem_free(resources->rdma_doca_dpa, resources->devptr_rdmas);
1754  if (tmp_result != DOCA_SUCCESS) {
1755  DOCA_LOG_ERR("Failed to free DOCA DPA device memory: %s", doca_error_get_descr(tmp_result));
1756  DOCA_ERROR_PROPAGATE(result, tmp_result);
1757  }
1758 
1759  /* Destroy DOCA DPA RDMAs*/
1760  for (i = 0; i < resources->num_ranks; i++) {
1761  tmp_result = destroy_rdma(resources->rdmas[i], resources->rdma_doca_device);
1762  if (tmp_result != DOCA_SUCCESS) {
1763  DOCA_LOG_ERR("Failed to destroy DOCA rdma instance: %s", doca_error_get_descr(tmp_result));
1764  DOCA_ERROR_PROPAGATE(result, tmp_result);
1765  }
1766  }
1767  free(resources->rdmas);
1768 
1769  /* Destroy DOCA DPA completions */
1770  for (i = 0; i < resources->num_ranks; i++) {
1771  tmp_result = doca_dpa_completion_destroy(resources->dpa_completions[i]);
1772  if (tmp_result != DOCA_SUCCESS) {
1773  DOCA_LOG_ERR("Failed to destroy DOCA DPA completion instance: %s",
1774  doca_error_get_descr(tmp_result));
1775  DOCA_ERROR_PROPAGATE(result, tmp_result);
1776  }
1777  }
1778  free(resources->dpa_completions);
1779 
1780  /* Free kernel events handles */
1781  free(resources->kernel_events_handle);
1782  /* Destroy DOCA DPA kernel events */
1783  for (i = 0; i < resources->num_ranks; i++) {
1784  tmp_result = doca_sync_event_destroy(resources->kernel_events[i]);
1785  if (tmp_result != DOCA_SUCCESS) {
1786  DOCA_LOG_ERR("Failed to destroy kernel_event: %s", doca_error_get_descr(tmp_result));
1787  DOCA_ERROR_PROPAGATE(result, tmp_result);
1788  }
1789  }
1790  free(resources->kernel_events);
1791 
1792  /* Destroy DOCA DPA completion event */
1793  tmp_result = doca_sync_event_destroy(resources->comp_event);
1794  if (tmp_result != DOCA_SUCCESS) {
1795  DOCA_LOG_ERR("Failed to destroy comp_event: %s", doca_error_get_descr(tmp_result));
1796  DOCA_ERROR_PROPAGATE(result, tmp_result);
1797  }
1798 
1799  /* Destroy DOCA DPA context */
1800 #ifdef DOCA_ARCH_DPU
1801  if (resources->rdma_doca_dpa != resources->pf_doca_dpa) {
1802  tmp_result = doca_dpa_destroy(resources->rdma_doca_dpa);
1803  if (tmp_result != DOCA_SUCCESS) {
1804  DOCA_LOG_ERR("Failed to destroy DOCA DPA context: %s", doca_error_get_descr(tmp_result));
1805  DOCA_ERROR_PROPAGATE(result, tmp_result);
1806  }
1807  }
1808 #endif
1809 
1810  tmp_result = doca_dpa_destroy(resources->pf_doca_dpa);
1811  if (tmp_result != DOCA_SUCCESS) {
1812  DOCA_LOG_ERR("Failed to destroy DOCA DPA context: %s", doca_error_get_descr(tmp_result));
1813  DOCA_ERROR_PROPAGATE(result, tmp_result);
1814  }
1815 
1816  /* Close DOCA device */
1817 #ifdef DOCA_ARCH_DPU
1818  tmp_result = doca_dev_close(resources->rdma_doca_device);
1819  if (tmp_result != DOCA_SUCCESS) {
1820  DOCA_LOG_ERR("Failed to close DOCA device: %s", doca_error_get_descr(tmp_result));
1821  DOCA_ERROR_PROPAGATE(result, tmp_result);
1822  }
1823 #endif
1824 
1825  tmp_result = doca_dev_close(resources->pf_doca_device);
1826  if (tmp_result != DOCA_SUCCESS) {
1827  DOCA_LOG_ERR("Failed to close DOCA device: %s", doca_error_get_descr(tmp_result));
1828  DOCA_ERROR_PROPAGATE(result, tmp_result);
1829  }
1830 
1831  return result;
1832 }
1833 
1835 {
1837 
1838  if (req->resources == NULL)
1839  return DOCA_SUCCESS;
1840 
1842  if (result != DOCA_SUCCESS) {
1843  DOCA_LOG_ERR("Failed to destroy a2a resources: %s", doca_error_get_descr(result));
1844  return result;
1845  }
1846  free(req->resources);
1847  req->resources = NULL;
1848 
1849  return result;
1850 }
1851 
1853 {
1855  uint64_t se_val;
1856  double elapsed_time_in_sec = 0;
1857  struct timespec ts = {
1858  .tv_sec = 0,
1859  .tv_nsec = SLEEP_IN_NANO_SEC,
1860  };
1861  double sleep_in_sec = (double)SLEEP_IN_NANO_SEC / 1000000000;
1862 
1863  if (req->resources == NULL) {
1864  DOCA_LOG_ERR("Failed to wait for completion event, resourced uninitialized");
1865  return DOCA_ERROR_UNEXPECTED;
1866  }
1867 
1868  while (1) {
1869  result = doca_sync_event_get(req->resources->comp_event, &se_val);
1870  if (result != DOCA_SUCCESS) {
1871  DOCA_LOG_ERR("Failed to get completion event value: %s", doca_error_get_descr(result));
1872  break;
1873  }
1874 
1875  if (se_val > (req->resources->a2a_seq_num - 1)) {
1876  result = DOCA_SUCCESS;
1877  break;
1878  }
1879 
1880  if (elapsed_time_in_sec > MAX_MPI_WAIT_TIME) {
1882  DOCA_LOG_ERR("Timeout polling completion event");
1883  break;
1884  }
1885 
1886  nanosleep(&ts, &ts);
1887  elapsed_time_in_sec += sleep_in_sec;
1888  }
1889 
1890  return result;
1891 }
1892 
1894  int sendcount,
1895  MPI_Datatype sendtype,
1896  void *recvbuf,
1897  int recvcount,
1898  MPI_Datatype recvtype,
1899  MPI_Comm comm,
1900  struct dpa_a2a_request *req)
1901 {
1902  int num_ranks, my_rank;
1903  /* Number of threads to run the kernel */
1904  unsigned int num_threads;
1906 
1907  /* If current process is not part of any communicator then exit */
1908  if (comm == MPI_COMM_NULL)
1909  return DOCA_SUCCESS;
1910 
1911  /* Get the rank of the current process */
1912  MPI_Comm_rank(comm, &my_rank);
1913  /* Get the number of processes */
1914  MPI_Comm_size(comm, &num_ranks);
1915  if (!req->resources) {
1916  req->resources = (struct a2a_resources *)calloc(1, sizeof(*(req->resources)));
1917  if (req->resources == NULL) {
1918  DOCA_LOG_ERR("Failed to allocate a2a resources");
1919  return DOCA_ERROR_NO_MEMORY;
1920  }
1921  /* Initialize all to all resources */
1922  req->resources->a2a_seq_num = 0;
1923  req->resources->comm = comm;
1924  req->resources->mesg_count = sendcount;
1925  req->resources->msg_type = sendtype;
1926  req->resources->my_rank = my_rank;
1927  req->resources->num_ranks = num_ranks;
1928  req->resources->sendbuf = sendbuf;
1929  req->resources->recvbuf = recvbuf;
1930  result = dpa_a2a_init(req->resources);
1931  if (result != DOCA_SUCCESS) {
1932  DOCA_LOG_ERR("Failed to initialize alltoall resources: %s", doca_error_get_descr(result));
1933  free(req->resources);
1934  return result;
1935  }
1936  }
1937 
1938  /* The number of threads should be the minimum between the number of processes and the maximum number of threads
1939  */
1940  num_threads = (req->resources->num_ranks < MAX_NUM_THREADS) ? req->resources->num_ranks : MAX_NUM_THREADS;
1941 
1942  /* Increment the sequence number */
1943  req->resources->a2a_seq_num++;
1944 
1945  /* Launch all to all kernel*/
1947  NULL,
1948  0,
1949  req->resources->comp_event,
1950  req->resources->a2a_seq_num,
1951  num_threads,
1952  &alltoall_kernel,
1954  req->resources->devptr_rdmas,
1955  (uint64_t)(req->resources->sendbuf),
1957  (uint64_t)sendcount,
1958  (uint64_t)req->resources->extent,
1959  (uint64_t)num_ranks,
1960  (uint64_t)my_rank,
1961  (uint64_t)(req->resources->devptr_recvbufs),
1962  (uint64_t)(req->resources->devptr_recvbufs_mmap_handles),
1965  req->resources->a2a_seq_num);
1966  if (result != DOCA_SUCCESS) {
1967  DOCA_LOG_ERR("Failed to launch alltoall kernel: %s", doca_error_get_descr(result));
1968  return result;
1969  }
1970 
1971  return result;
1972 }
1973 
1975  int sendcount,
1976  MPI_Datatype sendtype,
1977  void *recvbuf,
1978  int recvcount,
1979  MPI_Datatype recvtype,
1980  MPI_Comm comm)
1981 {
1982  struct dpa_a2a_request req = {.resources = NULL};
1984 
1985  /* Run DPA All to All non-blocking */
1986  result = dpa_ialltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, &req);
1987  if (result != DOCA_SUCCESS) {
1988  DOCA_LOG_ERR("dpa_ialltoall() failed: %s", doca_error_get_descr(result));
1989  return result;
1990  }
1991 
1992  /* Wait till the DPA All to All finishes */
1993  result = dpa_a2a_req_wait(&req);
1994  if (result != DOCA_SUCCESS) {
1995  DOCA_LOG_ERR("dpa_a2a_req_wait() failed: %s", doca_error_get_descr(result));
1996  return result;
1997  }
1998 
1999  /* Wait until all processes finish waiting */
2000  MPI_Barrier(comm);
2001 
2002  /* Finalize the request */
2003  result = dpa_a2a_req_finalize(&req);
2004  if (result != DOCA_SUCCESS) {
2005  DOCA_LOG_ERR("dpa_a2a_req_finalize() failed: %s", doca_error_get_descr(result));
2006  return result;
2007  }
2008 
2009  return result;
2010 }
2011 
2012 doca_error_t dpa_a2a(int argc, char **argv, struct a2a_config *cfg)
2013 {
2014  int my_rank, num_ranks, i;
2015  size_t buff_size, msg_size, msg_count;
2016  int *send_buf, *recv_buf, *send_buf_all, *recv_buf_all;
2017  MPI_Request reqs[2];
2019 
2020  /* Initialize MPI variables */
2021  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
2022  MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
2023 
2024  if (num_ranks > MAX_NUM_PROC) {
2025  if (my_rank == 0)
2026  DOCA_LOG_ERR("Invalid number of processes. Maximum number of processes is %d", MAX_NUM_PROC);
2027  return DOCA_ERROR_INVALID_VALUE;
2028  }
2029 
2030  /*
2031  * Define message size, message count and buffer size
2032  * If it's the default then the message size is the number of processes times size of one integer
2033  */
2034  if (cfg->msgsize == MESSAGE_SIZE_DEFAULT_LEN)
2035  msg_size = num_ranks * sizeof(int);
2036  else
2037  msg_size = (size_t)cfg->msgsize;
2038  msg_count = (msg_size / num_ranks) / sizeof(int);
2039  if (msg_count == 0) {
2040  if (my_rank == 0)
2041  DOCA_LOG_ERR("Message size %lu too small for the number of processes. Should be at least %lu",
2042  msg_size,
2043  num_ranks * sizeof(int));
2044  return DOCA_ERROR_INVALID_VALUE;
2045  }
2046 
2047  buff_size = msg_size / sizeof(int);
2048 
2049  /* Set devices names */
2050  strcpy(pf_device1_name, cfg->pf_device1_name);
2051  if (strncmp(cfg->pf_device2_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) != 0)
2052  strcpy(pf_device2_name, cfg->pf_device2_name);
2053  else
2054  strcpy(pf_device2_name, cfg->pf_device1_name);
2055 
2056  strcpy(rdma_device1_name, cfg->rdma_device1_name);
2057  if (strncmp(cfg->rdma_device2_name, IB_DEVICE_DEFAULT_NAME, strlen(IB_DEVICE_DEFAULT_NAME)) != 0)
2058  strcpy(rdma_device2_name, cfg->rdma_device2_name);
2059  else
2060  strcpy(rdma_device2_name, cfg->rdma_device1_name);
2061 
2062  if (my_rank == 0)
2063  DOCA_LOG_INFO("Number of processes = %d, message size = %lu, message count = %lu, buffer size = %lu",
2064  num_ranks,
2065  msg_size,
2066  msg_count,
2067  buff_size);
2068 
2069  /* Allocate and initialize the buffers */
2070  send_buf = calloc(buff_size, sizeof(int));
2071  recv_buf = calloc(buff_size, sizeof(int));
2072  send_buf_all = calloc(num_ranks * buff_size, sizeof(int));
2073  recv_buf_all = calloc(num_ranks * buff_size, sizeof(int));
2074 
2075  if (send_buf == NULL || recv_buf == NULL || send_buf_all == NULL || recv_buf_all == NULL) {
2076  DOCA_LOG_ERR("Failed to allocate memory for send/recv buffers");
2078  goto destroy_bufs;
2079  }
2080 
2081  /* Seed srand */
2082  srand(time(NULL) + my_rank);
2083  for (i = 0; i < buff_size; i++)
2084  send_buf[i] = compute_random_int();
2085 
2086  MPI_Barrier(MPI_COMM_WORLD);
2087 
2088  /* Perform DPA All to All */
2089  result = dpa_alltoall(send_buf, msg_count, MPI_INT, recv_buf, msg_count, MPI_INT, MPI_COMM_WORLD);
2090  if (result != DOCA_SUCCESS) {
2091  if (my_rank == 0)
2092  DOCA_LOG_ERR("DPA MPI alltoall failed: %s", doca_error_get_descr(result));
2093  goto destroy_bufs;
2094  }
2095 
2096  /* Receive all the sendbuf and the recvbuf from all the processes to print */
2097  MPI_Iallgather(send_buf, buff_size, MPI_INT, send_buf_all, buff_size, MPI_INT, MPI_COMM_WORLD, &reqs[0]);
2098 
2100  if (result != DOCA_SUCCESS) {
2101  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
2102  goto destroy_bufs;
2103  }
2104 
2105  MPI_Iallgather(recv_buf, buff_size, MPI_INT, recv_buf_all, buff_size, MPI_INT, MPI_COMM_WORLD, &reqs[1]);
2106 
2108  if (result != DOCA_SUCCESS) {
2109  DOCA_LOG_ERR("Timed out waiting on allgather: %s", doca_error_get_descr(result));
2110  goto destroy_bufs;
2111  }
2112 
2113  if (my_rank == 0) {
2114  printf(" ------------send buffs----------------------\n");
2115  print_buff(send_buf_all, buff_size, num_ranks);
2116  printf(" ------------recv buffs----------------------\n");
2117  print_buff(recv_buf_all, buff_size, num_ranks);
2118  }
2119 
2120 destroy_bufs:
2121  free(send_buf);
2122  free(send_buf_all);
2123  free(recv_buf);
2124  free(recv_buf_all);
2125 
2126  return result;
2127 }
#define NULL
Definition: __stddef_null.h:26
__SIZE_TYPE__ size_t
int32_t result
doca_dpa_dev_mmap_t mmap
static doca_error_t create_doca_dpa_completion_sync_event(struct doca_dpa *doca_dpa, struct doca_dev *doca_device, struct doca_sync_event **comp_event)
DOCA_LOG_REGISTER(A2A::Core)
bool rdma_device_exists_check(const char *device_name)
static doca_error_t create_rdma(struct doca_dpa *doca_dpa, struct doca_dev *doca_device, unsigned int rdma_caps, struct doca_dpa_completion *dpa_completion, struct doca_rdma **rdma)
static doca_error_t create_dpa_a2a_events(struct a2a_resources *resources)
doca_dpa_func_t alltoall_kernel
static doca_error_t open_dpa_devices(const char *pf_device_name, const char *rdma_device_name, struct doca_dev **pf_doca_device, struct doca_dev **rdma_doca_device)
static doca_error_t prepare_dpa_a2a_dpa_completions(struct a2a_resources *resources)
char rdma_device1_name[MAX_IB_DEVICE_NAME_LEN]
static doca_error_t connect_dpa_a2a_rdmas(struct a2a_resources *resources)
doca_error_t dpa_a2a_req_finalize(struct dpa_a2a_request *req)
struct doca_dpa_app * dpa_all2all_app
#define SLEEP_IN_NANO_SEC
doca_error_t dpa_ialltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, struct dpa_a2a_request *req)
char pf_device2_name[MAX_IB_DEVICE_NAME_LEN]
doca_error_t dpa_a2a(int argc, char **argv, struct a2a_config *cfg)
static doca_error_t prepare_dpa_a2a_rdmas(struct a2a_resources *resources)
static doca_error_t mpi_request_wait_timeout(MPI_Request *req, size_t timeout)
static doca_error_t create_mmap(struct doca_dev *doca_device, unsigned int mmap_permissions, void *memrange_addr, size_t memrange_len, struct doca_mmap **mmap, doca_dpa_dev_mmap_t *dpa_mmap_handle)
doca_error_t dpa_a2a_req_wait(struct dpa_a2a_request *req)
static int calc_width(int n)
static doca_error_t create_dpa_context(struct a2a_resources *resources)
static void print_buff(const int *buff, size_t columns, size_t rows)
doca_error_t dpa_a2a_init(struct a2a_resources *resources)
doca_error_t dpa_alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
bool dpa_device_exists_check(const char *device_name)
#define MAX_MPI_WAIT_TIME
char pf_device1_name[MAX_IB_DEVICE_NAME_LEN]
static int compute_random_int(void)
static doca_error_t create_doca_dpa_sync_event_from_export(struct doca_dpa *doca_dpa, struct doca_dev *doca_device, const uint8_t *remote_event_export_data, size_t remote_event_export_size, struct doca_sync_event_remote_net **remote_event, doca_dpa_dev_sync_event_remote_net_t *remote_event_dpa_handle)
doca_error_t dpa_a2a_destroy(struct a2a_resources *resources)
static doca_error_t destroy_rdma(struct doca_rdma *rdma, struct doca_dev *doca_device)
static doca_error_t prepare_dpa_a2a_memory(struct a2a_resources *resources)
char rdma_device2_name[MAX_IB_DEVICE_NAME_LEN]
static doca_error_t create_doca_dpa_remote_net_sync_event(struct doca_dpa *doca_dpa, struct doca_sync_event **kernel_event)
#define MAX_NUM_PROC
#define MAX_NUM_THREADS
#define MESSAGE_SIZE_DEFAULT_LEN
#define IB_DEVICE_DEFAULT_NAME
#define MAX_IB_DEVICE_NAME_LEN
uint32_t dpa_mmap_handle
struct rdma_resources resources
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_EXPERIMENTAL doca_error_t doca_ctx_set_datapath_on_dpa(struct doca_ctx *ctx, struct doca_dpa *dpa_dev)
This function binds the DOCA context to a dpa device.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
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.
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
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.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_destroy(struct doca_dpa_completion *dpa_comp)
Destroy DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_kernel_launch_update_set(struct doca_dpa *dpa, struct doca_sync_event *wait_event, uint64_t wait_threshold, struct doca_sync_event *comp_event, uint64_t comp_count, unsigned int num_threads, doca_dpa_func_t *func,...)
Submit a kernel to DPA that sets completion event.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_create(struct doca_dev *dev, struct doca_dpa **dpa)
Create a DOCA DPA Context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_get_dpa_handle(struct doca_dpa *dpa, doca_dpa_dev_t *handle)
Get DPA context handle.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_device_extend(struct doca_dpa *dpa, struct doca_dev *other_dev, struct doca_dpa **extended_dpa)
Create an extended DPA context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_mem_alloc(struct doca_dpa *dpa, size_t size, doca_dpa_dev_uintptr_t *dev_ptr)
Allocate DPA heap memory.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_start(struct doca_dpa_completion *dpa_comp)
Start DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_mem_free(struct doca_dpa *dpa, doca_dpa_dev_uintptr_t dev_ptr)
Free the previously allocated DPA memory.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_destroy(struct doca_dpa *dpa)
Destroy a DOCA DPA context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_completion_create(struct doca_dpa *dpa, unsigned int queue_size, struct doca_dpa_completion **dpa_comp)
Create DPA completion context.
void() doca_dpa_func_t(void)
Generic function pointer type.
Definition: doca_dpa.h:118
DOCA_EXPERIMENTAL doca_error_t doca_dpa_start(struct doca_dpa *dpa)
Start a DPA context.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_h2d_memcpy(struct doca_dpa *dpa, doca_dpa_dev_uintptr_t dst_ptr, void *src_ptr, size_t size)
Copy from host memory to DPA Heap.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_cap_is_supported(const struct doca_devinfo *devinfo)
Get whether the DOCA device supports DPA.
DOCA_EXPERIMENTAL doca_error_t doca_dpa_set_app(struct doca_dpa *dpa, struct doca_dpa_app *app)
Set program app for DPA context.
#define DOCA_ERROR_PROPAGATE(r, t)
Save the first encountered doca_error_t.
Definition: doca_error.h:83
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_TIME_OUT
Definition: doca_error.h:47
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_ERROR_UNEXPECTED
Definition: doca_error.h:60
@ DOCA_ERROR_NOT_FOUND
Definition: doca_error.h:54
@ 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
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
uint32_t doca_dpa_dev_mmap_t
Handle on the DPA for a doca_mmap instance.
Definition: doca_mmap.h:74
DOCA_STABLE doca_error_t doca_mmap_set_memrange(struct doca_mmap *mmap, void *addr, size_t len)
Set the memory range of DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_destroy(struct doca_mmap *mmap)
Destroy DOCA Memory Map structure.
DOCA_STABLE doca_error_t doca_mmap_create(struct doca_mmap **mmap)
Allocates zero size memory map object with default/unset attributes.
DOCA_STABLE doca_error_t doca_mmap_create_from_export(const union doca_data *user_data, const void *export_desc, size_t export_desc_len, struct doca_dev *dev, struct doca_mmap **mmap)
Creates a memory map object representing memory ranges in remote system memory space.
DOCA_STABLE doca_error_t doca_mmap_set_permissions(struct doca_mmap *mmap, uint32_t access_mask)
Set access flags of the registered memory.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_EXPERIMENTAL doca_error_t doca_mmap_dev_get_dpa_handle(struct doca_mmap *mmap, const struct doca_dev *dev, doca_dpa_dev_mmap_t *dpa_mmap_handle)
Extract mmap handle associated with the given DOCA device, for the DPA to operate on.
DOCA_STABLE doca_error_t doca_mmap_add_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Register DOCA memory map on a given device.
DOCA_STABLE doca_error_t doca_mmap_export_rdma(struct doca_mmap *mmap, const struct doca_dev *dev, const void **export_desc, size_t *export_desc_len)
Compose memory map representation for later import with doca_mmap_create_from_export() for one of the...
DOCA_EXPERIMENTAL doca_error_t doca_rdma_destroy(struct doca_rdma *rdma)
Destroy a DOCA RDMA instance.
DOCA_EXPERIMENTAL doca_error_t doca_rdma_dpa_completion_attach(struct doca_rdma *rdma, struct doca_dpa_completion *dpa_comp)
Attach DOCA RDMA to DPA completion context.
DOCA_EXPERIMENTAL doca_error_t doca_rdma_set_grh_enabled(struct doca_rdma *rdma, uint8_t grh_enabled)
Set whether to use GRH in connection. The value can be queried using doca_rdma_get_grh_enabled()....
DOCA_EXPERIMENTAL doca_error_t doca_rdma_set_permissions(struct doca_rdma *rdma, uint32_t permissions)
Set rdma permissions for doca_rdma. The value can be queried using doca_rdma_get_permissions()....
DOCA_EXPERIMENTAL doca_error_t doca_rdma_get_dpa_handle(struct doca_rdma *rdma, doca_dpa_dev_rdma_t *dpa_rdma)
Retrieve the handle in the dpa memory space of a doca_rdma.
DOCA_EXPERIMENTAL doca_error_t doca_rdma_export(struct doca_rdma *rdma, const void **local_rdma_conn_details, size_t *local_rdma_conn_details_size, struct doca_rdma_connection **rdma_connection)
Export doca_rdma connection details object The doca_rdma_conn_details are used in doca_rdma_connect()...
DOCA_EXPERIMENTAL struct doca_ctx * doca_rdma_as_ctx(struct doca_rdma *rdma)
Convert doca_rdma instance into a generalized context for use with doca core objects.
uint64_t doca_dpa_dev_rdma_t
Definition: doca_rdma.h:79
DOCA_EXPERIMENTAL doca_error_t doca_rdma_connect(struct doca_rdma *rdma, const void *remote_rdma_conn_details, size_t remote_rdma_conn_details_size, struct doca_rdma_connection *rdma_connection)
Connect to remote doca_rdma peer. Can only be called when the ctx is in DOCA_CTX_STATE_STARTING state...
DOCA_EXPERIMENTAL doca_error_t doca_rdma_create(struct doca_dev *dev, struct doca_rdma **rdma)
Create a DOCA RDMA instance.
DOCA_EXPERIMENTAL doca_error_t doca_rdma_cap_task_send_is_supported(const struct doca_devinfo *devinfo)
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_remote_net_create_from_export(struct doca_dev *dev, const uint8_t *data, size_t sz, struct doca_sync_event_remote_net **event)
Create a remote Sync Event handle from an export.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_remote_net_destroy(struct doca_sync_event_remote_net *event)
Destroy a Sync Event instance.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_start(struct doca_sync_event *event)
Start a Sync Event to be operate as stand-alone DOCA Core object only.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_get(struct doca_sync_event *event, uint64_t *value)
Get the value of a Sync Event synchronously.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_create(struct doca_sync_event **event)
Create a Sync Event handle.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_add_subscriber_location_dpa(struct doca_sync_event *event, struct doca_dpa *dpa)
Associate a DOCA DPA context as the Sync Event subscriber.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_remote_net_get_dpa_handle(struct doca_sync_event_remote_net *event, struct doca_dpa *dpa, doca_dpa_dev_sync_event_remote_net_t *dpa_remote_event)
Export remote Sync Event to be shared with the DPA.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_get_dpa_handle(struct doca_sync_event *event, struct doca_dpa *dpa, doca_dpa_dev_sync_event_t *dpa_dev_se_handle)
Export Sync Event to be shared with the DPA.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_add_publisher_location_remote_net(struct doca_sync_event *event)
Declare Sync Event publisher as a remote peer.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_add_subscriber_location_cpu(struct doca_sync_event *event, struct doca_dev *dev)
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_destroy(struct doca_sync_event *event)
Destroy a Sync Event instance.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_add_publisher_location_dpa(struct doca_sync_event *event, struct doca_dpa *dpa)
Associate a DOCA DPA context as the Sync Event publisher.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_export_to_remote_net(struct doca_sync_event *event, const uint8_t **data, size_t *sz)
Export Sync Event to be shared with a remote peer.
uint64_t doca_dpa_dev_sync_event_remote_net_t
DOCA Sync Event remote DPA handle.
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_RDMA_READ
Definition: doca_types.h:84
@ DOCA_ACCESS_FLAG_LOCAL_READ_ONLY
Definition: doca_types.h:82
@ DOCA_ACCESS_FLAG_RDMA_ATOMIC
Definition: doca_types.h:86
@ DOCA_ACCESS_FLAG_RDMA_WRITE
Definition: doca_types.h:85
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:298
struct doca_dpa * pf_doca_dpa
MPI_Datatype msg_type
doca_dpa_dev_t rdma_doca_dpa_handle
doca_dpa_dev_uintptr_t devptr_recvbufs_mmap_handles
doca_dpa_dev_uintptr_t devptr_kernel_events_handle
doca_dpa_dev_mmap_t sendbuf_dpa_mmap_handle
doca_dpa_dev_uintptr_t devptr_rp_remote_kernel_events
doca_dpa_dev_uintptr_t devptr_recvbufs
struct doca_sync_event * comp_event
doca_dpa_dev_uintptr_t devptr_rdmas
struct a2a_resources * resources