NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
udp_queues.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023-2024 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 <stdlib.h>
27 #include <string.h>
28 #include <rte_ethdev.h>
29 
30 #include "common.h"
31 
32 DOCA_LOG_REGISTER(GPU_PACKET_PROCESSING_UDP);
33 
35  struct doca_flow_port *df_port,
36  struct doca_gpu *gpu_dev,
37  struct doca_dev *ddev,
38  uint32_t queue_num,
39  uint32_t sem_num)
40 {
42  uint32_t cyclic_buffer_size = 0;
43 
44  if (udp_queues == NULL || df_port == NULL || gpu_dev == NULL || ddev == NULL || queue_num == 0 ||
45  sem_num == 0) {
46  DOCA_LOG_ERR("Can't create UDP queues, invalid input");
48  }
49 
51  udp_queues->ddev = ddev;
53  udp_queues->numq = queue_num;
54  udp_queues->nums = sem_num;
55 
56  for (uint32_t idx = 0; idx < queue_num; idx++) {
57  DOCA_LOG_INFO("Creating UDP Eth Rxq %d", idx);
58 
62  &(udp_queues->eth_rxq_cpu[idx]));
63  if (result != DOCA_SUCCESS) {
64  DOCA_LOG_ERR("Failed doca_eth_rxq_create: %s", doca_error_get_descr(result));
65  return DOCA_ERROR_BAD_STATE;
66  }
67 
69  if (result != DOCA_SUCCESS) {
70  DOCA_LOG_ERR("Failed doca_eth_rxq_set_type: %s", doca_error_get_descr(result));
71  return DOCA_ERROR_BAD_STATE;
72  }
73 
75  0,
76  0,
79  0,
80  0,
81  0,
82  &cyclic_buffer_size);
83  if (result != DOCA_SUCCESS) {
84  DOCA_LOG_ERR("Failed to get eth_rxq cyclic buffer size: %s", doca_error_get_descr(result));
86  return DOCA_ERROR_BAD_STATE;
87  }
88 
90  if (result != DOCA_SUCCESS) {
91  DOCA_LOG_ERR("Failed to create mmap: %s", doca_error_get_descr(result));
93  return DOCA_ERROR_BAD_STATE;
94  }
95 
97  if (result != DOCA_SUCCESS) {
98  DOCA_LOG_ERR("Failed to add dev to mmap: %s", doca_error_get_descr(result));
100  return DOCA_ERROR_BAD_STATE;
101  }
102 
103  result = doca_gpu_mem_alloc(udp_queues->gpu_dev,
104  cyclic_buffer_size,
107  &udp_queues->gpu_pkt_addr[idx],
108  NULL);
109  if (result != DOCA_SUCCESS || udp_queues->gpu_pkt_addr[idx] == NULL) {
110  DOCA_LOG_ERR("Failed to allocate gpu memory %s", doca_error_get_descr(result));
112  return DOCA_ERROR_BAD_STATE;
113  }
114 
115  /* Map GPU memory buffer used to receive packets with DMABuf */
116  result = doca_gpu_dmabuf_fd(udp_queues->gpu_dev,
117  udp_queues->gpu_pkt_addr[idx],
118  cyclic_buffer_size,
119  &(udp_queues->dmabuf_fd[idx]));
120  if (result != DOCA_SUCCESS) {
121  DOCA_LOG_INFO("Mapping receive queue buffer (0x%p size %dB) with nvidia-peermem mode",
122  udp_queues->gpu_pkt_addr[idx],
123  cyclic_buffer_size);
124 
125  /* If failed, use nvidia-peermem legacy method */
127  udp_queues->gpu_pkt_addr[idx],
128  cyclic_buffer_size);
129  if (result != DOCA_SUCCESS) {
130  DOCA_LOG_ERR("Failed to set memrange for mmap %s", doca_error_get_descr(result));
132  return DOCA_ERROR_BAD_STATE;
133  }
134  } else {
135  DOCA_LOG_INFO("Mapping receive queue buffer (0x%p size %dB dmabuf fd %d) with dmabuf mode",
136  udp_queues->gpu_pkt_addr[idx],
137  cyclic_buffer_size,
138  udp_queues->dmabuf_fd[idx]);
139 
141  udp_queues->dmabuf_fd[idx],
142  udp_queues->gpu_pkt_addr[idx],
143  0,
144  cyclic_buffer_size);
145  if (result != DOCA_SUCCESS) {
146  DOCA_LOG_ERR("Failed to set dmabuf memrange for mmap %s", doca_error_get_descr(result));
148  return DOCA_ERROR_BAD_STATE;
149  }
150  }
151 
155  if (result != DOCA_SUCCESS) {
156  DOCA_LOG_ERR("Failed to set permissions for mmap %s", doca_error_get_descr(result));
158  return DOCA_ERROR_BAD_STATE;
159  }
160 
162  if (result != DOCA_SUCCESS) {
163  DOCA_LOG_ERR("Failed to start mmap %s", doca_error_get_descr(result));
165  return DOCA_ERROR_BAD_STATE;
166  }
167 
170  0,
171  cyclic_buffer_size);
172  if (result != DOCA_SUCCESS) {
173  DOCA_LOG_ERR("Failed to set cyclic buffer %s", doca_error_get_descr(result));
175  return DOCA_ERROR_BAD_STATE;
176  }
177 
179  if (udp_queues->eth_rxq_ctx[idx] == NULL) {
180  DOCA_LOG_ERR("Failed doca_eth_rxq_as_doca_ctx: %s", doca_error_get_descr(result));
182  return DOCA_ERROR_BAD_STATE;
183  }
184 
186  if (result != DOCA_SUCCESS) {
187  DOCA_LOG_ERR("Failed doca_ctx_set_datapath_on_gpu: %s", doca_error_get_descr(result));
189  return DOCA_ERROR_BAD_STATE;
190  }
191 
193  if (result != DOCA_SUCCESS) {
194  DOCA_LOG_ERR("Failed doca_ctx_start: %s", doca_error_get_descr(result));
196  return DOCA_ERROR_BAD_STATE;
197  }
198 
200  if (result != DOCA_SUCCESS) {
201  DOCA_LOG_ERR("Failed doca_eth_rxq_get_gpu_handle: %s", doca_error_get_descr(result));
203  return DOCA_ERROR_BAD_STATE;
204  }
205 
206  result = doca_gpu_semaphore_create(udp_queues->gpu_dev, &(udp_queues->sem_cpu[idx]));
207  if (result != DOCA_SUCCESS) {
208  DOCA_LOG_ERR("Failed doca_gpu_semaphore_create: %s", doca_error_get_descr(result));
210  return DOCA_ERROR_BAD_STATE;
211  }
212 
213  /*
214  * Semaphore memory reside on CPU visible from GPU.
215  * CPU will poll in busy wait on this semaphore (multiple reads)
216  * while GPU access each item only once to update values.
217  */
218  result = doca_gpu_semaphore_set_memory_type(udp_queues->sem_cpu[idx], DOCA_GPU_MEM_TYPE_CPU_GPU);
219  if (result != DOCA_SUCCESS) {
220  DOCA_LOG_ERR("Failed doca_gpu_semaphore_set_memory_type: %s", doca_error_get_descr(result));
222  return DOCA_ERROR_BAD_STATE;
223  }
224 
225  result = doca_gpu_semaphore_set_items_num(udp_queues->sem_cpu[idx], udp_queues->nums);
226  if (result != DOCA_SUCCESS) {
227  DOCA_LOG_ERR("Failed doca_gpu_semaphore_set_items_num: %s", doca_error_get_descr(result));
229  return DOCA_ERROR_BAD_STATE;
230  }
231 
232  /*
233  * Semaphore memory reside on CPU visible from GPU.
234  * The CPU reads packets info from this structure.
235  * The GPU access each item only once to update values.
236  */
237  result = doca_gpu_semaphore_set_custom_info(udp_queues->sem_cpu[idx],
238  sizeof(struct stats_udp),
240  if (result != DOCA_SUCCESS) {
241  DOCA_LOG_ERR("Failed doca_gpu_semaphore_set_custom_info: %s", doca_error_get_descr(result));
243  return DOCA_ERROR_BAD_STATE;
244  }
245 
246  result = doca_gpu_semaphore_start(udp_queues->sem_cpu[idx]);
247  if (result != DOCA_SUCCESS) {
248  DOCA_LOG_ERR("Failed doca_gpu_semaphore_start: %s", doca_error_get_descr(result));
250  return DOCA_ERROR_BAD_STATE;
251  }
252 
253  result = doca_gpu_semaphore_get_gpu_handle(udp_queues->sem_cpu[idx], &(udp_queues->sem_gpu[idx]));
254  if (result != DOCA_SUCCESS) {
255  DOCA_LOG_ERR("Failed doca_gpu_semaphore_get_gpu_handle: %s", doca_error_get_descr(result));
257  return DOCA_ERROR_BAD_STATE;
258  }
259  }
260 
261  /* Create UDP based flow pipe */
263  if (result != DOCA_SUCCESS) {
264  DOCA_LOG_ERR("Function build_rxq_pipe returned %s", doca_error_get_descr(result));
265  return DOCA_ERROR_BAD_STATE;
266  }
267 
268  return DOCA_SUCCESS;
269 }
270 
272 {
274 
275  if (udp_queues == NULL) {
276  DOCA_LOG_ERR("Can't destroy UDP queues, invalid input");
278  }
279 
280  for (int idx = 0; idx < udp_queues->numq; idx++) {
281  DOCA_LOG_INFO("Destroying UDP queue %d", idx);
282 
283  if (udp_queues->sem_cpu[idx]) {
284  result = doca_gpu_semaphore_stop(udp_queues->sem_cpu[idx]);
285  if (result != DOCA_SUCCESS) {
286  DOCA_LOG_ERR("Failed doca_gpu_semaphore_start: %s", doca_error_get_descr(result));
287  return DOCA_ERROR_BAD_STATE;
288  }
289 
290  result = doca_gpu_semaphore_destroy(udp_queues->sem_cpu[idx]);
291  if (result != DOCA_SUCCESS) {
292  DOCA_LOG_ERR("Failed doca_gpu_semaphore_destroy: %s", doca_error_get_descr(result));
293  return DOCA_ERROR_BAD_STATE;
294  }
295  }
296 
298  if (result != DOCA_SUCCESS) {
299  DOCA_LOG_ERR("Failed doca_ctx_stop: %s", doca_error_get_descr(result));
300  return DOCA_ERROR_BAD_STATE;
301  }
302 
304  if (result != DOCA_SUCCESS) {
305  DOCA_LOG_ERR("Failed doca_eth_rxq_destroy: %s", doca_error_get_descr(result));
306  return DOCA_ERROR_BAD_STATE;
307  }
308 
310  if (result != DOCA_SUCCESS) {
311  DOCA_LOG_ERR("Failed to destroy mmap: %s", doca_error_get_descr(result));
312  return DOCA_ERROR_BAD_STATE;
313  }
314 
315  result = doca_gpu_mem_free(udp_queues->gpu_dev, udp_queues->gpu_pkt_addr[idx]);
316  if (result != DOCA_SUCCESS) {
317  DOCA_LOG_ERR("Failed to free gpu memory: %s", doca_error_get_descr(result));
318  return DOCA_ERROR_BAD_STATE;
319  }
320  }
321 
322  return DOCA_SUCCESS;
323 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
doca_error_t create_udp_pipe(struct rxq_udp_queues *udp_queues, struct doca_flow_port *port)
Definition: flow.c:176
#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 struct doca_flow_port * df_port
static struct rxq_udp_queues udp_queues
static struct doca_gpu * gpu_dev
static struct doca_dev * ddev
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.
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_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_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_GPU_MEM_TYPE_CPU_GPU
Definition: doca_types.h:135
@ DOCA_GPU_MEM_TYPE_GPU
Definition: doca_types.h:131
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_PCI_RELAXED_ORDERING
Definition: doca_types.h:95
struct doca_gpu_semaphore_gpu * sem_gpu[MAX_QUEUES]
Definition: common.h:95
struct doca_flow_port * port
Definition: common.h:85
struct doca_gpu_eth_rxq * eth_rxq_gpu[MAX_QUEUES]
Definition: common.h:80
struct doca_eth_rxq * eth_rxq_cpu[MAX_QUEUES]
Definition: common.h:79
uint16_t numq
Definition: common.h:77
struct doca_dev * ddev
Definition: common.h:75
uint16_t nums
Definition: common.h:93
struct doca_gpu_semaphore * sem_cpu[MAX_QUEUES]
Definition: common.h:94
struct doca_gpu * gpu_dev
Definition: common.h:74
struct doca_mmap * pkt_buff_mmap[MAX_QUEUES]
Definition: common.h:81
void * gpu_pkt_addr[MAX_QUEUES]
Definition: common.h:82
struct doca_ctx * eth_rxq_ctx[MAX_QUEUES]
Definition: common.h:78
int dmabuf_fd[MAX_QUEUES]
Definition: common.h:83
DOCA_LOG_REGISTER(GPU_PACKET_PROCESSING_UDP)
doca_error_t destroy_udp_queues(struct rxq_udp_queues *udp_queues)
Definition: udp_queues.c:271
doca_error_t create_udp_queues(struct rxq_udp_queues *udp_queues, struct doca_flow_port *df_port, struct doca_gpu *gpu_dev, struct doca_dev *ddev, uint32_t queue_num, uint32_t sem_num)
Definition: udp_queues.c:34