X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fdistributor%2Fmain.c;h=567c5e98919d0a998882ff7875aa334ecdd1d7e8;hb=fa19eb20d2126d8bc63acc8f336a353dfaf8c354;hp=03a05e3d92386869fdec2d45c6cd7dfa1f253e0e;hpb=4f5701f28bd41cbe582a03af4d82d1fa6c1cab91;p=dpdk.git diff --git a/examples/distributor/main.c b/examples/distributor/main.c index 03a05e3d92..567c5e9891 100644 --- a/examples/distributor/main.c +++ b/examples/distributor/main.c @@ -16,6 +16,7 @@ #include #include #include +#include #define RX_RING_SIZE 1024 #define TX_RING_SIZE 1024 @@ -37,6 +38,7 @@ volatile uint8_t quit_signal; volatile uint8_t quit_signal_rx; volatile uint8_t quit_signal_dist; volatile uint8_t quit_signal_work; +unsigned int power_lib_initialised; static volatile struct app_stats { struct { @@ -79,7 +81,7 @@ struct app_stats prev_app_stats; static const struct rte_eth_conf port_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, - .max_rx_pkt_len = ETHER_MAX_LEN, + .max_rx_pkt_len = RTE_ETHER_MAX_LEN, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, @@ -118,7 +120,13 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) if (!rte_eth_dev_is_valid_port(port)) return -1; - rte_eth_dev_info_get(port, &dev_info); + retval = rte_eth_dev_info_get(port, &dev_info); + if (retval != 0) { + printf("Error during getting device (port %u) info: %s\n", + port, strerror(-retval)); + return retval; + } + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; @@ -165,20 +173,32 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) return retval; struct rte_eth_link link; - rte_eth_link_get_nowait(port, &link); - while (!link.link_status) { + do { + retval = rte_eth_link_get_nowait(port, &link); + if (retval < 0) { + printf("Failed link get (port %u): %s\n", + port, rte_strerror(-retval)); + return retval; + } else if (link.link_status) + break; + printf("Waiting for Link up on port %"PRIu16"\n", port); sleep(1); - rte_eth_link_get_nowait(port, &link); - } + } while (!link.link_status); if (!link.link_status) { printf("Link down on port %"PRIu16"\n", port); return 0; } - struct ether_addr addr; - rte_eth_macaddr_get(port, &addr); + struct rte_ether_addr addr; + retval = rte_eth_macaddr_get(port, &addr); + if (retval < 0) { + printf("Failed to get MAC address (port %u): %s\n", + port, rte_strerror(-retval)); + return retval; + } + printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", port, @@ -186,7 +206,9 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); - rte_eth_promiscuous_enable(port); + retval = rte_eth_promiscuous_enable(port); + if (retval != 0) + return retval; return 0; } @@ -281,6 +303,8 @@ lcore_rx(struct lcore_params *p) if (++port == nb_ports) port = 0; } + if (power_lib_initialised) + rte_power_exit(rte_lcore_id()); /* set worker & tx threads quit flag */ printf("\nCore %u exiting rx task.\n", rte_lcore_id()); quit_signal = 1; @@ -363,7 +387,8 @@ lcore_distributor(struct lcore_params *p) } printf("\nCore %u exiting distributor task.\n", rte_lcore_id()); quit_signal_work = 1; - + if (power_lib_initialised) + rte_power_exit(rte_lcore_id()); rte_distributor_flush(d); /* Unblock any returns so workers can exit */ rte_distributor_clear_returns(d); @@ -435,6 +460,8 @@ lcore_tx(struct rte_ring *in_r) } } } + if (power_lib_initialised) + rte_power_exit(rte_lcore_id()); printf("\nCore %u exiting tx task.\n", rte_lcore_id()); return 0; } @@ -575,9 +602,33 @@ lcore_worker(struct lcore_params *p) if (num > 0) app_stats.worker_bursts[p->worker_id][num-1]++; } + if (power_lib_initialised) + rte_power_exit(rte_lcore_id()); + rte_free(p); return 0; } +static int +init_power_library(void) +{ + int ret = 0, lcore_id; + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + /* init power management library */ + ret = rte_power_init(lcore_id); + if (ret) { + RTE_LOG(ERR, POWER, + "Library initialization failed on core %u\n", + lcore_id); + /* + * Return on first failure, we'll fall back + * to non-power operation + */ + return ret; + } + } + return ret; +} + /* display usage */ static void print_usage(const char *prgname) @@ -657,7 +708,9 @@ main(int argc, char *argv[]) struct rte_distributor *d; struct rte_ring *dist_tx_ring; struct rte_ring *rx_dist_ring; - unsigned lcore_id, worker_id = 0; + struct rte_power_core_capabilities lcore_cap; + unsigned int lcore_id, worker_id = 0; + int distr_core_id = -1, rx_core_id = -1, tx_core_id = -1; unsigned nb_ports; uint16_t portid; uint16_t nb_ports_available; @@ -687,6 +740,9 @@ main(int argc, char *argv[]) "1 lcore for packet TX\n" "and at least 1 lcore for worker threads\n"); + if (init_power_library() == 0) + power_lib_initialised = 1; + nb_ports = rte_eth_dev_count_avail(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); @@ -742,54 +798,123 @@ main(int argc, char *argv[]) if (rx_dist_ring == NULL) rte_exit(EXIT_FAILURE, "Cannot create output ring\n"); - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (worker_id == rte_lcore_count() - 3) { - printf("Starting distributor on lcore_id %d\n", + if (power_lib_initialised) { + /* + * Here we'll pre-assign lcore ids to the rx, tx and + * distributor workloads if there's higher frequency + * on those cores e.g. if Turbo Boost is enabled. + * It's also worth mentioning that it will assign cores in a + * specific order, so that if there's less than three + * available, the higher frequency cores will go to the + * distributor first, then rx, then tx. + */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + + rte_power_get_capabilities(lcore_id, &lcore_cap); + + if (lcore_cap.priority != 1) + continue; + + if (distr_core_id < 0) { + distr_core_id = lcore_id; + printf("Distributor on priority core %d\n", lcore_id); - /* distributor core */ - struct lcore_params *p = - rte_malloc(NULL, sizeof(*p), 0); - if (!p) - rte_panic("malloc failure\n"); - *p = (struct lcore_params){worker_id, d, - rx_dist_ring, dist_tx_ring, mbuf_pool}; - rte_eal_remote_launch( - (lcore_function_t *)lcore_distributor, - p, lcore_id); - } else if (worker_id == rte_lcore_count() - 4) { - printf("Starting tx on worker_id %d, lcore_id %d\n", - worker_id, lcore_id); - /* tx core */ - rte_eal_remote_launch((lcore_function_t *)lcore_tx, - dist_tx_ring, lcore_id); - } else if (worker_id == rte_lcore_count() - 2) { - printf("Starting rx on worker_id %d, lcore_id %d\n", - worker_id, lcore_id); - /* rx core */ - struct lcore_params *p = - rte_malloc(NULL, sizeof(*p), 0); - if (!p) - rte_panic("malloc failure\n"); - *p = (struct lcore_params){worker_id, d, rx_dist_ring, - dist_tx_ring, mbuf_pool}; - rte_eal_remote_launch((lcore_function_t *)lcore_rx, - p, lcore_id); - } else { - printf("Starting worker on worker_id %d, lcore_id %d\n", - worker_id, lcore_id); - struct lcore_params *p = - rte_malloc(NULL, sizeof(*p), 0); - if (!p) - rte_panic("malloc failure\n"); - *p = (struct lcore_params){worker_id, d, rx_dist_ring, - dist_tx_ring, mbuf_pool}; - - rte_eal_remote_launch((lcore_function_t *)lcore_worker, - p, lcore_id); + continue; + } + if (rx_core_id < 0) { + rx_core_id = lcore_id; + printf("Rx on priority core %d\n", + lcore_id); + continue; + } + if (tx_core_id < 0) { + tx_core_id = lcore_id; + printf("Tx on priority core %d\n", + lcore_id); + continue; + } + } + } + + /* + * If there's any of the key workloads left without an lcore_id + * after the high performing core assignment above, pre-assign + * them here. + */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (lcore_id == (unsigned int)distr_core_id || + lcore_id == (unsigned int)rx_core_id || + lcore_id == (unsigned int)tx_core_id) + continue; + if (distr_core_id < 0) { + distr_core_id = lcore_id; + printf("Distributor on core %d\n", lcore_id); + continue; + } + if (rx_core_id < 0) { + rx_core_id = lcore_id; + printf("Rx on core %d\n", lcore_id); + continue; + } + if (tx_core_id < 0) { + tx_core_id = lcore_id; + printf("Tx on core %d\n", lcore_id); + continue; } - worker_id++; } + printf(" tx id %d, dist id %d, rx id %d\n", + tx_core_id, + distr_core_id, + rx_core_id); + + /* + * Kick off all the worker threads first, avoiding the pre-assigned + * lcore_ids for tx, rx and distributor workloads. + */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (lcore_id == (unsigned int)distr_core_id || + lcore_id == (unsigned int)rx_core_id || + lcore_id == (unsigned int)tx_core_id) + continue; + printf("Starting thread %d as worker, lcore_id %d\n", + worker_id, lcore_id); + struct lcore_params *p = + rte_malloc(NULL, sizeof(*p), 0); + if (!p) + rte_panic("malloc failure\n"); + *p = (struct lcore_params){worker_id++, d, rx_dist_ring, + dist_tx_ring, mbuf_pool}; + + rte_eal_remote_launch((lcore_function_t *)lcore_worker, + p, lcore_id); + } + + /* Start tx core */ + rte_eal_remote_launch((lcore_function_t *)lcore_tx, + dist_tx_ring, tx_core_id); + + /* Start distributor core */ + struct lcore_params *pd = + rte_malloc(NULL, sizeof(*pd), 0); + if (!pd) + rte_panic("malloc failure\n"); + *pd = (struct lcore_params){worker_id++, d, + rx_dist_ring, dist_tx_ring, mbuf_pool}; + rte_eal_remote_launch( + (lcore_function_t *)lcore_distributor, + pd, distr_core_id); + + /* Start rx core */ + struct lcore_params *pr = + rte_malloc(NULL, sizeof(*pr), 0); + if (!pr) + rte_panic("malloc failure\n"); + *pr = (struct lcore_params){worker_id++, d, rx_dist_ring, + dist_tx_ring, mbuf_pool}; + rte_eal_remote_launch((lcore_function_t *)lcore_rx, + pr, rx_core_id); + freq = rte_get_timer_hz(); t = rte_rdtsc() + freq; while (!quit_signal_dist) { @@ -806,5 +931,9 @@ main(int argc, char *argv[]) } print_stats(); + + rte_free(pd); + rte_free(pr); + return 0; }