app/testpmd: support multi-process
[dpdk.git] / app / test-pmd / parameters.c
index bff8042..3f94a82 100644 (file)
@@ -19,7 +19,6 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <arpa/inet.h>
 
 #include <rte_common.h>
 #include <rte_byteorder.h>
@@ -39,7 +38,7 @@
 #include <rte_ether.h>
 #include <rte_ethdev.h>
 #include <rte_string_fns.h>
-#ifdef RTE_LIBRTE_PMD_BOND
+#ifdef RTE_NET_BOND
 #include <rte_eth_bond.h>
 #endif
 #include <rte_flow.h>
 static void
 usage(char* progname)
 {
-       printf("usage: %s [EAL options] -- "
-#ifdef RTE_LIBRTE_CMDLINE
-              "[--interactive|-i] "
-              "[--cmdline-file=FILENAME] "
-#endif
-              "[--help|-h] | [--auto-start|-a] | ["
-              "--tx-first | --stats-period=PERIOD | "
-              "--coremask=COREMASK --portmask=PORTMASK --numa "
-              "--portlist=PORTLIST "
-              "--mbuf-size= | --total-num-mbufs= | "
-              "--nb-cores= | --nb-ports= | "
-#ifdef RTE_LIBRTE_CMDLINE
-              "--eth-peers-configfile= | "
-              "--eth-peer=X,M:M:M:M:M:M | "
-              "--tx-ip=SRC,DST | --tx-udp=PORT | "
-#endif
-              "--pkt-filter-mode= |"
-              "--rss-ip | --rss-udp | --rss-level-inner | --rss-level-outer |"
-              "--rxpt= | --rxht= | --rxwt= |"
-              " --rxfreet= | --txpt= | --txht= | --txwt= | --txfreet= | "
-              "--txrst= | --tx-offloads= | | --rx-offloads= | "
-              "--vxlan-gpe-port= | --geneve-parsed-port= | "
-              "--record-core-cycles | --record-burst-stats]\n",
+       printf("\nUsage: %s [EAL options] -- [testpmd options]\n\n",
               progname);
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
        printf("  --interactive: run in interactive mode.\n");
        printf("  --cmdline-file: execute cli commands before startup.\n");
 #endif
@@ -89,7 +66,7 @@ usage(char* progname)
        printf("  --nb-ports=N: set the number of forwarding ports "
               "(1 <= N <= %d).\n", nb_ports);
        printf("  --coremask=COREMASK: hexadecimal bitmask of cores running "
-              "the packet forwarding test. The master lcore is reserved for "
+              "the packet forwarding test. The main lcore is reserved for "
               "command line parsing only, and cannot be masked on for "
               "packet forwarding.\n");
        printf("  --portmask=PORTMASK: hexadecimal bitmask of ports used "
@@ -97,6 +74,7 @@ usage(char* progname)
        printf("  --portlist=PORTLIST: list of forwarding ports\n");
        printf("  --numa: enable NUMA-aware allocation of RX/TX rings and of "
               "RX memory buffers (mbufs).\n");
+       printf("  --no-numa: disable NUMA-aware allocation.\n");
        printf("  --port-numa-config=(port,socket)[,(port,socket)]: "
               "specify the socket on which the memory pool "
               "used by the port will be allocated.\n");
@@ -114,7 +92,7 @@ usage(char* progname)
        printf("  --max-pkt-len=N: set the maximum size of packet to N bytes.\n");
        printf("  --max-lro-pkt-size=N: set the maximum LRO aggregated packet "
               "size to N bytes.\n");
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
        printf("  --eth-peers-configfile=name: config file with ethernet addresses "
               "of peer ports.\n");
        printf("  --eth-peer=X,M:M:M:M:M:M: set the MAC address of the X peer "
@@ -131,11 +109,12 @@ usage(char* progname)
               "the packet will be enqueued into the rx drop-queue. "
               "If the drop-queue doesn't exist, the packet is dropped. "
               "By default drop-queue=127.\n");
-#ifdef RTE_LIBRTE_LATENCY_STATS
+#ifdef RTE_LIB_LATENCYSTATS
        printf("  --latencystats=N: enable latency and jitter statistcs "
               "monitoring on forwarding lcore id N.\n");
 #endif
        printf("  --disable-crc-strip: disable CRC stripping by hardware.\n");
+       printf("  --enable-scatter: enable scattered Rx.\n");
        printf("  --enable-lro: enable large receive offload.\n");
        printf("  --enable-rx-cksum: enable rx hardware checksum offload.\n");
        printf("  --enable-rx-timestamp: enable rx hardware timestamp offload.\n");
@@ -163,6 +142,8 @@ usage(char* progname)
        printf("  --hairpinq=N: set the number of hairpin queues per port to "
               "N.\n");
        printf("  --burst=N: set the number of packets per burst to N.\n");
+       printf("  --flowgen-clones=N: set the number of single packet clones to send in flowgen mode. Should be less than burst value.\n");
+       printf("  --flowgen-flows=N: set the number of flows in flowgen mode to N (1 <= N <= INT32_MAX).\n");
        printf("  --mbcache=N: set the cache of mbuf memory pool to N.\n");
        printf("  --rxpt=N: set prefetch threshold register of RX rings to N.\n");
        printf("  --rxht=N: set the host threshold register of RX rings to N.\n");
@@ -176,17 +157,16 @@ usage(char* progname)
               "(0 <= N <= value of txd).\n");
        printf("  --txrst=N: set the transmit RS bit threshold of TX rings to N "
               "(0 <= N <= value of txd).\n");
-       printf("  --tx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
-              "tx queues statistics counters mapping "
-              "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
-       printf("  --rx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
-              "rx queues statistics counters mapping "
-              "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
        printf("  --no-flush-rx: Don't flush RX streams before forwarding."
               " Used mainly with PCAP drivers.\n");
+       printf("  --rxoffs=X[,Y]*: set RX segment offsets for split.\n");
+       printf("  --rxpkts=X[,Y]*: set RX segment sizes to split.\n");
        printf("  --txpkts=X[,Y]*: set TX segment sizes"
                " or total packet length.\n");
        printf("  --txonly-multi-flow: generate multiple flows in txonly mode\n");
+       printf("  --tx-ip=src,dst: IP addresses in Tx-only mode\n");
+       printf("  --tx-udp=src[,dst]: UDP ports in Tx-only mode\n");
+       printf("  --eth-link-speed: force link speed.\n");
        printf("  --disable-link-check: disable check on link status when "
               "starting/stopping ports.\n");
        printf("  --disable-device-start: do not automatically start port\n");
@@ -205,8 +185,10 @@ usage(char* progname)
        printf("  --hot-plug: enable hot plug for device.\n");
        printf("  --vxlan-gpe-port=N: UPD port of tunnel VXLAN-GPE\n");
        printf("  --geneve-parsed-port=N: UPD port to parse GENEVE tunnel protocol\n");
+#ifndef RTE_EXEC_ENV_WINDOWS
        printf("  --mlockall: lock all memory\n");
        printf("  --no-mlockall: do not lock all memory\n");
+#endif
        printf("  --mp-alloc <native|anon|xmem|xmemhuge>: mempool allocation method.\n"
               "    native: use regular DPDK memory to create and populate mempool\n"
               "    anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
@@ -217,21 +199,21 @@ usage(char* progname)
        printf("  --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
        printf("  --noisy-lkup-num-writes=N: do N random writes per packet\n");
        printf("  --noisy-lkup-num-reads=N: do N random reads per packet\n");
-       printf("  --noisy-lkup-num-writes=N: do N random reads and writes per packet\n");
+       printf("  --noisy-lkup-num-reads-writes=N: do N random reads and writes per packet\n");
        printf("  --no-iova-contig: mempool memory can be IOVA non contiguous. "
               "valid only with --mp-alloc=anon\n");
        printf("  --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
               "enabled\n");
        printf("  --record-core-cycles: enable measurement of CPU cycles.\n");
        printf("  --record-burst-stats: enable display of RX and TX bursts.\n");
-       printf("  --hairpin-mode=0xXX: bitmask set the hairpin port mode.\n "
+       printf("  --hairpin-mode=0xXX: bitmask set the hairpin port mode.\n"
               "    0x10 - explicit Tx rule, 0x02 - hairpin ports paired\n"
               "    0x01 - hairpin ports loop, 0x00 - hairpin port self\n");
 }
 
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
 static int
-init_peer_eth_addrs(char *config_filename)
+init_peer_eth_addrs(const char *config_filename)
 {
        FILE *config_file;
        portid_t i;
@@ -249,7 +231,8 @@ init_peer_eth_addrs(char *config_filename)
                        break;
 
                if (rte_ether_unformat_addr(buf, &peer_eth_addrs[i]) < 0) {
-                       printf("Bad MAC address format on line %d\n", i+1);
+                       fprintf(stderr, "Bad MAC address format on line %d\n",
+                               i + 1);
                        fclose(config_file);
                        return -1;
                }
@@ -298,102 +281,15 @@ parse_fwd_portmask(const char *portmask)
                set_fwd_ports_mask((uint64_t) pm);
 }
 
-
-static int
-parse_queue_stats_mapping_config(const char *q_arg, int is_rx)
-{
-       char s[256];
-       const char *p, *p0 = q_arg;
-       char *end;
-       enum fieldnames {
-               FLD_PORT = 0,
-               FLD_QUEUE,
-               FLD_STATS_COUNTER,
-               _NUM_FLD
-       };
-       unsigned long int_fld[_NUM_FLD];
-       char *str_fld[_NUM_FLD];
-       int i;
-       unsigned size;
-
-       /* reset from value set at definition */
-       is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0);
-
-       while ((p = strchr(p0,'(')) != NULL) {
-               ++p;
-               if((p0 = strchr(p,')')) == NULL)
-                       return -1;
-
-               size = p0 - p;
-               if(size >= sizeof(s))
-                       return -1;
-
-               snprintf(s, sizeof(s), "%.*s", size, p);
-               if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
-                       return -1;
-               for (i = 0; i < _NUM_FLD; i++){
-                       errno = 0;
-                       int_fld[i] = strtoul(str_fld[i], &end, 0);
-                       if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
-                               return -1;
-               }
-               /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */
-               if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
-                       printf("Stats counter not in the correct range 0..%d\n",
-                                       RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
-                       return -1;
-               }
-
-               if (!is_rx) {
-                       if ((nb_tx_queue_stats_mappings >=
-                                               MAX_TX_QUEUE_STATS_MAPPINGS)) {
-                               printf("exceeded max number of TX queue "
-                                               "statistics mappings: %hu\n",
-                                               nb_tx_queue_stats_mappings);
-                               return -1;
-                       }
-                       tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id =
-                               (uint8_t)int_fld[FLD_PORT];
-                       tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id =
-                               (uint8_t)int_fld[FLD_QUEUE];
-                       tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id =
-                               (uint8_t)int_fld[FLD_STATS_COUNTER];
-                       ++nb_tx_queue_stats_mappings;
-               }
-               else {
-                       if ((nb_rx_queue_stats_mappings >=
-                                               MAX_RX_QUEUE_STATS_MAPPINGS)) {
-                               printf("exceeded max number of RX queue "
-                                               "statistics mappings: %hu\n",
-                                               nb_rx_queue_stats_mappings);
-                               return -1;
-                       }
-                       rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id =
-                               (uint8_t)int_fld[FLD_PORT];
-                       rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id =
-                               (uint8_t)int_fld[FLD_QUEUE];
-                       rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id =
-                               (uint8_t)int_fld[FLD_STATS_COUNTER];
-                       ++nb_rx_queue_stats_mappings;
-               }
-
-       }
-/* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */
-/* than to the default array (that was set at its definition) */
-       is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) :
-               (tx_queue_stats_mappings = tx_queue_stats_mappings_array);
-       return 0;
-}
-
 static void
 print_invalid_socket_id_error(void)
 {
        unsigned int i = 0;
 
-       printf("Invalid socket id, options are: ");
+       fprintf(stderr, "Invalid socket id, options are: ");
        for (i = 0; i < num_sockets; i++) {
-               printf("%u%s", socket_ids[i],
-                     (i == num_sockets - 1) ? "\n" : ",");
+               fprintf(stderr, "%u%s", socket_ids[i],
+                       (i == num_sockets - 1) ? "\n" : ",");
        }
 }
 
@@ -509,7 +405,8 @@ parse_ringnuma_config(const char *q_arg)
                }
                ring_flag = (uint8_t)int_fld[FLD_FLAG];
                if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) {
-                       printf("Invalid ring-flag=%d config for port =%d\n",
+                       fprintf(stderr,
+                               "Invalid ring-flag=%d config for port =%d\n",
                                ring_flag,port_id);
                        return -1;
                }
@@ -526,7 +423,8 @@ parse_ringnuma_config(const char *q_arg)
                        txring_numa[port_id] = socket_id;
                        break;
                default:
-                       printf("Invalid ring-flag=%d config for port=%d\n",
+                       fprintf(stderr,
+                               "Invalid ring-flag=%d config for port=%d\n",
                                ring_flag,port_id);
                        break;
                }
@@ -575,9 +473,49 @@ parse_event_printing_config(const char *optarg, int enable)
        return 0;
 }
 
+static int
+parse_link_speed(int n)
+{
+       uint32_t speed = ETH_LINK_SPEED_FIXED;
+
+       switch (n) {
+       case 1000:
+               speed |= ETH_LINK_SPEED_1G;
+               break;
+       case 10000:
+               speed |= ETH_LINK_SPEED_10G;
+               break;
+       case 25000:
+               speed |= ETH_LINK_SPEED_25G;
+               break;
+       case 40000:
+               speed |= ETH_LINK_SPEED_40G;
+               break;
+       case 50000:
+               speed |= ETH_LINK_SPEED_50G;
+               break;
+       case 100000:
+               speed |= ETH_LINK_SPEED_100G;
+               break;
+       case 200000:
+               speed |= ETH_LINK_SPEED_200G;
+               break;
+       case 100:
+       case 10:
+       default:
+               fprintf(stderr, "Unsupported fixed speed\n");
+               return 0;
+       }
+
+       return speed;
+}
+
 void
 launch_args_parse(int argc, char** argv)
 {
+#define PARAM_PROC_ID "proc-id"
+#define PARAM_NUM_PROCS "num-procs"
+
        int n, opt;
        char **argvopt;
        int opt_idx;
@@ -592,7 +530,7 @@ launch_args_parse(int argc, char** argv)
 
        static struct option lgopts[] = {
                { "help",                       0, 0, 0 },
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
                { "interactive",                0, 0, 0 },
                { "cmdline-file",               1, 0, 0 },
                { "auto-start",                 0, 0, 0 },
@@ -601,7 +539,6 @@ launch_args_parse(int argc, char** argv)
 #endif
                { "tx-first",                   0, 0, 0 },
                { "stats-period",               1, 0, 0 },
-               { "ports",                      1, 0, 0 },
                { "nb-cores",                   1, 0, 0 },
                { "nb-ports",                   1, 0, 0 },
                { "coremask",                   1, 0, 0 },
@@ -609,7 +546,7 @@ launch_args_parse(int argc, char** argv)
                { "portlist",                   1, 0, 0 },
                { "numa",                       0, 0, 0 },
                { "no-numa",                    0, 0, 0 },
-               { "mp-anon",                    0, 0, 0 },
+               { "mp-anon",                    0, 0, 0 }, /* deprecated */
                { "port-numa-config",           1, 0, 0 },
                { "ring-numa-config",           1, 0, 0 },
                { "socket-num",                 1, 0, 0 },
@@ -621,10 +558,10 @@ launch_args_parse(int argc, char** argv)
                { "pkt-filter-report-hash",     1, 0, 0 },
                { "pkt-filter-size",            1, 0, 0 },
                { "pkt-filter-drop-queue",      1, 0, 0 },
-#ifdef RTE_LIBRTE_LATENCY_STATS
+#ifdef RTE_LIB_LATENCYSTATS
                { "latencystats",               1, 0, 0 },
 #endif
-#ifdef RTE_LIBRTE_BITRATESTATS
+#ifdef RTE_LIB_BITRATESTATS
                { "bitrate-stats",              1, 0, 0 },
 #endif
                { "disable-crc-strip",          0, 0, 0 },
@@ -652,6 +589,8 @@ launch_args_parse(int argc, char** argv)
                { "hairpinq",                   1, 0, 0 },
                { "hairpin-mode",               1, 0, 0 },
                { "burst",                      1, 0, 0 },
+               { "flowgen-clones",             1, 0, 0 },
+               { "flowgen-flows",              1, 0, 0 },
                { "mbcache",                    1, 0, 0 },
                { "txpt",                       1, 0, 0 },
                { "txht",                       1, 0, 0 },
@@ -662,12 +601,13 @@ launch_args_parse(int argc, char** argv)
                { "rxht",                       1, 0, 0 },
                { "rxwt",                       1, 0, 0 },
                { "rxfreet",                    1, 0, 0 },
-               { "tx-queue-stats-mapping",     1, 0, 0 },
-               { "rx-queue-stats-mapping",     1, 0, 0 },
                { "no-flush-rx",        0, 0, 0 },
                { "flow-isolate-all",           0, 0, 0 },
+               { "rxoffs",                     1, 0, 0 },
+               { "rxpkts",                     1, 0, 0 },
                { "txpkts",                     1, 0, 0 },
                { "txonly-multi-flow",          0, 0, 0 },
+               { "eth-link-speed",             1, 0, 0 },
                { "disable-link-check",         0, 0, 0 },
                { "disable-device-start",       0, 0, 0 },
                { "no-lsc-interrupt",           0, 0, 0 },
@@ -679,8 +619,10 @@ launch_args_parse(int argc, char** argv)
                { "hot-plug",                   0, 0, 0 },
                { "vxlan-gpe-port",             1, 0, 0 },
                { "geneve-parsed-port",         1, 0, 0 },
+#ifndef RTE_EXEC_ENV_WINDOWS
                { "mlockall",                   0, 0, 0 },
                { "no-mlockall",                0, 0, 0 },
+#endif
                { "mp-alloc",                   1, 0, 0 },
                { "tx-ip",                      1, 0, 0 },
                { "tx-udp",                     1, 0, 0 },
@@ -694,12 +636,14 @@ launch_args_parse(int argc, char** argv)
                { "rx-mq-mode",                 1, 0, 0 },
                { "record-core-cycles",         0, 0, 0 },
                { "record-burst-stats",         0, 0, 0 },
+               { PARAM_NUM_PROCS,              1, 0, 0 },
+               { PARAM_PROC_ID,                1, 0, 0 },
                { 0, 0, 0, 0 },
        };
 
        argvopt = argv;
 
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
 #define SHORTOPTS "i"
 #else
 #define SHORTOPTS ""
@@ -707,7 +651,7 @@ launch_args_parse(int argc, char** argv)
        while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
                                 lgopts, &opt_idx)) != EOF) {
                switch (opt) {
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
                case 'i':
                        printf("Interactive-mode selected\n");
                        interactive = 1;
@@ -721,9 +665,9 @@ launch_args_parse(int argc, char** argv)
                case 0: /*long options */
                        if (!strcmp(lgopts[opt_idx].name, "help")) {
                                usage(argv[0]);
-                               rte_exit(EXIT_SUCCESS, "Displayed help\n");
+                               exit(EXIT_SUCCESS);
                        }
-#ifdef RTE_LIBRTE_CMDLINE
+#ifdef RTE_LIB_CMDLINE
                        if (!strcmp(lgopts[opt_idx].name, "interactive")) {
                                printf("Interactive-mode selected\n");
                                interactive = 1;
@@ -792,13 +736,13 @@ launch_args_parse(int argc, char** argv)
                                                 "Invalid tx-ip: %s", optarg);
 
                                *end++ = 0;
-                               if (inet_aton(optarg, &in) == 0)
+                               if (inet_pton(AF_INET, optarg, &in) == 0)
                                        rte_exit(EXIT_FAILURE,
                                                 "Invalid source IP address: %s\n",
                                                 optarg);
                                tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
 
-                               if (inet_aton(end, &in) == 0)
+                               if (inet_pton(AF_INET, end, &in) == 0)
                                        rte_exit(EXIT_FAILURE,
                                                 "Invalid destination IP address: %s\n",
                                                 optarg);
@@ -925,12 +869,9 @@ launch_args_parse(int argc, char** argv)
                        }
                        if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
                                n = atoi(optarg);
-                               if (n >= RTE_ETHER_MIN_LEN) {
+                               if (n >= RTE_ETHER_MIN_LEN)
                                        rx_mode.max_rx_pkt_len = (uint32_t) n;
-                                       if (n > RTE_ETHER_MAX_LEN)
-                                               rx_offloads |=
-                                                       DEV_RX_OFFLOAD_JUMBO_FRAME;
-                               } else
+                               else
                                        rte_exit(EXIT_FAILURE,
                                                 "Invalid max-pkt-len=%d - should be > %d\n",
                                                 n, RTE_ETHER_MIN_LEN);
@@ -1000,7 +941,7 @@ launch_args_parse(int argc, char** argv)
                                                 "drop queue %d invalid - must"
                                                 "be >= 0 \n", n);
                        }
-#ifdef RTE_LIBRTE_LATENCY_STATS
+#ifdef RTE_LIB_LATENCYSTATS
                        if (!strcmp(lgopts[opt_idx].name,
                                    "latencystats")) {
                                n = atoi(optarg);
@@ -1013,7 +954,7 @@ launch_args_parse(int argc, char** argv)
                                                 " must be >= 0\n", n);
                        }
 #endif
-#ifdef RTE_LIBRTE_BITRATESTATS
+#ifdef RTE_LIB_BITRATESTATS
                        if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
                                n = atoi(optarg);
                                if (n >= 0) {
@@ -1180,6 +1121,22 @@ launch_args_parse(int argc, char** argv)
                                else
                                        nb_pkt_per_burst = (uint16_t) n;
                        }
+                       if (!strcmp(lgopts[opt_idx].name, "flowgen-clones")) {
+                               n = atoi(optarg);
+                               if (n >= 0)
+                                       nb_pkt_flowgen_clones = (uint16_t) n;
+                               else
+                                       rte_exit(EXIT_FAILURE,
+                                                "clones must be >= 0 and <= current burst\n");
+                       }
+                       if (!strcmp(lgopts[opt_idx].name, "flowgen-flows")) {
+                               n = atoi(optarg);
+                               if (n > 0)
+                                       nb_flows_flowgen = (int) n;
+                               else
+                                       rte_exit(EXIT_FAILURE,
+                                                "flows must be >= 1\n");
+                       }
                        if (!strcmp(lgopts[opt_idx].name, "mbcache")) {
                                n = atoi(optarg);
                                if ((n >= 0) &&
@@ -1275,17 +1232,31 @@ launch_args_parse(int argc, char** argv)
                                else
                                        rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
                        }
-                       if (!strcmp(lgopts[opt_idx].name, "tx-queue-stats-mapping")) {
-                               if (parse_queue_stats_mapping_config(optarg, TX)) {
-                                       rte_exit(EXIT_FAILURE,
-                                                "invalid TX queue statistics mapping config entered\n");
-                               }
+                       if (!strcmp(lgopts[opt_idx].name, "rxoffs")) {
+                               unsigned int seg_off[MAX_SEGS_BUFFER_SPLIT];
+                               unsigned int nb_offs;
+
+                               nb_offs = parse_item_list
+                                               (optarg, "rxpkt offsets",
+                                                MAX_SEGS_BUFFER_SPLIT,
+                                                seg_off, 0);
+                               if (nb_offs > 0)
+                                       set_rx_pkt_offsets(seg_off, nb_offs);
+                               else
+                                       rte_exit(EXIT_FAILURE, "bad rxoffs\n");
                        }
-                       if (!strcmp(lgopts[opt_idx].name, "rx-queue-stats-mapping")) {
-                               if (parse_queue_stats_mapping_config(optarg, RX)) {
-                                       rte_exit(EXIT_FAILURE,
-                                                "invalid RX queue statistics mapping config entered\n");
-                               }
+                       if (!strcmp(lgopts[opt_idx].name, "rxpkts")) {
+                               unsigned int seg_len[MAX_SEGS_BUFFER_SPLIT];
+                               unsigned int nb_segs;
+
+                               nb_segs = parse_item_list
+                                               (optarg, "rxpkt segments",
+                                                MAX_SEGS_BUFFER_SPLIT,
+                                                seg_len, 0);
+                               if (nb_segs > 0)
+                                       set_rx_pkt_segments(seg_len, nb_segs);
+                               else
+                                       rte_exit(EXIT_FAILURE, "bad rxpkts\n");
                        }
                        if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
                                unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
@@ -1302,6 +1273,11 @@ launch_args_parse(int argc, char** argv)
                                txonly_multi_flow = 1;
                        if (!strcmp(lgopts[opt_idx].name, "no-flush-rx"))
                                no_flush_rx = 1;
+                       if (!strcmp(lgopts[opt_idx].name, "eth-link-speed")) {
+                               n = atoi(optarg);
+                               if (n >= 0 && parse_link_speed(n) > 0)
+                                       eth_link_speed = parse_link_speed(n);
+                       }
                        if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
                                no_link_check = 1;
                        if (!strcmp(lgopts[opt_idx].name, "disable-device-start"))
@@ -1436,14 +1412,18 @@ launch_args_parse(int argc, char** argv)
                                record_core_cycles = 1;
                        if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
                                record_burst_stats = 1;
+                       if (!strcmp(lgopts[opt_idx].name, PARAM_NUM_PROCS))
+                               num_procs = atoi(optarg);
+                       if (!strcmp(lgopts[opt_idx].name, PARAM_PROC_ID))
+                               proc_id = atoi(optarg);
                        break;
                case 'h':
                        usage(argv[0]);
-                       rte_exit(EXIT_SUCCESS, "Displayed help\n");
+                       exit(EXIT_SUCCESS);
                        break;
                default:
                        usage(argv[0]);
-                       printf("Invalid option: %s\n", argv[optind]);
+                       fprintf(stderr, "Invalid option: %s\n", argv[optind]);
                        rte_exit(EXIT_FAILURE,
                                 "Command line is incomplete or incorrect\n");
                        break;
@@ -1452,7 +1432,7 @@ launch_args_parse(int argc, char** argv)
 
        if (optind != argc) {
                usage(argv[0]);
-               printf("Invalid parameter: %s\n", argv[optind]);
+               fprintf(stderr, "Invalid parameter: %s\n", argv[optind]);
                rte_exit(EXIT_FAILURE, "Command line is incorrect\n");
        }