NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
erasure_coding_recover_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <time.h>
34 #include <unistd.h>
35 
36 #include <doca_buf.h>
37 #include <doca_buf_inventory.h>
38 #include <doca_ctx.h>
39 #include <doca_erasure_coding.h>
40 #include <doca_error.h>
41 #include <doca_log.h>
42 #include <doca_mmap.h>
43 #include <doca_pe.h>
44 #include <utils.h>
45 
46 #include "common.h"
47 
48 DOCA_LOG_REGISTER(EC_RECOVER);
49 
50 #define SLEEP_IN_NANOS (10 * 1000) /* sample the task every 10 microseconds */
51 /* assert function - if fails print error, clean up(state - ec_sample_objects) and exit */
52 #define SAMPLE_ASSERT(condition, result, state, error...) \
53  do { \
54  if (!(condition)) { \
55  DOCA_LOG_ERR(error); \
56  ec_cleanup(state); \
57  return result; \
58  } \
59  } while (0)
60 /* callback assert function - if fails print error, update the callback_result parameter and exit */
61 #define CB_ASSERT(condition, result, cb_result, error...) \
62  do { \
63  if (!(condition)) { \
64  DOCA_LOG_ERR(error); \
65  *(cb_result) = (result); \
66  goto free_task; \
67  } \
68  } while (0)
69 /* assert function - same as before just for doca error */
70 #define ASSERT_DOCA_ERR(result, state, error) \
71  SAMPLE_ASSERT((result) == DOCA_SUCCESS, (result), state, (error ": %s"), doca_error_get_descr(result))
72 
73 #define NUM_EC_TASKS (8) /* EC tasks number */
74 #define USER_MAX_PATH_NAME 255 /* Max file name length */
75 #define MAX_PATH_NAME (USER_MAX_PATH_NAME + 1) /* Max file name string length */
76 #define MAX_DATA_SIZE (MAX_PATH_NAME + 100) /* Max data file length - path + max int string size */
77 #define RECOVERED_FILE_NAME "_recovered" /* Recovered file extension (if file name not given) */
78 #define DATA_INFO_FILE_NAME "data_info" /* Data information file name - i.e. size & name of original file */
79 #define DATA_BLOCK_FILE_NAME "data_block_" /* Data blocks file name (attached index at the end) */
80 #define RDNC_BLOCK_FILE_NAME "rdnc_block_" /* Redundancy blocks file name (attached index at the end) */
81 
83  struct doca_buf *src_doca_buf; /* Source doca buffer as input for the task */
84  struct doca_buf *dst_doca_buf; /* Destination doca buffer as input for the task */
85  struct doca_ec *ec; /* DOCA Erasure coding context */
86  char *src_buffer; /* Source memory region to be used as input for the task */
87  char *dst_buffer; /* Destination memory region to be used as output for task results */
88  char *file_data; /* Block data pointer from reading block file */
89  char *block_file_data; /* Block data pointer from reading block file */
90  uint32_t *missing_indices; /* Data indices to that are missing and need recover */
91  FILE *out_file; /* Recovered file pointer to write to */
92  FILE *block_file; /* Block file pointer to write to */
93  struct doca_ec_matrix *encoding_matrix; /* Encoding matrix that will be use to create the redundancy */
94  struct doca_ec_matrix *decoding_matrix; /* Decoding matrix that will be use to recover the data */
95  struct program_core_objects core_state; /* DOCA core objects - please refer to struct program_core_objects */
96  bool run_pe_progress; /* Controls whether progress loop should run */
97 };
98 
99 /*
100  * Clean all the sample resources
101  *
102  * @state [in]: ec_sample_objects struct
103  * @ec [in]: ec context
104  */
105 static void ec_cleanup(struct ec_sample_objects *state)
106 {
108 
109  if (state->src_doca_buf != NULL) {
111  if (result != DOCA_SUCCESS)
112  DOCA_LOG_ERR("Failed to decrease DOCA buffer reference count: %s",
114  }
115  if (state->dst_doca_buf != NULL) {
117  if (result != DOCA_SUCCESS)
118  DOCA_LOG_ERR("Failed to decrease DOCA buffer reference count: %s",
120  }
121 
122  if (state->missing_indices != NULL)
123  free(state->missing_indices);
124  if (state->block_file_data != NULL)
125  free(state->block_file_data);
126  if (state->file_data != NULL)
127  free(state->file_data);
128  if (state->src_buffer != NULL)
129  free(state->src_buffer);
130  if (state->dst_buffer != NULL)
131  free(state->dst_buffer);
132  if (state->out_file != NULL)
133  fclose(state->out_file);
134  if (state->block_file != NULL)
135  fclose(state->block_file);
136  if (state->encoding_matrix != NULL) {
138  if (result != DOCA_SUCCESS)
139  DOCA_LOG_ERR("Failed to destroy ec encoding matrix: %s", doca_error_get_descr(result));
140  }
141  if (state->decoding_matrix != NULL) {
143  if (result != DOCA_SUCCESS)
144  DOCA_LOG_ERR("Failed to destroy ec decoding matrix: %s", doca_error_get_descr(result));
145  }
146 
147  if (state->core_state.ctx != NULL) {
149  if (result != DOCA_SUCCESS)
150  DOCA_LOG_ERR("Unable to stop context: %s", doca_error_get_descr(result));
151  state->core_state.ctx = NULL;
152  }
153  if (state->ec != NULL) {
154  result = doca_ec_destroy(state->ec);
155  if (result != DOCA_SUCCESS)
156  DOCA_LOG_ERR("Failed to destroy ec: %s", doca_error_get_descr(result));
157  }
158 
160  if (result != DOCA_SUCCESS) {
161  DOCA_LOG_ERR("Failed to destroy DOCA core objects: %s", doca_error_get_descr(result));
162  }
163 }
164 
173 static void ec_state_changed_callback(const union doca_data user_data,
174  struct doca_ctx *ctx,
175  enum doca_ctx_states prev_state,
176  enum doca_ctx_states next_state)
177 {
178  (void)ctx;
179  (void)prev_state;
180 
181  struct ec_sample_objects *state = (struct ec_sample_objects *)user_data.ptr;
182 
183  switch (next_state) {
184  case DOCA_CTX_STATE_IDLE:
185  DOCA_LOG_INFO("Erasure Coding context has been stopped");
186  /* We can stop progressing the PE */
187  state->run_pe_progress = false;
188  break;
193  DOCA_LOG_ERR("Erasure Coding context entered into starting state. Unexpected transition");
194  break;
196  DOCA_LOG_INFO("Erasure Coding context is running");
197  break;
206  DOCA_LOG_INFO("Erasure Coding context entered into stopping state. Any inflight tasks will be flushed");
207  break;
208  default:
209  break;
210  }
211 }
212 
227  const char *pci_addr,
228  tasks_check is_support_func,
229  uint32_t src_size,
230  uint32_t dst_size,
231  int num_src_buf,
232  int num_dst_buf,
233  uint64_t *max_block_size)
234 {
236  union doca_data ctx_user_data;
237  uint32_t max_buf_list_len = 0;
238 
239  result = open_doca_device_with_pci(pci_addr, is_support_func, &state->core_state.dev);
240  ASSERT_DOCA_ERR(result, state, "Unable to open the pci device");
241 
242  result = create_core_objects(&state->core_state, (uint32_t)(num_src_buf + num_dst_buf));
243  ASSERT_DOCA_ERR(result, state, "Failed to init core");
244 
245  result = doca_ec_create(state->core_state.dev, &state->ec);
246  ASSERT_DOCA_ERR(result, state, "Unable to create ec engine");
247 
249  ASSERT_DOCA_ERR(result, state, "Unable to query maximum block size supported");
250 
252  ASSERT_DOCA_ERR(result, state, "Unable to query mmax_buf_list_len supported");
253  if ((uint32_t)(num_src_buf + num_dst_buf) > max_buf_list_len) {
255  DOCA_LOG_ERR("Number of doca_buf [%d] exceed the limitation [%u]: %s",
256  num_src_buf + num_dst_buf,
257  max_buf_list_len,
259  return result;
260  }
261 
262  state->core_state.ctx = doca_ec_as_ctx(state->ec);
263  SAMPLE_ASSERT(state->core_state.ctx != NULL, DOCA_ERROR_UNEXPECTED, state, "Unable to retrieve ctx");
264 
266  ASSERT_DOCA_ERR(result, state, "Unable to connect context to progress engine");
267 
268  result = doca_mmap_set_memrange(state->core_state.dst_mmap, state->dst_buffer, dst_size);
269  ASSERT_DOCA_ERR(result, state, "Failed to set mmap mem range dst");
270 
272  ASSERT_DOCA_ERR(result, state, "Failed to start mmap dst");
273 
274  result = doca_mmap_set_memrange(state->core_state.src_mmap, state->src_buffer, src_size);
275  ASSERT_DOCA_ERR(result, state, "Failed to set mmap mem range src");
276 
278  ASSERT_DOCA_ERR(result, state, "Failed to start mmap src");
279 
280  /* Construct DOCA buffer for each address range */
282  state->core_state.src_mmap,
283  state->src_buffer,
284  src_size,
285  num_src_buf,
286  true,
287  &state->src_doca_buf);
288  ASSERT_DOCA_ERR(result, state, "Unable to acquire DOCA buffer representing source buffer");
289 
290  /* Construct DOCA buffer for each address range */
292  state->core_state.dst_mmap,
293  state->dst_buffer,
294  dst_size,
295  num_dst_buf,
296  false,
297  &state->dst_doca_buf);
298  ASSERT_DOCA_ERR(result, state, "Unable to acquire DOCA buffer representing destination buffer");
299 
300  /* Include state in user data of context to be used in callbacks */
301  ctx_user_data.ptr = state;
302  result = doca_ctx_set_user_data(state->core_state.ctx, ctx_user_data);
303  ASSERT_DOCA_ERR(result, state, "Unable to set user data to context");
304 
305  /* Set state change callback to be called whenever the context state changes */
307  ASSERT_DOCA_ERR(result, state, "Unable to set state change callback");
308 
309  return DOCA_SUCCESS;
310 }
311 
312 /*
313  * EC tasks mutual error callback
314  *
315  * @task [in]: the failed doca task
316  * @task_status [out]: the status of the task
317  * @cb_result [out]: the result of the callback
318  */
319 static void ec_task_error(struct doca_task *task, doca_error_t *task_status, doca_error_t *cb_result)
320 {
321  *task_status = DOCA_ERROR_UNEXPECTED;
322 
323  DOCA_LOG_ERR("EC Task finished unsuccessfully");
324 
325  /* Free task */
326  doca_task_free(task);
327 
328  *cb_result = DOCA_SUCCESS;
329 
330  /* Stop context once task is completed */
331  (void)doca_ctx_stop(doca_task_get_ctx(task));
332 }
333 
334 /*
335  * All the necessary variables for EC create task callback functions defined in this sample
336  */
338  const char *output_dir_path; /* The path in which the output file should be saved */
339  uint32_t block_size; /* The block size used for EC */
340  size_t rdnc_block_count; /* The number of redundancy blocks created for the data */
341  struct doca_buf *rdnc_blocks; /* The redundancy blocks created for the data */
342  doca_error_t *task_status; /* The status of the task (output parameter) */
343  doca_error_t *cb_result; /* The result of the callback (output parameter) */
344 };
345 
346 /*
347  * EC create task error callback
348  *
349  * @create_task [in]: the failed create task
350  * @task_user_data [in]: doca_data from the task
351  * @ctx_user_data [in]: doca_data from the context
352  */
353 static void ec_create_error_callback(struct doca_ec_task_create *create_task,
354  union doca_data task_user_data,
355  union doca_data ctx_user_data)
356 {
357  struct create_task_data *task_data = task_user_data.ptr;
358  (void)ctx_user_data;
359 
360  ec_task_error(doca_ec_task_create_as_task(create_task), task_data->task_status, task_data->cb_result);
361 }
362 
363 /*
364  * EC create task completed callback
365  *
366  * @create_task [in]: the completed create task
367  * @task_user_data [in]: doca_data from the task
368  * @ctx_user_data [in]: doca_data from the context
369  */
370 static void ec_create_completed_callback(struct doca_ec_task_create *create_task,
371  union doca_data task_user_data,
372  union doca_data ctx_user_data)
373 {
374  int ret;
375  size_t i;
376  uint8_t *resp_data;
378  char full_path[MAX_PATH_NAME];
379  struct create_task_data *task_data = task_user_data.ptr;
380  struct ec_sample_objects *state = ctx_user_data.ptr;
381 
382  *task_data->task_status = DOCA_SUCCESS;
383 
384  /* Write the result to output file */
385  result = doca_buf_get_data(task_data->rdnc_blocks, (void **)&resp_data);
387  result,
388  task_data->cb_result,
389  "Unable to retrieve data pointer from redundancy data blocks buffer");
390 
391  for (i = 0; i < task_data->rdnc_block_count; i++) {
392  ret = snprintf(full_path,
393  sizeof(full_path),
394  "%s/%s%ld",
395  task_data->output_dir_path,
397  i);
398  CB_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
400  task_data->cb_result,
401  "Path exceeded max path len");
402  state->block_file = fopen(full_path, "wr");
403  CB_ASSERT(state->block_file != NULL,
405  task_data->cb_result,
406  "Unable to open output file: %s",
407  full_path);
408  ret = fwrite(resp_data + i * task_data->block_size, task_data->block_size, 1, state->block_file);
409  CB_ASSERT(ret >= 0, DOCA_ERROR_IO_FAILED, task_data->cb_result, "Failed to write to file");
410  fclose(state->block_file);
411  state->block_file = NULL;
412  }
413 
414  DOCA_LOG_INFO("File was encoded successfully and saved in: %s", task_data->output_dir_path);
415 
416  *task_data->cb_result = DOCA_SUCCESS;
417 
418 free_task:
419  /* Free task */
421 
422  /* Stop context once task is completed */
423  (void)doca_ctx_stop(state->core_state.ctx);
424 }
425 
426 /*
427  * Run ec encode
428  *
429  * @pci_addr [in]: PCI address of a doca device
430  * @file_path [in]: file data for the ec task
431  * @matrix_type [in]: matrix type
432  * @output_dir_path [in]: path to the task output file
433  * @data_block_count [in]: data block count
434  * @rdnc_block_count [in]: redundancy block count
435  * @num_src_buf [in]: Number of doca_buf for source buffer
436  * @num_dst_buf [in]: Number of doca_buf for destination buffer
437  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
438  */
439 doca_error_t ec_encode(const char *pci_addr,
440  const char *file_path,
441  enum doca_ec_matrix_type matrix_type,
442  const char *output_dir_path,
443  uint32_t data_block_count,
444  uint32_t rdnc_block_count,
445  int num_src_buf,
446  int num_dst_buf)
447 {
449  int ret;
450  size_t i;
451  size_t file_size;
452  uint64_t max_block_size;
453  uint64_t block_size;
454  uint64_t src_size;
455  uint64_t dst_size;
456  struct ec_sample_objects state_object = {0};
457  struct ec_sample_objects *state = &state_object;
458  char full_path[MAX_PATH_NAME];
459  struct timespec ts = {
460  .tv_sec = 0,
461  .tv_nsec = SLEEP_IN_NANOS,
462  };
463  doca_error_t task_status = DOCA_SUCCESS;
464  doca_error_t callback_result = DOCA_SUCCESS;
465  struct doca_task *doca_task;
466  struct doca_ec_task_create *task;
467  struct create_task_data task_data;
468  union doca_data user_data;
469 
470  result = read_file(file_path, &state->file_data, &file_size);
471  ASSERT_DOCA_ERR(result, state, "Can't read input file");
472 
473  block_size = file_size / data_block_count;
474  if (block_size * data_block_count != file_size)
475  block_size++;
476  if (block_size % 64 != 0)
477  block_size += 64 - (block_size % 64);
478  src_size = (uint64_t)block_size * data_block_count;
479  dst_size = (uint64_t)block_size * rdnc_block_count;
480 
481  state->src_buffer = calloc(src_size, 1);
482  SAMPLE_ASSERT(state->src_buffer != NULL, DOCA_ERROR_NO_MEMORY, state, "Unable to allocate src_buffer string");
483  memcpy(state->src_buffer, state->file_data, file_size);
484 
485  state->dst_buffer = malloc(dst_size);
486  SAMPLE_ASSERT(state->dst_buffer != NULL, DOCA_ERROR_NO_MEMORY, state, "Unable to allocate dst_buffer string");
487 
488  for (i = 0; i < data_block_count; i++) {
489  ret = snprintf(full_path, sizeof(full_path), "%s/%s%ld", output_dir_path, DATA_BLOCK_FILE_NAME, i);
490  SAMPLE_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
492  state,
493  "Path exceeded max path len");
494  state->block_file = fopen(full_path, "wr");
495  SAMPLE_ASSERT(state->block_file != NULL,
497  state,
498  "Unable to open output file: %s",
499  full_path);
500  ret = fwrite(state->src_buffer + i * block_size, block_size, 1, state->block_file);
501  SAMPLE_ASSERT(ret >= 0, DOCA_ERROR_IO_FAILED, state, "Failed to write to file");
502  fclose(state->block_file);
503  state->block_file = NULL;
504  }
505 
506  ret = snprintf(full_path, sizeof(full_path), "%s/%s", output_dir_path, DATA_INFO_FILE_NAME);
507  SAMPLE_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
509  state,
510  "Path exceeded max path len");
511  state->block_file = fopen(full_path, "wr");
512  SAMPLE_ASSERT(state->block_file != NULL,
514  state,
515  "Unable to open output file: %s",
516  full_path);
517  ret = fprintf(state->block_file, "%ld %.*s", file_size, (int)strlen(file_path), file_path);
518  SAMPLE_ASSERT(ret >= 0, DOCA_ERROR_IO_FAILED, state, "Failed to write to file");
519  fclose(state->block_file);
520  state->block_file = NULL;
521 
522  result = ec_core_init(state,
523  pci_addr,
525  src_size,
526  dst_size,
527  num_src_buf,
528  num_dst_buf,
529  &max_block_size);
530  if (result != DOCA_SUCCESS)
531  return result;
532 
533  /* Set task configuration */
537  NUM_EC_TASKS);
538  ASSERT_DOCA_ERR(result, state, "Unable to set configuration for create tasks");
539 
540  /* Start the task */
542  ASSERT_DOCA_ERR(result, state, "Unable to start context");
543 
544  /* Create a matrix for the task */
546  matrix_type,
547  data_block_count,
548  rdnc_block_count,
549  &state->encoding_matrix);
550  ASSERT_DOCA_ERR(result, state, "Unable to create ec matrix");
551 
553  block_size <= max_block_size,
555  state,
556  "Block size (%lu) exceeds the maximum size supported (%lu). Try to increase the number of blocks or use a smaller file as input",
557  block_size,
558  max_block_size);
559 
560  /* Include all necessary parameters for completion callback in user data of task */
561  task_data = (struct create_task_data){.output_dir_path = output_dir_path,
562  .block_size = block_size,
563  .rdnc_block_count = rdnc_block_count,
564  .rdnc_blocks = state->dst_doca_buf,
565  .task_status = &task_status,
566  .cb_result = &callback_result};
567  user_data.ptr = &task_data;
568 
569  /* Construct EC create task */
571  state->encoding_matrix,
572  state->src_doca_buf,
573  state->dst_doca_buf,
574  user_data,
575  &task);
576  ASSERT_DOCA_ERR(result, state, "Unable to allocate and initiate task");
577 
578  doca_task = doca_ec_task_create_as_task(task);
579  SAMPLE_ASSERT(doca_task != NULL, DOCA_ERROR_UNEXPECTED, state, "Unable to retrieve task as doca_task");
580 
581  /* Enqueue ec create task */
582  result = doca_task_submit(doca_task);
583  ASSERT_DOCA_ERR(result, state, "Unable to submit task");
584 
585  state->run_pe_progress = true;
586 
587  /* Wait for create task completion and for context to return to idle */
588  while (state->run_pe_progress) {
589  if (doca_pe_progress(state->core_state.pe) == 0)
590  nanosleep(&ts, &ts);
591  }
592 
593  /* Check result of task and callback */
594  ASSERT_DOCA_ERR(task_status, state, "EC create task failed");
595 
596  if (callback_result == DOCA_SUCCESS)
597  DOCA_LOG_INFO("Success, redundancy blocks were created");
598  else
599  DOCA_LOG_ERR("Sample failed: %s", doca_error_get_descr(callback_result));
600 
601  /* Clean and destroy all relevant objects */
602  ec_cleanup(state);
603 
604  return callback_result;
605 }
606 
607 /*
608  * All the necessary variables for EC recover task callback functions defined in this sample
609  */
611  const char *dir_path; /* The path to the tasks output file */
612  char *output_file_path; /* The path of the recovered file */
613  int64_t file_size; /* The size of the input file */
614  int32_t block_size; /* The block size used for EC */
615  uint32_t data_block_count; /* The number of data blocks created */
616  size_t n_missing; /* The number of missing data blocks that are to be recovered on success
617  */
618  struct doca_buf *recovered_data_blocks; /* The buffer to which the blocks of recovered data will be written on
619  * success
620  */
621  doca_error_t *task_status; /* The status of the task (output parameter) */
622  doca_error_t *cb_result; /* The result of the callback (output parameter) */
623 };
624 
625 /*
626  * EC recover task error callback
627  *
628  * @recover_task [in]: the failed recover task
629  * @task_user_data [in]: doca_data from the task
630  * @ctx_user_data [in]: doca_data from the context
631  */
632 static void ec_recover_error_callback(struct doca_ec_task_recover *recover_task,
633  union doca_data task_user_data,
634  union doca_data ctx_user_data)
635 {
636  struct recover_task_data *task_data = task_user_data.ptr;
637  (void)ctx_user_data;
638 
639  ec_task_error(doca_ec_task_recover_as_task(recover_task), task_data->task_status, task_data->cb_result);
640 }
641 
642 /*
643  * EC recover task completed callback
644  *
645  * @recover_task [in]: the completed recover task
646  * @task_user_data [in]: doca_data from the task
647  * @ctx_user_data [in]: doca_data from the context
648  */
649 static void ec_recover_completed_callback(struct doca_ec_task_recover *recover_task,
650  union doca_data task_user_data,
651  union doca_data ctx_user_data)
652 {
653  int ret;
654  size_t i;
656  uint8_t *resp_data;
657  char full_path[MAX_PATH_NAME];
658  size_t block_file_size = 0, remaining_file_size;
659  struct recover_task_data *task_data = task_user_data.ptr;
660  struct ec_sample_objects *state = ctx_user_data.ptr;
661 
662  *task_data->task_status = DOCA_SUCCESS;
663 
664  /* write the result to output file */
665  result = doca_buf_get_data(task_data->recovered_data_blocks, (void **)&resp_data);
667  result,
668  task_data->cb_result,
669  "Unable to retrieve data pointer from redundancy data blocks buffer");
670 
671  for (i = 0; i < task_data->n_missing; i++) {
672  ret = snprintf(full_path,
673  sizeof(full_path),
674  "%s/%s%d",
675  task_data->dir_path,
677  state->missing_indices[i]);
678  CB_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
680  task_data->cb_result,
681  "Path exceeded max path len");
682  state->block_file = fopen(full_path, "wr");
683  CB_ASSERT(state->block_file != NULL,
685  task_data->cb_result,
686  "Unable to open output file: %s",
687  full_path);
688  ret = fwrite(resp_data + i * task_data->block_size, task_data->block_size, 1, state->block_file);
689  CB_ASSERT(ret >= 0, DOCA_ERROR_IO_FAILED, task_data->cb_result, "Failed to write to file");
690  fclose(state->block_file);
691  state->block_file = NULL;
692  }
693 
694  remaining_file_size = task_data->file_size;
695  for (i = 0; i < task_data->data_block_count; i++) {
696  ret = snprintf(full_path, sizeof(full_path), "%s/%s%ld", task_data->dir_path, DATA_BLOCK_FILE_NAME, i);
697  CB_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
699  task_data->cb_result,
700  "Path exceeded max path len");
701  result = read_file(full_path, &state->block_file_data, &block_file_size);
702  CB_ASSERT(result == DOCA_SUCCESS, result, task_data->cb_result, "Unable to open data file");
703  if (remaining_file_size < block_file_size)
704  block_file_size = remaining_file_size;
705  ret = fwrite(state->block_file_data, block_file_size, 1, state->out_file);
706  CB_ASSERT(ret >= 0, DOCA_ERROR_IO_FAILED, task_data->cb_result, "Failed to write to file");
707  remaining_file_size -= block_file_size;
708  free(state->block_file_data);
709  state->block_file_data = NULL;
710 
711  if (remaining_file_size == 0)
712  break;
713  }
714 
715  DOCA_LOG_INFO("File was decoded successfully and saved in: %s", task_data->output_file_path);
716 
717  *task_data->cb_result = DOCA_SUCCESS;
718 
719 free_task:
720  /* Free task */
722 
723  /* Stop context once task is completed */
724  (void)doca_ctx_stop(state->core_state.ctx);
725 }
726 
727 /*
728  * Run ec decode
729  *
730  * @pci_addr [in]: PCI address of a doca device
731  * @matrix_type [in]: matrix type
732  * @user_output_file_path [in]: path to the task output file
733  * @dir_path [in]: path to the tasks output file
734  * @data_block_count [in]: data block count
735  * @rdnc_block_count [in]: redundancy block count
736  * @num_src_buf [in]: Number of doca_buf for source buffer
737  * @num_dst_buf [in]: Number of doca_buf for destination buffer
738  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
739  */
740 doca_error_t ec_decode(const char *pci_addr,
741  enum doca_ec_matrix_type matrix_type,
742  const char *user_output_file_path,
743  const char *dir_path,
744  uint32_t data_block_count,
745  uint32_t rdnc_block_count,
746  int num_src_buf,
747  int num_dst_buf)
748 {
750  int ret;
751  size_t i;
752  uint64_t max_block_size;
753  size_t block_file_size;
754  uint64_t block_size = 0;
755  uint32_t str_len;
756  uint64_t src_size = -1;
757  uint64_t src_size_cur = 0;
758  uint64_t dst_size;
759  struct ec_sample_objects state_object = {0};
760  struct ec_sample_objects *state = &state_object;
761  size_t n_missing = 0;
762  char *end;
763  int64_t file_size;
764  char output_file_path[MAX_PATH_NAME];
765  char full_path[MAX_PATH_NAME];
766  struct timespec ts = {
767  .tv_sec = 0,
768  .tv_nsec = SLEEP_IN_NANOS,
769  };
770  doca_error_t task_status = DOCA_SUCCESS;
771  doca_error_t callback_result = DOCA_SUCCESS;
772  struct doca_task *doca_task;
773  struct doca_ec_task_recover *task;
774  struct recover_task_data task_data;
775  union doca_data user_data;
776 
777  ret = snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, DATA_INFO_FILE_NAME);
778  SAMPLE_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
780  state,
781  "Path exceeded max path len");
782  result = read_file(full_path, &state->block_file_data, &block_file_size);
783  ASSERT_DOCA_ERR(result, state, "Unable to open data file");
784  SAMPLE_ASSERT(block_file_size > 0, DOCA_ERROR_INVALID_VALUE, state, "File data info size is empty");
785  SAMPLE_ASSERT(strnlen(state->block_file_data, block_file_size) < MAX_DATA_SIZE,
787  state,
788  "File data info may be nonfinite");
789  file_size = strtol(state->block_file_data, &end, 10);
790  SAMPLE_ASSERT(file_size > 0, DOCA_ERROR_INVALID_VALUE, state, "File size from data info file none positive");
791  SAMPLE_ASSERT(*end != '\0', DOCA_ERROR_INVALID_VALUE, state, "Data info file not containing path");
792 
793  if (user_output_file_path != NULL) {
794  SAMPLE_ASSERT(strnlen(user_output_file_path, MAX_PATH_NAME) < MAX_PATH_NAME,
796  state,
797  "Path exceeded max path len");
798  strcpy(output_file_path, user_output_file_path);
799  } else {
800  str_len = block_file_size - (end + 1 - state->block_file_data);
801  SAMPLE_ASSERT(strnlen(end + 1, str_len) < USER_MAX_PATH_NAME - sizeof(RECOVERED_FILE_NAME),
803  state,
804  "File data info contain file path bigger then max size");
805  ret = snprintf(output_file_path,
806  sizeof(output_file_path),
807  "%.*s%s",
808  str_len,
809  end + 1,
811  SAMPLE_ASSERT(ret >= 0 && ret < (int)sizeof(output_file_path),
813  state,
814  "Path exceeded max path len");
815  }
816 
817  free(state->block_file_data);
818  state->block_file_data = NULL;
819 
820  state->out_file = fopen(output_file_path, "wr");
821  SAMPLE_ASSERT(state->out_file != NULL,
823  state,
824  "Unable to open output file: %s",
825  output_file_path);
826 
827  state->missing_indices = calloc(data_block_count + rdnc_block_count, sizeof(uint32_t));
828  SAMPLE_ASSERT(state->missing_indices != NULL, DOCA_ERROR_NO_MEMORY, state, "Unable to allocate missing_indices");
829 
830  for (i = 0; i < data_block_count + rdnc_block_count; i++) {
831  char *file_name = i < data_block_count ? DATA_BLOCK_FILE_NAME : RDNC_BLOCK_FILE_NAME;
832  size_t index = i < data_block_count ? i : i - data_block_count;
833 
834  ret = snprintf(full_path, sizeof(full_path), "%s/%s%ld", dir_path, file_name, index);
835  SAMPLE_ASSERT(ret >= 0 && ret < (int)sizeof(full_path),
837  state,
838  "Path exceeded max path len");
839  result = read_file(full_path, &state->block_file_data, &block_file_size);
840  if (result == DOCA_SUCCESS && block_file_size > 0 && block_size == 0) {
841  block_size = block_file_size;
842  SAMPLE_ASSERT(block_size % 64 == 0,
844  state,
845  "Block size is not 64 byte aligned");
846  src_size = (uint64_t)block_size * data_block_count;
847  state->src_buffer = malloc(src_size);
848  SAMPLE_ASSERT(state->src_buffer != NULL,
850  state,
851  "Unable to allocate src_buffer string");
852  }
853  if (result == DOCA_SUCCESS) {
854  SAMPLE_ASSERT((uint64_t)block_file_size == block_size,
856  state,
857  "Blocks are not same size");
858  DOCA_LOG_INFO("Copy: %s", full_path);
859  memcpy(state->src_buffer + src_size_cur, state->block_file_data, block_size);
860  src_size_cur += block_size;
861  free(state->block_file_data);
862  state->block_file_data = NULL;
863  } else
864  state->missing_indices[n_missing++] = i;
865  if (src_size_cur == src_size)
866  break;
867  }
868 
869  SAMPLE_ASSERT(src_size_cur == src_size, DOCA_ERROR_INVALID_VALUE, state, "Not enough data for recover");
870  SAMPLE_ASSERT(n_missing > 0,
872  state,
873  "Nothing to decode, all original data block are in place");
874  dst_size = block_size * n_missing;
875 
876  state->dst_buffer = malloc(dst_size);
877  SAMPLE_ASSERT(state->dst_buffer != NULL, DOCA_ERROR_NO_MEMORY, state, "Unable to allocate dst_buffer string");
878 
879  result = ec_core_init(state,
880  pci_addr,
882  src_size,
883  dst_size,
884  num_src_buf,
885  num_dst_buf,
886  &max_block_size);
887  if (result != DOCA_SUCCESS)
888  return result;
889 
891  block_size <= max_block_size,
893  state,
894  "Block size (%lu) exceeds the maximum size supported (%lu). Try to increase the number of blocks or use a smaller file as input",
895  block_size,
896  max_block_size);
897 
898  /* Set task configuration */
902  NUM_EC_TASKS);
903  ASSERT_DOCA_ERR(result, state, "Unable to set configuration for recover tasks");
904 
905  /* Start the task */
907  ASSERT_DOCA_ERR(result, state, "Unable to start context");
908 
909  /* Create a matrix for the task */
911  matrix_type,
912  data_block_count,
913  rdnc_block_count,
914  &state->encoding_matrix);
915  ASSERT_DOCA_ERR(result, state, "Unable to create ec matrix");
916 
918  state->encoding_matrix,
919  state->missing_indices,
920  n_missing,
921  &state->decoding_matrix);
922  ASSERT_DOCA_ERR(result, state, "Unable to create recovery matrix");
923 
924  /* Include all necessary parameters for completion callback in user data of task */
925  task_data = (struct recover_task_data){.dir_path = dir_path,
926  .output_file_path = output_file_path,
927  .file_size = file_size,
928  .block_size = block_size,
929  .data_block_count = data_block_count,
930  .n_missing = n_missing,
931  .recovered_data_blocks = state->dst_doca_buf,
932  .task_status = &task_status,
933  .cb_result = &callback_result};
934  user_data.ptr = &task_data;
935 
936  /* Construct EC recover task */
938  state->decoding_matrix,
939  state->src_doca_buf,
940  state->dst_doca_buf,
941  user_data,
942  &task);
943  ASSERT_DOCA_ERR(result, state, "Unable to allocate and initiate task");
944 
945  doca_task = doca_ec_task_recover_as_task(task);
946  SAMPLE_ASSERT(doca_task != NULL, DOCA_ERROR_UNEXPECTED, state, "Unable to retrieve task as doca_task");
947 
948  /* Enqueue ec recover task */
949  result = doca_task_submit(doca_task);
950  ASSERT_DOCA_ERR(result, state, "Unable to submit task");
951 
952  state->run_pe_progress = true;
953 
954  /* Wait for recover task completion and for context to return to idle */
955  while (state->run_pe_progress) {
956  if (doca_pe_progress(state->core_state.pe) == 0)
957  nanosleep(&ts, &ts);
958  }
959 
960  /* Check result of task and the callback */
961  ASSERT_DOCA_ERR(task_status, state, "EC recover task failed");
962 
963  if (callback_result == DOCA_SUCCESS)
964  DOCA_LOG_INFO("Success, data was recovered");
965  else
966  DOCA_LOG_ERR("Sample failed: %s", doca_error_get_descr(callback_result));
967 
968  /* The task was already freed and the context was stopped in the callbacks */
969 
970  /* Clean and destroy all relevant objects */
971  ec_cleanup(state);
972 
973  return callback_result;
974 }
975 
976 /*
977  * Delete data (that EC will recover)
978  *
979  * @output_path [in]: path to the task output file
980  * @missing_indices [in]: data indices to delete
981  * @n_missing [in]: indices count
982  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
983  */
984 doca_error_t ec_delete_data(const char *output_path, uint32_t *missing_indices, size_t n_missing)
985 {
986  char full_path[MAX_PATH_NAME];
987  int ret;
988  uint32_t i;
989 
990  for (i = 0; i < n_missing; i++) {
991  ret = snprintf(full_path,
992  sizeof(full_path),
993  "%s/%s%d",
994  output_path,
996  missing_indices[i]);
997  if ((ret >= 0 && ret < (int)sizeof(full_path)) && remove(full_path) == 0)
998  DOCA_LOG_INFO("Deleted successfully: %s", full_path);
999  else
1000  return DOCA_ERROR_IO_FAILED;
1001  }
1002  return DOCA_SUCCESS;
1003 }
1004 
1005 /*
1006  * Run ec_recover sample
1007  *
1008  * @pci_addr [in]: PCI address of a doca device
1009  * @input_path [in]: input file to encode or input blocks dir to decode
1010  * @output_path [in]: output might be a file or a folder - depends on the input and do_both
1011  * @do_both [in]: to do full process - encoding & decoding
1012  * @matrix_type [in]: matrix type
1013  * @data_block_count [in]: data block count
1014  * @rdnc_block_count [in]: redundancy block count
1015  * @missing_indices [in]: data indices to delete
1016  * @n_missing [in]: indices count
1017  * @num_src_buf [in]: Number of doca_buf for source buffer
1018  * @num_dst_buf [in]: Number of doca_buf for destination buffer
1019  * @return: DOCA_SUCCESS on success, DOCA_ERROR otherwise.
1020  */
1021 doca_error_t ec_recover(const char *pci_addr,
1022  const char *input_path,
1023  const char *output_path,
1024  bool do_both,
1025  enum doca_ec_matrix_type matrix_type,
1026  uint32_t data_block_count,
1027  uint32_t rdnc_block_count,
1028  uint32_t *missing_indices,
1029  size_t n_missing,
1030  int num_src_buf,
1031  int num_dst_buf)
1032 {
1034  struct stat path_stat;
1035  bool input_path_is_file;
1036  const char *dir_path = output_path;
1037  const char *output_file_path = NULL;
1038 
1039  if (stat(input_path, &path_stat) != 0) {
1040  DOCA_LOG_INFO("Can't read input file stat: %s", input_path);
1041  return DOCA_ERROR_IO_FAILED;
1042  }
1043  input_path_is_file = S_ISREG(path_stat.st_mode);
1044  if (!do_both && !input_path_is_file) { /* only decode mode */
1045  dir_path = input_path;
1046  output_file_path = output_path;
1047  }
1048 
1049  if (do_both || input_path_is_file)
1050  result = ec_encode(pci_addr,
1051  input_path,
1052  matrix_type,
1053  output_path,
1054  data_block_count,
1055  rdnc_block_count,
1056  num_src_buf,
1057  num_dst_buf);
1058  if (result != DOCA_SUCCESS)
1059  return result;
1060  if (do_both)
1061  result = ec_delete_data(output_path, missing_indices, n_missing);
1062  if (result != DOCA_SUCCESS)
1063  return result;
1064  if (do_both || !input_path_is_file)
1065  result = ec_decode(pci_addr,
1066  matrix_type,
1067  output_file_path,
1068  dir_path,
1069  data_block_count,
1070  rdnc_block_count,
1071  num_src_buf,
1072  num_dst_buf);
1073  return result;
1074 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
doca_error_t allocat_doca_buf_list(struct doca_buf_inventory *buf_inv, struct doca_mmap *mmap, void *buf_addr, size_t buf_len, int num_buf, bool set_data_pos, struct doca_buf **dbuf)
Definition: common.c:527
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
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
#define DATA_INFO_FILE_NAME
#define CB_ASSERT(condition, result, cb_result, error...)
static doca_error_t ec_core_init(struct ec_sample_objects *state, const char *pci_addr, tasks_check is_support_func, uint32_t src_size, uint32_t dst_size, int num_src_buf, int num_dst_buf, uint64_t *max_block_size)
DOCA_LOG_REGISTER(EC_RECOVER)
static void ec_cleanup(struct ec_sample_objects *state)
#define DATA_BLOCK_FILE_NAME
doca_error_t ec_recover(const char *pci_addr, const char *input_path, const char *output_path, bool do_both, enum doca_ec_matrix_type matrix_type, uint32_t data_block_count, uint32_t rdnc_block_count, uint32_t *missing_indices, size_t n_missing, int num_src_buf, int num_dst_buf)
#define SAMPLE_ASSERT(condition, result, state, error...)
static void ec_create_completed_callback(struct doca_ec_task_create *create_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define MAX_DATA_SIZE
static void ec_task_error(struct doca_task *task, doca_error_t *task_status, doca_error_t *cb_result)
#define NUM_EC_TASKS
#define RDNC_BLOCK_FILE_NAME
static void ec_recover_error_callback(struct doca_ec_task_recover *recover_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define ASSERT_DOCA_ERR(result, state, error)
static void ec_create_error_callback(struct doca_ec_task_create *create_task, union doca_data task_user_data, union doca_data ctx_user_data)
#define USER_MAX_PATH_NAME
#define RECOVERED_FILE_NAME
#define MAX_PATH_NAME
static void ec_state_changed_callback(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
static void ec_recover_completed_callback(struct doca_ec_task_recover *recover_task, union doca_data task_user_data, union doca_data ctx_user_data)
doca_error_t ec_decode(const char *pci_addr, enum doca_ec_matrix_type matrix_type, const char *user_output_file_path, const char *dir_path, uint32_t data_block_count, uint32_t rdnc_block_count, int num_src_buf, int num_dst_buf)
doca_error_t ec_delete_data(const char *output_path, uint32_t *missing_indices, size_t n_missing)
#define SLEEP_IN_NANOS
doca_error_t ec_encode(const char *pci_addr, const char *file_path, enum doca_ec_matrix_type matrix_type, const char *output_dir_path, uint32_t data_block_count, uint32_t rdnc_block_count, int num_src_buf, int num_dst_buf)
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_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_STABLE doca_error_t doca_ctx_set_state_changed_cb(struct doca_ctx *ctx, doca_ctx_state_changed_callback_t cb)
Set state changed callback.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
doca_ctx_states
This enum defines the states of a context.
Definition: doca_ctx.h:83
@ DOCA_CTX_STATE_STARTING
Definition: doca_ctx.h:93
@ DOCA_CTX_STATE_STOPPING
Definition: doca_ctx.h:106
@ DOCA_CTX_STATE_IDLE
Definition: doca_ctx.h:88
@ DOCA_CTX_STATE_RUNNING
Definition: doca_ctx.h:98
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_EXPERIMENTAL doca_error_t doca_ec_cap_task_create_is_supported(const struct doca_devinfo *devinfo)
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_create_set_conf(struct doca_ec *ec, doca_ec_task_create_completion_cb_t successful_task_completion_cb, doca_ec_task_create_completion_cb_t error_task_completion_cb, uint32_t num_tasks)
This method sets the create tasks configuration.
DOCA_EXPERIMENTAL doca_error_t doca_ec_destroy(struct doca_ec *ec)
Destroy a DOCA EC instance.
doca_ec_matrix_type
Types of coding matrix used for erasure codes.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_create_allocate_init(struct doca_ec *ec, const struct doca_ec_matrix *coding_matrix, const struct doca_buf *original_data_blocks, struct doca_buf *rdnc_blocks, union doca_data user_data, struct doca_ec_task_create **task)
This method allocates and initializes a create task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_get_max_buf_list_len(const struct doca_devinfo *devinfo, uint32_t *max_buf_list_len)
Get the maximum supported number of elements in DOCA linked-list buffer used for EC tasks.
DOCA_EXPERIMENTAL doca_error_t doca_ec_create(struct doca_dev *dev, struct doca_ec **ec)
Create a DOCA EC instance.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_recover_allocate_init(struct doca_ec *ec, const struct doca_ec_matrix *recover_matrix, const struct doca_buf *available_blocks, struct doca_buf *recovered_data_blocks, union doca_data user_data, struct doca_ec_task_recover **task)
This method allocates and initializes a recover task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_destroy(struct doca_ec_matrix *matrix)
Destroy coding matrix.
DOCA_EXPERIMENTAL struct doca_task * doca_ec_task_recover_as_task(struct doca_ec_task_recover *task)
This method converts an EC recover task to a doca_task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_task_recover_set_conf(struct doca_ec *ec, doca_ec_task_recover_completion_cb_t successful_task_completion_cb, doca_ec_task_recover_completion_cb_t error_task_completion_cb, uint32_t num_tasks)
This method sets the recover tasks configuration.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_get_max_block_size(const struct doca_devinfo *devinfo, uint64_t *max_block_size)
Get maximum block size supported for DOCA EC tasks.
DOCA_EXPERIMENTAL struct doca_task * doca_ec_task_create_as_task(struct doca_ec_task_create *task)
This method converts an EC create task to a doca_task.
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_create_recover(struct doca_ec *ec, const struct doca_ec_matrix *coding_matrix, uint32_t missing_indices[], size_t n_missing, struct doca_ec_matrix **matrix)
Generate coding matrix for Erasure Code recovery from failure. To use this function must call doca_ec...
DOCA_EXPERIMENTAL doca_error_t doca_ec_matrix_create(struct doca_ec *ec, enum doca_ec_matrix_type type, size_t data_block_count, size_t rdnc_block_count, struct doca_ec_matrix **matrix)
Generate coding matrix for Erasure Code encode i.e. most basic encode matrix. This is necessary for e...
DOCA_EXPERIMENTAL struct doca_ctx * doca_ec_as_ctx(struct doca_ec *ec)
Convert EC instance into context.
DOCA_EXPERIMENTAL doca_error_t doca_ec_cap_task_recover_is_supported(const struct doca_devinfo *devinfo)
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_UNEXPECTED
Definition: doca_error.h:60
@ 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
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_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
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_STABLE struct doca_ctx * doca_task_get_ctx(const struct doca_task *task)
Get context from a doca task.
doca_error_t(* tasks_check)(struct doca_devinfo *)
Definition: common.h:42
struct program_core_objects core_state
struct doca_ec_matrix * decoding_matrix
struct doca_ec_matrix * encoding_matrix
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_mmap * dst_mmap
Definition: common.h:48
struct doca_ctx * ctx
Definition: common.h:50
struct doca_buf * recovered_data_blocks
Convenience type for representing opaque data.
Definition: doca_types.h:56
void * ptr
Definition: doca_types.h:57
struct upf_accel_ctx * ctx
doca_error_t read_file(char const *path, char **out_bytes, size_t *out_bytes_len)
Definition: utils.c:56