NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
rmax_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022-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 <unistd.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 
31 #include "rmax_common.h"
32 
33 DOCA_LOG_REGISTER(rmax_common);
34 
35 /*
36  * ARGP Callback - Handle PCI device address parameter
37  *
38  * @param [in]: Input parameter
39  * @config [in/out]: Program configuration context
40  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
41  */
42 static doca_error_t pci_address_callback(void *param, void *config)
43 {
44  struct rmax_stream_config *cfg = (struct rmax_stream_config *)config;
45  char *pci_address = (char *)param;
46  int len;
47 
50  DOCA_LOG_ERR("Entered device PCI address exceeding the maximum size of %d",
53  }
54  strncpy(cfg->pci_address, pci_address, len + 1);
55  return DOCA_SUCCESS;
56 }
57 
58 /*
59  * ARGP Callback - Handle source IP address parameter
60  *
61  * @param [in]: Input parameter
62  * @config [in/out]: Program configuration context
63  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
64  */
65 static doca_error_t src_ip_callback(void *param, void *config)
66 {
67  struct rmax_stream_config *cfg = (struct rmax_stream_config *)config;
68  char *ip_addr_str = (char *)param;
69 
70  if (inet_pton(AF_INET, ip_addr_str, &cfg->src_ip.s_addr) != 1) {
71  DOCA_LOG_ERR("Invalid source IP address: %s", ip_addr_str);
73  }
74  return DOCA_SUCCESS;
75 }
76 
77 /*
78  * ARGP Callback - Handle destination port parameter
79  *
80  * @param [in]: Input parameter
81  * @config [in/out]: Program configuration context
82  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
83  */
84 static doca_error_t dst_port_callback(void *param, void *config)
85 {
86  struct rmax_stream_config *cfg = (struct rmax_stream_config *)config;
87  int port = *(int *)param;
88 
89  if (port <= 0 || port > 65535) {
90  DOCA_LOG_ERR("Invalid destination port: %d", port);
92  }
93  cfg->dst_port = port;
94  return DOCA_SUCCESS;
95 }
96 
97 /*
98  * ARGP Callback - Handle destination IP address parameter
99  *
100  * @param [in]: Input parameter
101  * @config [in/out]: Program configuration context
102  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
103  */
104 static doca_error_t dst_ip_callback(void *param, void *config)
105 {
106  struct rmax_stream_config *cfg = (struct rmax_stream_config *)config;
107  char *ip_addr_str = (char *)param;
108 
109  if (inet_pton(AF_INET, ip_addr_str, &cfg->dst_ip.s_addr) != 1) {
110  DOCA_LOG_ERR("Invalid destination IP address: %s", ip_addr_str);
112  }
113  return DOCA_SUCCESS;
114 }
115 
117 {
119  struct doca_argp_param *pci_param;
120  struct doca_argp_param *src_ip_param;
121  struct doca_argp_param *dst_ip_param;
122  struct doca_argp_param *dst_port_param;
123 
124  result = doca_argp_param_create(&pci_param);
125  if (result != DOCA_SUCCESS) {
126  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
127  return result;
128  }
129  doca_argp_param_set_short_name(pci_param, "p");
130  doca_argp_param_set_long_name(pci_param, "pci-addr");
131  doca_argp_param_set_description(pci_param, "DOCA device PCI address");
134  result = doca_argp_register_param(pci_param);
135  if (result != DOCA_SUCCESS) {
136  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
137  return result;
138  }
139 
140  result = doca_argp_param_create(&src_ip_param);
141  if (result != DOCA_SUCCESS) {
142  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
143  return result;
144  }
145  doca_argp_param_set_short_name(src_ip_param, "s");
146  doca_argp_param_set_long_name(src_ip_param, "src-ip");
147  doca_argp_param_set_description(src_ip_param, "source IP address");
150  doca_argp_param_set_mandatory(src_ip_param);
151  result = doca_argp_register_param(src_ip_param);
152  if (result != DOCA_SUCCESS) {
153  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
154  return result;
155  }
156 
157  result = doca_argp_param_create(&dst_ip_param);
158  if (result != DOCA_SUCCESS) {
159  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
160  return result;
161  }
162  doca_argp_param_set_short_name(dst_ip_param, "d");
163  doca_argp_param_set_long_name(dst_ip_param, "dst-ip");
164  doca_argp_param_set_description(dst_ip_param, "destination IP address");
167  doca_argp_param_set_mandatory(dst_ip_param);
168  result = doca_argp_register_param(dst_ip_param);
169  if (result != DOCA_SUCCESS) {
170  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
171  return result;
172  }
173 
174  result = doca_argp_param_create(&dst_port_param);
175  if (result != DOCA_SUCCESS) {
176  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
177  return result;
178  }
179  doca_argp_param_set_short_name(dst_port_param, "P");
180  doca_argp_param_set_long_name(dst_port_param, "dst-port");
181  doca_argp_param_set_description(dst_port_param, "destination port");
184  result = doca_argp_register_param(dst_port_param);
185  if (result != DOCA_SUCCESS) {
186  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
187  return result;
188  }
189 
190  return DOCA_SUCCESS;
191 }
192 
193 /*
194  * Free callback - free doca_buf allocated pointer
195  *
196  * @addr [in]: Memory range pointer
197  * @len [in]: Memory range length
198  * @opaque [in]: An opaque pointer passed to iterator
199  */
200 static void free_callback(void *addr, size_t len, void *opaque)
201 {
202  (void)len;
203  (void)opaque;
204  free(addr);
205 }
206 
207 doca_error_t rmax_flow_set_attributes(struct rmax_stream_config *config, struct doca_rmax_flow *flow)
208 {
210 
211  result = doca_rmax_flow_set_src_ip(flow, &config->src_ip);
212  if (result != DOCA_SUCCESS)
213  return result;
214 
215  result = doca_rmax_flow_set_dst_ip(flow, &config->dst_ip);
216  if (result != DOCA_SUCCESS)
217  return result;
218 
219  result = doca_rmax_flow_set_dst_port(flow, config->dst_port);
220  if (result != DOCA_SUCCESS)
221  return result;
222 
223  return result;
224 }
225 
226 doca_error_t rmax_stream_set_attributes(struct doca_rmax_in_stream *stream, struct rmax_stream_config *config)
227 {
228  size_t num_buffers = (config->hdr_size > 0) ? 2 : 1;
229  uint16_t pkt_size[MAX_BUFFERS];
231 
232  /* fill stream parameters */
233  if (config->scatter_all)
234  result = doca_rmax_in_stream_set_scatter_type_raw(stream);
235  else
236  result = doca_rmax_in_stream_set_scatter_type_ulp(stream);
237  if (result != DOCA_SUCCESS)
238  return result;
239 
240  result = doca_rmax_in_stream_set_elements_count(stream, config->num_elements);
241  if (result != DOCA_SUCCESS)
242  return result;
243 
244  if (num_buffers == 1)
245  pkt_size[0] = config->data_size;
246  else {
247  /* Header-Data Split mode */
248  pkt_size[0] = config->hdr_size;
249  pkt_size[1] = config->data_size;
250  }
251 
252  result = doca_rmax_in_stream_set_memblks_count(stream, num_buffers);
253  if (result != DOCA_SUCCESS)
254  return result;
255 
256  result = doca_rmax_in_stream_memblk_desc_set_min_size(stream, pkt_size);
257  if (result != DOCA_SUCCESS)
258  return result;
259 
260  result = doca_rmax_in_stream_memblk_desc_set_max_size(stream, pkt_size);
261  if (result != DOCA_SUCCESS)
262  return result;
263 
264  return DOCA_SUCCESS;
265 }
266 
268 {
270 
271  /* allow receiving rmax events using progress engine */
273  if (result != DOCA_SUCCESS)
274  return result;
275 
276  /* start the rmax context */
278  if (result != DOCA_SUCCESS)
279  return result;
280 
281  return DOCA_SUCCESS;
282 }
283 
285  struct doca_rmax_in_stream *stream,
286  struct rmax_stream_config *config,
287  struct doca_buf **buffer,
288  uint16_t *stride_size)
289 {
290  size_t page_size = sysconf(_SC_PAGESIZE);
291  size_t num_buffers = (config->hdr_size > 0) ? 2 : 1;
292  size_t size[MAX_BUFFERS] = {0, 0};
293  char *ptr_memory = NULL;
294  void *ptr[MAX_BUFFERS];
296 
297  /* query buffer size */
298  result = doca_rmax_in_stream_get_memblk_size(stream, size);
299  if (result != DOCA_SUCCESS) {
300  DOCA_LOG_ERR("Failed to get memory block size: %s", doca_error_get_descr(result));
301  return result;
302  }
303 
304  /* query stride size */
305  result = doca_rmax_in_stream_get_memblk_stride_size(stream, stride_size);
306  if (result != DOCA_SUCCESS) {
307  DOCA_LOG_ERR("Failed to get memory block stride size: %s", doca_error_get_descr(result));
308  return result;
309  }
310 
311  /* allocate memory */
312  ptr_memory = aligned_alloc(page_size, size[0] + size[1]);
313  if (ptr_memory == NULL)
314  return DOCA_ERROR_NO_MEMORY;
315 
316  result = doca_mmap_set_memrange(state->core_objects.src_mmap, ptr_memory, size[0] + size[1]);
317  if (result != DOCA_SUCCESS) {
318  DOCA_LOG_ERR("Failed to set mmap memory range, ptr %p, size %zu: %s",
319  ptr_memory,
320  size[0] + size[1],
322  return result;
323  }
324 
326  if (result != DOCA_SUCCESS) {
327  DOCA_LOG_ERR("Failed to set mmap free callback: %s", doca_error_get_descr(result));
328  return result;
329  }
330 
332  if (result != DOCA_SUCCESS) {
333  DOCA_LOG_ERR("Failed to start mmap: %s", doca_error_get_descr(result));
334  return result;
335  }
336 
337  if (num_buffers == 1) {
338  ptr[0] = ptr_memory;
339  } else {
340  ptr[0] = ptr_memory; /* header */
341  ptr[1] = ptr_memory + size[0]; /* data */
342  }
343 
344  /* build memory buffer chain */
345  for (size_t i = 0; i < num_buffers; ++i) {
346  struct doca_buf *buf;
347 
349  state->core_objects.src_mmap,
350  ptr[i],
351  size[i],
352  &buf);
353  if (result != DOCA_SUCCESS)
354  return result;
355  if (i == 0)
356  *buffer = buf;
357  else {
358  /* chain buffers */
359  result = doca_buf_chain_list(*buffer, buf);
360  if (result != DOCA_SUCCESS)
361  return result;
362  }
363  }
364 
365  /* set memory buffer(s) */
366  result = doca_rmax_in_stream_set_memblk(stream, *buffer);
367  if (result != DOCA_SUCCESS) {
368  DOCA_LOG_ERR("Failed to set stream memory block(s): %s", doca_error_get_descr(result));
369  return result;
370  }
371 
372  return result;
373 }
374 
376  struct doca_rmax_in_stream *stream,
377  struct doca_rmax_flow *flow,
378  struct doca_buf *buf)
379 {
381 
382  if (buf != NULL) {
384  if (result != DOCA_SUCCESS)
385  DOCA_LOG_WARN("Failed to remove buffers: %s", doca_error_get_descr(result));
386  }
387 
388  result = doca_rmax_flow_destroy(flow);
389  if (result != DOCA_SUCCESS)
390  DOCA_LOG_ERR("Failed to destroy DOCA Rmax flow: %s", doca_error_get_descr(result));
391 
392  if (state->core_objects.ctx != NULL) {
394  if (result != DOCA_SUCCESS)
395  DOCA_LOG_ERR("Failed to stop DOCA Rmax in stream context: %s", doca_error_get_descr(result));
396  }
397 
398  /* destroy stream */
399  result = doca_rmax_in_stream_destroy(stream);
400  if (result != DOCA_SUCCESS)
401  DOCA_LOG_ERR("Failed to destroy the stream: %s", doca_error_get_descr(result));
402 
404  if (result != DOCA_SUCCESS)
405  DOCA_LOG_ERR("Failed to destroy DOCA core related objects: %s", doca_error_get_descr(result));
406 
407  result = doca_rmax_release();
408  if (result != DOCA_SUCCESS)
409  DOCA_LOG_ERR("Failed to destroy the DOCA Rivermax: %s", doca_error_get_descr(result));
410 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
doca_error_t destroy_core_objects(struct program_core_objects *state)
Definition: common.c:392
uintptr_t addr
uint64_t len
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
@ DOCA_ARGP_TYPE_INT
Definition: doca_argp.h:57
static doca_error_t doca_buf_inventory_buf_get_by_addr(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *addr, size_t len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by addr & len argume...
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_chain_list(struct doca_buf *list1, struct doca_buf *list2)
Append list2 to list1.
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_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
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_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_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
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_mmap_set_free_cb(struct doca_mmap *mmap, doca_mmap_memrange_free_cb_t *free_cb, void *opaque)
Set callback that will free the memory range when destroying 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.
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
void * aligned_alloc(size_t alignment, size_t size)
Definition: os_utils.cpp:126
void rmax_create_stream_cleanup(struct rmax_program_state *state, struct doca_rmax_in_stream *stream, struct doca_rmax_flow *flow, struct doca_buf *buf)
Definition: rmax_common.c:375
doca_error_t rmax_stream_allocate_buf(struct rmax_program_state *state, struct doca_rmax_in_stream *stream, struct rmax_stream_config *config, struct doca_buf **buffer, uint16_t *stride_size)
Definition: rmax_common.c:284
DOCA_LOG_REGISTER(rmax_common)
static doca_error_t pci_address_callback(void *param, void *config)
Definition: rmax_common.c:42
doca_error_t rmax_stream_set_attributes(struct doca_rmax_in_stream *stream, struct rmax_stream_config *config)
Definition: rmax_common.c:226
static doca_error_t src_ip_callback(void *param, void *config)
Definition: rmax_common.c:65
doca_error_t rmax_flow_set_attributes(struct rmax_stream_config *config, struct doca_rmax_flow *flow)
Definition: rmax_common.c:207
static doca_error_t dst_ip_callback(void *param, void *config)
Definition: rmax_common.c:104
doca_error_t register_create_stream_params(void)
Definition: rmax_common.c:116
doca_error_t rmax_stream_start(struct rmax_program_state *state)
Definition: rmax_common.c:267
static doca_error_t dst_port_callback(void *param, void *config)
Definition: rmax_common.c:84
static void free_callback(void *addr, size_t len, void *opaque)
Definition: rmax_common.c:200
#define MAX_BUFFERS
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_ctx * ctx
Definition: common.h:50
struct program_core_objects core_objects
Definition: rmax_common.h:71
struct in_addr dst_ip
Definition: rmax_common.h:61
uint16_t data_size
Definition: rmax_common.h:57
uint32_t num_elements
Definition: rmax_common.h:58
char pci_address[DOCA_DEVINFO_PCI_ADDR_SIZE]
Definition: rmax_common.h:52
struct in_addr src_ip
Definition: rmax_common.h:62