NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
gpunetio_send_wait_time_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 <time.h>
27 
28 #include <doca_dpdk.h>
29 #include <doca_flow.h>
30 #include <doca_log.h>
31 #include <doca_bitfield.h>
32 
33 #include "../gpunetio_common.h"
34 
35 #define MAC_ADDR_BYTE_SZ 6
36 #define MAX_PORT_STR_LEN 128
37 struct doca_flow_port *df_port;
38 
39 DOCA_LOG_REGISTER(GPU_SEND_WAIT_TIME : SAMPLE);
40 
41 /*
42  * Initialize a DOCA network device.
43  *
44  * @nic_pcie_addr [in]: Network card PCIe address
45  * @ddev [out]: DOCA device
46  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
47  */
48 static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
49 {
51 
52  if (nic_pcie_addr == NULL || ddev == NULL)
54 
55  if (strnlen(nic_pcie_addr, DOCA_DEVINFO_PCI_ADDR_SIZE) >= DOCA_DEVINFO_PCI_ADDR_SIZE)
57 
58  result = open_doca_device_with_pci(nic_pcie_addr, NULL, ddev);
59  if (result != DOCA_SUCCESS) {
60  DOCA_LOG_ERR("Failed to open NIC device based on PCI address");
61  return result;
62  }
63 
64  return DOCA_SUCCESS;
65 }
66 
67 /*
68  * Init doca flow.
69  *
70  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
71  */
73 {
74  struct doca_flow_cfg *queue_flow_cfg;
76 
77  /* Initialize doca flow framework */
78  result = doca_flow_cfg_create(&queue_flow_cfg);
79  if (result != DOCA_SUCCESS) {
80  DOCA_LOG_ERR("Failed to create doca_flow_cfg: %s", doca_error_get_descr(result));
81  return result;
82  }
83 
84  result = doca_flow_cfg_set_pipe_queues(queue_flow_cfg, 1);
85  if (result != DOCA_SUCCESS) {
86  DOCA_LOG_ERR("Failed to set doca_flow_cfg pipe_queues: %s", doca_error_get_descr(result));
87  doca_flow_cfg_destroy(queue_flow_cfg);
88  return result;
89  }
90 
91  result = doca_flow_cfg_set_mode_args(queue_flow_cfg, "vnf,isolated");
92  if (result != DOCA_SUCCESS) {
93  DOCA_LOG_ERR("Failed to set doca_flow_cfg mode_args: %s", doca_error_get_descr(result));
94  doca_flow_cfg_destroy(queue_flow_cfg);
95  return result;
96  }
97 
98  result = doca_flow_init(queue_flow_cfg);
99  if (result != DOCA_SUCCESS) {
100  DOCA_LOG_ERR("Failed to init doca flow with: %s", doca_error_get_descr(result));
101  doca_flow_cfg_destroy(queue_flow_cfg);
102  return result;
103  }
104  doca_flow_cfg_destroy(queue_flow_cfg);
105 
106  return DOCA_SUCCESS;
107 }
108 
109 /*
110  * Start doca flow.
111  *
112  * @dev [in]: DOCA device
113  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
114  */
115 static doca_error_t start_doca_flow(struct doca_dev *dev)
116 {
117  struct doca_flow_port_cfg *port_cfg;
119 
120  /* Start doca flow port */
121  result = doca_flow_port_cfg_create(&port_cfg);
122  if (result != DOCA_SUCCESS) {
123  DOCA_LOG_ERR("Failed to create doca_flow_port_cfg: %s", doca_error_get_descr(result));
124  return result;
125  }
126 
127  result = doca_flow_port_cfg_set_port_id(port_cfg, 0);
128  if (result != DOCA_SUCCESS) {
129  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg port ID: %s", doca_error_get_descr(result));
130  doca_flow_port_cfg_destroy(port_cfg);
131  return result;
132  }
133 
134  result = doca_flow_port_cfg_set_dev(port_cfg, dev);
135  if (result != DOCA_SUCCESS) {
136  DOCA_LOG_ERR("Failed to set doca_flow_port_cfg dev: %s", doca_error_get_descr(result));
137  doca_flow_port_cfg_destroy(port_cfg);
138  return result;
139  }
140 
141  result = doca_flow_port_start(port_cfg, &df_port);
142  if (result != DOCA_SUCCESS) {
143  DOCA_LOG_ERR("Failed to start doca flow port with: %s", doca_error_get_descr(result));
144  doca_flow_port_cfg_destroy(port_cfg);
145  return result;
146  }
147 
148  return DOCA_SUCCESS;
149 }
150 
151 /*
152  * Get timestamp in nanoseconds
153  *
154  * @return: UTC timestamp
155  */
156 uint64_t get_ns(void)
157 {
158  struct timespec t;
159  int ret;
160 
161  ret = clock_gettime(CLOCK_REALTIME, &t);
162  if (ret != 0)
163  exit(EXIT_FAILURE);
164 
165  return (uint64_t)t.tv_nsec + (uint64_t)t.tv_sec * 1000 * 1000 * 1000;
166 }
167 
168 /*
169  * Create TX buf to send dummy packets to Ethernet broadcast address
170  *
171  * @txq [in]: DOCA Eth Tx queue with Tx buf
172  * @num_packets [in]: Number of packets in the doca_buf_arr of the txbuf
173  * @max_pkt_sz [in]: Max packet size
174  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
175  */
176 static doca_error_t create_tx_buf(struct txq_queue *txq, uint32_t num_packets, uint32_t max_pkt_sz)
177 {
178  doca_error_t status;
179  struct tx_buf *buf;
180 
181  if (txq == NULL || num_packets == 0 || max_pkt_sz == 0) {
182  DOCA_LOG_ERR("Invalid input arguments");
184  }
185 
186  buf = &(txq->txbuf);
187  buf->num_packets = num_packets;
188  buf->max_pkt_sz = max_pkt_sz;
189  buf->gpu_dev = txq->gpu_dev;
190 
191  status = doca_mmap_create(&(buf->mmap));
192  if (status != DOCA_SUCCESS) {
193  DOCA_LOG_ERR("Unable to create doca_buf: failed to create mmap");
194  return status;
195  }
196 
197  status = doca_mmap_add_dev(buf->mmap, txq->ddev);
198  if (status != DOCA_SUCCESS) {
199  DOCA_LOG_ERR("Unable to add dev to buf: doca mmap internal error");
200  return status;
201  }
202 
203  status = doca_gpu_mem_alloc(buf->gpu_dev,
204  buf->num_packets * buf->max_pkt_sz,
207  (void **)&(buf->gpu_pkt_addr),
208  NULL);
209  if ((status != DOCA_SUCCESS) || (buf->gpu_pkt_addr == NULL)) {
210  DOCA_LOG_ERR("Unable to alloc txbuf: failed to allocate gpu memory");
211  return status;
212  }
213 
214  /* Map GPU memory buffer used to send packets with DMABuf */
215  status = doca_gpu_dmabuf_fd(buf->gpu_dev,
216  buf->gpu_pkt_addr,
217  buf->num_packets * buf->max_pkt_sz,
218  &(buf->dmabuf_fd));
219  if (status != DOCA_SUCCESS) {
220  DOCA_LOG_INFO("Mapping send queue buffer (0x%p size %dB) with legacy nvidia-peermem mode",
221  buf->gpu_pkt_addr,
222  buf->num_packets * buf->max_pkt_sz);
223 
224  /* If failed, use nvidia-peermem legacy method */
225  status = doca_mmap_set_memrange(buf->mmap, buf->gpu_pkt_addr, (buf->num_packets * buf->max_pkt_sz));
226  if (status != DOCA_SUCCESS) {
227  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
228  return status;
229  }
230  } else {
231  DOCA_LOG_INFO("Mapping send queue buffer (0x%p size %dB dmabuf fd %d) with dmabuf mode",
232  buf->gpu_pkt_addr,
233  (buf->num_packets * buf->max_pkt_sz),
234  buf->dmabuf_fd);
235 
236  status = doca_mmap_set_dmabuf_memrange(buf->mmap,
237  buf->dmabuf_fd,
238  buf->gpu_pkt_addr,
239  0,
240  (buf->num_packets * buf->max_pkt_sz));
241  if (status != DOCA_SUCCESS) {
242  DOCA_LOG_ERR("Failed to set dmabuf memrange for mmap %s", doca_error_get_descr(status));
243  return status;
244  }
245  }
246 
248  if (status != DOCA_SUCCESS) {
249  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
250  return status;
251  }
252 
253  status = doca_mmap_start(buf->mmap);
254  if (status != DOCA_SUCCESS) {
255  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
256  return status;
257  }
258 
259  status = doca_buf_arr_create(buf->num_packets, &buf->buf_arr);
260  if (status != DOCA_SUCCESS) {
261  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
262  return status;
263  }
264 
265  status = doca_buf_arr_set_target_gpu(buf->buf_arr, buf->gpu_dev);
266  if (status != DOCA_SUCCESS) {
267  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
268  return status;
269  }
270 
271  status = doca_buf_arr_set_params(buf->buf_arr, buf->mmap, buf->max_pkt_sz, 0);
272  if (status != DOCA_SUCCESS) {
273  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
274  return status;
275  }
276 
277  status = doca_buf_arr_start(buf->buf_arr);
278  if (status != DOCA_SUCCESS) {
279  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
280  return status;
281  }
282 
283  status = doca_buf_arr_get_gpu_handle(buf->buf_arr, &(buf->buf_arr_gpu));
284  if (status != DOCA_SUCCESS) {
285  DOCA_LOG_ERR("Unable to get buff_arr GPU handle: %s", doca_error_get_descr(status));
286  return status;
287  }
288 
289  return DOCA_SUCCESS;
290 }
291 
292 /*
293  * Pre-prepare TX buf filling default values in GPU memory
294  *
295  * @txq [in]: DOCA Eth Tx queue handler
296  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
297  */
298 static doca_error_t prepare_tx_buf(struct txq_queue *txq, struct doca_dev *ddev)
299 {
300  uint8_t *cpu_pkt_addr;
301  uint8_t *pkt;
302  struct ether_hdr *hdr;
303  cudaError_t res_cuda;
304  doca_error_t status;
305  struct tx_buf *buf;
306  uint8_t mac_addr[MAC_ADDR_BYTE_SZ];
307  uint32_t idx;
308  const char *payload = "Sent from DOCA GPUNetIO";
309 
310  if (txq == NULL) {
311  DOCA_LOG_ERR("Invalid input arguments");
313  }
314 
315  buf = &(txq->txbuf);
316  buf->pkt_nbytes = strlen(payload);
317 
319  if (status != DOCA_SUCCESS) {
320  DOCA_LOG_ERR("Unable to get interface MAC address: %s", doca_error_get_descr(status));
321  return status;
322  }
323 
324  cpu_pkt_addr = (uint8_t *)calloc(buf->num_packets * buf->max_pkt_sz, sizeof(uint8_t));
325  if (cpu_pkt_addr == NULL) {
326  DOCA_LOG_ERR("Error in txbuf preparation, failed to allocate memory");
327  return DOCA_ERROR_NO_MEMORY;
328  }
329 
330  for (idx = 0; idx < buf->num_packets; idx++) {
331  pkt = cpu_pkt_addr + (idx * buf->max_pkt_sz);
332  hdr = (struct ether_hdr *)pkt;
333 
334  hdr->s_addr_bytes[0] = mac_addr[0];
335  hdr->s_addr_bytes[1] = mac_addr[1];
336  hdr->s_addr_bytes[2] = mac_addr[2];
337  hdr->s_addr_bytes[3] = mac_addr[3];
338  hdr->s_addr_bytes[4] = mac_addr[4];
339  hdr->s_addr_bytes[5] = mac_addr[5];
340 
341  hdr->d_addr_bytes[0] = 0x10;
342  hdr->d_addr_bytes[1] = 0x11;
343  hdr->d_addr_bytes[2] = 0x12;
344  hdr->d_addr_bytes[3] = 0x13;
345  hdr->d_addr_bytes[4] = 0x14;
346  hdr->d_addr_bytes[5] = 0x15;
347 
348  hdr->ether_type = DOCA_HTOBE16(DOCA_FLOW_ETHER_TYPE_IPV4);
349 
350  /* Assuming no TCP flags needed */
351  pkt = pkt + sizeof(struct ether_hdr);
352 
353  memcpy(pkt, payload, buf->pkt_nbytes);
354  }
355 
356  /* Copy the whole list of packets into GPU memory buffer */
357  res_cuda = cudaMemcpy(buf->gpu_pkt_addr, cpu_pkt_addr, buf->num_packets * buf->max_pkt_sz, cudaMemcpyDefault);
358  free(cpu_pkt_addr);
359  if (res_cuda != cudaSuccess) {
360  DOCA_LOG_ERR("Function CUDA Memcpy cqe_addr failed with %s", cudaGetErrorString(res_cuda));
361  return DOCA_ERROR_DRIVER;
362  }
363 
364  return DOCA_SUCCESS;
365 }
366 
367 /*
368  * Destroy TX buf
369  *
370  * @txq [in]: DOCA Eth Tx queue with Tx buf
371  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
372  */
374 {
375  doca_error_t status;
376  struct tx_buf *buf;
377 
378  if (txq == NULL) {
379  DOCA_LOG_ERR("Invalid input arguments");
381  }
382 
383  buf = &(txq->txbuf);
384 
385  /* Tx buf may not be created yet */
386  if (buf == NULL)
387  return DOCA_SUCCESS;
388 
389  if (buf->mmap) {
390  status = doca_mmap_destroy(buf->mmap);
391  if (status != DOCA_SUCCESS) {
392  DOCA_LOG_ERR("Unable to destroy doca_buf: failed to destroy mmap");
393  return status;
394  }
395  }
396 
397  if (buf->gpu_pkt_addr) {
398  status = doca_gpu_mem_free(txq->gpu_dev, buf->gpu_pkt_addr);
399  if (status != DOCA_SUCCESS) {
400  DOCA_LOG_ERR("Unable to stop buf: failed to free gpu memory");
401  return status;
402  }
403  }
404 
405  if (buf->buf_arr) {
406  status = doca_buf_arr_stop(buf->buf_arr);
407  if (status != DOCA_SUCCESS) {
408  DOCA_LOG_ERR("Unable to stop buf: failed to destroy doca_buf_arr");
409  return status;
410  }
411 
412  status = doca_buf_arr_destroy(buf->buf_arr);
413  if (status != DOCA_SUCCESS) {
414  DOCA_LOG_ERR("Unable to stop buf: failed to destroy doca_buf_arr");
415  return status;
416  }
417  }
418 
419  return DOCA_SUCCESS;
420 }
421 
422 /*
423  * Destroy DOCA Ethernet Tx queue for GPU
424  *
425  * @txq [in]: DOCA Eth Tx queue handler
426  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
427  */
428 static doca_error_t destroy_txq(struct txq_queue *txq)
429 {
431 
432  if (txq == NULL) {
433  DOCA_LOG_ERR("Can't destroy Tx queue, invalid input");
435  }
436 
438  if (result != DOCA_SUCCESS) {
439  DOCA_LOG_ERR("Failed doca_ctx_stop: %s", doca_error_get_descr(result));
440  return DOCA_ERROR_BAD_STATE;
441  }
442 
444  if (result != DOCA_SUCCESS) {
445  DOCA_LOG_ERR("Failed doca_eth_rxq_destroy: %s", doca_error_get_descr(result));
446  return DOCA_ERROR_BAD_STATE;
447  }
448 
450 
451  result = doca_dev_close(txq->ddev);
452  if (result != DOCA_SUCCESS) {
453  DOCA_LOG_ERR("Failed doca_dev_close: %s", doca_error_get_descr(result));
454  return DOCA_ERROR_BAD_STATE;
455  }
456 
457  return DOCA_SUCCESS;
458 }
459 
460 /*
461  * Create DOCA Ethernet Tx queue for GPU
462  *
463  * @txq [in]: DOCA Eth Tx queue handler
464  * @gpu_dev [in]: DOCA GPUNetIO device
465  * @ddev [in]: DOCA device
466  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
467  */
468 static doca_error_t create_txq(struct txq_queue *txq, struct doca_gpu *gpu_dev, struct doca_dev *ddev)
469 {
471 
472  if (txq == NULL || gpu_dev == NULL || ddev == NULL) {
473  DOCA_LOG_ERR("Can't create DOCA Eth Tx queue, invalid input");
475  }
476 
477  txq->gpu_dev = gpu_dev;
478  txq->ddev = ddev;
479 
481  if (result != DOCA_SUCCESS) {
482  DOCA_LOG_ERR("Failed doca_eth_txq_create: %s", doca_error_get_descr(result));
483  destroy_txq(txq);
484  return DOCA_ERROR_BAD_STATE;
485  }
486 
488  if (result != DOCA_SUCCESS) {
489  DOCA_LOG_ERR("Failed to set eth_txq l3 offloads: %s", doca_error_get_descr(result));
490  destroy_txq(txq);
491  return DOCA_ERROR_BAD_STATE;
492  }
493 
495  if (txq->eth_txq_ctx == NULL) {
496  DOCA_LOG_ERR("Failed doca_eth_txq_as_doca_ctx: %s", doca_error_get_descr(result));
497  destroy_txq(txq);
498  return DOCA_ERROR_BAD_STATE;
499  }
500 
502  if (result != DOCA_SUCCESS) {
503  DOCA_LOG_ERR("Failed doca_ctx_set_datapath_on_gpu: %s", doca_error_get_descr(result));
504  destroy_txq(txq);
505  return DOCA_ERROR_BAD_STATE;
506  }
507 
509  if (result != DOCA_SUCCESS) {
510  DOCA_LOG_ERR("Failed doca_ctx_start: %s", doca_error_get_descr(result));
511  destroy_txq(txq);
512  return DOCA_ERROR_BAD_STATE;
513  }
514 
516  if (result != DOCA_SUCCESS) {
517  DOCA_LOG_ERR("Failed doca_eth_txq_get_gpu_handle: %s", doca_error_get_descr(result));
518  destroy_txq(txq);
519  return DOCA_ERROR_BAD_STATE;
520  }
521 
522  return DOCA_SUCCESS;
523 }
524 
525 /*
526  * Launch GPUNetIO send wait on time sample
527  *
528  * @sample_cfg [in]: Sample config parameters
529  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
530  */
532 {
534  uint64_t *intervals_cpu = NULL;
535  uint64_t *intervals_gpu = NULL;
536  uint64_t time_seed;
537  struct doca_gpu *gpu_dev = NULL;
538  struct doca_dev *ddev = NULL;
539  struct txq_queue txq = {0};
540  enum doca_eth_wait_on_time_type wait_on_time_mode;
541  cudaStream_t stream;
542  cudaError_t res_rt = cudaSuccess;
543 
544  result = init_doca_device(sample_cfg->nic_pcie_addr, &ddev);
545  if (result != DOCA_SUCCESS) {
546  DOCA_LOG_ERR("Function init_doca_device returned %s", doca_error_get_descr(result));
547  return EXIT_FAILURE;
548  }
549 
551  if (result != DOCA_SUCCESS) {
552  DOCA_LOG_ERR("Wait on time offload error, returned %s", doca_error_get_descr(result));
553  goto exit;
554  }
555 
556  /* Init and start port for eth */
558  if (result != DOCA_SUCCESS) {
559  DOCA_LOG_ERR("Function create_txq returned %s", doca_error_get_descr(result));
560  goto exit;
561  }
562 
564  if (result != DOCA_SUCCESS) {
565  DOCA_LOG_ERR("Function start_doca_flow returned %s", doca_error_get_descr(result));
566  goto exit;
567  }
568 
569  if (wait_on_time_mode == DOCA_ETH_WAIT_ON_TIME_TYPE_DPDK) {
570  /*
571  * From CX7, tx_pp is not needed anymore.
572  */
573  result = doca_dpdk_port_probe(ddev, "tx_pp=500,txq_inline_max=0,dv_flow_en=2");
574  if (result != DOCA_SUCCESS) {
575  DOCA_LOG_ERR("Function doca_dpdk_port_probe returned %s", doca_error_get_descr(result));
576  return result;
577  }
578  }
579 
580  DOCA_LOG_INFO("Wait on time supported mode: %s",
581  (wait_on_time_mode == DOCA_ETH_WAIT_ON_TIME_TYPE_DPDK) ? "DPDK" : "Native");
582 
583  result = doca_gpu_create(sample_cfg->gpu_pcie_addr, &gpu_dev);
584  if (result != DOCA_SUCCESS) {
585  DOCA_LOG_ERR("Function doca_gpu_create returned %s", doca_error_get_descr(result));
586  goto exit;
587  }
588 
589  result = create_txq(&txq, gpu_dev, ddev);
590  if (result != DOCA_SUCCESS) {
591  DOCA_LOG_ERR("Function create_txq returned %s", doca_error_get_descr(result));
592  goto exit;
593  }
594 
596  if (result != DOCA_SUCCESS) {
597  DOCA_LOG_ERR("Function create_tx_buf returned %s", doca_error_get_descr(result));
598  goto exit;
599  }
600 
601  result = prepare_tx_buf(&txq, ddev);
602  if (result != DOCA_SUCCESS) {
603  DOCA_LOG_ERR("Function prepare_tx_buf returned %s", doca_error_get_descr(result));
604  goto exit;
605  }
606 
607  res_rt = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
608  if (res_rt != cudaSuccess) {
609  DOCA_LOG_ERR("Function cudaStreamCreateWithFlags error %d", res_rt);
610  return DOCA_ERROR_DRIVER;
611  }
612 
613  result = doca_gpu_mem_alloc(gpu_dev,
614  sizeof(uint64_t) * NUM_BURST_SEND,
617  (void **)&intervals_gpu,
618  (void **)&intervals_cpu);
619  if (result != DOCA_SUCCESS || intervals_gpu == NULL || intervals_cpu == NULL) {
620  DOCA_LOG_ERR("Failed to allocate gpu memory %s", doca_error_get_descr(result));
621  goto exit;
622  }
623 
624  time_seed = get_ns() + DELTA_NS;
625  for (int idx = 0; idx < NUM_BURST_SEND; idx++) {
627  time_seed + (sample_cfg->time_interval_ns * idx),
628  &intervals_cpu[idx]);
629  if (result != DOCA_SUCCESS) {
630  DOCA_LOG_ERR("Failed to get wait on time value for timestamp %ld, error %s",
631  time_seed + (sample_cfg->time_interval_ns * idx),
633  goto exit;
634  }
635  }
636 
637  DOCA_LOG_INFO("Launching CUDA kernel to send packets");
638  kernel_send_wait_on_time(stream, &txq, intervals_gpu);
639  cudaStreamSynchronize(stream);
640  /*
641  * This is needed only because it's a synthetic example.
642  * Typical application works in a continuous loop so there is no need to wait.
643  */
644  DOCA_LOG_INFO("Waiting 10 sec for %d packets to be sent", NUM_BURST_SEND * NUM_PACKETS_X_BURST);
645  sleep(10);
646 
647 exit:
648  if (intervals_gpu)
649  doca_gpu_mem_free(gpu_dev, intervals_gpu);
650 
651  result = destroy_tx_buf(&txq);
652  if (result != DOCA_SUCCESS) {
653  DOCA_LOG_ERR("Function create_txq returned %s", doca_error_get_descr(result));
654  return DOCA_ERROR_BAD_STATE;
655  }
656 
657  result = destroy_txq(&txq);
658  if (result != DOCA_SUCCESS) {
659  DOCA_LOG_ERR("Function create_txq returned %s", doca_error_get_descr(result));
660  return DOCA_ERROR_BAD_STATE;
661  }
662 
663  DOCA_LOG_INFO("Sample finished successfully");
664 
665  return DOCA_SUCCESS;
666 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define GPU_PAGE_SIZE
Definition: defines.h:58
#define MAX_SQ_DESCR_NUM
Definition: defines.h:74
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
static struct doca_gpu * gpu_dev
static struct doca_dev * ddev
#define NUM_PACKETS_X_BURST
doca_error_t kernel_send_wait_on_time(cudaStream_t stream, struct txq_queue *txq, uint64_t *intervals_gpu)
#define DELTA_NS
#define NUM_BURST_SEND
#define PACKET_SIZE
static doca_error_t destroy_txq(struct txq_queue *txq)
static doca_error_t init_doca_flow(void)
static doca_error_t init_doca_device(char *nic_pcie_addr, struct doca_dev **ddev)
uint64_t get_ns(void)
struct doca_flow_port * df_port
static doca_error_t destroy_tx_buf(struct txq_queue *txq)
doca_error_t gpunetio_send_wait_time(struct sample_send_wait_cfg *sample_cfg)
static doca_error_t start_doca_flow(struct doca_dev *dev)
static doca_error_t create_tx_buf(struct txq_queue *txq, uint32_t num_packets, uint32_t max_pkt_sz)
static doca_error_t prepare_tx_buf(struct txq_queue *txq, struct doca_dev *ddev)
static doca_error_t create_txq(struct txq_queue *txq, struct doca_gpu *gpu_dev, struct doca_dev *ddev)
#define MAC_ADDR_BYTE_SZ
DOCA_LOG_REGISTER(GPU_SEND_WAIT_TIME :SAMPLE)
#define DOCA_HTOBE16(_x)
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_destroy(struct doca_buf_arr *buf_arr)
Destroys a doca buf array instance.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_params(struct doca_buf_arr *buf_arr, struct doca_mmap *mmap, size_t elem_size, uint64_t start_offset)
Sets the buf array params.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_stop(struct doca_buf_arr *buf_arr)
Stops a started doca buf array.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_target_gpu(struct doca_buf_arr *buf_arr, struct doca_gpu *gpu_handler)
Configures the buf array to be created on the gpu device.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_get_gpu_handle(const struct doca_buf_arr *buf_arr, struct doca_gpu_buf_arr **gpu_buf_arr)
Retrieves the handle in the gpu memory space of a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_create(size_t num_elem, struct doca_buf_arr **buf_arr)
Allocates a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_start(struct doca_buf_arr *buf_arr)
This method enables the allocation of doca_bufs.
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.
DOCA_STABLE doca_error_t doca_devinfo_get_mac_addr(const struct doca_devinfo *devinfo, uint8_t *mac_addr, uint32_t size)
Get the MAC address of a DOCA devinfo.
#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_EXPERIMENTAL doca_error_t doca_dpdk_port_probe(struct doca_dev *dev, const char *devargs)
Attach a DPDK port specified by DOCA device.
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_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
DOCA_EXPERIMENTAL struct doca_ctx * doca_eth_txq_as_doca_ctx(struct doca_eth_txq *eth_txq)
Convert doca_eth_txq instance into a generalized context for use with doca core objects.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_get_gpu_handle(const struct doca_eth_txq *eth_txq, struct doca_gpu_eth_txq **eth_txq_ext)
Get a gpu handle of a doca_eth_txq.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_set_wait_on_time_offload(struct doca_eth_txq *eth_txq)
Set offload to enable wait on time feature on the queue. can only be called before calling doca_ctx_s...
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_create(struct doca_dev *dev, uint32_t max_burst_size, struct doca_eth_txq **eth_txq)
Create a DOCA ETH TXQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_destroy(struct doca_eth_txq *eth_txq)
Destroy a DOCA ETH TXQ instance.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_cap_get_wait_on_time_offload_supported(const struct doca_devinfo *devinfo, enum doca_eth_wait_on_time_type *wait_on_time_mode)
Check if wait on time offload is supported by the network device.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_calculate_timestamp(struct doca_eth_txq *eth_txq, uint64_t timestamp_ns, uint64_t *wait_on_time_value)
Calculate timestamp to use when setting the wait on time on the Tx queue.
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
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_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_cfg_create(struct doca_flow_cfg **cfg)
Create DOCA Flow configuration struct.
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_port_stop(struct doca_flow_port *port)
Stop a doca port.
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.
#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_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_eth_wait_on_time_type
Type of wait on time the network card can support.
Definition: doca_types.h:142
@ 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
@ DOCA_ETH_WAIT_ON_TIME_TYPE_DPDK
Definition: doca_types.h:148
uint8_t s_addr_bytes[ETHER_ADDR_LEN]
Definition: packets.h:62
char gpu_pcie_addr[DOCA_DEVINFO_PCI_ADDR_SIZE]
char nic_pcie_addr[DOCA_DEVINFO_PCI_ADDR_SIZE]
Definition: common.h:120
struct doca_mmap * mmap
Definition: common.h:127
struct doca_buf_arr * buf_arr
Definition: common.h:128
uint32_t pkt_nbytes
Definition: common.h:125
struct doca_gpu_buf_arr * buf_arr_gpu
Definition: common.h:129
uint8_t * gpu_pkt_addr
Definition: common.h:126
uint32_t max_pkt_sz
Definition: common.h:124
int dmabuf_fd
Definition: common.h:130
uint32_t num_packets
Definition: common.h:123
struct doca_gpu * gpu_dev
Definition: common.h:121
struct tx_buf txbuf
struct doca_dev * ddev
struct doca_gpu_eth_txq * eth_txq_gpu
struct doca_ctx * eth_txq_ctx
struct doca_eth_txq * eth_txq_cpu
struct doca_gpu * gpu_dev