X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fl3fwd%2Fmain.c;h=dda430d68a203ff0a2f1e55f2197ee71c9913eb0;hb=b685f931e1ce33d287e3891d4f19ab07f8d2aa79;hp=570693b3295e9afeb967370913f543fe3c2271ff;hpb=35b2d13fd6fdcbd191f2a30d74648faeb1186c65;p=dpdk.git diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index 570693b329..dda430d68a 100644 --- a/examples/l3fwd/main.c +++ b/examples/l3fwd/main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -46,12 +46,7 @@ #include #include "l3fwd.h" - -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 +#include "l3fwd_event.h" #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS #define MAX_RX_QUEUE_PER_PORT 128 @@ -289,7 +284,9 @@ print_usage(const char *prgname) " [--hash-entry-num]" " [--ipv6]" " [--parse-ptype]" - " [--per-port-pool]\n\n" + " [--per-port-pool]" + " [--mode]" + " [--eventq-sched]\n\n" " -p PORTMASK: Hexadecimal bitmask of ports to configure\n" " -P : Enable promiscuous mode\n" @@ -304,7 +301,16 @@ print_usage(const char *prgname) " --hash-entry-num: Specify the hash entry number in hexadecimal to be setup\n" " --ipv6: Set if running ipv6 packets\n" " --parse-ptype: Set to use software to analyze packet type\n" - " --per-port-pool: Use separate buffer pool per port\n\n", + " --per-port-pool: Use separate buffer pool per port\n" + " --mode: Packet transfer mode for I/O, poll or eventdev\n" + " Default mode = poll\n" + " --eventq-sched: Event queue synchronization method\n" + " ordered, atomic or parallel.\n" + " Default: atomic\n" + " Valid only if --mode=eventdev\n" + " --event-eth-rxqs: Number of ethernet RX queues per device.\n" + " Default: 1\n" + " Valid only if --mode=eventdev\n\n", prgname); } @@ -440,8 +446,49 @@ parse_eth_dest(const char *optarg) *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; } +static void +parse_mode(const char *optarg) +{ + struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc(); + + if (!strcmp(optarg, "poll")) + evt_rsrc->enabled = false; + else if (!strcmp(optarg, "eventdev")) + evt_rsrc->enabled = true; +} + +static void +parse_eventq_sched(const char *optarg) +{ + struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc(); + + if (!strcmp(optarg, "ordered")) + evt_rsrc->sched_type = RTE_SCHED_TYPE_ORDERED; + if (!strcmp(optarg, "atomic")) + evt_rsrc->sched_type = RTE_SCHED_TYPE_ATOMIC; + if (!strcmp(optarg, "parallel")) + evt_rsrc->sched_type = RTE_SCHED_TYPE_PARALLEL; +} + +static void +parse_event_eth_rx_queues(const char *eth_rx_queues) +{ + struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc(); + char *end = NULL; + uint8_t num_eth_rx_queues; + + /* parse decimal string */ + num_eth_rx_queues = strtoul(eth_rx_queues, &end, 10); + if ((eth_rx_queues[0] == '\0') || (end == NULL) || (*end != '\0')) + return; + + if (num_eth_rx_queues == 0) + return; + + evt_rsrc->eth_rx_queues = num_eth_rx_queues; +} + #define MAX_JUMBO_PKT_LEN 9600 -#define MEMPOOL_CACHE_SIZE 256 static const char short_options[] = "p:" /* portmask */ @@ -458,6 +505,9 @@ static const char short_options[] = #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num" #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype" #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool" +#define CMD_LINE_OPT_MODE "mode" +#define CMD_LINE_OPT_EVENTQ_SYNC "eventq-sched" +#define CMD_LINE_OPT_EVENT_ETH_RX_QUEUES "event-eth-rxqs" enum { /* long options mapped to a short option */ @@ -472,6 +522,9 @@ enum { CMD_LINE_OPT_HASH_ENTRY_NUM_NUM, CMD_LINE_OPT_PARSE_PTYPE_NUM, CMD_LINE_OPT_PARSE_PER_PORT_POOL, + CMD_LINE_OPT_MODE_NUM, + CMD_LINE_OPT_EVENTQ_SYNC_NUM, + CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM, }; static const struct option lgopts[] = { @@ -483,6 +536,10 @@ static const struct option lgopts[] = { {CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, CMD_LINE_OPT_HASH_ENTRY_NUM_NUM}, {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, CMD_LINE_OPT_PARSE_PTYPE_NUM}, {CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL}, + {CMD_LINE_OPT_MODE, 1, 0, CMD_LINE_OPT_MODE_NUM}, + {CMD_LINE_OPT_EVENTQ_SYNC, 1, 0, CMD_LINE_OPT_EVENTQ_SYNC_NUM}, + {CMD_LINE_OPT_EVENT_ETH_RX_QUEUES, 1, 0, + CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM}, {NULL, 0, 0, 0} }; @@ -508,6 +565,10 @@ parse_args(int argc, char **argv) char **argvopt; int option_index; char *prgname = argv[0]; + uint8_t lcore_params = 0; + uint8_t eventq_sched = 0; + uint8_t eth_rx_q = 0; + struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc(); argvopt = argv; @@ -546,6 +607,7 @@ parse_args(int argc, char **argv) print_usage(prgname); return -1; } + lcore_params = 1; break; case CMD_LINE_OPT_ETH_DEST_NUM: @@ -607,6 +669,20 @@ parse_args(int argc, char **argv) per_port_pool = 1; break; + case CMD_LINE_OPT_MODE_NUM: + parse_mode(optarg); + break; + + case CMD_LINE_OPT_EVENTQ_SYNC_NUM: + parse_eventq_sched(optarg); + eventq_sched = 1; + break; + + case CMD_LINE_OPT_EVENT_ETH_RX_QUEUES_NUM: + parse_event_eth_rx_queues(optarg); + eth_rx_q = 1; + break; + default: print_usage(prgname); return -1; @@ -619,6 +695,21 @@ parse_args(int argc, char **argv) return -1; } + if (evt_rsrc->enabled && lcore_params) { + fprintf(stderr, "lcore config is not valid when event mode is selected\n"); + return -1; + } + + if (!evt_rsrc->enabled && eth_rx_q) { + fprintf(stderr, "eth_rx_queues is valid only when event mode is selected\n"); + return -1; + } + + if (!evt_rsrc->enabled && eventq_sched) { + fprintf(stderr, "eventq_sched is valid only when event mode is selected\n"); + return -1; + } + /* * Nothing is selected, pick longest-prefix match * as default match. @@ -654,7 +745,7 @@ print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) printf("%s%s", name, buf); } -static int +int init_mem(uint16_t portid, unsigned int nb_mbuf) { struct lcore_conf *qconf; @@ -718,6 +809,7 @@ check_all_ports_link_status(uint32_t port_mask) uint16_t portid; uint8_t count, all_ports_up, print_flag = 0; struct rte_eth_link link; + int ret; printf("\nChecking link status"); fflush(stdout); @@ -731,7 +823,14 @@ check_all_ports_link_status(uint32_t port_mask) if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); - rte_eth_link_get_nowait(portid, &link); + ret = rte_eth_link_get_nowait(portid, &link); + if (ret < 0) { + all_ports_up = 0; + if (print_flag == 1) + printf("Port %u link get failed: %s\n", + portid, rte_strerror(-ret)); + continue; + } /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) @@ -800,41 +899,18 @@ prepare_ptype_parser(uint16_t portid, uint16_t queueid) return 0; } -int -main(int argc, char **argv) +static void +l3fwd_poll_resource_setup(void) { - struct lcore_conf *qconf; + uint8_t nb_rx_queue, queue, socketid; struct rte_eth_dev_info dev_info; + uint32_t n_tx_queue, nb_lcores; struct rte_eth_txconf *txconf; - int ret; - unsigned nb_ports; + struct lcore_conf *qconf; uint16_t queueid, portid; - unsigned lcore_id; - uint32_t n_tx_queue, nb_lcores; - uint8_t nb_rx_queue, queue, socketid; - - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); - argc -= ret; - argv += ret; - - force_quit = false; - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - - /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - dest_eth_addr[portid] = - RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); - *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; - } - - /* parse application arguments (after the EAL ones) */ - ret = parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); + unsigned int nb_ports; + unsigned int lcore_id; + int ret; if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); @@ -850,9 +926,6 @@ main(int argc, char **argv) nb_lcores = rte_lcore_count(); - /* Setup function pointers for lookup method. */ - setup_l3fwd_lookup_tables(); - /* initialize all ports */ RTE_ETH_FOREACH_DEV(portid) { struct rte_eth_conf local_port_conf = port_conf; @@ -874,7 +947,12 @@ main(int argc, char **argv) printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)n_tx_queue ); - rte_eth_dev_info_get(portid, &dev_info); + ret = rte_eth_dev_info_get(portid, &dev_info); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "Error during getting device (port %u) info: %s\n", + portid, strerror(-ret)); + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; @@ -904,7 +982,12 @@ main(int argc, char **argv) "Cannot adjust number of descriptors: err=%d, " "port=%d\n", ret, portid); - rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); + ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot get MAC address: err=%d, port=%d\n", + ret, portid); + print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); print_ethaddr("Destination:", @@ -971,14 +1054,10 @@ main(int argc, char **argv) fflush(stdout); /* init RX queues */ for(queue = 0; queue < qconf->n_rx_queue; ++queue) { - struct rte_eth_dev *dev; - struct rte_eth_conf *conf; struct rte_eth_rxconf rxq_conf; portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; - dev = &rte_eth_devices[portid]; - conf = &dev->data->dev_conf; if (numa_on) socketid = @@ -989,9 +1068,14 @@ main(int argc, char **argv) printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); - rte_eth_dev_info_get(portid, &dev_info); + ret = rte_eth_dev_info_get(portid, &dev_info); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "Error during getting device (port %u) info: %s\n", + portid, strerror(-ret)); + rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = conf->rxmode.offloads; + rxq_conf.offloads = port_conf.rxmode.offloads; if (!per_port_pool) ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, @@ -1008,8 +1092,145 @@ main(int argc, char **argv) ret, portid); } } +} - printf("\n"); +static inline int +l3fwd_service_enable(uint32_t service_id) +{ + uint8_t min_service_count = UINT8_MAX; + uint32_t slcore_array[RTE_MAX_LCORE]; + unsigned int slcore = 0; + uint8_t service_count; + int32_t slcore_count; + + if (!rte_service_lcore_count()) + return -ENOENT; + + slcore_count = rte_service_lcore_list(slcore_array, RTE_MAX_LCORE); + if (slcore_count < 0) + return -ENOENT; + /* Get the core which has least number of services running. */ + while (slcore_count--) { + /* Reset default mapping */ + rte_service_map_lcore_set(service_id, + slcore_array[slcore_count], 0); + service_count = rte_service_lcore_count_services( + slcore_array[slcore_count]); + if (service_count < min_service_count) { + slcore = slcore_array[slcore_count]; + min_service_count = service_count; + } + } + if (rte_service_map_lcore_set(service_id, slcore, 1)) + return -ENOENT; + rte_service_lcore_start(slcore); + + return 0; +} + +static void +l3fwd_event_service_setup(void) +{ + struct l3fwd_event_resources *evt_rsrc = l3fwd_get_eventdev_rsrc(); + struct rte_event_dev_info evdev_info; + uint32_t service_id, caps; + int ret, i; + + rte_event_dev_info_get(evt_rsrc->event_d_id, &evdev_info); + if (!(evdev_info.event_dev_cap & RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED)) { + ret = rte_event_dev_service_id_get(evt_rsrc->event_d_id, + &service_id); + if (ret != -ESRCH && ret != 0) + rte_exit(EXIT_FAILURE, + "Error in starting eventdev service\n"); + l3fwd_service_enable(service_id); + } + + for (i = 0; i < evt_rsrc->rx_adptr.nb_rx_adptr; i++) { + ret = rte_event_eth_rx_adapter_caps_get(evt_rsrc->event_d_id, + evt_rsrc->rx_adptr.rx_adptr[i], &caps); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Failed to get Rx adapter[%d] caps\n", + evt_rsrc->rx_adptr.rx_adptr[i]); + ret = rte_event_eth_rx_adapter_service_id_get( + evt_rsrc->event_d_id, + &service_id); + if (ret != -ESRCH && ret != 0) + rte_exit(EXIT_FAILURE, + "Error in starting Rx adapter[%d] service\n", + evt_rsrc->rx_adptr.rx_adptr[i]); + l3fwd_service_enable(service_id); + } + + for (i = 0; i < evt_rsrc->tx_adptr.nb_tx_adptr; i++) { + ret = rte_event_eth_tx_adapter_caps_get(evt_rsrc->event_d_id, + evt_rsrc->tx_adptr.tx_adptr[i], &caps); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Failed to get Rx adapter[%d] caps\n", + evt_rsrc->tx_adptr.tx_adptr[i]); + ret = rte_event_eth_tx_adapter_service_id_get( + evt_rsrc->event_d_id, + &service_id); + if (ret != -ESRCH && ret != 0) + rte_exit(EXIT_FAILURE, + "Error in starting Rx adapter[%d] service\n", + evt_rsrc->tx_adptr.tx_adptr[i]); + l3fwd_service_enable(service_id); + } +} + +int +main(int argc, char **argv) +{ + struct l3fwd_event_resources *evt_rsrc; + struct lcore_conf *qconf; + uint16_t queueid, portid; + unsigned int lcore_id; + uint8_t queue; + int i, ret; + + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); + argc -= ret; + argv += ret; + + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + dest_eth_addr[portid] = + RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); + *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; + } + + evt_rsrc = l3fwd_get_eventdev_rsrc(); + /* parse application arguments (after the EAL ones) */ + ret = parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); + + /* Setup function pointers for lookup method. */ + setup_l3fwd_lookup_tables(); + + evt_rsrc->per_port_pool = per_port_pool; + evt_rsrc->pkt_pool = pktmbuf_pool; + evt_rsrc->port_mask = enabled_port_mask; + /* Configure eventdev parameters if user has requested */ + if (evt_rsrc->enabled) { + l3fwd_event_resource_setup(&port_conf); + if (l3fwd_em_on) + l3fwd_lkp.main_loop = evt_rsrc->ops.em_event_loop; + else + l3fwd_lkp.main_loop = evt_rsrc->ops.lpm_event_loop; + l3fwd_event_service_setup(); + } else + l3fwd_poll_resource_setup(); /* start ports */ RTE_ETH_FOREACH_DEV(portid) { @@ -1029,8 +1250,13 @@ main(int argc, char **argv) * to itself through 2 cross-connected ports of the * target machine. */ - if (promiscuous_on) - rte_eth_promiscuous_enable(portid); + if (promiscuous_on) { + ret = rte_eth_promiscuous_enable(portid); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "rte_eth_promiscuous_enable: err=%s, port=%u\n", + rte_strerror(-ret), portid); + } } printf("\n"); @@ -1047,27 +1273,46 @@ main(int argc, char **argv) } } - check_all_ports_link_status(enabled_port_mask); ret = 0; /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l3fwd_lkp.main_loop, NULL, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (rte_eal_wait_lcore(lcore_id) < 0) { - ret = -1; - break; + if (evt_rsrc->enabled) { + for (i = 0; i < evt_rsrc->rx_adptr.nb_rx_adptr; i++) + rte_event_eth_rx_adapter_stop( + evt_rsrc->rx_adptr.rx_adptr[i]); + for (i = 0; i < evt_rsrc->tx_adptr.nb_tx_adptr; i++) + rte_event_eth_tx_adapter_stop( + evt_rsrc->tx_adptr.tx_adptr[i]); + + RTE_ETH_FOREACH_DEV(portid) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + rte_eth_dev_stop(portid); } - } - /* stop ports */ - RTE_ETH_FOREACH_DEV(portid) { - if ((enabled_port_mask & (1 << portid)) == 0) - continue; - printf("Closing port %d...", portid); - rte_eth_dev_stop(portid); - rte_eth_dev_close(portid); - printf(" Done\n"); + rte_eal_mp_wait_lcore(); + RTE_ETH_FOREACH_DEV(portid) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + rte_eth_dev_close(portid); + } + + rte_event_dev_stop(evt_rsrc->event_d_id); + rte_event_dev_close(evt_rsrc->event_d_id); + + } else { + rte_eal_mp_wait_lcore(); + + RTE_ETH_FOREACH_DEV(portid) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } } printf("Bye...\n");