11/*
2- * Copyright (c) 2021-2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
2+ * Copyright (c) 2021-2025 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without modification, are permitted
55 * provided that the following conditions are met:
2828#include <rte_malloc.h>
2929
3030#include <doca_log.h>
31+ #include <doca_dev.h>
32+ #include <doca_dpdk.h>
3133#include <doca_mmap.h>
3234#include <doca_buf_inventory.h>
3335
3436#include "dpdk_utils.h"
37+ #include "utils.h"
3538
3639DOCA_LOG_REGISTER (NUTILS );
3740
@@ -46,200 +49,16 @@ DOCA_LOG_REGISTER(NUTILS);
4649 addr[12], addr[13], addr[14], addr[15]
4750#endif
4851
52+ #define AUX_DEV_IDENTIFIER_PREFIX "auxiliary:mlx5_core.sf."
53+ #define AUX_DEV_IDENTIFIER_MAX_SIZE (32)
54+ #define DEV_IDENTIFIER_MAX_SIZE (MAX(AUX_DEV_IDENTIFIER_MAX_SIZE, DOCA_DEVINFO_PCI_ADDR_SIZE))
55+
4956struct dpdk_mempool_shadow {
5057 struct doca_dev * device ; /* DOCA device used to register memory */
5158 struct doca_mmap * * mmap_arr ; /* DOCA mmap array that has mapped the packet buffers */
5259 uint32_t nb_mmaps ; /* Number of elements in mmap_arr */
5360};
5461
55- /*
56- * Bind port to all the peer ports
57- *
58- * @port_id [in]: port ID
59- * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
60- */
61- static doca_error_t bind_hairpin_queues (uint16_t port_id )
62- {
63- /* Configure the Rx and Tx hairpin queues for the selected port */
64- int result = 0 , peer_port , peer_ports_len ;
65- uint16_t peer_ports [RTE_MAX_ETHPORTS ];
66-
67- /* bind current Tx to all peer Rx */
68- peer_ports_len = rte_eth_hairpin_get_peer_ports (port_id , peer_ports , RTE_MAX_ETHPORTS , 1 );
69- if (peer_ports_len < 0 ) {
70- DOCA_LOG_ERR ("Failed to get hairpin peer Rx ports of port %d, (%d)" , port_id , peer_ports_len );
71- return DOCA_ERROR_DRIVER ;
72- }
73- for (peer_port = 0 ; peer_port < peer_ports_len ; peer_port ++ ) {
74- result = rte_eth_hairpin_bind (port_id , peer_ports [peer_port ]);
75- if (result < 0 ) {
76- DOCA_LOG_ERR ("Failed to bind hairpin queues (%d)" , result );
77- return DOCA_ERROR_DRIVER ;
78- }
79- }
80- /* bind all peer Tx to current Rx */
81- peer_ports_len = rte_eth_hairpin_get_peer_ports (port_id , peer_ports , RTE_MAX_ETHPORTS , 0 );
82- if (peer_ports_len < 0 ) {
83- DOCA_LOG_ERR ("Failed to get hairpin peer Tx ports of port %d, (%d)" , port_id , peer_ports_len );
84- return DOCA_ERROR_DRIVER ;
85- }
86-
87- for (peer_port = 0 ; peer_port < peer_ports_len ; peer_port ++ ) {
88- result = rte_eth_hairpin_bind (peer_ports [peer_port ], port_id );
89- if (result < 0 ) {
90- DOCA_LOG_ERR ("Failed to bind hairpin queues (%d)" , result );
91- return DOCA_ERROR_DRIVER ;
92- }
93- }
94- return DOCA_SUCCESS ;
95- }
96-
97- /*
98- * Unbind port from all its peer ports
99- *
100- * @port_id [in]: port ID
101- * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
102- */
103- static doca_error_t unbind_hairpin_queues (uint16_t port_id )
104- {
105- /* Configure the Rx and Tx hairpin queues for the selected port */
106- int result = 0 , peer_port , peer_ports_len ;
107- uint16_t peer_ports [RTE_MAX_ETHPORTS ];
108-
109- /* unbind current Tx from all peer Rx */
110- peer_ports_len = rte_eth_hairpin_get_peer_ports (port_id , peer_ports , RTE_MAX_ETHPORTS , 1 );
111- if (peer_ports_len < 0 ) {
112- DOCA_LOG_ERR ("Failed to get hairpin peer Tx ports of port %d, (%d)" , port_id , peer_ports_len );
113- return DOCA_ERROR_DRIVER ;
114- }
115-
116- for (peer_port = 0 ; peer_port < peer_ports_len ; peer_port ++ ) {
117- result = rte_eth_hairpin_unbind (port_id , peer_ports [peer_port ]);
118- if (result < 0 ) {
119- DOCA_LOG_ERR ("Failed to bind hairpin queues (%d)" , result );
120- return DOCA_ERROR_DRIVER ;
121- }
122- }
123- /* unbind all peer Tx from current Rx */
124- peer_ports_len = rte_eth_hairpin_get_peer_ports (port_id , peer_ports , RTE_MAX_ETHPORTS , 0 );
125- if (peer_ports_len < 0 ) {
126- DOCA_LOG_ERR ("Failed to get hairpin peer Tx ports of port %d, (%d)" , port_id , peer_ports_len );
127- return DOCA_ERROR_DRIVER ;
128- }
129- for (peer_port = 0 ; peer_port < peer_ports_len ; peer_port ++ ) {
130- result = rte_eth_hairpin_unbind (peer_ports [peer_port ], port_id );
131- if (result < 0 ) {
132- DOCA_LOG_ERR ("Failed to bind hairpin queues (%d)" , result );
133- return DOCA_ERROR_DRIVER ;
134- }
135- }
136- return DOCA_SUCCESS ;
137- }
138-
139- /*
140- * Set up all hairpin queues
141- *
142- * @port_id [in]: port ID
143- * @peer_port_id [in]: peer port ID
144- * @reserved_hairpin_q_list [in]: list of hairpin queues index
145- * @hairpin_queue_len [in]: length of reserved_hairpin_q_list
146- * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
147- */
148- static doca_error_t setup_hairpin_queues (uint16_t port_id ,
149- uint16_t peer_port_id ,
150- uint16_t * reserved_hairpin_q_list ,
151- int hairpin_queue_len )
152- {
153- /* Port:
154- * 0. RX queue
155- * 1. RX hairpin queue rte_eth_rx_hairpin_queue_setup
156- * 2. TX hairpin queue rte_eth_tx_hairpin_queue_setup
157- */
158-
159- int result = 0 , hairpin_q ;
160- uint16_t nb_tx_rx_desc = 2048 ;
161- uint32_t manual = 1 ;
162- uint32_t tx_exp = 1 ;
163- struct rte_eth_hairpin_conf hairpin_conf = {
164- .peer_count = 1 ,
165- .manual_bind = !!manual ,
166- .tx_explicit = !!tx_exp ,
167- .peers [0 ] = {peer_port_id , 0 },
168- };
169-
170- for (hairpin_q = 0 ; hairpin_q < hairpin_queue_len ; hairpin_q ++ ) {
171- // TX
172- hairpin_conf .peers [0 ].queue = reserved_hairpin_q_list [hairpin_q ];
173- result = rte_eth_tx_hairpin_queue_setup (port_id ,
174- reserved_hairpin_q_list [hairpin_q ],
175- nb_tx_rx_desc ,
176- & hairpin_conf );
177- if (result < 0 ) {
178- DOCA_LOG_ERR ("Failed to setup hairpin queues (%d)" , result );
179- return DOCA_ERROR_DRIVER ;
180- }
181-
182- // RX
183- hairpin_conf .peers [0 ].queue = reserved_hairpin_q_list [hairpin_q ];
184- result = rte_eth_rx_hairpin_queue_setup (port_id ,
185- reserved_hairpin_q_list [hairpin_q ],
186- nb_tx_rx_desc ,
187- & hairpin_conf );
188- if (result < 0 ) {
189- DOCA_LOG_ERR ("Failed to setup hairpin queues (%d)" , result );
190- return DOCA_ERROR_DRIVER ;
191- }
192- }
193- return DOCA_SUCCESS ;
194- }
195-
196- /*
197- * Unbind hairpin queues from all ports
198- *
199- * @nb_ports [in]: number of ports
200- */
201- static void disable_hairpin_queues (uint16_t nb_ports )
202- {
203- doca_error_t result ;
204- uint16_t port_id ;
205-
206- for (port_id = 0 ; port_id < nb_ports ; port_id ++ ) {
207- if (!rte_eth_dev_is_valid_port (port_id ))
208- continue ;
209- result = unbind_hairpin_queues (port_id );
210- if (result != DOCA_SUCCESS )
211- DOCA_LOG_ERR ("Disabling hairpin queues failed: err=%d, port=%u" , result , port_id );
212- }
213- }
214-
215- /*
216- * Bind hairpin queues to all ports
217- *
218- * @nb_ports [in]: number of ports
219- * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
220- */
221- static doca_error_t enable_hairpin_queues (uint8_t nb_ports )
222- {
223- uint16_t port_id ;
224- uint16_t n = 0 ;
225- doca_error_t result ;
226-
227- for (port_id = 0 ; port_id < RTE_MAX_ETHPORTS ; port_id ++ ) {
228- if (!rte_eth_dev_is_valid_port (port_id ))
229- /* the device ID might not be contiguous */
230- continue ;
231- result = bind_hairpin_queues (port_id );
232- if (result != DOCA_SUCCESS ) {
233- DOCA_LOG_ERR ("Hairpin bind failed on port=%u" , port_id );
234- disable_hairpin_queues (port_id );
235- return result ;
236- }
237- if (++ n >= nb_ports )
238- break ;
239- }
240- return DOCA_SUCCESS ;
241- }
242-
24362/*
24463 * Creates a new mempool in memory to hold the mbufs
24564 *
@@ -271,18 +90,14 @@ static doca_error_t allocate_mempool(const uint32_t total_nb_mbufs,
27190 */
27291static doca_error_t port_init (struct rte_mempool * mbuf_pool , uint8_t port , struct application_dpdk_config * app_config )
27392{
274- doca_error_t result ;
27593 int ret = 0 ;
27694 int symmetric_hash_key_length = RSS_KEY_LEN ;
277- const uint16_t nb_hairpin_queues = app_config -> port_config .nb_hairpin_q ;
27895 const uint16_t rx_rings = app_config -> port_config .nb_queues ;
27996 const uint16_t tx_rings = app_config -> port_config .nb_queues ;
28097 const uint16_t rss_support = !!(app_config -> port_config .rss_support && (app_config -> port_config .nb_queues > 1 ));
281- bool isolated = !!app_config -> port_config .isolated_mode ;
282- uint16_t q , queue_index ;
98+ uint16_t q ;
28399 struct rte_ether_addr addr ;
284100 struct rte_eth_dev_info dev_info ;
285- struct rte_flow_error error ;
286101 uint8_t symmetric_hash_key [RSS_KEY_LEN ] = {
287102 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A ,
288103 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A , 0x6D , 0x5A ,
@@ -316,7 +131,7 @@ static doca_error_t port_init(struct rte_mempool *mbuf_pool, uint8_t port, struc
316131 port_conf .txmode .offloads = app_config -> port_config .tx_offloads ;
317132
318133 /* Configure the Ethernet device */
319- ret = rte_eth_dev_configure (port , rx_rings + nb_hairpin_queues , tx_rings + nb_hairpin_queues , & port_conf );
134+ ret = rte_eth_dev_configure (port , rx_rings , tx_rings , & port_conf );
320135 if (ret < 0 ) {
321136 DOCA_LOG_ERR ("Failed to configure the ethernet device - (%d)" , ret );
322137 return DOCA_ERROR_DRIVER ;
@@ -354,58 +169,6 @@ static doca_error_t port_init(struct rte_mempool *mbuf_pool, uint8_t port, struc
354169 }
355170 }
356171
357- /* Enabled hairpin queue before port start */
358- if (nb_hairpin_queues ) {
359- uint16_t rss_queue_list [nb_hairpin_queues ];
360-
361- if (app_config -> port_config .self_hairpin && rte_eth_dev_is_valid_port (port ^ 1 )) {
362- /* Hairpin to both self and peer */
363- assert ((nb_hairpin_queues % 2 ) == 0 );
364- for (queue_index = 0 ; queue_index < nb_hairpin_queues / 2 ; queue_index ++ )
365- rss_queue_list [queue_index ] = app_config -> port_config .nb_queues + queue_index * 2 ;
366- result = setup_hairpin_queues (port , port , rss_queue_list , nb_hairpin_queues / 2 );
367- if (result != DOCA_SUCCESS ) {
368- DOCA_LOG_ERR ("Cannot hairpin self port %" PRIu8 ", ret: %s" ,
369- port ,
370- doca_error_get_descr (result ));
371- return result ;
372- }
373- for (queue_index = 0 ; queue_index < nb_hairpin_queues / 2 ; queue_index ++ )
374- rss_queue_list [queue_index ] = app_config -> port_config .nb_queues + queue_index * 2 + 1 ;
375- result = setup_hairpin_queues (port , port ^ 1 , rss_queue_list , nb_hairpin_queues / 2 );
376- if (result != DOCA_SUCCESS ) {
377- DOCA_LOG_ERR ("Cannot hairpin peer port %" PRIu8 ", ret: %s" ,
378- port ^ 1 ,
379- doca_error_get_descr (result ));
380- return result ;
381- }
382- } else {
383- /* Hairpin to self or peer */
384- for (queue_index = 0 ; queue_index < nb_hairpin_queues ; queue_index ++ )
385- rss_queue_list [queue_index ] = app_config -> port_config .nb_queues + queue_index ;
386- if (rte_eth_dev_is_valid_port (port ^ 1 ))
387- result = setup_hairpin_queues (port , port ^ 1 , rss_queue_list , nb_hairpin_queues );
388- else
389- result = setup_hairpin_queues (port , port , rss_queue_list , nb_hairpin_queues );
390- if (result != DOCA_SUCCESS ) {
391- DOCA_LOG_ERR ("Cannot hairpin port %" PRIu8 ", ret=%d" , port , result );
392- return result ;
393- }
394- }
395- }
396-
397- /* Set isolated mode (true or false) before port start */
398- ret = rte_flow_isolate (port , isolated , & error );
399- if (ret < 0 ) {
400- DOCA_LOG_ERR ("Port %u could not be set isolated mode to %s (%s)" ,
401- port ,
402- isolated ? "true" : "false" ,
403- error .message );
404- return DOCA_ERROR_DRIVER ;
405- }
406- if (isolated )
407- DOCA_LOG_INFO ("Ingress traffic on port %u is in isolated mode" , port );
408-
409172 /* Start the Ethernet port */
410173 ret = rte_eth_dev_start (port );
411174 if (ret < 0 ) {
@@ -547,24 +310,11 @@ doca_error_t dpdk_queues_and_ports_init(struct application_dpdk_config *app_dpdk
547310 }
548311 }
549312
550- /* Enable hairpin queues */
551- if (app_dpdk_config -> port_config .nb_hairpin_q > 0 ) {
552- result = enable_hairpin_queues (app_dpdk_config -> port_config .nb_ports );
553- if (result != DOCA_SUCCESS )
554- goto ports_cleanup ;
555- }
556-
557313 return DOCA_SUCCESS ;
558-
559- ports_cleanup :
560- dpdk_ports_fini (app_dpdk_config , RTE_MAX_ETHPORTS );
561- return result ;
562314}
563315
564316void dpdk_queues_and_ports_fini (struct application_dpdk_config * app_dpdk_config )
565317{
566- disable_hairpin_queues (RTE_MAX_ETHPORTS );
567-
568318 dpdk_ports_fini (app_dpdk_config , RTE_MAX_ETHPORTS );
569319}
570320
@@ -904,6 +654,24 @@ void print_header_info(const struct rte_mbuf *packet, const bool l2, const bool
904654 print_l4_header (packet );
905655}
906656
657+ void dpdk_fini_with_devs (uint16_t nb_devs )
658+ {
659+ struct doca_dev * dev ;
660+ doca_error_t result ;
661+ int i ;
662+
663+ dpdk_fini ();
664+ for (i = 0 ; i < nb_devs ; i ++ ) {
665+ result = doca_dpdk_port_as_dev (i , & dev );
666+ if (result != DOCA_SUCCESS )
667+ DOCA_LOG_WARN ("Failed to get device for closing port %d: %s" , i , doca_error_get_descr (result ));
668+
669+ result = doca_dev_close (dev );
670+ if (result != DOCA_SUCCESS )
671+ DOCA_LOG_WARN ("Failed to close device for port %d: %s" , i , doca_error_get_descr (result ));
672+ }
673+ }
674+
907675doca_error_t dpdk_init (int argc , char * * argv )
908676{
909677 int result ;
0 commit comments