NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
gpunetio_simple_receive_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 <arpa/inet.h>
27 #include <doca_flow.h>
28 #include <doca_log.h>
29 
30 #include "gpunetio_common.h"
31 
32 #include "common.h"
33 
34 #define FLOW_NB_COUNTERS 524228 /* 1024 x 512 */
35 #define MBUF_NUM 8192
36 #define MBUF_SIZE 2048
37 
38 struct doca_flow_port *df_port;
40 
41 DOCA_LOG_REGISTER(SIMPLE_RECEIVE : SAMPLE);
42 
43 /*
44  * Signal handler to quit application gracefully
45  *
46  * @signum [in]: signal received
47  */
48 static void signal_handler(int signum)
49 {
50  if (signum == SIGINT || signum == SIGTERM) {
51  DOCA_LOG_INFO("Signal %d received, preparing to exit!", signum);
52  DOCA_GPUNETIO_VOLATILE(force_quit) = true;
53  }
54 }
55 
56 /*
57  * Initialize a DOCA network device.
58  *
59  * @nic_pcie_addr [in]: Network card PCIe address
60  * @ddev [out]: DOCA device
61  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
62  */
63 static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
64 {
66 
67  if (nic_pcie_addr == NULL || ddev == NULL)
69 
70  if (strnlen(nic_pcie_addr, DOCA_DEVINFO_PCI_ADDR_SIZE) >= DOCA_DEVINFO_PCI_ADDR_SIZE)
72 
73  result = open_doca_device_with_pci(nic_pcie_addr, NULL, ddev);
74  if (result != DOCA_SUCCESS) {
75  DOCA_LOG_ERR("Failed to open NIC device based on PCI address");
76  return result;
77  }
78 
79  return DOCA_SUCCESS;
80 }
81 
82 /*
83  * Init doca flow.
84  *
85  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
86  */
88 {
89  struct doca_flow_cfg *queue_flow_cfg;
91 
92  /* Initialize doca flow framework */
93  result = doca_flow_cfg_create(&queue_flow_cfg);
94  if (result != DOCA_SUCCESS) {
95  DOCA_LOG_ERR("Failed to create doca_flow_cfg: %s", doca_error_get_descr(result));
96  return result;
97  }
98 
99  result = doca_flow_cfg_set_pipe_queues(queue_flow_cfg, 1);
100  if (result != DOCA_SUCCESS) {
101  DOCA_LOG_ERR("Failed to set doca_flow_cfg pipe_queues: %s", doca_error_get_descr(result));
102  doca_flow_cfg_destroy(queue_flow_cfg);
103  return result;
104  }
105 
106  result = doca_flow_cfg_set_mode_args(queue_flow_cfg, "vnf,isolated");
107  if (result != DOCA_SUCCESS) {
108  DOCA_LOG_ERR("Failed to set doca_flow_cfg mode_args: %s", doca_error_get_descr(result));
109  doca_flow_cfg_destroy(queue_flow_cfg);
110  return result;
111  }
112 
114  if (result != DOCA_SUCCESS) {
115  DOCA_LOG_ERR("Failed to set doca_flow_cfg nr_counters: %s", doca_error_get_descr(result));
116  doca_flow_cfg_destroy(queue_flow_cfg);
117  return result;
118  }
119 
120  result = doca_flow_init(queue_flow_cfg);
121  if (result != DOCA_SUCCESS) {
122  DOCA_LOG_ERR("Failed to init doca flow with: %s", doca_error_get_descr(result));
123  doca_flow_cfg_destroy(queue_flow_cfg);
124  return result;
125  }
126  doca_flow_cfg_destroy(queue_flow_cfg);
127 
128  return DOCA_SUCCESS;
129 }
130 
131 /*
132  * Start doca flow.
133  *
134  * @dev [in]: DOCA device
135  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
136  */
137 static doca_error_t start_doca_flow(struct doca_dev *dev)
138 {
139  struct doca_flow_port_cfg *port_cfg;
141 
142  /* Start doca flow port */
143  result = doca_flow_port_cfg_create(&port_cfg);
144  if (result != DOCA_SUCCESS) {
145  DOCA_LOG_ERR("Failed to create doca_flow_port_cfg: %s", doca_error_get_descr(result));
146  return result;
147  }
148 
149  result = doca_flow_port_cfg_set_port_id(port_cfg, 0);
150  if (result != DOCA_SUCCESS) {
151  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg port ID: %s", doca_error_get_descr(result));
152  doca_flow_port_cfg_destroy(port_cfg);
153  return result;
154  }
155 
156  result = doca_flow_port_cfg_set_dev(port_cfg, dev);
157  if (result != DOCA_SUCCESS) {
158  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg dev: %s", doca_error_get_descr(result));
159  doca_flow_port_cfg_destroy(port_cfg);
160  return result;
161  }
162 
163  result = doca_flow_port_start(port_cfg, &df_port);
164  if (result != DOCA_SUCCESS) {
165  DOCA_LOG_ERR("Failed to start doca flow port with: %s", doca_error_get_descr(result));
166  doca_flow_port_cfg_destroy(port_cfg);
167  return result;
168  }
169 
170  return DOCA_SUCCESS;
171 }
172 
173 /*
174  * Create DOCA Flow UDP pipeline
175  *
176  * @rxq [in]: Receive queue handler
177  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
178  */
180 {
182  struct doca_flow_match match = {0};
183  struct doca_flow_fwd fwd = {0};
184  struct doca_flow_fwd miss_fwd = {0};
185  struct doca_flow_pipe_cfg *pipe_cfg;
186  struct doca_flow_pipe_entry *entry;
187  uint16_t flow_queue_id;
188  uint16_t rss_queues[1];
189  struct doca_flow_monitor monitor = {
191  };
192  const char *pipe_name = "GPU_RXQ_UDP_PIPE";
193 
194  if (rxq == NULL || df_port == NULL)
196 
199 
200  doca_eth_rxq_get_flow_queue_id(rxq->eth_rxq_cpu, &flow_queue_id);
201  rss_queues[0] = flow_queue_id;
202 
207  fwd.rss.nr_queues = 1;
208 
209  miss_fwd.type = DOCA_FLOW_FWD_DROP;
210 
212  if (result != DOCA_SUCCESS) {
213  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
214  return result;
215  }
216 
217  result = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_name);
218  if (result != DOCA_SUCCESS) {
219  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
220  goto destroy_pipe_cfg;
221  }
223  if (result != DOCA_SUCCESS) {
224  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
225  goto destroy_pipe_cfg;
226  }
227  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, false);
228  if (result != DOCA_SUCCESS) {
229  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
230  goto destroy_pipe_cfg;
231  }
232  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
233  if (result != DOCA_SUCCESS) {
234  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
235  goto destroy_pipe_cfg;
236  }
238  if (result != DOCA_SUCCESS) {
239  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
240  goto destroy_pipe_cfg;
241  }
242 
243  result = doca_flow_pipe_create(pipe_cfg, &fwd, &miss_fwd, &(rxq->rxq_pipe));
244  if (result != DOCA_SUCCESS) {
245  DOCA_LOG_ERR("RxQ pipe creation failed with: %s", doca_error_get_descr(result));
246  goto destroy_pipe_cfg;
247  }
248  doca_flow_pipe_cfg_destroy(pipe_cfg);
249 
250  /* Add HW offload */
252  if (result != DOCA_SUCCESS) {
253  DOCA_LOG_ERR("RxQ pipe entry creation failed with: %s", doca_error_get_descr(result));
254  return result;
255  }
256 
258  if (result != DOCA_SUCCESS) {
259  DOCA_LOG_ERR("RxQ pipe entry process failed with: %s", doca_error_get_descr(result));
260  return result;
261  }
262 
263  DOCA_LOG_DBG("Created Pipe %s", pipe_name);
264 
265  return DOCA_SUCCESS;
266 
268  doca_flow_pipe_cfg_destroy(pipe_cfg);
269  return result;
270 }
271 
272 /*
273  * Create DOCA Flow root pipeline
274  *
275  * @rxq [in]: Receive queue handler
276  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
277  */
279 {
281  struct doca_flow_monitor monitor = {
283  };
284 
285  struct doca_flow_match udp_match = {
287  .outer.l3_type = DOCA_FLOW_L3_TYPE_IP4,
288  .outer.ip4.next_proto = IPPROTO_UDP,
289  };
290 
291  struct doca_flow_fwd udp_fwd = {
293  };
294 
295  struct doca_flow_pipe_cfg *pipe_cfg;
296  const char *pipe_name = "ROOT_PIPE";
297 
298  if (rxq == NULL)
300 
301  udp_fwd.next_pipe = rxq->rxq_pipe;
302 
304  if (result != DOCA_SUCCESS) {
305  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
306  return result;
307  }
308 
309  result = doca_flow_pipe_cfg_set_name(pipe_cfg, pipe_name);
310  if (result != DOCA_SUCCESS) {
311  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg name: %s", doca_error_get_descr(result));
312  goto destroy_pipe_cfg;
313  }
315  if (result != DOCA_SUCCESS) {
316  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg type: %s", doca_error_get_descr(result));
317  goto destroy_pipe_cfg;
318  }
319  result = doca_flow_pipe_cfg_set_is_root(pipe_cfg, true);
320  if (result != DOCA_SUCCESS) {
321  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg is_root: %s", doca_error_get_descr(result));
322  goto destroy_pipe_cfg;
323  }
325  if (result != DOCA_SUCCESS) {
326  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
327  goto destroy_pipe_cfg;
328  }
329 
330  result = doca_flow_pipe_create(pipe_cfg, NULL, NULL, &rxq->root_pipe);
331  if (result != DOCA_SUCCESS) {
332  DOCA_LOG_ERR("Root pipe creation failed with: %s", doca_error_get_descr(result));
333  goto destroy_pipe_cfg;
334  }
335  doca_flow_pipe_cfg_destroy(pipe_cfg);
336 
338  0,
339  rxq->root_pipe,
340  &udp_match,
341  NULL,
342  NULL,
343  NULL,
344  NULL,
345  NULL,
346  NULL,
347  &udp_fwd,
348  NULL,
349  &rxq->root_udp_entry);
350  if (result != DOCA_SUCCESS) {
351  DOCA_LOG_ERR("Root pipe UDP entry creation failed with: %s", doca_error_get_descr(result));
352  return result;
353  }
354 
356  if (result != DOCA_SUCCESS) {
357  DOCA_LOG_ERR("Root pipe entry process failed with: %s", doca_error_get_descr(result));
358  return result;
359  }
360 
361  DOCA_LOG_DBG("Created Pipe %s", pipe_name);
362 
363  return DOCA_SUCCESS;
364 
366  doca_flow_pipe_cfg_destroy(pipe_cfg);
367  return result;
368 }
369 
370 /*
371  * Destroy DOCA Ethernet Tx queue for GPU
372  *
373  * @rxq [in]: DOCA Eth Rx queue handler
374  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
375  */
376 static doca_error_t destroy_rxq(struct rxq_queue *rxq)
377 {
379 
380  if (rxq == NULL) {
381  DOCA_LOG_ERR("Can't destroy UDP queues, invalid input");
383  }
384 
385  DOCA_LOG_INFO("Destroying Rxq");
386 
387  if (rxq->root_pipe != NULL) {
389  }
390  if (rxq->rxq_pipe != NULL) {
392  }
393 
394  if (df_port != NULL) {
396  if (result != DOCA_SUCCESS) {
397  DOCA_LOG_ERR("Failed to stop DOCA flow port, err: %s", doca_error_get_name(result));
398  return DOCA_ERROR_BAD_STATE;
399  }
400  }
401 
402  if (rxq->eth_rxq_ctx != NULL) {
404  if (result != DOCA_SUCCESS) {
405  DOCA_LOG_ERR("Failed doca_ctx_stop: %s", doca_error_get_descr(result));
406  return DOCA_ERROR_BAD_STATE;
407  }
408  }
409 
410  if (rxq->gpu_pkt_addr != NULL) {
411  result = doca_gpu_mem_free(rxq->gpu_dev, rxq->gpu_pkt_addr);
412  if (result != DOCA_SUCCESS) {
413  DOCA_LOG_ERR("Failed to free gpu memory: %s", doca_error_get_descr(result));
414  return DOCA_ERROR_BAD_STATE;
415  }
416  }
417 
418  if (rxq->eth_rxq_cpu != NULL) {
420  if (result != DOCA_SUCCESS) {
421  DOCA_LOG_ERR("Failed doca_eth_rxq_destroy: %s", doca_error_get_descr(result));
422  return DOCA_ERROR_BAD_STATE;
423  }
424  }
425 
426  if (rxq->pkt_buff_mmap != NULL) {
428  if (result != DOCA_SUCCESS) {
429  DOCA_LOG_ERR("Failed to destroy mmap: %s", doca_error_get_descr(result));
430  return DOCA_ERROR_BAD_STATE;
431  }
432  }
433 
434  result = doca_dev_close(rxq->ddev);
435  if (result != DOCA_SUCCESS) {
436  DOCA_LOG_ERR("Failed to destroy Eth dev: %s", doca_error_get_descr(result));
437  return DOCA_ERROR_BAD_STATE;
438  }
439 
440  if (df_port != NULL)
442 
443  return DOCA_SUCCESS;
444 }
445 
446 /*
447  * Create DOCA Ethernet Tx queue for GPU
448  *
449  * @rxq [in]: DOCA Eth Tx queue handler
450  * @gpu_dev [in]: DOCA GPUNetIO device
451  * @ddev [in]: DOCA device
452  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
453  */
454 static doca_error_t create_rxq(struct rxq_queue *rxq, struct doca_gpu *gpu_dev, struct doca_dev *ddev)
455 {
457  uint32_t cyclic_buffer_size = 0;
458 
459  if (rxq == NULL || gpu_dev == NULL || ddev == NULL) {
460  DOCA_LOG_ERR("Can't create UDP queues, invalid input");
462  }
463 
464  rxq->gpu_dev = gpu_dev;
465  rxq->ddev = ddev;
466  rxq->port = df_port;
467 
468  DOCA_LOG_INFO("Creating Sample Eth Rxq");
469 
471  if (result != DOCA_SUCCESS) {
472  DOCA_LOG_ERR("Failed doca_eth_rxq_create: %s", doca_error_get_descr(result));
473  return DOCA_ERROR_BAD_STATE;
474  }
475 
477  if (result != DOCA_SUCCESS) {
478  DOCA_LOG_ERR("Failed doca_eth_rxq_set_type: %s", doca_error_get_descr(result));
479  return DOCA_ERROR_BAD_STATE;
480  }
481 
483  0,
484  0,
485  MAX_PKT_SIZE,
486  MAX_PKT_NUM,
487  0,
488  0,
489  0,
490  &cyclic_buffer_size);
491  if (result != DOCA_SUCCESS) {
492  DOCA_LOG_ERR("Failed to get eth_rxq cyclic buffer size: %s", doca_error_get_descr(result));
493  goto exit_error;
494  }
495 
497  if (result != DOCA_SUCCESS) {
498  DOCA_LOG_ERR("Failed to create mmap: %s", doca_error_get_descr(result));
499  goto exit_error;
500  }
501 
503  if (result != DOCA_SUCCESS) {
504  DOCA_LOG_ERR("Failed to add dev to mmap: %s", doca_error_get_descr(result));
505  goto exit_error;
506  }
507 
508  result = doca_gpu_mem_alloc(rxq->gpu_dev,
509  cyclic_buffer_size,
512  &rxq->gpu_pkt_addr,
513  NULL);
514  if (result != DOCA_SUCCESS || rxq->gpu_pkt_addr == NULL) {
515  DOCA_LOG_ERR("Failed to allocate gpu memory %s", doca_error_get_descr(result));
516  goto exit_error;
517  }
518 
519  /* Map GPU memory buffer used to receive packets with DMABuf */
520  result = doca_gpu_dmabuf_fd(rxq->gpu_dev, rxq->gpu_pkt_addr, cyclic_buffer_size, &(rxq->dmabuf_fd));
521  if (result != DOCA_SUCCESS) {
522  DOCA_LOG_INFO("Mapping receive queue buffer (0x%p size %dB) with nvidia-peermem mode",
523  rxq->gpu_pkt_addr,
524  cyclic_buffer_size);
525 
526  /* If failed, use nvidia-peermem legacy method */
527  result = doca_mmap_set_memrange(rxq->pkt_buff_mmap, rxq->gpu_pkt_addr, cyclic_buffer_size);
528  if (result != DOCA_SUCCESS) {
529  DOCA_LOG_ERR("Failed to set memrange for mmap %s", doca_error_get_descr(result));
530  goto exit_error;
531  }
532  } else {
533  DOCA_LOG_INFO("Mapping receive queue buffer (0x%p size %dB dmabuf fd %d) with dmabuf mode",
534  rxq->gpu_pkt_addr,
535  cyclic_buffer_size,
536  rxq->dmabuf_fd);
537 
539  rxq->dmabuf_fd,
540  rxq->gpu_pkt_addr,
541  0,
542  cyclic_buffer_size);
543  if (result != DOCA_SUCCESS) {
544  DOCA_LOG_ERR("Failed to set dmabuf memrange for mmap %s", doca_error_get_descr(result));
545  goto exit_error;
546  }
547  }
548 
550  if (result != DOCA_SUCCESS) {
551  DOCA_LOG_ERR("Failed to set permissions for mmap %s", doca_error_get_descr(result));
552  goto exit_error;
553  }
554 
556  if (result != DOCA_SUCCESS) {
557  DOCA_LOG_ERR("Failed to start mmap %s", doca_error_get_descr(result));
558  goto exit_error;
559  }
560 
561  result = doca_eth_rxq_set_pkt_buf(rxq->eth_rxq_cpu, rxq->pkt_buff_mmap, 0, cyclic_buffer_size);
562  if (result != DOCA_SUCCESS) {
563  DOCA_LOG_ERR("Failed to set cyclic buffer %s", doca_error_get_descr(result));
564  goto exit_error;
565  }
566 
568  if (rxq->eth_rxq_ctx == NULL) {
569  DOCA_LOG_ERR("Failed doca_eth_rxq_as_doca_ctx: %s", doca_error_get_descr(result));
570  goto exit_error;
571  }
572 
574  if (result != DOCA_SUCCESS) {
575  DOCA_LOG_ERR("Failed doca_ctx_set_datapath_on_gpu: %s", doca_error_get_descr(result));
576  goto exit_error;
577  }
578 
580  if (result != DOCA_SUCCESS) {
581  DOCA_LOG_ERR("Failed doca_ctx_start: %s", doca_error_get_descr(result));
582  goto exit_error;
583  }
584 
586  if (result != DOCA_SUCCESS) {
587  DOCA_LOG_ERR("Failed doca_eth_rxq_get_gpu_handle: %s", doca_error_get_descr(result));
588  goto exit_error;
589  }
590 
591  /* Create UDP based flow pipe */
592  result = create_udp_pipe(rxq);
593  if (result != DOCA_SUCCESS) {
594  DOCA_LOG_ERR("Function create_udp_pipe returned %s", doca_error_get_descr(result));
595  goto exit_error;
596  }
597 
598  /* Create root pipe with UDP pipe as unique entry */
599  result = create_root_pipe(rxq);
600  if (result != DOCA_SUCCESS) {
601  DOCA_LOG_ERR("Function create_root_pipe returned %s", doca_error_get_descr(result));
602  goto exit_error;
603  }
604 
605  return DOCA_SUCCESS;
606 
607 exit_error:
608  destroy_rxq(rxq);
609  return DOCA_ERROR_BAD_STATE;
610 }
611 
612 /*
613  * Launch GPUNetIO simple receive sample
614  *
615  * @sample_cfg [in]: Sample config parameters
616  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
617  */
619 {
621  struct doca_gpu *gpu_dev = NULL;
622  struct doca_dev *ddev = NULL;
623  struct rxq_queue rxq = {0};
624  cudaStream_t stream;
625  cudaError_t res_rt = cudaSuccess;
626  uint32_t *cpu_exit_condition;
627  uint32_t *gpu_exit_condition;
628 
629  result = init_doca_device(sample_cfg->nic_pcie_addr, &ddev);
630  if (result != DOCA_SUCCESS) {
631  DOCA_LOG_ERR("Function init_doca_device returned %s", doca_error_get_descr(result));
632  return EXIT_FAILURE;
633  }
634 
636  if (result != DOCA_SUCCESS) {
637  DOCA_LOG_ERR("Function init_doca_flow returned %s", doca_error_get_descr(result));
638  goto exit;
639  }
640 
642  if (result != DOCA_SUCCESS) {
643  DOCA_LOG_ERR("Function start_doca_flow returned %s", doca_error_get_descr(result));
644  goto exit;
645  }
646 
647  /* Gracefully terminate sample if ctrlc */
648  DOCA_GPUNETIO_VOLATILE(force_quit) = false;
649  signal(SIGINT, signal_handler);
650  signal(SIGTERM, signal_handler);
651 
652  result = doca_gpu_create(sample_cfg->gpu_pcie_addr, &gpu_dev);
653  if (result != DOCA_SUCCESS) {
654  DOCA_LOG_ERR("Function doca_gpu_create returned %s", doca_error_get_descr(result));
655  goto exit;
656  }
657 
658  result = create_rxq(&rxq, gpu_dev, ddev);
659  if (result != DOCA_SUCCESS) {
660  DOCA_LOG_ERR("Function create_rxq returned %s", doca_error_get_descr(result));
661  goto exit;
662  }
663 
664  res_rt = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
665  if (res_rt != cudaSuccess) {
666  DOCA_LOG_ERR("Function cudaStreamCreateWithFlags error %d", res_rt);
667  return DOCA_ERROR_DRIVER;
668  }
669 
670  result = doca_gpu_mem_alloc(gpu_dev,
671  sizeof(uint32_t),
674  (void **)&gpu_exit_condition,
675  (void **)&cpu_exit_condition);
676  if (result != DOCA_SUCCESS || gpu_exit_condition == NULL || cpu_exit_condition == NULL) {
677  DOCA_LOG_ERR("Function doca_gpu_mem_alloc returned %s", doca_error_get_descr(result));
678  return EXIT_FAILURE;
679  }
680  cpu_exit_condition[0] = 0;
681 
682  DOCA_LOG_INFO("Launching CUDA kernel to receive packets");
683 
684  kernel_receive_packets(stream, &rxq, gpu_exit_condition);
685 
686  DOCA_LOG_INFO("Waiting for termination");
687  /* This loop keeps busy main thread until force_quit is set to 1 (e.g. typing ctrl+c) */
688  while (DOCA_GPUNETIO_VOLATILE(force_quit) == false)
689  ;
690  DOCA_GPUNETIO_VOLATILE(*cpu_exit_condition) = 1;
691 
692  DOCA_LOG_INFO("Exiting from sample");
693 
694  cudaStreamSynchronize(stream);
695 exit:
696 
697  result = destroy_rxq(&rxq);
698  if (result != DOCA_SUCCESS) {
699  DOCA_LOG_ERR("Function destroy_rxq returned %s", doca_error_get_descr(result));
700  return DOCA_ERROR_BAD_STATE;
701  }
702 
703  DOCA_LOG_INFO("Sample finished successfully");
704 
705  return DOCA_SUCCESS;
706 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define GPU_PAGE_SIZE
Definition: defines.h:58
#define MAX_PKT_SIZE
Definition: defines.h:65
#define MAX_PKT_NUM
Definition: defines.h:64
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static uint16_t * rss_queues
Definition: flow_parser.c:114
static struct doca_flow_monitor monitor
Definition: flow_parser.c:108
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
static struct doca_gpu * gpu_dev
static struct doca_dev * ddev
doca_error_t kernel_receive_packets(cudaStream_t stream, struct rxq_queue *rxq, uint32_t *gpu_exit_condition)
static doca_error_t create_udp_pipe(struct rxq_queue *rxq)
static doca_error_t init_doca_flow(void)
static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
#define FLOW_NB_COUNTERS
static doca_error_t create_root_pipe(struct rxq_queue *rxq)
struct doca_flow_port * df_port
DOCA_LOG_REGISTER(SIMPLE_RECEIVE :SAMPLE)
static doca_error_t create_rxq(struct rxq_queue *rxq, struct doca_gpu *gpu_dev, struct doca_dev *ddev)
static doca_error_t start_doca_flow(struct doca_dev *dev)
static doca_error_t destroy_rxq(struct rxq_queue *rxq)
doca_error_t gpunetio_simple_receive(struct sample_send_wait_cfg *sample_cfg)
static void signal_handler(int signum)
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_EXPERIMENTAL doca_error_t doca_ctx_set_datapath_on_gpu(struct doca_ctx *ctx, struct doca_gpu *gpu_dev)
This function binds the DOCA context to a gpu device.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
#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 doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_name(doca_error_t error)
Returns the string representation of an error code name.
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_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_get_flow_queue_id(struct doca_eth_rxq *eth_rxq, uint16_t *flow_queue_id)
Get the DPDK queue ID of the doca_eth receive queue. can only be called after calling doca_ctx_start(...
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_set_type(struct doca_eth_rxq *eth_rxq, enum doca_eth_rxq_type type)
Set RX queue type property for doca_eth_rxq. can only be called before calling doca_ctx_start().
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_destroy(struct doca_eth_rxq *eth_rxq)
Destroy a DOCA ETH RXQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_get_gpu_handle(const struct doca_eth_rxq *eth_rxq, struct doca_gpu_eth_rxq **eth_rxq_ext)
Get a gpu handle of a doca_eth_rxq.
DOCA_EXPERIMENTAL struct doca_ctx * doca_eth_rxq_as_doca_ctx(struct doca_eth_rxq *eth_rxq)
Convert doca_eth_rxq instance into a generalized context for use with doca core objects.
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_create(struct doca_dev *dev, uint32_t max_burst_size, uint32_t max_packet_size, struct doca_eth_rxq **eth_rxq)
Create a DOCA ETH RXQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_set_pkt_buf(struct doca_eth_rxq *eth_rxq, struct doca_mmap *mmap, uint32_t mmap_offset, uint32_t mmap_len)
Set Eth packet buffer for a doca_eth_rxq. can only be called before calling doca_ctx_start().
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_estimate_packet_buf_size(enum doca_eth_rxq_type type, uint32_t rate, uint16_t pkt_max_time, uint32_t max_packet_size, uint32_t max_burst_size, uint8_t log_max_lro_pkt_sz, uint16_t head_size, uint16_t tail_size, uint32_t *buf_size)
Get the recommended size for the mmap buffer of a doca_eth_rxq.
@ DOCA_ETH_RXQ_TYPE_CYCLIC
Definition: doca_eth_rxq.h:65
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
@ DOCA_FLOW_L3_TYPE_IP4
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_mode_args(struct doca_flow_cfg *cfg, const char *mode_args)
Set DOCA mode args.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_name(struct doca_flow_pipe_cfg *cfg, const char *name)
Set pipe's name.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_control_add_entry(uint16_t pipe_queue, uint32_t priority, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_match *match_mask, const struct doca_flow_match_condition *condition, const struct doca_flow_actions *actions, const struct doca_flow_actions *actions_mask, const struct doca_flow_action_descs *action_descs, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a control pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_start(const struct doca_flow_port_cfg *cfg, struct doca_flow_port **port)
Start a doca port.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_is_root(struct doca_flow_pipe_cfg *cfg, bool is_root)
Set if pipe is root or not.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_STABLE doca_error_t doca_flow_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_type(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_type type)
Set pipe's type.
DOCA_EXPERIMENTAL doca_error_t doca_flow_init(struct doca_flow_cfg *cfg)
Initialize the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_dev(struct doca_flow_port_cfg *cfg, struct doca_dev *dev)
Set port's device.
DOCA_STABLE doca_error_t doca_flow_cfg_set_nr_counters(struct doca_flow_cfg *cfg, uint32_t nr_counters)
Set number of counters to configure.
DOCA_STABLE void doca_flow_pipe_destroy(struct doca_flow_pipe *pipe)
Destroy one pipe.
DOCA_STABLE doca_error_t doca_flow_port_stop(struct doca_flow_port *port)
Stop a doca port.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_monitor(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_monitor *monitor)
Set pipe's monitor.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_EXPERIMENTAL doca_error_t doca_flow_port_cfg_set_port_id(struct doca_flow_port_cfg *cfg, uint16_t port_id)
Set the logical port ID.
DOCA_STABLE doca_error_t doca_flow_port_cfg_create(struct doca_flow_port_cfg **cfg)
Create DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_port_cfg_destroy(struct doca_flow_port_cfg *cfg)
Destroy DOCA Flow port configuration struct.
DOCA_STABLE doca_error_t doca_flow_cfg_set_pipe_queues(struct doca_flow_cfg *cfg, uint16_t pipe_queues)
Set pipe queues.
DOCA_STABLE doca_error_t doca_flow_cfg_destroy(struct doca_flow_cfg *cfg)
Destroy DOCA Flow configuration struct.
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_RSS_UDP
Definition: doca_flow.h:768
@ DOCA_FLOW_PIPE_CONTROL
Definition: doca_flow.h:223
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_NO_WAIT
Definition: doca_flow.h:115
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_DROP
Definition: doca_flow.h:748
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
@ DOCA_FLOW_L4_META_UDP
Definition: doca_flow.h:310
#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_set_permissions(struct doca_mmap *mmap, uint32_t access_mask)
Set access flags of the registered memory.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_add_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Register DOCA memory map on a given device.
DOCA_STABLE doca_error_t doca_mmap_set_dmabuf_memrange(struct doca_mmap *mmap, int dmabuf_fd, void *addr, size_t dmabuf_offset, size_t len)
Set the memory range of DOCA memory map using dmabuf.
@ DOCA_GPU_MEM_TYPE_GPU_CPU
Definition: doca_types.h:133
@ DOCA_GPU_MEM_TYPE_GPU
Definition: doca_types.h:131
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
forwarding configuration
Definition: doca_flow.h:779
struct doca_flow_pipe * next_pipe
Definition: doca_flow.h:800
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
enum doca_flow_resource_type rss_type
Definition: doca_flow.h:784
struct doca_flow_resource_rss_cfg rss
Definition: doca_flow.h:787
struct doca_flow_header_eth eth
Definition: doca_flow.h:440
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
doca monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_resource_type counter_type
Definition: doca_flow.h:988
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
struct doca_eth_rxq * eth_rxq_cpu
struct doca_dev * ddev
struct doca_gpu * gpu_dev
struct doca_mmap * pkt_buff_mmap
struct doca_flow_pipe_entry * root_udp_entry
struct doca_flow_port * port
struct doca_flow_pipe * rxq_pipe
struct doca_ctx * eth_rxq_ctx
void * gpu_pkt_addr
struct doca_flow_pipe * root_pipe
struct doca_gpu_eth_rxq * eth_rxq_gpu
char gpu_pcie_addr[DOCA_DEVINFO_PCI_ADDR_SIZE]
char nic_pcie_addr[DOCA_DEVINFO_PCI_ADDR_SIZE]