26 #include <rte_ethdev.h>
27 #include <rte_ether.h>
28 #include <rte_malloc.h>
38 #define RSS_KEY_LEN 40
41 #define IPv6_BYTES_FMT \
42 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \
43 "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
44 #define IPv6_BYTES(addr) \
45 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], \
46 addr[12], addr[13], addr[14], addr[15]
64 int result = 0, peer_port, peer_ports_len;
65 uint16_t peer_ports[RTE_MAX_ETHPORTS];
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);
73 for (peer_port = 0; peer_port < peer_ports_len; peer_port++) {
74 result = rte_eth_hairpin_bind(port_id, peer_ports[peer_port]);
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);
87 for (peer_port = 0; peer_port < peer_ports_len; peer_port++) {
88 result = rte_eth_hairpin_bind(peer_ports[peer_port], port_id);
106 int result = 0, peer_port, peer_ports_len;
107 uint16_t peer_ports[RTE_MAX_ETHPORTS];
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);
116 for (peer_port = 0; peer_port < peer_ports_len; peer_port++) {
117 result = rte_eth_hairpin_unbind(port_id, peer_ports[peer_port]);
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);
129 for (peer_port = 0; peer_port < peer_ports_len; peer_port++) {
130 result = rte_eth_hairpin_unbind(peer_ports[peer_port], port_id);
149 uint16_t peer_port_id,
150 uint16_t *reserved_hairpin_q_list,
151 int hairpin_queue_len)
159 int result = 0, hairpin_q;
160 uint16_t nb_tx_rx_desc = 2048;
163 struct rte_eth_hairpin_conf hairpin_conf = {
165 .manual_bind = !!manual,
166 .tx_explicit = !!tx_exp,
167 .peers[0] = {peer_port_id, 0},
170 for (hairpin_q = 0; hairpin_q < hairpin_queue_len; hairpin_q++) {
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],
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],
206 for (port_id = 0; port_id <
nb_ports; port_id++) {
207 if (!rte_eth_dev_is_valid_port(port_id))
227 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
228 if (!rte_eth_dev_is_valid_port(port_id))
233 DOCA_LOG_ERR(
"Hairpin bind failed on port=%u", port_id);
252 const uint32_t mbuf_size,
253 struct rte_mempool **mbuf_pool)
256 rte_pktmbuf_pool_create(
"MBUF_POOL", total_nb_mbufs,
MBUF_CACHE_SIZE, 0, mbuf_size, rte_socket_id());
257 if (*mbuf_pool ==
NULL) {
277 const uint16_t nb_hairpin_queues =
app_config->port_config.nb_hairpin_q;
278 const uint16_t rx_rings =
app_config->port_config.nb_queues;
279 const uint16_t tx_rings =
app_config->port_config.nb_queues;
280 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;
283 struct rte_ether_addr
addr;
285 struct rte_flow_error error;
287 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
288 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
289 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
291 const struct rte_eth_conf port_conf_default = {
292 .lpbk_mode =
app_config->port_config.lpbk_support,
297 .rss_key_len = symmetric_hash_key_length,
298 .rss_key = symmetric_hash_key,
299 .rss_hf = (RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP),
303 struct rte_eth_conf port_conf = port_conf_default;
305 ret = rte_eth_dev_info_get(port, &
dev_info);
307 DOCA_LOG_ERR(
"Failed getting device (port %u) info, error=%s", port, strerror(-ret));
310 if (*
dev_info.dev_flags & RTE_ETH_DEV_REPRESENTOR &&
app_config->port_config.switch_mode) {
311 DOCA_LOG_INFO(
"Skip represent port %d init in switch mode", port);
315 port_conf.rxmode.mq_mode = rss_support ? RTE_ETH_MQ_RX_RSS : RTE_ETH_MQ_RX_NONE;
316 port_conf.txmode.offloads =
app_config->port_config.tx_offloads;
319 ret = rte_eth_dev_configure(port, rx_rings + nb_hairpin_queues, tx_rings + nb_hairpin_queues, &port_conf);
321 DOCA_LOG_ERR(
"Failed to configure the ethernet device - (%d)", ret);
324 if (port_conf_default.rx_adv_conf.rss_conf.rss_hf != port_conf.rx_adv_conf.rss_conf.rss_hf) {
325 DOCA_LOG_DBG(
"Port %u modified RSS hash function based on hardware support, requested:%#" PRIx64
326 " configured:%#" PRIx64
"",
328 port_conf_default.rx_adv_conf.rss_conf.rss_hf,
329 port_conf.rx_adv_conf.rss_conf.rss_hf);
333 ret = rte_eth_promiscuous_enable(port);
335 DOCA_LOG_ERR(
"Failed to Enable RX in promiscuous mode - (%d)", ret);
340 for (q = 0; q < rx_rings; q++) {
341 ret = rte_eth_rx_queue_setup(port, q,
RX_RING_SIZE, rte_eth_dev_socket_id(port),
NULL, mbuf_pool);
349 for (q = 0; q < tx_rings; q++) {
350 ret = rte_eth_tx_queue_setup(port, q,
TX_RING_SIZE, rte_eth_dev_socket_id(port),
NULL);
358 if (nb_hairpin_queues) {
359 uint16_t rss_queue_list[nb_hairpin_queues];
361 if (
app_config->port_config.self_hairpin && rte_eth_dev_is_valid_port(port ^ 1)) {
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;
368 DOCA_LOG_ERR(
"Cannot hairpin self port %" PRIu8
", ret: %s",
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;
377 DOCA_LOG_ERR(
"Cannot hairpin peer port %" PRIu8
", ret: %s",
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))
398 ret = rte_flow_isolate(port, isolated, &error);
400 DOCA_LOG_ERR(
"Port %u could not be set isolated mode to %s (%s)",
402 isolated ?
"true" :
"false",
407 DOCA_LOG_INFO(
"Ingress traffic on port %u is in isolated mode", port);
410 ret = rte_eth_dev_start(port);
412 DOCA_LOG_ERR(
"Cannot start port %" PRIu8
", ret=%d", port, ret);
417 rte_eth_macaddr_get(port, &
addr);
418 DOCA_LOG_DBG(
"Port %u MAC: %02" PRIx8
" %02" PRIx8
" %02" PRIx8
" %02" PRIx8
" %02" PRIx8
" %02" PRIx8
"",
431 if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (
int)rte_socket_id()) {
432 DOCA_LOG_WARN(
"Port %u is on remote NUMA node to polling thread", port);
449 for (port_id =
nb_ports; port_id >= 0; port_id--) {
450 if (!rte_eth_dev_is_valid_port(port_id))
452 result = rte_eth_dev_stop(port_id);
456 result = rte_eth_dev_close(port_id);
463 rte_mempool_free(app_dpdk_config->
mbuf_pool);
480 const uint32_t mbuf_size =
app_config->port_config.mbuf_size ?
app_config->port_config.mbuf_size :
481 RTE_MBUF_DEFAULT_BUF_SIZE;
492 if (
app_config->port_config.enable_mbuf_metadata) {
493 ret = rte_flow_dynf_metadata_register();
500 for (port_id = 0, n = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
501 if (!rte_eth_dev_is_valid_port(port_id))
521 ret = rte_eth_dev_count_avail();
522 if (app_dpdk_config->
port_config.
nb_ports > 0 && ret < app_dpdk_config->port_config.nb_ports) {
523 DOCA_LOG_ERR(
"Application will only function with %u ports, num_of_ports=%d",
530 ret = rte_lcore_count();
531 if (app_dpdk_config->
port_config.
nb_queues > 0 && ret < app_dpdk_config->port_config.nb_queues) {
532 DOCA_LOG_ERR(
"At least %u cores are needed for the application to run, available_cores=%d",
579 const struct rte_ether_addr *smac,
580 const uint32_t ethertype)
582 char dmac_buf[RTE_ETHER_ADDR_FMT_SIZE];
583 char smac_buf[RTE_ETHER_ADDR_FMT_SIZE];
585 rte_ether_format_addr(dmac_buf, RTE_ETHER_ADDR_FMT_SIZE, dmac);
586 rte_ether_format_addr(smac_buf, RTE_ETHER_ADDR_FMT_SIZE, smac);
587 DOCA_LOG_DBG(
"DMAC=%s, SMAC=%s, ether_type=0x%04x", dmac_buf, smac_buf, ethertype);
597 struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(packet,
struct rte_ether_hdr *);
599 print_ether_addr(ð_hdr->dst_addr, ð_hdr->src_addr, htonl(eth_hdr->ether_type) >> 16);
609 static void print_ipv4_addr(
const rte_be32_t dip,
const rte_be32_t sip,
const char *packet_type)
612 (dip & 0xff000000) >> 24,
613 (dip & 0x00ff0000) >> 16,
614 (dip & 0x0000ff00) >> 8,
616 (sip & 0xff000000) >> 24,
617 (sip & 0x00ff0000) >> 16,
618 (sip & 0x0000ff00) >> 8,
645 if (RTE_ETH_IS_IPV4_HDR(packet->packet_type)) {
647 rte_pktmbuf_mtod_offset(packet,
struct rte_ipv4_hdr *,
sizeof(
struct rte_ether_hdr));
651 rte_get_ptype_l4_name(packet->packet_type));
652 }
else if (RTE_ETH_IS_IPV6_HDR(packet->packet_type)) {
653 struct rte_ipv6_hdr *ipv6_hdr =
654 rte_pktmbuf_mtod_offset(packet,
struct rte_ipv6_hdr *,
sizeof(
struct rte_ether_hdr));
656 print_ipv6_addr(ipv6_hdr->dst_addr, ipv6_hdr->src_addr, rte_get_ptype_l4_name(packet->packet_type));
669 const struct rte_tcp_hdr *
tcp_hdr;
670 const struct rte_udp_hdr *
udp_hdr;
672 if (!RTE_ETH_IS_IPV4_HDR(packet->packet_type))
675 ipv4_hdr = rte_pktmbuf_mtod_offset(packet,
struct rte_ipv4_hdr *,
sizeof(
struct rte_ether_hdr));
709 struct rte_mempool_memhdr *memhdr,
710 unsigned int mem_idx)
716 struct doca_mmap *new_mmap;
751 uint32_t nb_iterated_chunks, nb_chunks;
754 if (mempool_shadow ==
NULL) {
760 nb_chunks = mbuf_pool->nb_mem_chunks;
761 mempool_shadow->
mmap_arr = (
struct doca_mmap **)rte_zmalloc(
NULL,
sizeof(
struct doca_mmap *) * nb_chunks, 0);
770 if (nb_iterated_chunks != mempool_shadow->
nb_mmaps) {
775 return mempool_shadow;
789 struct doca_mmap *new_mmap;
832 if (mempool_shadow ==
NULL) {
838 mempool_shadow->
mmap_arr = (
struct doca_mmap **)rte_zmalloc(
NULL,
sizeof(
struct doca_mmap *) * ext_num, 0);
846 for (i = 0; i < ext_num; ++i) {
854 return mempool_shadow;
862 for (mmap_idx = 0; mmap_idx < mempool_shadow->
nb_mmaps; mmap_idx++)
866 rte_free(mempool_shadow);
870 struct doca_buf_inventory *inventory,
872 size_t mem_range_size,
873 struct doca_buf **out_buf)
880 for (mmap_idx = 0; mmap_idx < mempool_shadow->
nb_mmaps; mmap_idx++) {
881 struct doca_mmap *
mmap = mempool_shadow->
mmap_arr[mmap_idx];
885 if (mmap_begin <= mem_range_start && mem_range_start < mmap_begin + mmap_len &&
886 mem_range_size <= mmap_begin + mmap_len - mem_range_start)
889 (
void *)mem_range_start,
897 void print_header_info(
const struct rte_mbuf *packet,
const bool l2,
const bool l3,
const bool l4)
911 result = rte_eal_init(argc, argv);
923 result = rte_eal_cleanup();
struct rte_eth_dev_info dev_info
if(bitoffset % 64+bitlength > 64) result|
static void print_ipv6_addr(const uint8_t dst_addr[16], const uint8_t src_addr[16], const char *packet_type)
static doca_error_t port_init(struct rte_mempool *mbuf_pool, uint8_t port, struct application_dpdk_config *app_config)
void dpdk_mempool_shadow_destroy(struct dpdk_mempool_shadow *mempool_shadow)
static doca_error_t enable_hairpin_queues(uint8_t nb_ports)
static void disable_hairpin_queues(uint16_t nb_ports)
doca_error_t dpdk_init(int argc, char **argv)
struct dpdk_mempool_shadow * dpdk_mempool_shadow_create_extbuf(const struct rte_pktmbuf_extmem **ext_mem, uint32_t ext_num, struct doca_dev *device)
static void print_l2_header(const struct rte_mbuf *packet)
static doca_error_t setup_hairpin_queues(uint16_t port_id, uint16_t peer_port_id, uint16_t *reserved_hairpin_q_list, int hairpin_queue_len)
static doca_error_t dpdk_ext_chunk_to_mmap(struct dpdk_mempool_shadow *mempool_shadow, void *chunk, size_t len)
static void print_ether_addr(const struct rte_ether_addr *dmac, const struct rte_ether_addr *smac, const uint32_t ethertype)
doca_error_t dpdk_queues_and_ports_init(struct application_dpdk_config *app_dpdk_config)
static void print_l3_header(const struct rte_mbuf *packet)
static doca_error_t dpdk_ports_init(struct application_dpdk_config *app_config)
void dpdk_queues_and_ports_fini(struct application_dpdk_config *app_dpdk_config)
static doca_error_t unbind_hairpin_queues(uint16_t port_id)
doca_error_t dpdk_mempool_shadow_find_buf_by_data(struct dpdk_mempool_shadow *mempool_shadow, struct doca_buf_inventory *inventory, uintptr_t mem_range_start, size_t mem_range_size, struct doca_buf **out_buf)
static doca_error_t bind_hairpin_queues(uint16_t port_id)
static doca_error_t allocate_mempool(const uint32_t total_nb_mbufs, const uint32_t mbuf_size, struct rte_mempool **mbuf_pool)
static void dpdk_ports_fini(struct application_dpdk_config *app_dpdk_config, uint16_t nb_ports)
static void print_ipv4_addr(const rte_be32_t dip, const rte_be32_t sip, const char *packet_type)
static void print_l4_header(const struct rte_mbuf *packet)
DOCA_LOG_REGISTER(NUTILS)
struct dpdk_mempool_shadow * dpdk_mempool_shadow_create(struct rte_mempool *mbuf_pool, struct doca_dev *device)
void print_header_info(const struct rte_mbuf *packet, const bool l2, const bool l3, const bool l4)
static void dpdk_chunk_to_mmap_cb(struct rte_mempool *mp, void *opaque, struct rte_mempool_memhdr *memhdr, unsigned int mem_idx)
static doca_error_t doca_buf_inventory_buf_get_by_data(struct doca_buf_inventory *inventory, struct doca_mmap *mmap, void *data, size_t data_len, struct doca_buf **buf)
Allocate single element from buffer inventory and point it to the buffer defined by data & data_len a...
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.
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
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_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_get_memrange(const struct doca_mmap *mmap, void **addr, size_t *len)
Get the memory range of 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.
__UINTPTR_TYPE__ uintptr_t
struct rte_mempool * mbuf_pool
struct application_port_config port_config
struct doca_mmap ** mmap_arr