diff options
| author | Siho Shin <victory8500@naver.com> | 2026-06-27 08:59:14 +0900 |
|---|---|---|
| committer | Siho Shin <victory8500@naver.com> | 2026-06-27 08:59:14 +0900 |
| commit | 5d2722de9290472bb8fbd120d1ec506f7765e209 (patch) | |
| tree | 1254b5f3542f528871bcfdd0356f81095e66d480 /dma/host_recv.c | |
Diffstat (limited to 'dma/host_recv.c')
| -rw-r--r-- | dma/host_recv.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/dma/host_recv.c b/dma/host_recv.c new file mode 100644 index 0000000..9fdffab --- /dev/null +++ b/dma/host_recv.c @@ -0,0 +1,251 @@ +#define _GNU_SOURCE + +#include <doca_error.h> +#include <doca_dev.h> +#include <doca_mmap.h> + +#include <errno.h> +#include <getopt.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#define META_MAGIC 0x444f4341444d4131ULL /* "DOCADMA1" */ +#define DEFAULT_DESC_PATH "descriptor.bin" +#define DEFAULT_BUF_PATH "buffer.json" + +static void die_errno(const char *what) +{ + fprintf(stderr, "%s: %s\n", what, strerror(errno)); + exit(EXIT_FAILURE); +} + +static void die_doca(const char *what, doca_error_t err) +{ + fprintf(stderr, "%s: DOCA error code %d\n", what, (int)err); + exit(EXIT_FAILURE); +} + +static int write_file_all(const char *path, const void *data, size_t len) +{ + FILE *f = fopen(path, "wb"); + + if (f == NULL) + return -1; + + if (len > 0 && fwrite(data, 1, len, f) != len) { + fclose(f); + return -1; + } + + if (fclose(f) != 0) + return -1; + + return 0; +} + +static int write_remote_buffer_json(const char *path, uintptr_t addr, size_t len) +{ + FILE *f = fopen(path, "w"); + + if (f == NULL) + return -1; + + fprintf(f, + "{\n" + " \"magic\": \"0x%016" PRIx64 "\",\n" + " \"addr\": \"0x%016" PRIxPTR "\",\n" + " \"len\": %" PRIu64 "\n" + "}\n", + (uint64_t)META_MAGIC, + addr, + (uint64_t)len); + + if (fclose(f) != 0) + return -1; + + return 0; +} + +static doca_error_t open_doca_device_by_pci(const char *pci_addr, + struct doca_dev **dev) +{ + struct doca_devinfo **dev_list = NULL; + uint32_t nb_devs = 0; + doca_error_t result; + uint32_t i; + + result = doca_devinfo_create_list(&dev_list, &nb_devs); + if (result != DOCA_SUCCESS) + return result; + + for (i = 0; i < nb_devs; i++) { + uint8_t is_equal = 0; + + if (pci_addr == NULL) { + result = doca_dev_open(dev_list[i], dev); + doca_devinfo_destroy_list(dev_list); + return result; + } + + result = doca_devinfo_is_equal_pci_addr(dev_list[i], + pci_addr, + &is_equal); + if (result == DOCA_SUCCESS && is_equal) { + result = doca_dev_open(dev_list[i], dev); + doca_devinfo_destroy_list(dev_list); + return result; + } + } + + doca_devinfo_destroy_list(dev_list); + return DOCA_ERROR_NOT_FOUND; +} + +static doca_error_t create_started_host_mmap(struct doca_dev *dev, + void *addr, + size_t len, + struct doca_mmap **mmap) +{ + doca_error_t result; + + /* + * DOCA 2.x commonly uses: + * doca_mmap_create(const union doca_data *user_data, struct doca_mmap **mmap) + */ + result = doca_mmap_create(mmap); + if (result != DOCA_SUCCESS) + return result; + + result = doca_mmap_set_memrange(*mmap, addr, len); + if (result != DOCA_SUCCESS) + goto destroy; + + result = doca_mmap_set_permissions(*mmap, DOCA_ACCESS_FLAG_PCI_READ_WRITE); + if (result != DOCA_SUCCESS) + goto destroy; + + result = doca_mmap_add_dev(*mmap, dev); + if (result != DOCA_SUCCESS) + goto destroy; + + result = doca_mmap_start(*mmap); + if (result != DOCA_SUCCESS) + goto destroy; + + return DOCA_SUCCESS; + +destroy: + doca_mmap_destroy(*mmap); + *mmap = NULL; + return result; +} + +static void usage(const char *prog) +{ + fprintf(stderr, + "Usage: %s -p <host-pci-bdf> -s <bytes> -o <output-file> " + "[-d descriptor.bin] [-b buffer.json]\n\n" + "Example:\n" + " sudo %s -p 0000:3b:00.0 -s 268435456 -o received_256M.bin\n", + prog, prog); +} + +int main(int argc, char **argv) +{ + const char *pci = NULL; + const char *out_path = NULL; + const char *desc_path = DEFAULT_DESC_PATH; + const char *buf_path = DEFAULT_BUF_PATH; + size_t size = 0; + + struct doca_dev *dev = NULL; + struct doca_mmap *mmap = NULL; + + void *host_buf = NULL; + const void *export_desc = NULL; + size_t export_desc_len = 0; + + int opt; + doca_error_t result; + + while ((opt = getopt(argc, argv, "p:s:o:d:b:h")) != -1) { + switch (opt) { + case 'p': + pci = optarg; + break; + case 's': + size = strtoull(optarg, NULL, 0); + break; + case 'o': + out_path = optarg; + break; + case 'd': + desc_path = optarg; + break; + case 'b': + buf_path = optarg; + break; + case 'h': + default: + usage(argv[0]); + return EXIT_FAILURE; + } + } + + if (pci == NULL || out_path == NULL || size == 0) { + usage(argv[0]); + return EXIT_FAILURE; + } + + result = open_doca_device_by_pci(pci, &dev); + if (result != DOCA_SUCCESS) + die_doca("open_doca_device_by_pci", result); + + if (posix_memalign(&host_buf, 4096, size) != 0) + die_errno("posix_memalign"); + + memset(host_buf, 0, size); + + result = create_started_host_mmap(dev, host_buf, size, &mmap); + if (result != DOCA_SUCCESS) + die_doca("create_started_host_mmap", result); + + result = doca_mmap_export_pci(mmap, dev, &export_desc, &export_desc_len); + if (result != DOCA_SUCCESS) + die_doca("doca_mmap_export_pci", result); + + if (export_desc == NULL || export_desc_len == 0) { + fprintf(stderr, "doca_mmap_export_pci returned empty descriptor\n"); + exit(EXIT_FAILURE); + } + + if (write_file_all(desc_path, export_desc, export_desc_len) != 0) + die_errno("write descriptor"); + + if (write_remote_buffer_json(buf_path, (uintptr_t)host_buf, size) != 0) + die_errno("write buffer metadata"); + + printf("Host receive buffer exported.\n"); + printf(" descriptor: %s (%zu bytes)\n", desc_path, export_desc_len); + printf(" buffer: %s\n", buf_path); + printf(" addr: 0x%016" PRIxPTR "\n", (uintptr_t)host_buf); + printf(" len: %zu\n", size); + printf("\nCopy %s and %s to the DPU, run dpu sender, then press ENTER here.\n", + desc_path, buf_path); + + (void)getchar(); + + if (write_file_all(out_path, host_buf, size) != 0) + die_errno("write output file"); + + printf("Wrote host buffer to %s\n", out_path); + + doca_mmap_destroy(mmap); + doca_dev_close(dev); + free(host_buf); + + return EXIT_SUCCESS; +} |
