NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
dma_copy_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 <stdint.h>
27 #include <string.h>
28 #include <time.h>
29 #include <netinet/in.h>
30 #include <errno.h>
31 #include <sys/epoll.h>
32 #include <unistd.h>
33 
34 #include <doca_buf.h>
35 #include <doca_buf_inventory.h>
36 #include <doca_ctx.h>
37 #include <doca_dev.h>
38 #include <doca_dma.h>
39 #include <doca_mmap.h>
40 
41 #include <samples/common.h>
42 
43 #include "pack.h"
44 #include "utils.h"
45 
46 #include "dma_copy_core.h"
47 
48 #define CC_MAX_QUEUE_SIZE 10 /* Max number of messages on Comm Channel queue */
49 #define SLEEP_IN_NANOS (10 * 1000) /* Sample the task every 10 microseconds */
50 #define STATUS_SUCCESS true /* Successful status */
51 #define STATUS_FAILURE false /* Unsuccessful status */
52 
53 DOCA_LOG_REGISTER(DMA_COPY_CORE);
54 
55 /*
56  * Get DOCA DMA maximum buffer size allowed
57  *
58  * @resources [in]: DOCA DMA resources pointer
59  * @max_buf_size [out]: Maximum buffer size allowed
60  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
61  */
62 static doca_error_t get_dma_max_buf_size(struct dma_copy_resources *resources, uint64_t *max_buf_size)
63 {
64  struct doca_devinfo *dma_dev_info = doca_dev_as_devinfo(resources->state->dev);
66 
67  result = doca_dma_cap_task_memcpy_get_max_buf_size(dma_dev_info, max_buf_size);
68  if (result != DOCA_SUCCESS)
69  DOCA_LOG_ERR("Failed to retrieve maximum buffer size allowed from DOCA DMA device: %s",
71  else
72  DOCA_LOG_DBG("DOCA DMA device supports maximum buffer size of %" PRIu64 " bytes", *max_buf_size);
73 
74  return result;
75 }
76 
77 /*
78  * Validate file size
79  *
80  * @file_path [in]: File to validate
81  * @file_size [out]: File size
82  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
83  */
84 static doca_error_t validate_file_size(const char *file_path, uint64_t *file_size)
85 {
86  FILE *fp;
87  long size;
88 
89  fp = fopen(file_path, "r");
90  if (fp == NULL) {
91  DOCA_LOG_ERR("Failed to open %s", file_path);
92  return DOCA_ERROR_IO_FAILED;
93  }
94 
95  if (fseek(fp, 0, SEEK_END) != 0) {
96  DOCA_LOG_ERR("Failed to calculate file size");
97  fclose(fp);
98  return DOCA_ERROR_IO_FAILED;
99  }
100 
101  size = ftell(fp);
102  if (size == -1) {
103  DOCA_LOG_ERR("Failed to calculate file size");
104  fclose(fp);
105  return DOCA_ERROR_IO_FAILED;
106  }
107 
108  fclose(fp);
109 
110  DOCA_LOG_INFO("The file size is %ld", size);
111 
112  *file_size = size;
113 
114  return DOCA_SUCCESS;
115 }
116 
117 /*
118  * ARGP validation Callback - check if input file exists
119  *
120  * @config [in]: Program configuration context
121  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
122  */
124 {
125  struct dma_copy_cfg *cfg = (struct dma_copy_cfg *)config;
126 
127  if (access(cfg->file_path, F_OK | R_OK) == 0) {
128  cfg->is_file_found_locally = true;
129  return validate_file_size(cfg->file_path, &cfg->file_size);
130  }
131 
132  return DOCA_SUCCESS;
133 }
134 
135 /*
136  * ARGP Callback - Handle Comch DOCA device PCI address parameter
137  *
138  * @param [in]: Input parameter
139  * @config [in/out]: Program configuration context
140  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
141  */
142 static doca_error_t dev_pci_addr_callback(void *param, void *config)
143 {
144  struct dma_copy_cfg *cfg = (struct dma_copy_cfg *)config;
145  const char *dev_pci_addr = (char *)param;
146 
147  if (strnlen(dev_pci_addr, DOCA_DEVINFO_PCI_ADDR_SIZE) == DOCA_DEVINFO_PCI_ADDR_SIZE) {
148  DOCA_LOG_ERR("Entered device PCI address exceeding the maximum size of %d",
151  }
152 
153  strlcpy(cfg->cc_dev_pci_addr, dev_pci_addr, DOCA_DEVINFO_PCI_ADDR_SIZE);
154 
155  return DOCA_SUCCESS;
156 }
157 
158 /*
159  * ARGP Callback - Handle file parameter
160  *
161  * @param [in]: Input parameter
162  * @config [in/out]: Program configuration context
163  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
164  */
165 static doca_error_t file_path_callback(void *param, void *config)
166 {
167  struct dma_copy_cfg *cfg = (struct dma_copy_cfg *)config;
168  char *file_path = (char *)param;
169  int file_path_len = strnlen(file_path, MAX_ARG_SIZE);
170 
171  if (file_path_len == MAX_ARG_SIZE) {
172  DOCA_LOG_ERR("Entered file path exceeded buffer size - MAX=%d", MAX_ARG_SIZE - 1);
174  }
175 
176  strlcpy(cfg->file_path, file_path, MAX_ARG_SIZE);
177 
178  return DOCA_SUCCESS;
179 }
180 
181 /*
182  * ARGP Callback - Handle Comch DOCA device representor PCI address parameter
183  *
184  * @param [in]: Input parameter
185  * @config [in/out]: Program configuration context
186  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
187  */
188 static doca_error_t rep_pci_addr_callback(void *param, void *config)
189 {
190  struct dma_copy_cfg *cfg = (struct dma_copy_cfg *)config;
191  const char *rep_pci_addr = (char *)param;
192 
193  if (cfg->mode == DMA_COPY_MODE_DPU) {
194  if (strnlen(rep_pci_addr, DOCA_DEVINFO_REP_PCI_ADDR_SIZE) == DOCA_DEVINFO_REP_PCI_ADDR_SIZE) {
195  DOCA_LOG_ERR("Entered device representor PCI address exceeding the maximum size of %d",
198  }
199 
200  strlcpy(cfg->cc_dev_rep_pci_addr, rep_pci_addr, DOCA_DEVINFO_REP_PCI_ADDR_SIZE);
201  }
202 
203  return DOCA_SUCCESS;
204 }
205 
206 /*
207  * Save remote buffer information into a file
208  *
209  * @cfg [in]: Application configuration
210  * @buffer [in]: Buffer to read information from
211  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
212  */
213 static doca_error_t save_buffer_into_a_file(struct dma_copy_cfg *cfg, const char *buffer)
214 {
215  FILE *fp;
216 
217  fp = fopen(cfg->file_path, "w");
218  if (fp == NULL) {
219  DOCA_LOG_ERR("Failed to create the DMA copy file");
220  return DOCA_ERROR_IO_FAILED;
221  }
222 
223  if (fwrite(buffer, 1, cfg->file_size, fp) != cfg->file_size) {
224  DOCA_LOG_ERR("Failed to write full content into the output file");
225  fclose(fp);
226  return DOCA_ERROR_IO_FAILED;
227  }
228 
229  fclose(fp);
230 
231  return DOCA_SUCCESS;
232 }
233 
234 /*
235  * Fill local buffer with file content
236  *
237  * @cfg [in]: Application configuration
238  * @buffer [out]: Buffer to save information into
239  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
240  */
242 {
243  FILE *fp;
244 
245  fp = fopen(cfg->file_path, "r");
246  if (fp == NULL) {
247  DOCA_LOG_ERR("Failed to open %s", cfg->file_path);
248  return DOCA_ERROR_IO_FAILED;
249  }
250 
251  /* Read file content and store it in the local buffer which will be exported */
252  if (fread(buffer, 1, cfg->file_size, fp) != cfg->file_size) {
253  DOCA_LOG_ERR("Failed to read content from file: %s", cfg->file_path);
254  fclose(fp);
255  return DOCA_ERROR_IO_FAILED;
256  }
257  fclose(fp);
258 
259  return DOCA_SUCCESS;
260 }
261 
262 /*
263  * Allocate memory and populate it into the memory map
264  *
265  * @mmap [in]: DOCA memory map
266  * @buffer_len [in]: Allocated buffer length
267  * @access_flags [in]: The access permissions of the mmap
268  * @buffer [out]: Allocated buffer
269  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
270  */
271 static doca_error_t memory_alloc_and_populate(struct doca_mmap *mmap,
272  size_t buffer_len,
273  uint32_t access_flags,
274  char **buffer)
275 {
277 
278  result = doca_mmap_set_permissions(mmap, access_flags);
279  if (result != DOCA_SUCCESS) {
280  DOCA_LOG_ERR("Unable to set access permissions of memory map: %s", doca_error_get_descr(result));
281  return result;
282  }
283 
284  *buffer = (char *)malloc(buffer_len);
285  if (*buffer == NULL) {
286  DOCA_LOG_ERR("Failed to allocate memory for source buffer");
287  return DOCA_ERROR_NO_MEMORY;
288  }
289 
290  result = doca_mmap_set_memrange(mmap, *buffer, buffer_len);
291  if (result != DOCA_SUCCESS) {
292  DOCA_LOG_ERR("Unable to set memrange of memory map: %s", doca_error_get_descr(result));
293  free(*buffer);
294  return result;
295  }
296 
297  /* Populate local buffer into memory map to allow access from DPU side after exporting */
299  if (result != DOCA_SUCCESS) {
300  DOCA_LOG_ERR("Unable to populate memory map: %s", doca_error_get_descr(result));
301  free(*buffer);
302  }
303 
304  return result;
305 }
306 
307 /*
308  * DPU side function for submitting DMA task into the progress engine, wait for its completion and save it into a file
309  * if needed.
310  *
311  * @cfg [in]: Application configuration
312  * @resources [in]: DMA copy resources
313  * @bytes_to_copy [in]: Number of bytes to DMA copy
314  * @buffer [in]: local DMA buffer
315  * @local_doca_buf [in]: local DOCA buffer
316  * @remote_doca_buf [in]: remote DOCA buffer
317  * @num_remaining_tasks [in]: Number of remaining tasks
318  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
319  */
322  size_t bytes_to_copy,
323  char *buffer,
324  struct doca_buf *local_doca_buf,
325  struct doca_buf *remote_doca_buf,
326  size_t *num_remaining_tasks)
327 {
328  struct program_core_objects *state = resources->state;
329  struct doca_dma_task_memcpy *dma_task;
330  struct doca_task *task;
331  union doca_data task_user_data = {0};
332  void *data;
333  struct doca_buf *src_buf;
334  struct doca_buf *dst_buf;
335  struct timespec ts = {
336  .tv_sec = 0,
337  .tv_nsec = SLEEP_IN_NANOS,
338  };
340  doca_error_t task_result;
341 
342  /* Determine DMA copy direction */
343  if (cfg->is_file_found_locally) {
344  src_buf = local_doca_buf;
345  dst_buf = remote_doca_buf;
346  } else {
347  src_buf = remote_doca_buf;
348  dst_buf = local_doca_buf;
349  }
350 
351  /* Set data position in src_buf */
352  result = doca_buf_get_data(src_buf, &data);
353  if (result != DOCA_SUCCESS) {
354  DOCA_LOG_ERR("Failed to get data address from DOCA buffer: %s", doca_error_get_descr(result));
355  return result;
356  }
357  result = doca_buf_set_data(src_buf, data, bytes_to_copy);
358  if (result != DOCA_SUCCESS) {
359  DOCA_LOG_ERR("Failed to set data for DOCA buffer: %s", doca_error_get_descr(result));
360  return result;
361  }
362 
363  /* Include result in user data of task to be used in the callbacks */
364  task_user_data.ptr = &task_result;
365  /* Allocate and construct DMA task */
366  result = doca_dma_task_memcpy_alloc_init(resources->dma_ctx, src_buf, dst_buf, task_user_data, &dma_task);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to allocate DMA memcpy task: %s", doca_error_get_descr(result));
369  return result;
370  }
371 
372  task = doca_dma_task_memcpy_as_task(dma_task);
373 
374  /* Submit DMA task */
375  result = doca_task_submit(task);
376  if (result != DOCA_SUCCESS) {
377  DOCA_LOG_ERR("Failed to submit DMA task: %s", doca_error_get_descr(result));
378  goto free_task;
379  }
380 
381  /* Wait for all tasks to be completed */
382  while (*num_remaining_tasks > 0) {
383  if (doca_pe_progress(state->pe) == 0)
384  nanosleep(&ts, &ts);
385  }
386 
387  /* Check result of task according to the result we update in the callbacks */
388  if (task_result != DOCA_SUCCESS) {
389  DOCA_LOG_ERR("DMA copy failed: %s", doca_error_get_descr(task_result));
390  result = task_result;
391  goto free_task;
392  }
393 
394  DOCA_LOG_INFO("DMA copy was done Successfully");
395 
396  /* If the buffer was copied into to DPU, save it as a file */
397  if (!cfg->is_file_found_locally) {
398  DOCA_LOG_INFO("Writing DMA buffer into a file on %s", cfg->file_path);
400  if (result != DOCA_SUCCESS)
401  return result;
402  }
403 
404 free_task:
405  doca_task_free(task);
406  return result;
407 }
408 
409 /*
410  * Check if DOCA device is DMA capable
411  *
412  * @devinfo [in]: Device to check
413  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
414  */
415 static doca_error_t check_dev_dma_capable(struct doca_devinfo *devinfo)
416 {
418 }
419 
421 {
423  struct doca_argp_param *file_path_param, *dev_pci_addr_param, *rep_pci_addr_param;
424 
425  /* Create and register string to dma copy param */
426  result = doca_argp_param_create(&file_path_param);
427  if (result != DOCA_SUCCESS) {
428  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
429  return result;
430  }
431  doca_argp_param_set_short_name(file_path_param, "f");
432  doca_argp_param_set_long_name(file_path_param, "file");
433  doca_argp_param_set_description(file_path_param,
434  "Full path to file to be copied/created after a successful DMA copy");
437  doca_argp_param_set_mandatory(file_path_param);
438  result = doca_argp_register_param(file_path_param);
439  if (result != DOCA_SUCCESS) {
440  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
441  return result;
442  }
443 
444  /* Create and register DOCA Comch device PCI address */
445  result = doca_argp_param_create(&dev_pci_addr_param);
446  if (result != DOCA_SUCCESS) {
447  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
448  return result;
449  }
450  doca_argp_param_set_short_name(dev_pci_addr_param, "p");
451  doca_argp_param_set_long_name(dev_pci_addr_param, "pci-addr");
452  doca_argp_param_set_description(dev_pci_addr_param, "DOCA Comch device PCI address");
454  doca_argp_param_set_type(dev_pci_addr_param, DOCA_ARGP_TYPE_STRING);
455  doca_argp_param_set_mandatory(dev_pci_addr_param);
456  result = doca_argp_register_param(dev_pci_addr_param);
457  if (result != DOCA_SUCCESS) {
458  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
459  return result;
460  }
461 
462  /* Create and register DOCA Comch device representor PCI address */
463  result = doca_argp_param_create(&rep_pci_addr_param);
464  if (result != DOCA_SUCCESS) {
465  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
466  return result;
467  }
468  doca_argp_param_set_short_name(rep_pci_addr_param, "r");
469  doca_argp_param_set_long_name(rep_pci_addr_param, "rep-pci");
470  doca_argp_param_set_description(rep_pci_addr_param,
471  "DOCA Comch device representor PCI address (needed only on DPU)");
473  doca_argp_param_set_type(rep_pci_addr_param, DOCA_ARGP_TYPE_STRING);
474  result = doca_argp_register_param(rep_pci_addr_param);
475  if (result != DOCA_SUCCESS) {
476  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
477  return result;
478  }
479 
480  /* Register validation callback */
482  if (result != DOCA_SUCCESS) {
483  DOCA_LOG_ERR("Failed to register program validation callback: %s", doca_error_get_descr(result));
484  return result;
485  }
486 
487  /* Register version callback for DOCA SDK & RUNTIME */
489  if (result != DOCA_SUCCESS) {
490  DOCA_LOG_ERR("Failed to register version callback: %s", doca_error_get_descr(result));
491  return result;
492  }
493 
494  return DOCA_SUCCESS;
495 }
496 
497 doca_error_t open_dma_device(struct doca_dev **dev)
498 {
500 
502  if (result != DOCA_SUCCESS)
503  DOCA_LOG_ERR("Failed to open DOCA DMA capable device: %s", doca_error_get_descr(result));
504 
505  return result;
506 }
507 
508 /*
509  * DMA Memcpy task completed callback
510  *
511  * @dma_task [in]: Completed task
512  * @task_user_data [in]: doca_data from the task
513  * @ctx_user_data [in]: doca_data from the context
514  */
515 static void dma_memcpy_completed_callback(struct doca_dma_task_memcpy *dma_task,
516  union doca_data task_user_data,
517  union doca_data ctx_user_data)
518 {
519  size_t *num_remaining_tasks = (size_t *)ctx_user_data.ptr;
520  doca_error_t *result = (doca_error_t *)task_user_data.ptr;
521 
522  (void)dma_task;
523  /* Decrement number of remaining tasks */
524  --*num_remaining_tasks;
525  /* Assign success to the result */
526  *result = DOCA_SUCCESS;
527 }
528 
529 /*
530  * Memcpy task error callback
531  *
532  * @dma_task [in]: failed task
533  * @task_user_data [in]: doca_data from the task
534  * @ctx_user_data [in]: doca_data from the context
535  */
536 static void dma_memcpy_error_callback(struct doca_dma_task_memcpy *dma_task,
537  union doca_data task_user_data,
538  union doca_data ctx_user_data)
539 {
540  size_t *num_remaining_tasks = (size_t *)ctx_user_data.ptr;
541  struct doca_task *task = doca_dma_task_memcpy_as_task(dma_task);
542  doca_error_t *result = (doca_error_t *)task_user_data.ptr;
543 
544  /* Decrement number of remaining tasks */
545  --*num_remaining_tasks;
546  /* Get the result of the task */
547  *result = doca_task_get_status(task);
548 }
549 
550 /*
551  * Destroy copy resources
552  *
553  * @resources [in]: DMA copy resources
554  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
555  */
557 {
558  struct program_core_objects *state = resources->state;
559  doca_error_t result = DOCA_SUCCESS, tmp_result;
560 
561  if (resources->dma_ctx != NULL) {
562  tmp_result = doca_dma_destroy(resources->dma_ctx);
563  if (tmp_result != DOCA_SUCCESS) {
564  DOCA_ERROR_PROPAGATE(result, tmp_result);
565  DOCA_LOG_ERR("Failed to destroy DOCA DMA context: %s", doca_error_get_descr(tmp_result));
566  }
567  }
568 
569  tmp_result = destroy_core_objects(state);
570  if (tmp_result != DOCA_SUCCESS) {
571  DOCA_ERROR_PROPAGATE(result, tmp_result);
572  DOCA_LOG_ERR("Failed to destroy DOCA core objects: %s", doca_error_get_descr(tmp_result));
573  }
574 
575  free(resources->state);
576 
577  return result;
578 }
579 
580 /*
581  * Allocate DMA copy resources
582  *
583  * @resources [out]: DOCA DMA copy resources
584  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
585  */
587 {
588  struct program_core_objects *state = NULL;
589  doca_error_t result, tmp_result;
590  /* Two buffers for source and destination */
591  uint32_t max_bufs = 2;
592 
593  resources->state = malloc(sizeof(*(resources->state)));
594  if (resources->state == NULL) {
596  DOCA_LOG_ERR("Failed to allocate DOCA program core objects: %s", doca_error_get_descr(result));
597  return result;
598  }
599  state = resources->state;
600 
601  /* Open DOCA dma device */
602  result = open_dma_device(&state->dev);
603  if (result != DOCA_SUCCESS) {
604  DOCA_LOG_ERR("Failed to open DMA device: %s", doca_error_get_descr(result));
605  goto free_state;
606  }
607 
608  result = create_core_objects(state, max_bufs);
609  if (result != DOCA_SUCCESS) {
610  DOCA_LOG_ERR("Failed to create core objects: %s", doca_error_get_descr(result));
612  }
613 
614  result = doca_dma_create(state->dev, &resources->dma_ctx);
615  if (result != DOCA_SUCCESS) {
616  DOCA_LOG_ERR("Unable to create DOCA DMA context: %s", doca_error_get_descr(result));
618  }
619 
620  state->ctx = doca_dma_as_ctx(resources->dma_ctx);
621 
622  result = doca_pe_connect_ctx(state->pe, state->ctx);
623  if (result != DOCA_SUCCESS) {
624  DOCA_LOG_ERR("Unable to set DOCA progress engine to DOCA DMA: %s", doca_error_get_descr(result));
625  goto destroy_dma;
626  }
627 
631  NUM_DMA_TASKS);
632  if (result != DOCA_SUCCESS) {
633  DOCA_LOG_ERR("Unable to set configurations for DMA memcpy task: %s", doca_error_get_descr(result));
634  goto destroy_dma;
635  }
636 
637  return result;
638 
639 destroy_dma:
640  tmp_result = doca_dma_destroy(resources->dma_ctx);
641  if (tmp_result != DOCA_SUCCESS) {
642  DOCA_ERROR_PROPAGATE(result, tmp_result);
643  DOCA_LOG_ERR("Failed to destroy DOCA DMA context: %s", doca_error_get_descr(tmp_result));
644  }
646  tmp_result = destroy_core_objects(state);
647  if (tmp_result != DOCA_SUCCESS) {
648  DOCA_ERROR_PROPAGATE(result, tmp_result);
649  DOCA_LOG_ERR("Failed to destroy DOCA core objects: %s", doca_error_get_descr(tmp_result));
650  }
651 free_state:
652  free(resources->state);
653 
654  return result;
655 }
656 
657 /*
658  * Helper function to send a status message across the comch
659  *
660  * @comch_connection [in]: comch connection to send the status message across
661  * @status [in]: true means the status is success, false means a failure
662  */
663 static void send_status_msg(struct doca_comch_connection *comch_connection, bool status)
664 {
665  struct comch_msg_dma_status status_msg = {.type = COMCH_MSG_STATUS};
667 
668  status_msg.is_success = status;
669 
670  result = comch_utils_send(comch_connection, &status_msg, sizeof(struct comch_msg_dma_status));
671  if (result != DOCA_SUCCESS) {
672  DOCA_LOG_ERR("Failed to send status message: %s", doca_error_get_descr(result));
673  }
674 }
675 
676 /*
677  * Process and respond to a DMA direction negotiation message on the host
678  *
679  * @cfg [in]: dma copy configuration information
680  * @comch_connection [in]: comch connection the message was received on
681  * @dir_msg [in]: the direction message received
682  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
683  */
685  struct doca_comch_connection *comch_connection,
686  struct comch_msg_dma_direction *dir_msg)
687 {
688  struct comch_msg_dma_export_discriptor *exp_msg;
689  char export_msg[cfg->max_comch_buffer];
690  size_t exp_msg_len;
691  const void *export_desc;
692  size_t export_desc_len;
694 
695  if (!cfg->is_file_found_locally) {
696  cfg->file_size = ntohq(dir_msg->file_size);
697 
698  /* Allocate a buffer to receive the file data */
699  result = memory_alloc_and_populate(cfg->file_mmap,
700  cfg->file_size,
702  &cfg->file_buffer);
703  if (result != DOCA_SUCCESS) {
704  DOCA_LOG_ERR("Failed to allocate recv buffer: %s", doca_error_get_descr(result));
705  return DOCA_ERROR_NO_MEMORY;
706  }
707  }
708 
709  /* Export the host mmap to the DPU to start the DMA */
710  exp_msg = (struct comch_msg_dma_export_discriptor *)export_msg;
712  exp_msg->host_addr = htonq((uintptr_t)cfg->file_buffer);
713 
714  result = doca_mmap_export_pci(cfg->file_mmap, cfg->dev, &export_desc, &export_desc_len);
715  if (result != DOCA_SUCCESS) {
716  DOCA_LOG_ERR("Failed to export DOCA mmap: %s", doca_error_get_descr(result));
717  return result;
718  }
719 
720  exp_msg_len = export_desc_len + sizeof(struct comch_msg_dma_export_discriptor);
721  if (exp_msg_len > cfg->max_comch_buffer) {
722  DOCA_LOG_ERR("Export message exceeds max length of comch. Message len: %lu, Max len: %u",
723  exp_msg_len,
724  cfg->max_comch_buffer);
726  }
727 
729  memcpy(exp_msg->exported_mmap, export_desc, export_desc_len);
730 
731  /* It is assumed there are enough tasks for message to succeed - progress should not be called from callback */
732  return comch_utils_send(comch_connection, exp_msg, exp_msg_len);
733 }
734 
735 void host_recv_event_cb(struct doca_comch_event_msg_recv *event,
736  uint8_t *recv_buffer,
737  uint32_t msg_len,
738  struct doca_comch_connection *comch_connection)
739 {
740  struct dma_copy_cfg *cfg = comch_utils_get_user_data(comch_connection);
741  struct comch_msg_dma_status *status;
742  struct comch_msg *comch_msg;
744 
745  (void)event;
746 
747  if (cfg == NULL) {
748  DOCA_LOG_ERR("Cannot get configuration information");
749  return;
750  }
751 
752  /* Message must at least contain a message type */
753  if (msg_len < sizeof(enum comch_msg_type)) {
754  DOCA_LOG_ERR("Received a message that is too small. Length: %u", msg_len);
755  send_status_msg(comch_connection, STATUS_FAILURE);
756  cfg->comch_state = COMCH_ERROR;
757  return;
758  }
759 
760  /* All messages should take the format of a comch_msg struct */
761  comch_msg = (struct comch_msg *)recv_buffer;
762 
763  /*
764  * The host will have started the DMA negotiation by sending a dma_direction message.
765  * It should receive the same format message back from the DPU containing file size if file in on DPU.
766  * The host will allocate space to receive the file or use preallocated memory if the file is on the host.
767  * The file location data is exported to the DPU.
768  * When DMA has completed, a status message should be received.
769  */
770 
771  switch (comch_msg->type) {
772  case COMCH_MSG_DIRECTION:
773  if (msg_len != sizeof(struct comch_msg_dma_direction)) {
774  DOCA_LOG_ERR("Direction message has bad length. Length: %u, expected: %lu",
775  msg_len,
776  sizeof(struct comch_msg_dma_direction));
777  send_status_msg(comch_connection, STATUS_FAILURE);
778  cfg->comch_state = COMCH_ERROR;
779  return;
780  }
781 
783  comch_connection,
784  (struct comch_msg_dma_direction *)recv_buffer);
785  if (result != DOCA_SUCCESS) {
786  send_status_msg(comch_connection, STATUS_FAILURE);
787  cfg->comch_state = COMCH_ERROR;
788  return;
789  }
790 
791  break;
792  case COMCH_MSG_STATUS:
793  if (msg_len != sizeof(struct comch_msg_dma_status)) {
794  DOCA_LOG_ERR("Status message has bad length. Length: %u, expected: %lu",
795  msg_len,
796  sizeof(struct comch_msg_dma_status));
797  send_status_msg(comch_connection, STATUS_FAILURE);
798  cfg->comch_state = COMCH_ERROR;
799  return;
800  }
801 
802  status = (struct comch_msg_dma_status *)recv_buffer;
803  if (status->is_success == STATUS_FAILURE)
804  cfg->comch_state = COMCH_ERROR;
805  else
806  cfg->comch_state = COMCH_COMPLETE;
807 
808  break;
809  default:
810  DOCA_LOG_ERR("Received bad message type. Type: %u", comch_msg->type);
811  send_status_msg(comch_connection, STATUS_FAILURE);
812  cfg->comch_state = COMCH_ERROR;
813  return;
814  }
815 }
816 
817 /*
818  * Helper to send a DMA direction notification request
819  *
820  * @dma_cfg [in]: dma copy configuration information
821  * @comch_cfg [in]: comch object to send message across
822  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
823  */
825 {
826  struct comch_msg_dma_direction dir_msg = {.type = COMCH_MSG_DIRECTION};
827 
828  if (dma_cfg->is_file_found_locally) {
829  DOCA_LOG_INFO("File was found locally, it will be DMA copied to the DPU");
830  dir_msg.file_in_host = true;
831  dir_msg.file_size = htonq(dma_cfg->file_size);
832  } else {
833  DOCA_LOG_INFO("File was not found locally, it will be DMA copied from the DPU");
834  dir_msg.file_in_host = false;
835  }
836 
838 }
839 
841 {
842  doca_error_t result, tmp_result;
843  struct timespec ts = {
844  .tv_nsec = SLEEP_IN_NANOS,
845  };
846 
848  if (dma_cfg->max_comch_buffer == 0) {
849  DOCA_LOG_ERR("Comch max buffer length is 0");
851  }
852 
853  /* Open DOCA dma device */
854  result = open_dma_device(&dma_cfg->dev);
855  if (result != DOCA_SUCCESS) {
856  DOCA_LOG_ERR("Failed to open DOCA DMA device: %s", doca_error_get_descr(result));
857  return result;
858  }
859 
860  result = doca_mmap_create(&dma_cfg->file_mmap);
861  if (result != DOCA_SUCCESS) {
862  DOCA_LOG_ERR("Unable to create mmap: %s", doca_error_get_descr(result));
863  goto close_device;
864  }
865 
866  result = doca_mmap_add_dev(dma_cfg->file_mmap, dma_cfg->dev);
867  if (result != DOCA_SUCCESS) {
868  DOCA_LOG_ERR("Unable to add device to mmap: %s", doca_error_get_descr(result));
869  goto destroy_mmap;
870  }
871 
872  /*
873  * If the file is local, allocate a DMA buffer and populate it now.
874  * If file is remote, the buffer can be allocated in the callback when the size if known.
875  */
876  if (dma_cfg->is_file_found_locally == true) {
878  dma_cfg->file_size,
880  &dma_cfg->file_buffer);
881  if (result != DOCA_SUCCESS)
882  goto destroy_mmap;
883 
884  result = fill_buffer_with_file_content(dma_cfg, dma_cfg->file_buffer);
885  if (result != DOCA_SUCCESS)
886  goto free_buffer;
887  }
888 
889  dma_cfg->comch_state = COMCH_NEGOTIATING;
891  if (result != DOCA_SUCCESS) {
892  DOCA_LOG_ERR("Failed to send direction negotiation message: %s", doca_error_get_descr(result));
893  goto free_buffer;
894  }
895 
896  /* Wait for a signal that the DPU has completed the DMA copy */
897  while (dma_cfg->comch_state == COMCH_NEGOTIATING) {
898  nanosleep(&ts, &ts);
900  if (result != DOCA_SUCCESS) {
901  DOCA_LOG_ERR("Comch connection unexpectedly dropped: %s", doca_error_get_descr(result));
902  goto free_buffer;
903  }
904  }
905 
906  if (dma_cfg->comch_state == COMCH_ERROR) {
907  DOCA_LOG_ERR("Failure was detected in dma copy");
909  goto free_buffer;
910  }
911 
912  DOCA_LOG_INFO("Final status message was successfully received");
913 
914  if (!dma_cfg->is_file_found_locally) {
915  /* File was copied successfully into the buffer, save it into file */
916  DOCA_LOG_INFO("Writing DMA buffer into a file on %s", dma_cfg->file_path);
917  result = save_buffer_into_a_file(dma_cfg, dma_cfg->file_buffer);
918  }
919 
920 free_buffer:
921  free(dma_cfg->file_buffer);
922 destroy_mmap:
923  tmp_result = doca_mmap_destroy(dma_cfg->file_mmap);
924  if (tmp_result != DOCA_SUCCESS) {
925  DOCA_LOG_ERR("Failed to destroy DOCA mmap: %s", doca_error_get_descr(tmp_result));
926  DOCA_ERROR_PROPAGATE(result, tmp_result);
927  }
928 close_device:
929  tmp_result = doca_dev_close(dma_cfg->dev);
930  if (tmp_result != DOCA_SUCCESS) {
931  DOCA_LOG_ERR("Failed to close DOCA device: %s", doca_error_get_descr(tmp_result));
932  DOCA_ERROR_PROPAGATE(result, tmp_result);
933  }
934  return result;
935 }
936 
937 /*
938  * Process and respond to a DMA direction negotiation message on the DPU
939  *
940  * @cfg [in]: dma copy configuration information
941  * @comch_connection [in]: comch connection the message was received on
942  * @dir_msg [in]: the direction message received
943  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
944  */
946  struct doca_comch_connection *comch_connection,
947  struct comch_msg_dma_direction *dir_msg)
948 {
949  struct comch_msg_dma_direction resp_dir_msg = {.type = COMCH_MSG_DIRECTION};
951 
952  /* Make sure file is located only on one side */
953  if (cfg->is_file_found_locally && dir_msg->file_in_host == true) {
954  DOCA_LOG_ERR("Error - File was found on both Host and DPU");
956 
957  } else if (!cfg->is_file_found_locally) {
958  if (!dir_msg->file_in_host) {
959  DOCA_LOG_ERR("Error - File was not found on both Host and DPU");
961  }
962  cfg->file_size = ntohq(dir_msg->file_size);
963  }
964 
965  /* Verify file size against the HW limitation */
966  if (cfg->file_size > cfg->max_dma_buf_size) {
967  DOCA_LOG_ERR("DMA device maximum allowed file size in bytes is %" PRIu64
968  ", received file size is %" PRIu64 " bytes",
969  cfg->max_dma_buf_size,
970  cfg->file_size);
972  }
973 
974  /* Populate and send response to host */
975  if (cfg->is_file_found_locally) {
976  DOCA_LOG_INFO("File was found locally, it will be DMA copied to the Host");
977  resp_dir_msg.file_in_host = false;
978  resp_dir_msg.file_size = htonq(cfg->file_size);
979  } else {
980  DOCA_LOG_INFO("File was not found locally, it will be DMA copied from the Host");
981  resp_dir_msg.file_in_host = true;
982  }
983 
984  result = comch_utils_send(comch_connection, &resp_dir_msg, sizeof(struct comch_msg_dma_direction));
985  if (result != DOCA_SUCCESS) {
986  DOCA_LOG_ERR("Failed to send DMA direction message: %s", doca_error_get_descr(result));
987  return result;
988  }
989 
990  return result;
991 }
992 
993 /*
994  * Process an export descriptor message on the DPU
995  *
996  * @cfg [in]: dma copy configuration information
997  * @des_msg [in]: the export descriptor message received
998  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
999  */
1001  struct comch_msg_dma_export_discriptor *des_msg)
1002 {
1003  size_t desc_len = ntohq(des_msg->export_desc_len);
1004 
1005  cfg->exported_mmap = malloc(desc_len);
1006  if (cfg->exported_mmap == NULL) {
1007  DOCA_LOG_ERR("Failed to allocate export descriptor memory");
1008  return DOCA_ERROR_NO_MEMORY;
1009  }
1010 
1011  memcpy(cfg->exported_mmap, des_msg->exported_mmap, desc_len);
1012  cfg->exported_mmap_len = desc_len;
1013  cfg->host_addr = (uint8_t *)ntohq(des_msg->host_addr);
1014 
1015  return DOCA_SUCCESS;
1016 }
1017 
1018 void dpu_recv_event_cb(struct doca_comch_event_msg_recv *event,
1019  uint8_t *recv_buffer,
1020  uint32_t msg_len,
1021  struct doca_comch_connection *comch_connection)
1022 {
1023  struct dma_copy_cfg *cfg = comch_utils_get_user_data(comch_connection);
1024  struct comch_msg_dma_status *status;
1025  struct comch_msg *comch_msg;
1027 
1028  (void)event;
1029 
1030  if (cfg == NULL) {
1031  DOCA_LOG_ERR("Cannot get configuration information");
1032  return;
1033  }
1034 
1035  /* Message must at least contain a message type */
1036  if (msg_len < sizeof(enum comch_msg_type)) {
1037  DOCA_LOG_ERR("Received a message that is too small. Length: %u", msg_len);
1038  send_status_msg(comch_connection, STATUS_FAILURE);
1039  cfg->comch_state = COMCH_ERROR;
1040  return;
1041  }
1042 
1043  /* All messages should take the format of a comch_msg struct */
1044  comch_msg = (struct comch_msg *)recv_buffer;
1045 
1046  /*
1047  * The first message a DPU receives should be a direction negotiation request.
1048  * This should be responded to as an ack or containing the file information if file is local to the DPU.
1049  * The host will respond will memory information the DPU can read from or write to.
1050  * At this stage the DMA can be triggered.
1051  */
1052 
1053  switch (comch_msg->type) {
1054  case COMCH_MSG_DIRECTION:
1055  if (msg_len != sizeof(struct comch_msg_dma_direction)) {
1056  DOCA_LOG_ERR("Direction message has bad length. Length: %u, expected: %lu",
1057  msg_len,
1058  sizeof(struct comch_msg_dma_direction));
1059  send_status_msg(comch_connection, STATUS_FAILURE);
1060  cfg->comch_state = COMCH_ERROR;
1061  return;
1062  }
1063 
1065  comch_connection,
1066  (struct comch_msg_dma_direction *)recv_buffer);
1067  if (result != DOCA_SUCCESS) {
1068  send_status_msg(comch_connection, STATUS_FAILURE);
1069  cfg->comch_state = COMCH_ERROR;
1070  return;
1071  }
1072  break;
1074  if (msg_len <= sizeof(struct comch_msg_dma_export_discriptor)) {
1075  DOCA_LOG_ERR("Direction message has bad length. Length: %u, expected at least: %lu",
1076  msg_len,
1077  sizeof(struct comch_msg_dma_direction));
1078  send_status_msg(comch_connection, STATUS_FAILURE);
1079  cfg->comch_state = COMCH_ERROR;
1080  return;
1081  }
1082 
1084  if (result != DOCA_SUCCESS) {
1085  send_status_msg(comch_connection, STATUS_FAILURE);
1086  cfg->comch_state = COMCH_ERROR;
1087  return;
1088  }
1089 
1090  /* All information is successfully received to do DMA */
1091  cfg->comch_state = COMCH_COMPLETE;
1092  break;
1093  case COMCH_MSG_STATUS:
1094  if (msg_len != sizeof(struct comch_msg_dma_status)) {
1095  DOCA_LOG_ERR("Status message has bad length. Length: %u, expected: %lu",
1096  msg_len,
1097  sizeof(struct comch_msg_dma_status));
1098  send_status_msg(comch_connection, STATUS_FAILURE);
1099  cfg->comch_state = COMCH_ERROR;
1100  return;
1101  }
1102 
1103  status = (struct comch_msg_dma_status *)recv_buffer;
1104  if (status->is_success == STATUS_FAILURE)
1105  cfg->comch_state = COMCH_ERROR;
1106 
1107  break;
1108  default:
1109  DOCA_LOG_ERR("Received bad message type. Type: %u", comch_msg->type);
1110  send_status_msg(comch_connection, STATUS_FAILURE);
1111  cfg->comch_state = COMCH_ERROR;
1112  return;
1113  }
1114 }
1115 
1117 {
1118  struct dma_copy_resources resources = {0};
1119  struct program_core_objects *state = NULL;
1120  /* Allocate memory to be used for read operation in case file is found locally, otherwise grant write access */
1121  uint32_t access_flags = dma_cfg->is_file_found_locally ? DOCA_ACCESS_FLAG_LOCAL_READ_ONLY :
1123  struct doca_buf *remote_doca_buf = NULL;
1124  struct doca_buf *local_doca_buf = NULL;
1125  struct doca_mmap *remote_mmap = NULL;
1126  union doca_data ctx_user_data = {0};
1127  /* Number of tasks submitted to progress engine */
1128  size_t num_remaining_tasks = 1;
1129  doca_error_t result, tmp_result;
1130  struct timespec ts = {
1131  .tv_nsec = SLEEP_IN_NANOS,
1132  };
1133 
1134  /* Allocate DMA copy resources */
1136  if (result != DOCA_SUCCESS) {
1137  DOCA_LOG_ERR("Failed to allocate DMA copy resources: %s", doca_error_get_descr(result));
1138  return result;
1139  }
1140  state = resources.state;
1141 
1143  if (result != DOCA_SUCCESS)
1144  goto destroy_dma_resources;
1145 
1146  /* Include tasks counter in user data of context to be decremented in callbacks */
1147  ctx_user_data.ptr = &num_remaining_tasks;
1148  doca_ctx_set_user_data(state->ctx, ctx_user_data);
1149 
1150  result = doca_ctx_start(state->ctx);
1151  if (result != DOCA_SUCCESS) {
1152  DOCA_LOG_ERR("Unable to start DMA context: %s", doca_error_get_descr(result));
1153  goto destroy_dma_resources;
1154  }
1155 
1156  /* Wait until all DMA metadata is received on comch */
1157  while (dma_cfg->comch_state == COMCH_NEGOTIATING) {
1158  nanosleep(&ts, &ts);
1160  if (result != DOCA_SUCCESS) {
1161  DOCA_LOG_ERR("Comch connection unexpectedly dropped: %s", doca_error_get_descr(result));
1162  goto stop_dma;
1163  }
1164  }
1165 
1166  if (dma_cfg->comch_state == COMCH_ERROR) {
1167  DOCA_LOG_ERR("Comch DMA metadata negotiation failed");
1169  goto stop_dma;
1170  }
1171 
1172  /* Configure buffer to send/recv file on */
1173  result = memory_alloc_and_populate(state->src_mmap, dma_cfg->file_size, access_flags, &dma_cfg->file_buffer);
1174  if (result != DOCA_SUCCESS)
1175  goto stop_dma;
1176 
1177  /* Create a local DOCA mmap from export descriptor */
1179  (const void *)dma_cfg->exported_mmap,
1180  dma_cfg->exported_mmap_len,
1181  state->dev,
1182  &remote_mmap);
1183  if (result != DOCA_SUCCESS) {
1184  DOCA_LOG_ERR("Failed to create memory map from export: %s", doca_error_get_descr(result));
1185  goto free_buffer;
1186  }
1187 
1188  /* Construct DOCA buffer for remote (Host) address range */
1190  remote_mmap,
1191  dma_cfg->host_addr,
1192  dma_cfg->file_size,
1193  &remote_doca_buf);
1194  if (result != DOCA_SUCCESS) {
1195  DOCA_LOG_ERR("Unable to acquire DOCA remote buffer: %s", doca_error_get_descr(result));
1197  goto destroy_remote_mmap;
1198  }
1199 
1200  /* Construct DOCA buffer for local (DPU) address range */
1202  state->src_mmap,
1203  dma_cfg->file_buffer,
1204  dma_cfg->file_size,
1205  &local_doca_buf);
1206  if (result != DOCA_SUCCESS) {
1207  DOCA_LOG_ERR("Unable to acquire DOCA local buffer: %s", doca_error_get_descr(result));
1209  goto destroy_remote_buf;
1210  }
1211 
1212  /* Fill buffer in file content if relevant */
1213  if (dma_cfg->is_file_found_locally) {
1214  result = fill_buffer_with_file_content(dma_cfg, dma_cfg->file_buffer);
1215  if (result != DOCA_SUCCESS) {
1217  goto destroy_local_buf;
1218  }
1219  }
1220 
1221  /* Submit DMA task into the progress engine and wait until task completion */
1222  result = dpu_submit_dma_task(dma_cfg,
1223  &resources,
1224  dma_cfg->file_size,
1225  dma_cfg->file_buffer,
1226  local_doca_buf,
1227  remote_doca_buf,
1228  &num_remaining_tasks);
1229  if (result != DOCA_SUCCESS) {
1231  goto destroy_local_buf;
1232  }
1233 
1235 
1236 destroy_local_buf:
1237  tmp_result = doca_buf_dec_refcount(local_doca_buf, NULL);
1238  if (tmp_result != DOCA_SUCCESS) {
1239  DOCA_ERROR_PROPAGATE(result, tmp_result);
1240  DOCA_LOG_ERR("Failed to destroy local DOCA buffer: %s", doca_error_get_descr(tmp_result));
1241  }
1242 destroy_remote_buf:
1243  tmp_result = doca_buf_dec_refcount(remote_doca_buf, NULL);
1244  if (tmp_result != DOCA_SUCCESS) {
1245  DOCA_ERROR_PROPAGATE(result, tmp_result);
1246  DOCA_LOG_ERR("Failed to destroy remote DOCA buffer: %s", doca_error_get_descr(tmp_result));
1247  }
1248 destroy_remote_mmap:
1249  tmp_result = doca_mmap_destroy(remote_mmap);
1250  if (tmp_result != DOCA_SUCCESS) {
1251  DOCA_ERROR_PROPAGATE(result, tmp_result);
1252  DOCA_LOG_ERR("Failed to destroy remote DOCA mmap: %s", doca_error_get_descr(tmp_result));
1253  }
1254 free_buffer:
1255  free(dma_cfg->file_buffer);
1256 stop_dma:
1257  tmp_result = request_stop_ctx(state->pe, state->ctx);
1258  if (tmp_result != DOCA_SUCCESS) {
1259  DOCA_ERROR_PROPAGATE(result, tmp_result);
1260  DOCA_LOG_ERR("Unable to stop context: %s", doca_error_get_descr(tmp_result));
1261  }
1262  state->ctx = NULL;
1264  if (dma_cfg->exported_mmap != NULL)
1265  free(dma_cfg->exported_mmap);
1266  tmp_result = destroy_dma_copy_resources(&resources);
1267  if (tmp_result != DOCA_SUCCESS) {
1268  DOCA_ERROR_PROPAGATE(result, tmp_result);
1269  DOCA_LOG_ERR("Failed to destroy DMA copy resources: %s", doca_error_get_descr(tmp_result));
1270  }
1271  return result;
1272 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
void * comch_utils_get_user_data(struct doca_comch_connection *connection)
Definition: comch_utils.c:254
doca_error_t comch_utils_progress_connection(struct doca_comch_connection *connection)
Definition: comch_utils.c:264
struct doca_comch_connection * comch_util_get_connection(struct comch_cfg *comch_cfg)
Definition: comch_utils.c:276
doca_error_t comch_utils_send(struct doca_comch_connection *connection, const void *msg, uint32_t len)
Definition: comch_utils.c:212
uint32_t comch_utils_get_max_buffer_size(struct comch_cfg *comch_cfg)
Definition: comch_utils.c:286
doca_error_t request_stop_ctx(struct doca_pe *pe, struct doca_ctx *ctx)
Definition: common.c:367
doca_error_t destroy_core_objects(struct program_core_objects *state)
Definition: common.c:392
doca_error_t create_core_objects(struct program_core_objects *state, uint32_t max_bufs)
Definition: common.c:302
doca_error_t open_doca_device_with_capabilities(tasks_check func, struct doca_dev **retval)
Definition: common.c:188
doca_error_t destroy_dma_resources(struct dma_resources *resources)
Definition: dma_common.c:513
static doca_error_t file_path_callback(void *param, void *config)
#define STATUS_FAILURE
Definition: dma_copy_core.c:51
doca_error_t open_dma_device(struct doca_dev **dev)
static doca_error_t host_process_dma_direction_and_size(struct dma_copy_cfg *cfg, struct doca_comch_connection *comch_connection, struct comch_msg_dma_direction *dir_msg)
static doca_error_t send_file_direction_request(struct dma_copy_cfg *dma_cfg, struct comch_cfg *comch_cfg)
static doca_error_t dpu_process_export_descriptor(struct dma_copy_cfg *cfg, struct comch_msg_dma_export_discriptor *des_msg)
static void send_status_msg(struct doca_comch_connection *comch_connection, bool status)
static doca_error_t args_validation_callback(void *config)
static doca_error_t dpu_process_dma_direction_and_size(struct dma_copy_cfg *cfg, struct doca_comch_connection *comch_connection, struct comch_msg_dma_direction *dir_msg)
static doca_error_t memory_alloc_and_populate(struct doca_mmap *mmap, size_t buffer_len, uint32_t access_flags, char **buffer)
void host_recv_event_cb(struct doca_comch_event_msg_recv *event, uint8_t *recv_buffer, uint32_t msg_len, struct doca_comch_connection *comch_connection)
void dpu_recv_event_cb(struct doca_comch_event_msg_recv *event, uint8_t *recv_buffer, uint32_t msg_len, struct doca_comch_connection *comch_connection)
static doca_error_t dpu_submit_dma_task(struct dma_copy_cfg *cfg, struct dma_copy_resources *resources, size_t bytes_to_copy, char *buffer, struct doca_buf *local_doca_buf, struct doca_buf *remote_doca_buf, size_t *num_remaining_tasks)
static doca_error_t rep_pci_addr_callback(void *param, void *config)
static doca_error_t fill_buffer_with_file_content(struct dma_copy_cfg *cfg, char *buffer)
DOCA_LOG_REGISTER(DMA_COPY_CORE)
static void dma_memcpy_completed_callback(struct doca_dma_task_memcpy *dma_task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t get_dma_max_buf_size(struct dma_copy_resources *resources, uint64_t *max_buf_size)
Definition: dma_copy_core.c:62
static void dma_memcpy_error_callback(struct doca_dma_task_memcpy *dma_task, union doca_data task_user_data, union doca_data ctx_user_data)
static doca_error_t allocate_dma_copy_resources(struct dma_copy_resources *resources)
doca_error_t register_dma_copy_params(void)
static doca_error_t validate_file_size(const char *file_path, uint64_t *file_size)
Definition: dma_copy_core.c:84
static doca_error_t save_buffer_into_a_file(struct dma_copy_cfg *cfg, const char *buffer)
doca_error_t dpu_start_dma_copy(struct dma_copy_cfg *dma_cfg, struct comch_cfg *comch_cfg)
#define STATUS_SUCCESS
Definition: dma_copy_core.c:50
static doca_error_t check_dev_dma_capable(struct doca_devinfo *devinfo)
static doca_error_t dev_pci_addr_callback(void *param, void *config)
static doca_error_t destroy_dma_copy_resources(struct dma_copy_resources *resources)
#define SLEEP_IN_NANOS
Definition: dma_copy_core.c:49
doca_error_t host_start_dma_copy(struct dma_copy_cfg *dma_cfg, struct comch_cfg *comch_cfg)
@ COMCH_ERROR
Definition: dma_copy_core.h:84
@ COMCH_COMPLETE
Definition: dma_copy_core.h:83
@ COMCH_NEGOTIATING
Definition: dma_copy_core.h:82
#define MAX_ARG_SIZE
Definition: dma_copy_core.h:39
#define NUM_DMA_TASKS
Definition: dma_copy_core.h:41
comch_msg_type
Definition: dma_copy_core.h:48
@ COMCH_MSG_EXPORT_DESCRIPTOR
Definition: dma_copy_core.h:50
@ COMCH_MSG_DIRECTION
Definition: dma_copy_core.h:49
@ COMCH_MSG_STATUS
Definition: dma_copy_core.h:51
@ DMA_COPY_MODE_DPU
Definition: dma_copy_core.h:45
doca_dpa_dev_mmap_t mmap
struct rdma_resources resources
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_validation_callback(doca_argp_validation_cb_t callback)
Register program validation callback function.
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_version_callback(doca_argp_param_cb_t callback)
Register an alternative version callback.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
static doca_error_t doca_buf_inventory_buf_get_by_addr(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *addr, size_t len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by addr & len argume...
DOCA_STABLE doca_error_t doca_buf_dec_refcount(struct doca_buf *buf, uint16_t *refcount)
Decrease the object reference count by 1, if 0 reached, return the element back to the inventory.
DOCA_STABLE doca_error_t doca_buf_get_data(const struct doca_buf *buf, void **data)
Get the buffer's data.
DOCA_STABLE doca_error_t doca_buf_set_data(struct doca_buf *buf, void *data, size_t data_len)
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
#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
#define DOCA_DEVINFO_PCI_ADDR_SIZE
Buffer size to hold PCI BDF format: "XXXX:XX:XX.X". Including a null terminator.
Definition: doca_dev.h:313
DOCA_STABLE struct doca_devinfo * doca_dev_as_devinfo(const struct doca_dev *dev)
Get local device info from device. This should be useful when wanting to query information about devi...
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
DOCA_STABLE struct doca_task * doca_dma_task_memcpy_as_task(struct doca_dma_task_memcpy *task)
This method converts a memcpy task to doca_task.
DOCA_STABLE doca_error_t doca_dma_task_memcpy_alloc_init(struct doca_dma *dma, const struct doca_buf *src, struct doca_buf *dst, union doca_data user_data, struct doca_dma_task_memcpy **task)
This method allocates and initializes a DMA memcpy task.
DOCA_STABLE struct doca_ctx * doca_dma_as_ctx(struct doca_dma *dma)
DOCA_STABLE doca_error_t doca_dma_task_memcpy_set_conf(struct doca_dma *dma, doca_dma_task_memcpy_completion_cb_t task_completion_cb, doca_dma_task_memcpy_completion_cb_t task_error_cb, uint32_t num_memcpy_tasks)
This method sets the DMA memcpy tasks configuration.
DOCA_STABLE doca_error_t doca_dma_cap_task_memcpy_is_supported(const struct doca_devinfo *devinfo)
DOCA_STABLE doca_error_t doca_dma_cap_task_memcpy_get_max_buf_size(const struct doca_devinfo *devinfo, uint64_t *buf_size)
DOCA_STABLE doca_error_t doca_dma_create(struct doca_dev *dev, struct doca_dma **dma)
DOCA_STABLE doca_error_t doca_dma_destroy(struct doca_dma *dma)
#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_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_ERROR_IO_FAILED
Definition: doca_error.h:55
@ 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
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
Definition: doca_log.h:496
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_export_pci(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_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
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_task_get_status(const struct doca_task *task)
Get task status.
DOCA_STABLE doca_error_t doca_pe_connect_ctx(struct doca_pe *pe, struct doca_ctx *ctx)
This method connects a context to a progress engine.
DOCA_STABLE doca_error_t doca_task_submit(struct doca_task *task)
Submit a task to a progress engine.
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_STABLE void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_LOCAL_READ_ONLY
Definition: doca_types.h:82
@ DOCA_ACCESS_FLAG_PCI_READ_WRITE
Definition: doca_types.h:91
@ DOCA_ACCESS_FLAG_PCI_READ_ONLY
Definition: doca_types.h:87
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
uint64_t ntohq(uint64_t value)
Definition: pack.c:30
#define htonq
Definition: pack.h:48
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:298
enum comch_msg_type type
Definition: dma_copy_core.h:55
enum comch_msg_type type
Definition: dma_copy_core.h:68
enum comch_msg_type type
Definition: dma_copy_core.h:73
uint8_t * exported_mmap
uint8_t * host_addr
uint64_t file_size
Definition: dma_copy_core.h:93
struct doca_dev * dev
Definition: dma_copy_core.h:96
enum dma_comch_state comch_state
uint64_t max_dma_buf_size
Definition: dma_copy_core.h:97
char file_path[MAX_ARG_SIZE]
Definition: dma_copy_core.h:89
uint32_t max_comch_buffer
size_t exported_mmap_len
char * file_buffer
Definition: dma_copy_core.h:94
bool is_file_found_locally
Definition: dma_copy_core.h:92
struct doca_mmap * file_mmap
Definition: dma_copy_core.h:95
enum ip_frag_mode mode
Definition: ip_frag_dp.h:57
struct doca_pe * pe
Definition: common.h:51
struct doca_mmap * src_mmap
Definition: common.h:47
struct doca_buf_inventory * buf_inv
Definition: common.h:49
struct doca_dev * dev
Definition: common.h:46
struct doca_ctx * ctx
Definition: common.h:50
Convenience type for representing opaque data.
Definition: doca_types.h:56
void * ptr
Definition: doca_types.h:57
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: utils.c:123
noreturn doca_error_t sdk_version_callback(void *param, void *doca_config)
Definition: utils.c:41