// (c) 2023 Fraunhofer IIS, Maximilian Engelhardt #ifndef MWE_COMMON_H #define MWE_COMMON_H #include #include #include #include #define NUM_MBUFS 1024*1024 #define MBUF_CACHE_SIZE 250 int hwts_dynfield_offset = 0; uint64_t hwts_dynflag_tx_mask = 0; static const struct rte_eth_conf port_conf_default = { .rxmode = { .mtu = 9600, }, }; #define ASSERT(cond, text) do { \ int ret = cond; \ if (!ret) { \ fprintf(stderr, "%s:%d: assertion { %s } failed (%s)\n", __FILE__, __LINE__, #cond, text); \ abort(); \ } \ } while (0) #define ASSERTP(cond) do { \ int ret = cond; \ if (!(ret == 0)) { \ fprintf(stderr, "%s:%d: assertion { %s == 0 } failed (%s)\n", __FILE__, __LINE__, #cond, strerror(ret)); \ abort(); \ } \ } while (0) bool run = true; struct rte_mempool *mbuf_pool; struct Header { uint8_t stream_id; uint64_t stream_pos; } __attribute__((packed)); void signalHandler( int signum ) { run = false; } void init_dpdk(int *argc, char **argv[]) { signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); int ret = rte_eal_init(*argc, *argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); *argc -= ret; *argv += ret; auto nb_ports = rte_eth_dev_count_avail(); ASSERT(nb_ports>0, "No Port available!"); mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, 10000, rte_socket_id()); int port_id = 0; struct rte_eth_conf port_conf = port_conf_default; uint16_t rx_rings = 1; uint16_t tx_rings = 2; uint16_t nb_rxd = 4096; uint16_t nb_txd = 4096; struct rte_eth_dev_info dev_info{}; struct rte_eth_txconf txconf{}; rte_eth_dev_info_get(port_id, &dev_info); if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; port_conf.rxmode.offloads = RTE_ETH_RX_OFFLOAD_TIMESTAMP; port_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP; // Configure the Ethernet device. rte_eth_dev_configure(port_id, rx_rings, tx_rings, &port_conf); rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); // RX setup for (int q = 0; q < rx_rings; q++) { ASSERTP(rte_eth_rx_queue_setup(port_id, q, nb_rxd, rte_eth_dev_socket_id(port_id), NULL, mbuf_pool)); } // TX setup txconf = dev_info.default_txconf; txconf.offloads = port_conf.txmode.offloads; for (int q = 0; q < tx_rings; q++) { ASSERTP(rte_eth_tx_queue_setup(port_id, q, nb_txd, rte_eth_dev_socket_id(port_id), &txconf)); } rte_mbuf_dyn_rx_timestamp_register(&hwts_dynfield_offset, NULL); rte_mbuf_dyn_tx_timestamp_register(&hwts_dynfield_offset, &hwts_dynflag_tx_mask); if (hwts_dynfield_offset < 0) { printf("ERROR: Failed to register timestamp field\n"); } ASSERTP(rte_eth_dev_set_mtu(port_id, 9100)); ASSERTP(rte_eth_promiscuous_enable(port_id)); ASSERTP(rte_eth_dev_start(port_id)); struct rte_ether_addr localaddr{}; rte_eth_macaddr_get(port_id, &localaddr); rte_flow_flush(port_id, nullptr); } void print_xstats() { rte_eth_xstat_name stats_names[512]; rte_eth_xstat stats[512]; auto num_names = rte_eth_xstats_get_names(0, stats_names, 512); auto num_stats = rte_eth_xstats_get(0, stats, 512); for (int i = 0; i < num_stats; ++i) { auto name = std::string(stats_names[i].name); if (stats[i].value == 0) continue; printf("%s: %lu\n", stats_names[i].name, stats[i].value); } } #endif