X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-eventdev%2Ftest_pipeline_common.c;h=12a58fbbfb60eea4ac0745817b49e25ef84fb228;hb=e279bbe4b2b831972ae53d95c37a17fdff13a700;hp=63f54daefce37f08a68aafc6d511679d76b1356b;hpb=385cefd91ee207a89fb2005dcf0a6761fe241ecf;p=dpdk.git diff --git a/app/test-eventdev/test_pipeline_common.c b/app/test-eventdev/test_pipeline_common.c index 63f54daefc..12a58fbbfb 100644 --- a/app/test-eventdev/test_pipeline_common.c +++ b/app/test-eventdev/test_pipeline_common.c @@ -5,6 +5,58 @@ #include "test_pipeline_common.h" +static int32_t +pipeline_event_tx_burst_service_func(void *args) +{ + + int i; + struct tx_service_data *tx = args; + const uint8_t dev = tx->dev_id; + const uint8_t port = tx->port_id; + struct rte_event ev[BURST_SIZE + 1]; + + uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev, BURST_SIZE, 0); + + if (!nb_rx) { + for (i = 0; i < tx->nb_ethports; i++) + rte_eth_tx_buffer_flush(i, 0, tx->tx_buf[i]); + return 0; + } + + for (i = 0; i < nb_rx; i++) { + struct rte_mbuf *m = ev[i].mbuf; + rte_eth_tx_buffer(m->port, 0, tx->tx_buf[m->port], m); + } + tx->processed_pkts += nb_rx; + + return 0; +} + +static int32_t +pipeline_event_tx_service_func(void *args) +{ + + int i; + struct tx_service_data *tx = args; + const uint8_t dev = tx->dev_id; + const uint8_t port = tx->port_id; + struct rte_event ev; + + uint16_t nb_rx = rte_event_dequeue_burst(dev, port, &ev, 1, 0); + + if (!nb_rx) { + for (i = 0; i < tx->nb_ethports; i++) + rte_eth_tx_buffer_flush(i, 0, tx->tx_buf[i]); + return 0; + } + + struct rte_mbuf *m = ev.mbuf; + rte_eth_tx_buffer(m->port, 0, tx->tx_buf[m->port], m); + tx->processed_pkts++; + + return 0; +} + int pipeline_test_result(struct evt_test *test, struct evt_options *opt) { @@ -38,6 +90,73 @@ pipeline_opt_dump(struct evt_options *opt, uint8_t nb_queues) evt_dump_producer_type(opt); } +static inline uint64_t +processed_pkts(struct test_pipeline *t) +{ + uint8_t i; + uint64_t total = 0; + + rte_smp_rmb(); + if (t->mt_unsafe) + total = t->tx_service.processed_pkts; + else + for (i = 0; i < t->nb_workers; i++) + total += t->worker[i].processed_pkts; + + return total; +} + +int +pipeline_launch_lcores(struct evt_test *test, struct evt_options *opt, + int (*worker)(void *)) +{ + int ret, lcore_id; + struct test_pipeline *t = evt_test_priv(test); + + int port_idx = 0; + /* launch workers */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (!(opt->wlcores[lcore_id])) + continue; + + ret = rte_eal_remote_launch(worker, + &t->worker[port_idx], lcore_id); + if (ret) { + evt_err("failed to launch worker %d", lcore_id); + return ret; + } + port_idx++; + } + + uint64_t perf_cycles = rte_get_timer_cycles(); + const uint64_t perf_sample = rte_get_timer_hz(); + + static float total_mpps; + static uint64_t samples; + + uint64_t prev_pkts = 0; + + while (t->done == false) { + const uint64_t new_cycles = rte_get_timer_cycles(); + + if ((new_cycles - perf_cycles) > perf_sample) { + const uint64_t curr_pkts = processed_pkts(t); + + float mpps = (float)(curr_pkts - prev_pkts)/1000000; + + prev_pkts = curr_pkts; + perf_cycles = new_cycles; + total_mpps += mpps; + ++samples; + printf(CLGRN"\r%.3f mpps avg %.3f mpps"CLNRM, + mpps, total_mpps/samples); + fflush(stdout); + } + } + printf("\n"); + return 0; +} + int pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues) { @@ -47,7 +166,7 @@ pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues) */ lcores = 2; - if (!rte_eth_dev_count()) { + if (!rte_eth_dev_count_avail()) { evt_err("test needs minimum 1 ethernet dev"); return -1; } @@ -94,7 +213,7 @@ pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues) int pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt) { - int i; + uint16_t i; uint8_t nb_queues = 1; uint8_t mt_state = 0; struct test_pipeline *t = evt_test_priv(test); @@ -103,8 +222,6 @@ pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt) .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, - .offloads = DEV_RX_OFFLOAD_CRC_STRIP, - .ignore_offload_bitfield = 1, }, .rx_adv_conf = { .rss_conf = { @@ -115,23 +232,34 @@ pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt) }; RTE_SET_USED(opt); - if (!rte_eth_dev_count()) { + if (!rte_eth_dev_count_avail()) { evt_err("No ethernet ports found.\n"); return -ENODEV; } - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { struct rte_eth_dev_info dev_info; + struct rte_eth_conf local_port_conf = port_conf; - memset(&dev_info, 0, sizeof(struct rte_eth_dev_info)); rte_eth_dev_info_get(i, &dev_info); mt_state = !(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MT_LOCKFREE); rx_conf = dev_info.default_rxconf; rx_conf.offloads = port_conf.rxmode.offloads; + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + evt_info("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + i, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + if (rte_eth_dev_configure(i, nb_queues, nb_queues, - &port_conf) + &local_port_conf) < 0) { evt_err("Failed to configure eth port [%d]\n", i); return -EINVAL; @@ -151,6 +279,10 @@ pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt) } t->mt_unsafe |= mt_state; + t->tx_service.tx_buf[i] = + rte_malloc(NULL, RTE_ETH_TX_BUFFER_SIZE(BURST_SIZE), 0); + if (t->tx_service.tx_buf[i] == NULL) + rte_panic("Unable to allocate Tx buffer memory."); rte_eth_promiscuous_enable(i); } @@ -214,7 +346,7 @@ pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride, memset(&queue_conf, 0, sizeof(struct rte_event_eth_rx_adapter_queue_conf)); queue_conf.ev.sched_type = opt->sched_type_list[0]; - for (prod = 0; prod < rte_eth_dev_count(); prod++) { + RTE_ETH_FOREACH_DEV(prod) { uint32_t cap; ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id, @@ -271,17 +403,79 @@ pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride, return ret; } +int +pipeline_event_tx_service_setup(struct evt_test *test, struct evt_options *opt, + uint8_t tx_queue_id, uint8_t tx_port_id, + const struct rte_event_port_conf p_conf) +{ + int ret; + struct rte_service_spec serv; + struct test_pipeline *t = evt_test_priv(test); + struct tx_service_data *tx = &t->tx_service; + + ret = rte_event_port_setup(opt->dev_id, tx_port_id, &p_conf); + if (ret) { + evt_err("failed to setup port %d", tx_port_id); + return ret; + } + + if (rte_event_port_link(opt->dev_id, tx_port_id, &tx_queue_id, + NULL, 1) != 1) { + evt_err("failed to link queues to port %d", tx_port_id); + return -EINVAL; + } + + tx->dev_id = opt->dev_id; + tx->queue_id = tx_queue_id; + tx->port_id = tx_port_id; + tx->nb_ethports = rte_eth_dev_count_avail(); + tx->t = t; + + /* Register Tx service */ + memset(&serv, 0, sizeof(struct rte_service_spec)); + snprintf(serv.name, sizeof(serv.name), "Tx_service"); + + if (evt_has_burst_mode(opt->dev_id)) + serv.callback = pipeline_event_tx_burst_service_func; + else + serv.callback = pipeline_event_tx_service_func; + + serv.callback_userdata = (void *)tx; + ret = rte_service_component_register(&serv, &tx->service_id); + if (ret) { + evt_err("failed to register Tx service"); + return ret; + } + + ret = evt_service_setup(tx->service_id); + if (ret) { + evt_err("Failed to setup service core for Tx service\n"); + return ret; + } + + rte_service_runstate_set(tx->service_id, 1); + + return 0; +} + + void pipeline_ethdev_destroy(struct evt_test *test, struct evt_options *opt) { - int i; + uint16_t i; RTE_SET_USED(test); RTE_SET_USED(opt); + struct test_pipeline *t = evt_test_priv(test); + + if (t->mt_unsafe) { + rte_service_component_runstate_set(t->tx_service.service_id, 0); + rte_service_runstate_set(t->tx_service.service_id, 0); + rte_service_component_unregister(t->tx_service.service_id); + } - for (i = 0; i < rte_eth_dev_count(); i++) { + RTE_ETH_FOREACH_DEV(i) { rte_event_eth_rx_adapter_stop(i); rte_eth_dev_stop(i); - rte_eth_dev_close(i); } }