NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
eth_l2_fwd_core.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 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 <inttypes.h>
27 #include <time.h>
28 
29 #include <doca_buf.h>
30 #include <doca_common_defines.h>
31 #include <doca_ctx.h>
32 #include <doca_eth_rxq.h>
34 #include <doca_eth_txq.h>
36 #include <doca_log.h>
37 #include <doca_pe.h>
38 
39 #include <samples/common.h>
41 
42 #include "eth_l2_fwd_core.h"
43 
44 #define NS_PER_SEC 1E9 /* Nano-seconds per second */
45 #define STATS_MAX_BUFF_SIZE 1024 /* Max buffer size to hold statistics string */
46 
47 DOCA_LOG_REGISTER(ETH_L2_FWD : Core);
48 
49 /* Flag for forcing the application to stop and terminate gracefully */
50 static bool force_app_stop = false;
51 
52 static uint32_t total_forwardings = 0;
53 
54 /* Global variables with default values that may change according to the app's input args */
55 uint32_t max_forwardings = 0;
56 
57 /* Ethernet L2 Forwarding application device statistics */
59  uint64_t rx_pkts; /* Number of RX packets that were handled without being dropped */
60  uint64_t rx_dropped; /* Number of RX packets that were dropped (by SW) */
61  uint64_t total_tx_pkts; /* Total number of TX packets */
62 };
63 
64 /* Ethernet L2 Forwarding application statistics */
66  struct eth_l2_fwd_dev_stats dev1_stats; /* Device 1 statistics */
67  struct eth_l2_fwd_dev_stats dev2_stats; /* Device 2 statistics */
68  uint64_t initial_time_ns; /* Time (in nanoseconds) at the beginning of the forwarding phase */
69 };
70 
71 static struct eth_l2_fwd_stats stats = {.dev1_stats.rx_pkts = 0,
72  .dev1_stats.rx_dropped = 0,
73  .dev1_stats.total_tx_pkts = 0,
74  .dev2_stats.rx_pkts = 0,
75  .dev2_stats.rx_dropped = 0,
76  .dev2_stats.total_tx_pkts = 0};
77 
78 /*
79  * Prints the forwarding statistics of the running application instance
80  *
81  * @note By default, this function is used only once at the end of the forwarding phase,
82  * but is designed to handle multiple calls during the application's run as well
83  *
84  */
85 static void eth_l2_fwd_show_stats(void)
86 {
87  struct timespec t;
88  static uint64_t prev_total_rx_pkts_dev1 = 0;
89  static uint64_t prev_total_rx_pkts_dev2 = 0;
90  static uint64_t prev_total_tx_pkts_dev1 = 0;
91  static uint64_t prev_total_tx_pkts_dev2 = 0;
92  static uint64_t prev_time_ns = 0;
93  size_t buff_size = STATS_MAX_BUFF_SIZE;
94  char buff[buff_size];
95  char *buff_cursor = buff;
96  int curr_buff_offset = 0;
97 
98  if (clock_gettime(CLOCK_REALTIME, &t) != 0) {
99  DOCA_LOG_ERR("Failed to show statistics: Failed to get time specification with clock_gettime()");
100  return;
101  }
102 
103  if (prev_time_ns == 0)
104  prev_time_ns = stats.initial_time_ns;
105 
106  uint64_t curr_time_ns = (uint64_t)t.tv_nsec + (uint64_t)t.tv_sec * NS_PER_SEC;
107  uint64_t diff_ns = curr_time_ns - prev_time_ns;
108 
109  uint64_t dev1_total_rx_pkts = stats.dev1_stats.rx_pkts + stats.dev1_stats.rx_dropped;
110  uint64_t dev1_diff_total_pkts_rx = dev1_total_rx_pkts - prev_total_rx_pkts_dev1;
111  uint64_t dev1_diff_pkts_tx = stats.dev1_stats.total_tx_pkts - prev_total_tx_pkts_dev1;
112 
113  uint64_t dev2_total_rx_pkts = stats.dev2_stats.rx_pkts + stats.dev2_stats.rx_dropped;
114  uint64_t dev2_diff_total_pkts_rx = dev2_total_rx_pkts - prev_total_rx_pkts_dev2;
115  uint64_t dev2_diff_pkts_tx = stats.dev2_stats.total_tx_pkts - prev_total_tx_pkts_dev2;
116 
117  uint64_t dev1_rx_pps = ((double)(dev1_diff_total_pkts_rx) / diff_ns) * NS_PER_SEC;
118  uint64_t dev1_tx_pps = ((double)(dev1_diff_pkts_tx) / diff_ns) * NS_PER_SEC;
119 
120  uint64_t dev2_rx_pps = ((double)(dev2_diff_total_pkts_rx) / diff_ns) * NS_PER_SEC;
121  uint64_t dev2_tx_pps = ((double)(dev2_diff_pkts_tx) / diff_ns) * NS_PER_SEC;
122 
123  curr_buff_offset += snprintf(
124  buff_cursor,
125  buff_size,
126  "\n**************************** Forward statistics for device 1 *****************************\n");
127  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
128  buff_size - curr_buff_offset,
129  "RX-packets: %-17" PRIu64 " RX-SW-dropped: %-17" PRIu64 " RX-total: %-17" PRIu64
130  "\n",
133  dev1_total_rx_pkts);
134  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
135  buff_size - curr_buff_offset,
136  "TX-packets: %-" PRIu64 "\n",
138  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
139  buff_size - curr_buff_offset,
140  "\nThroughput (since last call)\n");
141  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
142  buff_size - curr_buff_offset,
143  "RX-pps: %-" PRIu64 "\n",
144  dev1_rx_pps);
145  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
146  buff_size - curr_buff_offset,
147  "TX-pps: %-" PRIu64 "\n",
148  dev1_tx_pps);
149  curr_buff_offset += snprintf(
150  buff_cursor + curr_buff_offset,
151  buff_size - curr_buff_offset,
152  "******************************************************************************************\n");
153 
154  curr_buff_offset += snprintf(
155  buff_cursor + curr_buff_offset,
156  buff_size - curr_buff_offset,
157  "\n**************************** Forward statistics for device 2 *****************************\n");
158  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
159  buff_size - curr_buff_offset,
160  "RX-packets: %-17" PRIu64 " RX-SW-dropped: %-17" PRIu64 " RX-total: %-17" PRIu64
161  "\n",
164  dev2_total_rx_pkts);
165  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
166  buff_size - curr_buff_offset,
167  "TX-packets: %-" PRIu64 "\n",
169  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
170  buff_size - curr_buff_offset,
171  "\nThroughput (since last call)\n");
172  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
173  buff_size - curr_buff_offset,
174  "RX-pps: %-" PRIu64 "\n",
175  dev2_rx_pps);
176  curr_buff_offset += snprintf(buff_cursor + curr_buff_offset,
177  buff_size - curr_buff_offset,
178  "TX-pps: %-" PRIu64 "\n",
179  dev2_tx_pps);
180  snprintf(buff_cursor + curr_buff_offset,
181  buff_size - curr_buff_offset,
182  "******************************************************************************************");
183 
184  DOCA_LOG_INFO("%s", buff);
185 
186  prev_total_rx_pkts_dev1 = dev1_total_rx_pkts;
187  prev_total_tx_pkts_dev1 = stats.dev1_stats.total_tx_pkts;
188 
189  prev_total_rx_pkts_dev2 = dev2_total_rx_pkts;
190  prev_total_tx_pkts_dev2 = stats.dev2_stats.total_tx_pkts;
191 
192  prev_time_ns = curr_time_ns;
193 }
194 
195 /*
196  * Function that checks if a device have the required TXQ/RXQ capabilities
197  * to be used by open_doca_device_with_ibdev_name()
198  *
199  * @devinfo [in]: DOCA device info to query for capabilities
200  * @return: DOCA_SUCCESS on success and DOCA_ERROR_... otherwise
201  */
202 static doca_error_t check_device_caps(struct doca_devinfo *devinfo)
203 {
205 
206  result =
208  if (result != DOCA_SUCCESS)
209  return result;
210 
214  if (result != DOCA_SUCCESS)
215  return result;
216 
217  return DOCA_SUCCESS;
218 }
219 
228 static doca_error_t create_mmap(struct doca_dev *dev1, struct doca_dev *dev2, struct mmap_resources *mmap_res)
229 {
231 
232  mmap_res->mmap_buffer = (uint8_t *)malloc(mmap_res->mmap_size);
233  if (mmap_res->mmap_buffer == NULL) {
234  DOCA_LOG_ERR("Failed to allocate memory for mmap's buffer");
235  return DOCA_ERROR_NO_MEMORY;
236  }
237 
238  result = doca_mmap_create(&mmap_res->mmap);
239  if (result != DOCA_SUCCESS) {
240  DOCA_LOG_ERR("Failed to create mmap: %s", doca_error_get_descr(result));
241  return result;
242  }
243 
245  if (result != DOCA_SUCCESS) {
246  DOCA_LOG_ERR("Failed to set memory permissions: %s", doca_error_get_descr(result));
247  return result;
248  }
249 
250  result = doca_mmap_set_memrange(mmap_res->mmap, mmap_res->mmap_buffer, mmap_res->mmap_size);
251  if (result != DOCA_SUCCESS) {
252  DOCA_LOG_ERR("Failed to set memory range: %s", doca_error_get_descr(result));
253  return result;
254  }
255 
256  result = doca_mmap_set_max_num_devices(mmap_res->mmap, 2);
257  if (result != DOCA_SUCCESS) {
258  DOCA_LOG_ERR("Failed to set mmap max number of devices: %s", doca_error_get_descr(result));
259  return result;
260  }
261 
262  result = doca_mmap_add_dev(mmap_res->mmap, dev1);
263  if (result != DOCA_SUCCESS) {
264  DOCA_LOG_ERR("Failed to add device 1 to mmap: %s", doca_error_get_descr(result));
265  return result;
266  }
267  result = doca_mmap_add_dev(mmap_res->mmap, dev2);
268  if (result != DOCA_SUCCESS) {
269  DOCA_LOG_ERR("Failed to add device 2 to mmap: %s", doca_error_get_descr(result));
270  return result;
271  }
272 
273  result = doca_mmap_start(mmap_res->mmap);
274  if (result != DOCA_SUCCESS) {
275  DOCA_LOG_ERR("Failed to start mmap: %s", doca_error_get_descr(result));
276  return result;
277  }
278 
279  return DOCA_SUCCESS;
280 }
281 
282 /*
283  * ETH RXQ managed receive event batch successful completion callback for device 1
284  *
285  * @event_batch_managed_recv [in]: The managed receive event batch
286  * @events_number [in]: Number of retrieved events, each representing a single received packet
287  * @event_batch_user_data [in]: User provided data, holding a pointer to the ETH TXQ context to forward the packets
288  * with
289  * @status [in]: Status of retrieved event batch
290  * @pkt_array [in]: Array of doca_bufs containing the received packets
291  */
292 static void rx_success_cb1(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv,
293  uint16_t events_number,
294  union doca_data event_batch_user_data,
295  doca_error_t status,
296  struct doca_buf **pkt_array)
297 {
298  /* Unused parameters */
299  (void)status;
300  (void)event_batch_managed_recv;
301 
303  struct doca_eth_txq *eth_txq = (struct doca_eth_txq *)(event_batch_user_data.ptr);
304  union doca_data send_task_data;
305  struct doca_buf **batch_pkt_array;
306  union doca_data *task_user_data_array;
307  struct doca_task_batch *task_batch_send;
308 
309  send_task_data.ptr = pkt_array; // This "trick" allows freeing the array when tx_success_cb is called
310 
312  events_number,
313  send_task_data,
314  &batch_pkt_array,
315  &task_user_data_array,
316  &task_batch_send);
318  stats.dev1_stats.rx_dropped += events_number;
320  return;
321  }
322 
323  memcpy(batch_pkt_array, pkt_array, sizeof(struct doca_buf *) * events_number);
324 
325  /* Return value is not checked since this is data-path (previous call result check prevents incorrect behavior)
326  When debugging, the return value should be checked */
327  (void)doca_task_batch_submit(task_batch_send);
328 
329  stats.dev1_stats.rx_pkts += events_number;
330 }
331 
332 /*
333  * ETH RXQ managed receive event batch successful completion callback for device 2
334  *
335  * @event_batch_managed_recv [in]: The managed receive event batch
336  * @events_number [in]: Number of retrieved events, each representing a single received packet
337  * @event_batch_user_data [in]: User provided data, holding a pointer to the ETH TXQ context to forward the packets
338  * with
339  * @status [in]: Status of retrieved event batch
340  * @pkt_array [in]: Array of doca_bufs containing the received packets
341  */
342 static void rx_success_cb2(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv,
343  uint16_t events_number,
344  union doca_data event_batch_user_data,
345  doca_error_t status,
346  struct doca_buf **pkt_array)
347 {
348  /* Unused parameters */
349  (void)status;
350  (void)event_batch_managed_recv;
351 
353  struct doca_eth_txq *eth_txq = (struct doca_eth_txq *)(event_batch_user_data.ptr);
354  union doca_data send_task_data;
355  struct doca_buf **batch_pkt_array;
356  union doca_data *task_user_data_array;
357  struct doca_task_batch *task_batch_send;
358 
359  send_task_data.ptr = pkt_array; // This "trick" allows freeing the array when tx_success_cb is called
360 
362  events_number,
363  send_task_data,
364  &batch_pkt_array,
365  &task_user_data_array,
366  &task_batch_send);
367  if (result != DOCA_SUCCESS) {
368  stats.dev1_stats.rx_dropped += events_number;
370  return;
371  }
372 
373  memcpy(batch_pkt_array, pkt_array, sizeof(struct doca_buf *) * events_number);
374 
375  /* Return value is not checked since this is data-path (previous call result check prevents incorrect behavior)
376  When debugging, the return value should be checked */
377  (void)doca_task_batch_submit(task_batch_send);
378 
379  stats.dev2_stats.rx_pkts += events_number;
380 }
381 
382 /*
383  * A common ETH RXQ managed receive event batch error completion callback
384  *
385  * @event_batch_managed_recv [in]: The managed receive event batch
386  * @events_number [in]: Number of retrieved events, each representing a single received packet
387  * @event_batch_user_data [in]: User provided data, holding a pointer to the ETH TXQ context to forward the packets
388  * with
389  * @status [in]: Status of retrieved event batch
390  * @pkt_array [in]: Array of doca_bufs containing the received packets
391  */
392 static void rx_error_cb(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv,
393  uint16_t events_number,
394  union doca_data event_batch_user_data,
395  doca_error_t status,
396  struct doca_buf **pkt_array)
397 {
398  /* Unused parameters */
399  (void)events_number;
400  (void)pkt_array;
401  (void)event_batch_managed_recv;
402 
403  struct doca_eth_txq *eth_txq = (struct doca_eth_txq *)(event_batch_user_data.ptr);
404  struct doca_ctx *eth_txq_ctx = doca_eth_txq_as_doca_ctx(eth_txq);
405  enum doca_ctx_states ctx_state;
406  (void)doca_ctx_get_state(eth_txq_ctx, &ctx_state);
407 
408  /* If the context is stopping then this callback was expectedly called during a draining process */
409  if (ctx_state != DOCA_CTX_STATE_STOPPING)
410  DOCA_LOG_ERR("Failed to receive packets: %s", doca_error_get_name(status));
411 
412  force_app_stop = true;
413 }
414 
415 /*
416  * ETH TXQ send task batch successful completion callback for device 1
417  *
418  * @task_batch [in]: Completed task batch
419  * @tasks_num [in]: Task number associated with task batch
420  * @ctx_user_data [in]: Context's user provided data
421  * @task_batch_user_data [in]: Task batch user provided data, holding the packets array from the RX success callback
422  * @task_user_data_array [in]: Array of user provided data, each used for identifying each task behind task batch
423  * @pkt_array [in]: Array of packets, each associated to one send task that's part of the send task batch
424  * @status_array [in]: Array of status, each associated to one send task that's part of the send task batch
425  */
426 static void tx_success_cb1(struct doca_task_batch *task_batch,
427  uint16_t tasks_num,
428  union doca_data ctx_user_data,
429  union doca_data task_batch_user_data,
430  union doca_data *task_user_data_array,
431  struct doca_buf **pkt_array,
432  doca_error_t *status_array)
433 {
434  /* Unused parameters */
435  (void)tasks_num;
436  (void)ctx_user_data;
437  (void)task_user_data_array;
438  (void)pkt_array;
439  (void)status_array;
440 
441  struct doca_buf **pkt_array_handle = (struct doca_buf **)task_batch_user_data.ptr;
443 
444  doca_task_batch_free(task_batch);
445 
447  stats.dev1_stats.total_tx_pkts += tasks_num;
448 }
449 
450 /*
451  * ETH TXQ send task batch successful completion callback for device 2
452  *
453  * @task_batch [in]: Completed task batch
454  * @tasks_num [in]: Task number associated with task batch
455  * @ctx_user_data [in]: Context's user provided data
456  * @task_batch_user_data [in]: Task batch user provided data, holding the packets array from the RX success callback
457  * @task_user_data_array [in]: Array of user provided data, each used for identifying each task behind task batch
458  * @pkt_array [in]: Array of packets, each associated to one send task that's part of the send task batch
459  * @status_array [in]: Array of status, each associated to one send task that's part of the send task batch
460  */
461 static void tx_success_cb2(struct doca_task_batch *task_batch,
462  uint16_t tasks_num,
463  union doca_data ctx_user_data,
464  union doca_data task_batch_user_data,
465  union doca_data *task_user_data_array,
466  struct doca_buf **pkt_array,
467  doca_error_t *status_array)
468 {
469  /* Unused parameters */
470  (void)tasks_num;
471  (void)ctx_user_data;
472  (void)task_user_data_array;
473  (void)pkt_array;
474  (void)status_array;
475 
476  struct doca_buf **pkt_array_handle = (struct doca_buf **)task_batch_user_data.ptr;
478 
479  doca_task_batch_free(task_batch);
480 
482  stats.dev2_stats.total_tx_pkts += tasks_num;
483 }
484 
485 /*
486  * A common ETH TXQ send task batch error completion callback
487  *
488  * @task_batch [in]: Completed task batch
489  * @tasks_num [in]: Task number associated with task batch
490  * @ctx_user_data [in]: Context's user provided data
491  * @task_batch_user_data [in]: Task batch user provided data, holding the packets array from the RX success callback
492  * @task_user_data_array [in]: Array of user provided data, each used for identifying each task behind task batch
493  * @pkt_array [in]: Array of packets, each associated to one send task that's part of the send task batch
494  * @status_array [in]: Array of status, each associated to one send task that's part of the send task batch
495  */
496 static void tx_error_cb(struct doca_task_batch *task_batch,
497  uint16_t tasks_num,
498  union doca_data ctx_user_data,
499  union doca_data task_batch_user_data,
500  union doca_data *task_user_data_array,
501  struct doca_buf **pkt_array,
502  doca_error_t *status_array)
503 {
504  /* Unused parameters */
505  (void)tasks_num;
506  (void)ctx_user_data;
507  (void)task_user_data_array;
508  (void)pkt_array;
509  (void)status_array;
510 
511  struct doca_ctx *eth_txq_ctx = doca_task_batch_get_ctx(task_batch);
512  enum doca_ctx_states ctx_state;
513  (void)doca_ctx_get_state(eth_txq_ctx, &ctx_state);
514 
515  /* If the context is stopping then this callback was expectedly called during a draining process */
516  if (ctx_state != DOCA_CTX_STATE_STOPPING)
517  DOCA_LOG_ERR("Failed to send packets");
518 
519  struct doca_buf **pkt_array_handle = (struct doca_buf **)task_batch_user_data.ptr;
521 
522  doca_task_batch_free(task_batch);
523 
524  force_app_stop = true;
525 }
526 
527 /*
528  * Initialize (create and start) an ETH RXQ context
529  *
530  * @cfg [in]: Ethernet L2 Forwarding application configuration to use for context creation
531  * @dev_resrc [in]: Resources of the device to create the ETH RXQ context with
532  * @pe [in]: DOCA progress engine to which the ETH RXQ context will be connected
533  * @rx_success_cb [in]: RXQ event batch managed receive successful completion callback to set in registration
534  * @data [in]: Pointer to data to save as user_data
535  * @return: DOCA_SUCCESS on success and DOCA_ERROR_... otherwise
536  */
538  struct eth_l2_fwd_dev_resources *dev_resrc,
539  struct doca_pe *pe,
541  void *data)
542 {
543  union doca_data user_data;
545  uint32_t max_burst_size, max_pkt_size;
546 
548  if (result != DOCA_SUCCESS) {
549  DOCA_LOG_ERR("Failed to get RXQ max burst size capability: %s", doca_error_get_descr(result));
550  return result;
551  }
552 
553  if (max_burst_size < cfg->max_burst_size) {
554  DOCA_LOG_ERR("Failed to create ETH RXQ context: max burst size to set is to big");
555  return DOCA_ERROR_TOO_BIG;
556  }
557 
559  if (result != DOCA_SUCCESS) {
560  DOCA_LOG_ERR("Failed to get RXQ max packet size capability: %s", doca_error_get_descr(result));
561  return result;
562  }
563 
564  if (max_pkt_size < cfg->max_pkt_size) {
565  DOCA_LOG_ERR("Failed to create ETH RXQ context: max packet size to set is to big");
566  return DOCA_ERROR_TOO_BIG;
567  }
568 
569  result = doca_eth_rxq_create(dev_resrc->mlxdev, cfg->max_burst_size, cfg->max_pkt_size, &dev_resrc->eth_rxq);
570  if (result != DOCA_SUCCESS) {
571  DOCA_LOG_ERR("Failed to create ETH RXQ context: %s", doca_error_get_descr(result));
572  return result;
573  }
574 
576  if (result != DOCA_SUCCESS) {
577  DOCA_LOG_ERR("Failed to set ETH RXQ type: %s", doca_error_get_descr(result));
578  return result;
579  }
580 
582  dev_resrc->mmap_resrc.mmap,
583  0,
584  dev_resrc->mmap_resrc.mmap_size);
585  if (result != DOCA_SUCCESS) {
586  DOCA_LOG_ERR("Failed to set packet buffer: %s", doca_error_get_descr(result));
587  return result;
588  }
589 
590  user_data.ptr = data;
594  user_data,
596  rx_error_cb);
597  if (result != DOCA_SUCCESS) {
598  DOCA_LOG_ERR("Failed to register managed receive event batch: %s", doca_error_get_descr(result));
599  return result;
600  }
601 
602  dev_resrc->eth_rxq_ctx = doca_eth_rxq_as_doca_ctx(dev_resrc->eth_rxq);
603  if (dev_resrc->eth_rxq_ctx == NULL) {
604  DOCA_LOG_ERR("Failed to retrieve DOCA ETH RXQ context as DOCA context: %s",
606  return result;
607  }
608 
609  result = doca_pe_connect_ctx(pe, dev_resrc->eth_rxq_ctx);
610  if (result != DOCA_SUCCESS) {
611  DOCA_LOG_ERR("Failed to set PE for ETH RXQ context: %s", doca_error_get_descr(result));
612  return result;
613  }
614 
615  result = doca_ctx_start(dev_resrc->eth_rxq_ctx);
616  if (result != DOCA_SUCCESS) {
617  DOCA_LOG_ERR("Failed to start DOCA context: %s", doca_error_get_descr(result));
618  return result;
619  }
620 
622  if (result != DOCA_SUCCESS) {
623  DOCA_LOG_ERR("Failed to get flow queue ID of RXQ: %s", doca_error_get_descr(result));
624  return result;
625  }
626 
627  return DOCA_SUCCESS;
628 }
629 
630 /*
631  * Initialize (create and start) an ETH TXQ context
632  *
633  * @cfg [in]: Ethernet L2 Forwarding application configuration to use for context creation and configuration
634  * @dev_resrc [in]: Resources of the device to create the ETH TXQ context with
635  * @pe [in]: DOCA progress engine to which the ETH TXQ context will be connected
636  * @tx_success_cb [in]: TXQ task batch send successful completion callback to set in configuration
637  * @return: DOCA_SUCCESS on success and DOCA_ERROR_... otherwise
638  */
640  struct eth_l2_fwd_dev_resources *dev_resrc,
641  struct doca_pe *pe,
643 {
645  uint32_t max_burst_size;
646 
647  result = doca_eth_txq_cap_get_max_burst_size(doca_dev_as_devinfo(dev_resrc->mlxdev), 1, 0, &max_burst_size);
648  if (result != DOCA_SUCCESS) {
649  DOCA_LOG_ERR("Failed to get TXQ max burst size capability: %s", doca_error_get_descr(result));
650  return result;
651  }
652 
653  if (max_burst_size < cfg->max_burst_size) {
654  DOCA_LOG_ERR("Failed to create ETH TXQ context: max burst size to set is to big");
655  return DOCA_ERROR_TOO_BIG;
656  }
657 
658  result = doca_eth_txq_create(dev_resrc->mlxdev, cfg->max_burst_size, &dev_resrc->eth_txq);
659  if (result != DOCA_SUCCESS) {
660  DOCA_LOG_ERR("Failed to create ETH TXQ context: %s", doca_error_get_descr(result));
661  return result;
662  }
663 
665  if (result != DOCA_SUCCESS) {
666  DOCA_LOG_ERR("Failed to set ETH TXQ type: %s", doca_error_get_descr(result));
667  return result;
668  }
669 
672  cfg->num_task_batches,
673  tx_success_cb,
674  tx_error_cb);
675  if (result != DOCA_SUCCESS) {
676  DOCA_LOG_ERR("Failed to configure send task: %s", doca_error_get_descr(result));
677  return result;
678  }
679 
680  dev_resrc->eth_txq_ctx = doca_eth_txq_as_doca_ctx(dev_resrc->eth_txq);
681  if (dev_resrc->eth_txq_ctx == NULL) {
682  DOCA_LOG_ERR("Failed to retrieve DOCA ETH TXQ context as DOCA context: %s",
684  return result;
685  }
686 
687  result = doca_pe_connect_ctx(pe, dev_resrc->eth_txq_ctx);
688  if (result != DOCA_SUCCESS) {
689  DOCA_LOG_ERR("Failed to set PE for ETH TXQ context: %s", doca_error_get_descr(result));
690  return result;
691  }
692 
693  result = doca_ctx_start(dev_resrc->eth_txq_ctx);
694  if (result != DOCA_SUCCESS) {
695  DOCA_LOG_ERR("Failed to start DOCA context: %s", doca_error_get_descr(result));
696  return result;
697  }
698 
699  return DOCA_SUCCESS;
700 }
701 
702 /*
703  * Forward packets
704  *
705  * @pe [in]: DOCA progress engine to run
706  * @return: DOCA_SUCCESS on success and DOCA_ERROR_... otherwise
707  */
708 static doca_error_t forward_pkts(struct doca_pe *pe)
709 {
710  struct timespec t;
711 
712  if (clock_gettime(CLOCK_REALTIME, &t) != 0) {
713  DOCA_LOG_ERR("Failed to get time specification with clock_gettime()");
714  return DOCA_ERROR_IO_FAILED;
715  }
716 
717  stats.initial_time_ns = (uint64_t)t.tv_nsec + (uint64_t)t.tv_sec * NS_PER_SEC;
718 
719  DOCA_LOG_INFO("Starting packets forwarding");
720 
721  /* Check if max forwardings was set to 0 and therefore there's no limit */
722  if (max_forwardings == 0) {
723  while (!force_app_stop)
724  (void)doca_pe_progress(pe);
725  } else {
727  (void)doca_pe_progress(pe);
728  }
729 
731 
732  DOCA_LOG_INFO("Finished packets forwarding");
733  return DOCA_SUCCESS;
734 }
735 
737 {
738  struct eth_rxq_flow_config flow_cfg;
740 
741  result = open_doca_device_with_ibdev_name((uint8_t *)cfg->mlxdev_name1,
742  strlen(cfg->mlxdev_name1),
744  &state->dev_resrc1.mlxdev);
745  if (result != DOCA_SUCCESS) {
746  DOCA_LOG_ERR("Failed to open the first device based on IB device name: %s", cfg->mlxdev_name1);
747  return result;
748  }
749 
750  result = open_doca_device_with_ibdev_name((uint8_t *)cfg->mlxdev_name2,
751  strlen(cfg->mlxdev_name2),
753  &state->dev_resrc2.mlxdev);
754  if (result != DOCA_SUCCESS) {
755  DOCA_LOG_ERR("Failed to open the second device based on IB device name: %s", cfg->mlxdev_name2);
756  return result;
757  }
758 
759  result = doca_pe_create(&state->pe);
760  if (result != DOCA_SUCCESS) {
761  DOCA_LOG_ERR("Failed to create DOCA progress engine: %s", doca_error_get_descr(result));
762  return result;
763  }
764 
765  uint32_t recommended_size;
767  cfg->pkts_recv_rate,
768  cfg->pkt_max_process_time,
769  cfg->max_pkt_size,
770  cfg->max_burst_size,
772  0,
773  0,
774  &recommended_size);
775  if (result != DOCA_SUCCESS) {
776  DOCA_LOG_ERR("Failed to estimate buffer size: %s", doca_error_get_descr(result));
777  return result;
778  }
779 
780  /* Check if forwarding from device 1 to device 2 is desired */
781  if (cfg->one_sided_fwd == 0 || cfg->one_sided_fwd == 1) {
782  state->dev_resrc1.mmap_resrc.mmap_size = recommended_size;
784  if (result != DOCA_SUCCESS) {
785  DOCA_LOG_ERR("Failed to create mmap for device 1: %s", doca_error_get_descr(result));
786  return result;
787  }
788 
790  if (result != DOCA_SUCCESS) {
791  DOCA_LOG_ERR("Failed to initialize DOCA flow port for device 1: %s",
793  return result;
794  }
795 
796  result = init_eth_txq_ctx(cfg, &state->dev_resrc2, state->pe, tx_success_cb2);
797  if (result != DOCA_SUCCESS) {
798  DOCA_LOG_ERR("Failed to initialize ETH TXQ context for device 2: %s",
800  return result;
801  }
802 
803  // Sending the second device's ETH TXQ context (pointer) to save as user_data
804  // and allow forwarding via completion callback (see rx_success_cb)
806  &state->dev_resrc1,
807  state->pe,
809  (void *)state->dev_resrc2.eth_txq);
810  if (result != DOCA_SUCCESS) {
811  DOCA_LOG_ERR("Failed to initialize ETH RXQ context for device 1: %s",
813  return result;
814  }
815 
816  flow_cfg.dev = state->dev_resrc1.mlxdev;
817  flow_cfg.rxq_flow_queue_ids = &(state->dev_resrc1.rxq_flow_queue_id);
818  flow_cfg.nb_queues = 1;
819 
821  if (result != DOCA_SUCCESS) {
822  DOCA_LOG_ERR("Failed to allocate ETH RXQ flow resources for device 1: %s",
824  return result;
825  }
826  }
827 
828  /* Check if forwarding from device 2 to device 1 is desired */
829  if (cfg->one_sided_fwd == 0 || cfg->one_sided_fwd == 2) {
830  state->dev_resrc2.mmap_resrc.mmap_size = recommended_size;
832  if (result != DOCA_SUCCESS) {
833  DOCA_LOG_ERR("Failed to create mmap for device 2: %s", doca_error_get_descr(result));
834  return result;
835  }
836 
838  if (result != DOCA_SUCCESS) {
839  DOCA_LOG_ERR("Failed to initialize DOCA flow port for device 2: %s",
841  return result;
842  }
843 
844  result = init_eth_txq_ctx(cfg, &state->dev_resrc1, state->pe, tx_success_cb1);
845  if (result != DOCA_SUCCESS) {
846  DOCA_LOG_ERR("Failed to initialize ETH TXQ context for device 1: %s",
848  return result;
849  }
850 
851  // Sending the second device's ETH TXQ context (pointer) to save as user_data
852  // and allow forwarding via completion callback (see rx_success_cb)
854  &state->dev_resrc2,
855  state->pe,
857  (void *)state->dev_resrc1.eth_txq);
858  if (result != DOCA_SUCCESS) {
859  DOCA_LOG_ERR("Failed to initialize ETH RXQ context for device 2: %s",
861  return result;
862  }
863 
864  flow_cfg.dev = state->dev_resrc2.mlxdev;
865  flow_cfg.rxq_flow_queue_ids = &(state->dev_resrc2.rxq_flow_queue_id);
866  flow_cfg.nb_queues = 1;
867 
869  if (result != DOCA_SUCCESS) {
870  DOCA_LOG_ERR("Failed to allocate ETH RXQ flow resources for device 2: %s",
872  return result;
873  }
874  }
875 
876  result = forward_pkts(state->pe);
877  if (result != DOCA_SUCCESS) {
878  DOCA_LOG_ERR("Failed to forward packets: %s", doca_error_get_descr(result));
879  return result;
880  }
881 
882  DOCA_LOG_INFO("Ethernet L2 Forwarding Application execution finished successfully");
883  return DOCA_SUCCESS;
884 }
885 
887 {
888  force_app_stop = true;
889 }
890 
892 {
894  enum doca_ctx_states ctx_state;
895  uint8_t num_ctx_in_progress = 0;
896 
897  if (state->dev_resrc1.flow_resrc.root_pipe != NULL)
899 
900  if (state->dev_resrc2.flow_resrc.root_pipe != NULL)
902 
903  if (state->dev_resrc1.flow_resrc.df_port != NULL) {
905  if (result != DOCA_SUCCESS) {
906  DOCA_LOG_ERR("Failed to stop DOCA flow port for device 1: %s", doca_error_get_descr(result));
907  return result;
908  }
909  }
910 
911  if (state->dev_resrc2.flow_resrc.df_port != NULL) {
913  if (result != DOCA_SUCCESS) {
914  DOCA_LOG_ERR("Failed to stop DOCA flow port for device 1: %s", doca_error_get_descr(result));
915  return result;
916  }
917  }
918 
919  if (state->dev_resrc1.eth_rxq_ctx != NULL) {
922  ++num_ctx_in_progress;
923  else if (result != DOCA_SUCCESS) {
924  DOCA_LOG_ERR("Failed to stop device 1 ETH RXQ DOCA CTX: %s", doca_error_get_descr(result));
925  return result;
926  } else /* DOCA_SUCCESS */
927  state->dev_resrc1.eth_rxq_ctx = NULL;
928  }
929 
930  if (state->dev_resrc2.eth_rxq_ctx != NULL) {
933  ++num_ctx_in_progress;
934  else if (result != DOCA_SUCCESS) {
935  DOCA_LOG_ERR("Failed to stop device 2 ETH RXQ DOCA CTX: %s", doca_error_get_descr(result));
936  return result;
937  } else /* DOCA_SUCCESS */
938  state->dev_resrc2.eth_rxq_ctx = NULL;
939  }
940 
941  if (state->dev_resrc1.eth_txq_ctx != NULL) {
944  ++num_ctx_in_progress;
945  else if (result != DOCA_SUCCESS) {
946  DOCA_LOG_ERR("Failed to stop device 1 ETH TXQ DOCA CTX: %s", doca_error_get_descr(result));
947  return result;
948  } else /* DOCA_SUCCESS */
949  state->dev_resrc1.eth_txq_ctx = NULL;
950  }
951 
952  if (state->dev_resrc2.eth_txq_ctx != NULL) {
955  ++num_ctx_in_progress;
956  else if (result != DOCA_SUCCESS) {
957  DOCA_LOG_ERR("Failed to stop device 2 ETH TXQ DOCA CTX: %s", doca_error_get_descr(result));
958  return result;
959  } else /* DOCA_SUCCESS */
960  state->dev_resrc2.eth_txq_ctx = NULL;
961  }
962 
963  /* Draining till all contexts states are IDLE */
964  while (num_ctx_in_progress > 0) {
965  (void)doca_pe_progress(state->pe);
966 
967  if (state->dev_resrc1.eth_rxq_ctx != NULL) {
968  result = doca_ctx_get_state(state->dev_resrc1.eth_rxq_ctx, &ctx_state);
969  if (result != DOCA_SUCCESS) {
970  DOCA_LOG_ERR("Failed get status of ETH RXQ DOCA CTX for device 1: %s",
972  return result;
973  }
974 
975  if (ctx_state == DOCA_CTX_STATE_IDLE) {
976  state->dev_resrc1.eth_rxq_ctx = NULL;
977  --num_ctx_in_progress;
978  }
979  }
980 
981  if (state->dev_resrc2.eth_rxq_ctx != NULL) {
982  result = doca_ctx_get_state(state->dev_resrc2.eth_rxq_ctx, &ctx_state);
983  if (result != DOCA_SUCCESS) {
984  DOCA_LOG_ERR("Failed get status of ETH RXQ DOCA CTX for device 2: %s",
986  return result;
987  }
988 
989  if (ctx_state == DOCA_CTX_STATE_IDLE) {
990  state->dev_resrc2.eth_rxq_ctx = NULL;
991  --num_ctx_in_progress;
992  }
993  }
994 
995  if (state->dev_resrc1.eth_txq_ctx != NULL) {
996  result = doca_ctx_get_state(state->dev_resrc1.eth_txq_ctx, &ctx_state);
997  if (result != DOCA_SUCCESS) {
998  DOCA_LOG_ERR("Failed get status of ETH TXQ DOCA CTX for device 1: %s",
1000  return result;
1001  }
1002 
1003  if (ctx_state == DOCA_CTX_STATE_IDLE) {
1004  state->dev_resrc1.eth_txq_ctx = NULL;
1005  --num_ctx_in_progress;
1006  }
1007  }
1008 
1009  if (state->dev_resrc2.eth_txq_ctx != NULL) {
1010  result = doca_ctx_get_state(state->dev_resrc2.eth_txq_ctx, &ctx_state);
1011  if (result != DOCA_SUCCESS) {
1012  DOCA_LOG_ERR("Failed get status of ETH TXQ DOCA CTX for device 2: %s",
1014  return result;
1015  }
1016 
1017  if (ctx_state == DOCA_CTX_STATE_IDLE) {
1018  state->dev_resrc2.eth_txq_ctx = NULL;
1019  --num_ctx_in_progress;
1020  }
1021  }
1022  }
1023 
1024  if (state->dev_resrc1.eth_txq != NULL) {
1026  if (result != DOCA_SUCCESS) {
1027  DOCA_LOG_ERR("Failed to destroy device 1 ETH TXQ CTX: %s", doca_error_get_descr(result));
1028  return result;
1029  }
1030  }
1031 
1032  if (state->dev_resrc2.eth_txq != NULL) {
1034  if (result != DOCA_SUCCESS) {
1035  DOCA_LOG_ERR("Failed to destroy device 2 ETH TXQ CTX: %s", doca_error_get_descr(result));
1036  return result;
1037  }
1038  }
1039 
1040  if (state->dev_resrc1.eth_rxq != NULL) {
1042  if (result != DOCA_SUCCESS) {
1043  DOCA_LOG_ERR("Failed to destroy device 1 ETH RXQ CTX: %s", doca_error_get_descr(result));
1044  return result;
1045  }
1046  }
1047 
1048  if (state->dev_resrc2.eth_rxq != NULL) {
1050  if (result != DOCA_SUCCESS) {
1051  DOCA_LOG_ERR("Failed to destroy device 2 ETH RXQ CTX: %s", doca_error_get_descr(result));
1052  return result;
1053  }
1054  }
1055 
1056  if (state->dev_resrc1.mmap_resrc.mmap != NULL) {
1058  if (result != DOCA_SUCCESS) {
1059  DOCA_LOG_ERR("Failed to destroy DOCA mmap of device 1: %s", doca_error_get_descr(result));
1060  return result;
1061  }
1062  }
1063 
1064  if (state->dev_resrc2.mmap_resrc.mmap != NULL) {
1066  if (result != DOCA_SUCCESS) {
1067  DOCA_LOG_ERR("Failed to destroy DOCA mmap of device 2: %s", doca_error_get_descr(result));
1068  return result;
1069  }
1070  }
1071 
1072  if (state->dev_resrc1.mmap_resrc.mmap_buffer != NULL)
1073  free(state->dev_resrc1.mmap_resrc.mmap_buffer);
1074 
1075  if (state->dev_resrc2.mmap_resrc.mmap_buffer != NULL)
1076  free(state->dev_resrc2.mmap_resrc.mmap_buffer);
1077 
1078  if (state->pe != NULL) {
1079  result = doca_pe_destroy(state->pe);
1080  if (result != DOCA_SUCCESS) {
1081  DOCA_LOG_ERR("Failed to destroy DOCA progress engine: %s", doca_error_get_descr(result));
1082  return result;
1083  }
1084  }
1085 
1086  if (state->dev_resrc1.mlxdev != NULL) {
1088  if (result != DOCA_SUCCESS) {
1089  DOCA_LOG_ERR("Failed to close DOCA device 1: %s", doca_error_get_descr(result));
1090  return result;
1091  }
1092  }
1093 
1094  if (state->dev_resrc2.mlxdev != NULL) {
1096  if (result != DOCA_SUCCESS) {
1097  DOCA_LOG_ERR("Failed to close DOCA device 2: %s", doca_error_get_descr(result));
1098  return result;
1099  }
1100  }
1101 
1103 
1104  DOCA_LOG_INFO("Ethernet L2 Forwarding Application resources cleanup finished successfully");
1105  return DOCA_SUCCESS;
1106 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
doca_error_t open_doca_device_with_ibdev_name(const uint8_t *value, size_t val_size, tasks_check func, struct doca_dev **retval)
Definition: common.c:84
#define doca_unlikely(x)
static bool force_app_stop
doca_error_t eth_l2_fwd_cleanup(struct eth_l2_fwd_resources *state)
static void eth_l2_fwd_show_stats(void)
static doca_error_t check_device_caps(struct doca_devinfo *devinfo)
static struct eth_l2_fwd_stats stats
static doca_error_t forward_pkts(struct doca_pe *pe)
DOCA_LOG_REGISTER(ETH_L2_FWD :Core)
static void rx_success_cb1(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv, uint16_t events_number, union doca_data event_batch_user_data, doca_error_t status, struct doca_buf **pkt_array)
#define STATS_MAX_BUFF_SIZE
doca_error_t eth_l2_fwd_execute(struct eth_l2_fwd_cfg *cfg, struct eth_l2_fwd_resources *state)
static doca_error_t init_eth_txq_ctx(struct eth_l2_fwd_cfg *cfg, struct eth_l2_fwd_dev_resources *dev_resrc, struct doca_pe *pe, doca_eth_txq_task_batch_send_completion_cb_t tx_success_cb)
static void rx_error_cb(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv, uint16_t events_number, union doca_data event_batch_user_data, doca_error_t status, struct doca_buf **pkt_array)
uint32_t max_forwardings
static void rx_success_cb2(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv, uint16_t events_number, union doca_data event_batch_user_data, doca_error_t status, struct doca_buf **pkt_array)
static void tx_success_cb2(struct doca_task_batch *task_batch, uint16_t tasks_num, union doca_data ctx_user_data, union doca_data task_batch_user_data, union doca_data *task_user_data_array, struct doca_buf **pkt_array, doca_error_t *status_array)
static uint32_t total_forwardings
static doca_error_t create_mmap(struct doca_dev *dev1, struct doca_dev *dev2, struct mmap_resources *mmap_res)
static void tx_success_cb1(struct doca_task_batch *task_batch, uint16_t tasks_num, union doca_data ctx_user_data, union doca_data task_batch_user_data, union doca_data *task_user_data_array, struct doca_buf **pkt_array, doca_error_t *status_array)
void eth_l2_fwd_force_stop(void)
static void tx_error_cb(struct doca_task_batch *task_batch, uint16_t tasks_num, union doca_data ctx_user_data, union doca_data task_batch_user_data, union doca_data *task_user_data_array, struct doca_buf **pkt_array, doca_error_t *status_array)
static doca_error_t init_eth_rxq_ctx(struct eth_l2_fwd_cfg *cfg, struct eth_l2_fwd_dev_resources *dev_resrc, struct doca_pe *pe, doca_eth_rxq_event_batch_managed_recv_handler_cb_t rx_success_cb, void *data)
#define NS_PER_SEC
#define ETH_L2_FWD_LOG_MAX_LRO_DEFAULT
doca_error_t allocate_eth_rxq_flow_resources(struct eth_rxq_flow_config *cfg, struct eth_rxq_flow_resources *resources)
doca_error_t rxq_common_init_doca_flow(struct doca_dev *dev, struct eth_rxq_flow_resources *resources)
static struct doca_pe * pe
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_get_state(const struct doca_ctx *ctx, enum doca_ctx_states *state)
Get context state.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
doca_ctx_states
This enum defines the states of a context.
Definition: doca_ctx.h:83
@ DOCA_CTX_STATE_STOPPING
Definition: doca_ctx.h:106
@ DOCA_CTX_STATE_IDLE
Definition: doca_ctx.h:88
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.
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_TOO_BIG
Definition: doca_error.h:65
@ DOCA_ERROR_IO_FAILED
Definition: doca_error.h:55
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_IN_PROGRESS
Definition: doca_error.h:64
DOCA_EXPERIMENTAL void doca_eth_rxq_event_batch_managed_recv_pkt_array_free(struct doca_buf **pkt_array)
This method frees the packet array acquired using managed receive event batch and returns it to the o...
void(* doca_eth_rxq_event_batch_managed_recv_handler_cb_t)(struct doca_eth_rxq_event_batch_managed_recv *event_batch_managed_recv, uint16_t events_number, union doca_data event_batch_user_data, doca_error_t status, struct doca_buf **pkt_array)
Function to be executed on managed receive event batch occurrence.
DOCA_EXPERIMENTAL doca_error_t doca_eth_rxq_event_batch_managed_recv_register(struct doca_eth_rxq *eth_rxq, enum doca_event_batch_events_number events_number_max, enum doca_event_batch_events_number events_number_min, union doca_data user_data, doca_eth_rxq_event_batch_managed_recv_handler_cb_t success_event_batch_handler, doca_eth_rxq_event_batch_managed_recv_handler_cb_t error_event_batch_handler)
This method registers a doca_eth_rxq_event_managed_recv event batch. Allows user to get multiple even...
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_task_batch_send_set_conf(struct doca_eth_txq *eth_txq, enum doca_task_batch_max_tasks_number max_tasks_number, uint16_t num_task_batches, doca_eth_txq_task_batch_send_completion_cb_t success_completion_cb, doca_eth_txq_task_batch_send_completion_cb_t error_completion_cb)
This method sets the task_batch of send tasks configuration.
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_task_batch_send_allocate(struct doca_eth_txq *eth_txq, uint16_t tasks_num, union doca_data task_batch_user_data, struct doca_buf ***pkt_array, union doca_data **task_user_data_array, struct doca_task_batch **task_batch)
This method allocates a doca_taskbtach of doca_eth_txq_task_send tasks.
void(* doca_eth_txq_task_batch_send_completion_cb_t)(struct doca_task_batch *task_batch, uint16_t tasks_num, union doca_data ctx_user_data, union doca_data task_batch_user_data, union doca_data *task_user_data_array, struct doca_buf **pkt_array, doca_error_t *status_array)
Function to execute on task_batch completion.
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_cap_get_max_burst_size(const struct doca_devinfo *devinfo, uint32_t max_send_buf_list_len, uint16_t max_lso_header_size, uint32_t *max_burst_size)
Get the maximum burst size supported by the device.
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_set_type(struct doca_eth_txq *eth_txq, enum doca_eth_txq_type type)
Set TX queue type property for doca_eth_txq. can only be called before calling doca_ctx_start().
DOCA_EXPERIMENTAL doca_error_t doca_eth_txq_cap_is_type_supported(const struct doca_devinfo *devinfo, enum doca_eth_txq_type type, enum doca_eth_txq_data_path_type data_path_type)
Check if TX queue type is supported.
@ DOCA_ETH_TXQ_DATA_PATH_TYPE_CPU
Definition: doca_eth_txq.h:72
@ DOCA_ETH_TXQ_TYPE_REGULAR
Definition: doca_eth_txq.h:65
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_cap_is_type_supported(const struct doca_devinfo *devinfo, enum doca_eth_rxq_type type, enum doca_eth_rxq_data_path_type data_path_type)
Check if RX queue type is supported.
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_cap_get_max_packet_size(const struct doca_devinfo *devinfo, uint32_t *max_packet_size)
Get the maximum packet size supported by the device.
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_cap_get_max_burst_size(const struct doca_devinfo *devinfo, uint32_t *max_burst_size)
Get the maximum burst size supported by the device.
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_MANAGED_MEMPOOL
Definition: doca_eth_rxq.h:75
@ DOCA_ETH_RXQ_DATA_PATH_TYPE_CPU
Definition: doca_eth_rxq.h:95
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_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
#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_set_max_num_devices(struct doca_mmap *mmap, uint32_t max_num_devices)
Set a new max number of devices to add to a 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_pe_destroy(struct doca_pe *pe)
Destroy doca progress engine.
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.
DOCA_EXPERIMENTAL struct doca_ctx * doca_task_batch_get_ctx(const struct doca_task_batch *task_batch)
Get context from a doca task_batch.
DOCA_EXPERIMENTAL void doca_task_batch_free(struct doca_task_batch *task_batch)
Free a task_batch back to where it was allocated from.
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_EXPERIMENTAL doca_error_t doca_task_batch_submit(struct doca_task_batch *task_batch)
Submit a task_batch to a progress engine.
DOCA_STABLE doca_error_t doca_pe_create(struct doca_pe **pe)
Creates DOCA progress engine.
@ DOCA_TASK_BATCH_MAX_TASKS_NUMBER_128
Definition: doca_pe.h:52
@ DOCA_EVENT_BATCH_EVENTS_NUMBER_128
Definition: doca_pe.h:66
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
void rx_success_cb(struct doca_rmax_in_stream_event_rx_data *event_rx_data, union doca_data event_user_data)
struct doca_eth_txq * eth_txq
struct doca_ctx * eth_rxq_ctx
struct doca_ctx * eth_txq_ctx
struct doca_eth_rxq * eth_rxq
struct mmap_resources mmap_resrc
struct eth_rxq_flow_resources flow_resrc
struct doca_dev * mlxdev
struct eth_l2_fwd_dev_resources dev_resrc1
struct eth_l2_fwd_dev_resources dev_resrc2
struct doca_pe * pe
struct eth_l2_fwd_dev_stats dev1_stats
uint64_t initial_time_ns
struct eth_l2_fwd_dev_stats dev2_stats
uint16_t * rxq_flow_queue_ids
struct doca_dev * dev
struct doca_flow_pipe * root_pipe
struct doca_flow_port * df_port
uint8_t * mmap_buffer
struct doca_mmap * mmap
uint32_t mmap_size
Convenience type for representing opaque data.
Definition: doca_types.h:56
void * ptr
Definition: doca_types.h:57