#include "pipeline_common.h"
+struct fastpath_data *fdata;
+
struct config_data cdata = {
.num_packets = (1L << 25), /* do ~32M packets */
.num_fids = 512,
fdata->tx_core[lcore_id] || fdata->worker_core[lcore_id]);
}
-static void
-eth_tx_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,
- void *userdata)
-{
- int port_id = (uintptr_t) userdata;
- unsigned int _sent = 0;
-
- do {
- /* Note: hard-coded TX queue */
- _sent += rte_eth_tx_burst(port_id, 0, &pkts[_sent],
- unsent - _sent);
- } while (_sent != unsent);
-}
-
/*
* Parse the coremask given as argument (hexadecimal string) and fill
* the global configuration (core role and core count) with the parsed
}
}
-/*
- * Initializes a given port using global settings and with the RX buffers
- * coming from the mbuf_pool passed as a parameter.
- */
-static inline int
-port_init(uint8_t port, struct rte_mempool *mbuf_pool)
-{
- static const struct rte_eth_conf port_conf_default = {
- .rxmode = {
- .mq_mode = ETH_MQ_RX_RSS,
- .max_rx_pkt_len = ETHER_MAX_LEN,
- .ignore_offload_bitfield = 1,
- },
- .rx_adv_conf = {
- .rss_conf = {
- .rss_hf = ETH_RSS_IP |
- ETH_RSS_TCP |
- ETH_RSS_UDP,
- }
- }
- };
- const uint16_t rx_rings = 1, tx_rings = 1;
- const uint16_t rx_ring_size = 512, tx_ring_size = 512;
- struct rte_eth_conf port_conf = port_conf_default;
- int retval;
- uint16_t q;
- struct rte_eth_dev_info dev_info;
- struct rte_eth_txconf txconf;
-
- if (port >= rte_eth_dev_count())
- return -1;
-
- rte_eth_dev_info_get(port, &dev_info);
- if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
- port_conf.txmode.offloads |=
- DEV_TX_OFFLOAD_MBUF_FAST_FREE;
-
- /* Configure the Ethernet device. */
- retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
- if (retval != 0)
- return retval;
-
- /* Allocate and set up 1 RX queue per Ethernet port. */
- for (q = 0; q < rx_rings; q++) {
- retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
- rte_eth_dev_socket_id(port), NULL, mbuf_pool);
- if (retval < 0)
- return retval;
- }
-
- txconf = dev_info.default_txconf;
- txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE;
- txconf.offloads = port_conf_default.txmode.offloads;
- /* Allocate and set up 1 TX queue per Ethernet port. */
- for (q = 0; q < tx_rings; q++) {
- retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
- rte_eth_dev_socket_id(port), &txconf);
- if (retval < 0)
- return retval;
- }
-
- /* Start the Ethernet port. */
- retval = rte_eth_dev_start(port);
- if (retval < 0)
- return retval;
-
- /* Display the port MAC address. */
- struct ether_addr addr;
- rte_eth_macaddr_get(port, &addr);
- printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
- " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
- (unsigned int)port,
- addr.addr_bytes[0], addr.addr_bytes[1],
- addr.addr_bytes[2], addr.addr_bytes[3],
- addr.addr_bytes[4], addr.addr_bytes[5]);
-
- /* Enable RX in promiscuous mode for the Ethernet device. */
- rte_eth_promiscuous_enable(port);
-
- return 0;
-}
-
-static int
-init_ports(unsigned int num_ports)
-{
- uint8_t portid;
- unsigned int i;
-
- if (!cdata.num_mbuf)
- cdata.num_mbuf = 16384 * num_ports;
-
- struct rte_mempool *mp = rte_pktmbuf_pool_create("packet_pool",
- /* mbufs */ cdata.num_mbuf,
- /* cache_size */ 512,
- /* priv_size*/ 0,
- /* data_room_size */ RTE_MBUF_DEFAULT_BUF_SIZE,
- rte_socket_id());
-
- for (portid = 0; portid < num_ports; portid++)
- if (port_init(portid, mp) != 0)
- rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n",
- portid);
-
- for (i = 0; i < num_ports; i++) {
- void *userdata = (void *)(uintptr_t) i;
- fdata->tx_buf[i] =
- rte_malloc(NULL, RTE_ETH_TX_BUFFER_SIZE(32), 0);
- if (fdata->tx_buf[i] == NULL)
- rte_panic("Out of memory\n");
- rte_eth_tx_buffer_init(fdata->tx_buf[i], 32);
- rte_eth_tx_buffer_set_err_callback(fdata->tx_buf[i],
- eth_tx_buffer_retry,
- userdata);
- }
-
- return 0;
-}
-
static void
-do_capability_setup(uint16_t nb_ethdev, uint8_t eventdev_id)
+do_capability_setup(uint8_t eventdev_id)
{
- int i;
- uint8_t mt_unsafe = 0;
+ int ret;
+ uint16_t i;
+ uint8_t generic_pipeline = 0;
uint8_t burst = 0;
- for (i = 0; i < nb_ethdev; i++) {
- struct rte_eth_dev_info dev_info;
- memset(&dev_info, 0, sizeof(struct rte_eth_dev_info));
+ RTE_ETH_FOREACH_DEV(i) {
+ uint32_t caps = 0;
- rte_eth_dev_info_get(i, &dev_info);
- /* Check if it is safe ask worker to tx. */
- mt_unsafe |= !(dev_info.tx_offload_capa &
- DEV_TX_OFFLOAD_MT_LOCKFREE);
+ ret = rte_event_eth_tx_adapter_caps_get(eventdev_id, i, &caps);
+ if (ret)
+ rte_exit(EXIT_FAILURE,
+ "Invalid capability for Tx adptr port %d\n", i);
+ generic_pipeline |= !(caps &
+ RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT);
}
struct rte_event_dev_info eventdev_info;
burst = eventdev_info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE ? 1 :
0;
- if (mt_unsafe)
+ if (generic_pipeline)
set_worker_generic_setup_data(&fdata->cap, burst);
else
- set_worker_tx_setup_data(&fdata->cap, burst);
+ set_worker_tx_enq_setup_data(&fdata->cap, burst);
}
static void
signal_handler(int signum)
{
+ static uint8_t once;
+ uint16_t portid;
+
if (fdata->done)
rte_exit(1, "Exiting on signal %d\n", signum);
- if (signum == SIGINT || signum == SIGTERM) {
+ if ((signum == SIGINT || signum == SIGTERM) && !once) {
printf("\n\nSignal %d received, preparing to exit...\n",
signum);
+ if (cdata.dump_dev)
+ rte_event_dev_dump(0, stdout);
+ once = 1;
fdata->done = 1;
+ rte_smp_wmb();
+
+ RTE_ETH_FOREACH_DEV(portid) {
+ rte_event_eth_rx_adapter_stop(portid);
+ rte_event_eth_tx_adapter_stop(portid);
+ rte_eth_dev_stop(portid);
+ }
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_ETH_FOREACH_DEV(portid) {
+ rte_eth_dev_close(portid);
+ }
+
+ rte_event_dev_stop(0);
+ rte_event_dev_close(0);
}
if (signum == SIGTSTP)
rte_event_dev_dump(0, stdout);
main(int argc, char **argv)
{
struct worker_data *worker_data;
- unsigned int num_ports;
+ uint16_t num_ports;
+ uint16_t portid;
int lcore_id;
int err;
/* Parse cli options*/
parse_app_args(argc, argv);
- num_ports = rte_eth_dev_count();
+ num_ports = rte_eth_dev_count_avail();
if (num_ports == 0)
rte_panic("No ethernet ports found\n");
fprintf(stderr, "Warning: More than one eventdev, using idx 0");
- do_capability_setup(num_ports, 0);
+ do_capability_setup(0);
fdata->cap.check_opt();
worker_data = rte_calloc(0, cdata.num_workers,
if (worker_data == NULL)
rte_panic("rte_calloc failed\n");
- int dev_id = fdata->cap.evdev_setup(&cons_data, worker_data);
+ int dev_id = fdata->cap.evdev_setup(worker_data);
if (dev_id < 0)
rte_exit(EXIT_FAILURE, "Error setting up eventdev\n");
- init_ports(num_ports);
fdata->cap.adptr_setup(num_ports);
+ /* Start the Ethernet port. */
+ RTE_ETH_FOREACH_DEV(portid) {
+ err = rte_eth_dev_start(portid);
+ if (err < 0)
+ rte_exit(EXIT_FAILURE, "Error starting ethdev %d\n",
+ portid);
+ }
+
int worker_idx = 0;
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
if (lcore_id >= MAX_NUM_CORE)
if (fdata->tx_core[lcore_id])
printf(
- "[%s()] lcore %d executing NIC Tx, and using eventdev port %u\n",
- __func__, lcore_id, cons_data.port_id);
+ "[%s()] lcore %d executing NIC Tx\n",
+ __func__, lcore_id);
if (fdata->sched_core[lcore_id])
printf("[%s()] lcore %d executing scheduler\n",
rte_eal_mp_wait_lcore();
- if (cdata.dump_dev)
- rte_event_dev_dump(dev_id, stdout);
-
if (!cdata.quiet && (port_stat(dev_id, worker_data[0].port_id) !=
(uint64_t)-ENOTSUP)) {
printf("\nPort Workload distribution:\n");