61a3b0e5e7
Running with stdout suppressed or redirected for further processing is very confusing in the case of errors. Fix it by logging errors and warnings to stderr. Since lines with log messages are touched anyway concatenate split format strings to make it easier to search using grep. Fix indent of format string arguments. Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru> Acked-by: Xiaoyun Li <xiaoyun.li@intel.com>
1432 lines
44 KiB
C
1432 lines
44 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2010-2017 Intel Corporation
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/queue.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <rte_common.h>
|
|
#include <rte_byteorder.h>
|
|
#include <rte_log.h>
|
|
#include <rte_debug.h>
|
|
#include <rte_cycles.h>
|
|
#include <rte_memory.h>
|
|
#include <rte_launch.h>
|
|
#include <rte_eal.h>
|
|
#include <rte_per_lcore.h>
|
|
#include <rte_lcore.h>
|
|
#include <rte_atomic.h>
|
|
#include <rte_branch_prediction.h>
|
|
#include <rte_mempool.h>
|
|
#include <rte_interrupts.h>
|
|
#include <rte_pci.h>
|
|
#include <rte_ether.h>
|
|
#include <rte_ethdev.h>
|
|
#include <rte_string_fns.h>
|
|
#ifdef RTE_NET_BOND
|
|
#include <rte_eth_bond.h>
|
|
#endif
|
|
#include <rte_flow.h>
|
|
|
|
#include "testpmd.h"
|
|
|
|
static void
|
|
usage(char* progname)
|
|
{
|
|
printf("\nUsage: %s [EAL options] -- [testpmd options]\n\n",
|
|
progname);
|
|
#ifdef RTE_LIB_CMDLINE
|
|
printf(" --interactive: run in interactive mode.\n");
|
|
printf(" --cmdline-file: execute cli commands before startup.\n");
|
|
#endif
|
|
printf(" --auto-start: start forwarding on init "
|
|
"[always when non-interactive].\n");
|
|
printf(" --help: display this message and quit.\n");
|
|
printf(" --tx-first: start forwarding sending a burst first "
|
|
"(only if interactive is disabled).\n");
|
|
printf(" --stats-period=PERIOD: statistics will be shown "
|
|
"every PERIOD seconds (only if interactive is disabled).\n");
|
|
printf(" --nb-cores=N: set the number of forwarding cores "
|
|
"(1 <= N <= %d).\n", nb_lcores);
|
|
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 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 "
|
|
"by the packet forwarding test.\n");
|
|
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");
|
|
printf(" --ring-numa-config=(port,flag,socket)[,(port,flag,socket)]: "
|
|
"specify the socket on which the TX/RX rings for "
|
|
"the port will be allocated "
|
|
"(flag: 1 for RX; 2 for TX; 3 for RX and TX).\n");
|
|
printf(" --socket-num=N: set socket from which all memory is allocated "
|
|
"in NUMA mode.\n");
|
|
printf(" --mbuf-size=N,[N1[,..Nn]: set the data size of mbuf to "
|
|
"N bytes. If multiple numbers are specified the extra pools "
|
|
"will be created to receive with packet split features\n");
|
|
printf(" --total-num-mbufs=N: set the number of mbufs to be allocated "
|
|
"in mbuf pools.\n");
|
|
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_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 "
|
|
"port (0 <= X < %d).\n", RTE_MAX_ETHPORTS);
|
|
#endif
|
|
printf(" --pkt-filter-mode=N: set Flow Director mode "
|
|
"(N: none (default mode) or signature or perfect).\n");
|
|
printf(" --pkt-filter-report-hash=N: set Flow Director report mode "
|
|
"(N: none or match (default) or always).\n");
|
|
printf(" --pkt-filter-size=N: set Flow Director mode "
|
|
"(N: 64K (default mode) or 128K or 256K).\n");
|
|
printf(" --pkt-filter-drop-queue=N: set drop-queue. "
|
|
"In perfect mode, when you add a rule with queue = -1 "
|
|
"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_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");
|
|
printf(" --enable-hw-vlan: enable hardware vlan.\n");
|
|
printf(" --enable-hw-vlan-filter: enable hardware vlan filter.\n");
|
|
printf(" --enable-hw-vlan-strip: enable hardware vlan strip.\n");
|
|
printf(" --enable-hw-vlan-extend: enable hardware vlan extend.\n");
|
|
printf(" --enable-hw-qinq-strip: enable hardware qinq strip.\n");
|
|
printf(" --enable-drop-en: enable per queue packet drop.\n");
|
|
printf(" --disable-rss: disable rss.\n");
|
|
printf(" --port-topology=<paired|chained|loop>: set port topology (paired "
|
|
"is default).\n");
|
|
printf(" --forward-mode=N: set forwarding mode (N: %s).\n",
|
|
list_pkt_forwarding_modes());
|
|
printf(" --forward-mode=5tswap: set forwarding mode to "
|
|
"swap L2,L3,L4 for MAC, IPv4/IPv6 and TCP/UDP only.\n");
|
|
printf(" --rss-ip: set RSS functions to IPv4/IPv6 only .\n");
|
|
printf(" --rss-udp: set RSS functions to IPv4/IPv6 + UDP.\n");
|
|
printf(" --rss-level-inner: set RSS hash level to innermost\n");
|
|
printf(" --rss-level-outer: set RSS hash level to outermost\n");
|
|
printf(" --rxq=N: set the number of RX queues per port to N.\n");
|
|
printf(" --rxd=N: set the number of descriptors in RX rings to N.\n");
|
|
printf(" --txq=N: set the number of TX queues per port to N.\n");
|
|
printf(" --txd=N: set the number of descriptors in TX rings to N.\n");
|
|
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(" --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");
|
|
printf(" --rxfreet=N: set the free threshold of RX descriptors to N "
|
|
"(0 <= N < value of rxd).\n");
|
|
printf(" --rxwt=N: set the write-back threshold register of RX rings to N.\n");
|
|
printf(" --txpt=N: set the prefetch threshold register of TX rings to N.\n");
|
|
printf(" --txht=N: set the nhost threshold register of TX rings to N.\n");
|
|
printf(" --txwt=N: set the write-back threshold register of TX rings to N.\n");
|
|
printf(" --txfreet=N: set the transmit free threshold of TX rings to N "
|
|
"(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(" --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");
|
|
printf(" --no-lsc-interrupt: disable link status change interrupt.\n");
|
|
printf(" --no-rmv-interrupt: disable device removal interrupt.\n");
|
|
printf(" --bitrate-stats=N: set the logical core N to perform "
|
|
"bit-rate calculation.\n");
|
|
printf(" --print-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|flow_aged|all>: "
|
|
"enable print of designated event or all of them.\n");
|
|
printf(" --mask-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|flow_aged|all>: "
|
|
"disable print of designated event or all of them.\n");
|
|
printf(" --flow-isolate-all: "
|
|
"requests flow API isolated mode on all ports at initialization time.\n");
|
|
printf(" --tx-offloads=0xXXXXXXXX: hexadecimal bitmask of TX queue offloads\n");
|
|
printf(" --rx-offloads=0xXXXXXXXX: hexadecimal bitmask of RX queue offloads\n");
|
|
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"
|
|
" xmem: use anonymous memory to create and populate mempool\n"
|
|
" xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
|
|
printf(" --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
|
|
printf(" --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
|
|
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-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"
|
|
" 0x10 - explicit Tx rule, 0x02 - hairpin ports paired\n"
|
|
" 0x01 - hairpin ports loop, 0x00 - hairpin port self\n");
|
|
}
|
|
|
|
#ifdef RTE_LIB_CMDLINE
|
|
static int
|
|
init_peer_eth_addrs(const char *config_filename)
|
|
{
|
|
FILE *config_file;
|
|
portid_t i;
|
|
char buf[50];
|
|
|
|
config_file = fopen(config_filename, "r");
|
|
if (config_file == NULL) {
|
|
perror("Failed to open eth config file\n");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
|
|
|
|
if (fgets(buf, sizeof(buf), config_file) == NULL)
|
|
break;
|
|
|
|
if (rte_ether_unformat_addr(buf, &peer_eth_addrs[i]) < 0) {
|
|
fprintf(stderr, "Bad MAC address format on line %d\n",
|
|
i + 1);
|
|
fclose(config_file);
|
|
return -1;
|
|
}
|
|
}
|
|
fclose(config_file);
|
|
nb_peer_eth_addrs = (portid_t) i;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Parse the coremask given as argument (hexadecimal string) and set
|
|
* the global configuration of forwarding cores.
|
|
*/
|
|
static void
|
|
parse_fwd_coremask(const char *coremask)
|
|
{
|
|
char *end;
|
|
unsigned long long int cm;
|
|
|
|
/* parse hexadecimal string */
|
|
end = NULL;
|
|
cm = strtoull(coremask, &end, 16);
|
|
if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0'))
|
|
rte_exit(EXIT_FAILURE, "Invalid fwd core mask\n");
|
|
else if (set_fwd_lcores_mask((uint64_t) cm) < 0)
|
|
rte_exit(EXIT_FAILURE, "coremask is not valid\n");
|
|
}
|
|
|
|
/*
|
|
* Parse the coremask given as argument (hexadecimal string) and set
|
|
* the global configuration of forwarding cores.
|
|
*/
|
|
static void
|
|
parse_fwd_portmask(const char *portmask)
|
|
{
|
|
char *end;
|
|
unsigned long long int pm;
|
|
|
|
/* parse hexadecimal string */
|
|
end = NULL;
|
|
pm = strtoull(portmask, &end, 16);
|
|
if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
|
|
rte_exit(EXIT_FAILURE, "Invalid fwd port mask\n");
|
|
else
|
|
set_fwd_ports_mask((uint64_t) pm);
|
|
}
|
|
|
|
static void
|
|
print_invalid_socket_id_error(void)
|
|
{
|
|
unsigned int i = 0;
|
|
|
|
fprintf(stderr, "Invalid socket id, options are: ");
|
|
for (i = 0; i < num_sockets; i++) {
|
|
fprintf(stderr, "%u%s", socket_ids[i],
|
|
(i == num_sockets - 1) ? "\n" : ",");
|
|
}
|
|
}
|
|
|
|
static int
|
|
parse_portnuma_config(const char *q_arg)
|
|
{
|
|
char s[256];
|
|
const char *p, *p0 = q_arg;
|
|
char *end;
|
|
uint8_t i, socket_id;
|
|
portid_t port_id;
|
|
unsigned size;
|
|
enum fieldnames {
|
|
FLD_PORT = 0,
|
|
FLD_SOCKET,
|
|
_NUM_FLD
|
|
};
|
|
unsigned long int_fld[_NUM_FLD];
|
|
char *str_fld[_NUM_FLD];
|
|
|
|
/* reset from value set at definition */
|
|
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;
|
|
}
|
|
port_id = (portid_t)int_fld[FLD_PORT];
|
|
if (port_id_is_invalid(port_id, ENABLED_WARN) ||
|
|
port_id == (portid_t)RTE_PORT_ALL) {
|
|
print_valid_ports();
|
|
return -1;
|
|
}
|
|
socket_id = (uint8_t)int_fld[FLD_SOCKET];
|
|
if (new_socket_id(socket_id)) {
|
|
if (num_sockets >= RTE_MAX_NUMA_NODES) {
|
|
print_invalid_socket_id_error();
|
|
return -1;
|
|
}
|
|
socket_ids[num_sockets++] = socket_id;
|
|
}
|
|
port_numa[port_id] = socket_id;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
parse_ringnuma_config(const char *q_arg)
|
|
{
|
|
char s[256];
|
|
const char *p, *p0 = q_arg;
|
|
char *end;
|
|
uint8_t i, ring_flag, socket_id;
|
|
portid_t port_id;
|
|
unsigned size;
|
|
enum fieldnames {
|
|
FLD_PORT = 0,
|
|
FLD_FLAG,
|
|
FLD_SOCKET,
|
|
_NUM_FLD
|
|
};
|
|
unsigned long int_fld[_NUM_FLD];
|
|
char *str_fld[_NUM_FLD];
|
|
#define RX_RING_ONLY 0x1
|
|
#define TX_RING_ONLY 0x2
|
|
#define RXTX_RING 0x3
|
|
|
|
/* reset from value set at definition */
|
|
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;
|
|
}
|
|
port_id = (portid_t)int_fld[FLD_PORT];
|
|
if (port_id_is_invalid(port_id, ENABLED_WARN) ||
|
|
port_id == (portid_t)RTE_PORT_ALL) {
|
|
print_valid_ports();
|
|
return -1;
|
|
}
|
|
socket_id = (uint8_t)int_fld[FLD_SOCKET];
|
|
if (new_socket_id(socket_id)) {
|
|
if (num_sockets >= RTE_MAX_NUMA_NODES) {
|
|
print_invalid_socket_id_error();
|
|
return -1;
|
|
}
|
|
socket_ids[num_sockets++] = socket_id;
|
|
}
|
|
ring_flag = (uint8_t)int_fld[FLD_FLAG];
|
|
if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) {
|
|
fprintf(stderr,
|
|
"Invalid ring-flag=%d config for port =%d\n",
|
|
ring_flag,port_id);
|
|
return -1;
|
|
}
|
|
|
|
switch (ring_flag & RXTX_RING) {
|
|
case RX_RING_ONLY:
|
|
rxring_numa[port_id] = socket_id;
|
|
break;
|
|
case TX_RING_ONLY:
|
|
txring_numa[port_id] = socket_id;
|
|
break;
|
|
case RXTX_RING:
|
|
rxring_numa[port_id] = socket_id;
|
|
txring_numa[port_id] = socket_id;
|
|
break;
|
|
default:
|
|
fprintf(stderr,
|
|
"Invalid ring-flag=%d config for port=%d\n",
|
|
ring_flag,port_id);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
parse_event_printing_config(const char *optarg, int enable)
|
|
{
|
|
uint32_t mask = 0;
|
|
|
|
if (!strcmp(optarg, "unknown"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN;
|
|
else if (!strcmp(optarg, "intr_lsc"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC;
|
|
else if (!strcmp(optarg, "queue_state"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE;
|
|
else if (!strcmp(optarg, "intr_reset"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET;
|
|
else if (!strcmp(optarg, "vf_mbox"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_VF_MBOX;
|
|
else if (!strcmp(optarg, "ipsec"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_IPSEC;
|
|
else if (!strcmp(optarg, "macsec"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_MACSEC;
|
|
else if (!strcmp(optarg, "intr_rmv"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV;
|
|
else if (!strcmp(optarg, "dev_probed"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_NEW;
|
|
else if (!strcmp(optarg, "dev_released"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_DESTROY;
|
|
else if (!strcmp(optarg, "flow_aged"))
|
|
mask = UINT32_C(1) << RTE_ETH_EVENT_FLOW_AGED;
|
|
else if (!strcmp(optarg, "all"))
|
|
mask = ~UINT32_C(0);
|
|
else {
|
|
fprintf(stderr, "Invalid event: %s\n", optarg);
|
|
return -1;
|
|
}
|
|
if (enable)
|
|
event_print_mask |= mask;
|
|
else
|
|
event_print_mask &= ~mask;
|
|
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)
|
|
{
|
|
int n, opt;
|
|
char **argvopt;
|
|
int opt_idx;
|
|
portid_t pid;
|
|
enum { TX, RX };
|
|
/* Default offloads for all ports. */
|
|
uint64_t rx_offloads = rx_mode.offloads;
|
|
uint64_t tx_offloads = tx_mode.offloads;
|
|
struct rte_eth_dev_info dev_info;
|
|
uint16_t rec_nb_pkts;
|
|
int ret;
|
|
|
|
static struct option lgopts[] = {
|
|
{ "help", 0, 0, 0 },
|
|
#ifdef RTE_LIB_CMDLINE
|
|
{ "interactive", 0, 0, 0 },
|
|
{ "cmdline-file", 1, 0, 0 },
|
|
{ "auto-start", 0, 0, 0 },
|
|
{ "eth-peers-configfile", 1, 0, 0 },
|
|
{ "eth-peer", 1, 0, 0 },
|
|
#endif
|
|
{ "tx-first", 0, 0, 0 },
|
|
{ "stats-period", 1, 0, 0 },
|
|
{ "nb-cores", 1, 0, 0 },
|
|
{ "nb-ports", 1, 0, 0 },
|
|
{ "coremask", 1, 0, 0 },
|
|
{ "portmask", 1, 0, 0 },
|
|
{ "portlist", 1, 0, 0 },
|
|
{ "numa", 0, 0, 0 },
|
|
{ "no-numa", 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 },
|
|
{ "mbuf-size", 1, 0, 0 },
|
|
{ "total-num-mbufs", 1, 0, 0 },
|
|
{ "max-pkt-len", 1, 0, 0 },
|
|
{ "max-lro-pkt-size", 1, 0, 0 },
|
|
{ "pkt-filter-mode", 1, 0, 0 },
|
|
{ "pkt-filter-report-hash", 1, 0, 0 },
|
|
{ "pkt-filter-size", 1, 0, 0 },
|
|
{ "pkt-filter-drop-queue", 1, 0, 0 },
|
|
#ifdef RTE_LIB_LATENCYSTATS
|
|
{ "latencystats", 1, 0, 0 },
|
|
#endif
|
|
#ifdef RTE_LIB_BITRATESTATS
|
|
{ "bitrate-stats", 1, 0, 0 },
|
|
#endif
|
|
{ "disable-crc-strip", 0, 0, 0 },
|
|
{ "enable-lro", 0, 0, 0 },
|
|
{ "enable-rx-cksum", 0, 0, 0 },
|
|
{ "enable-rx-timestamp", 0, 0, 0 },
|
|
{ "enable-scatter", 0, 0, 0 },
|
|
{ "enable-hw-vlan", 0, 0, 0 },
|
|
{ "enable-hw-vlan-filter", 0, 0, 0 },
|
|
{ "enable-hw-vlan-strip", 0, 0, 0 },
|
|
{ "enable-hw-vlan-extend", 0, 0, 0 },
|
|
{ "enable-hw-qinq-strip", 0, 0, 0 },
|
|
{ "enable-drop-en", 0, 0, 0 },
|
|
{ "disable-rss", 0, 0, 0 },
|
|
{ "port-topology", 1, 0, 0 },
|
|
{ "forward-mode", 1, 0, 0 },
|
|
{ "rss-ip", 0, 0, 0 },
|
|
{ "rss-udp", 0, 0, 0 },
|
|
{ "rss-level-outer", 0, 0, 0 },
|
|
{ "rss-level-inner", 0, 0, 0 },
|
|
{ "rxq", 1, 0, 0 },
|
|
{ "txq", 1, 0, 0 },
|
|
{ "rxd", 1, 0, 0 },
|
|
{ "txd", 1, 0, 0 },
|
|
{ "hairpinq", 1, 0, 0 },
|
|
{ "hairpin-mode", 1, 0, 0 },
|
|
{ "burst", 1, 0, 0 },
|
|
{ "flowgen-clones", 1, 0, 0 },
|
|
{ "mbcache", 1, 0, 0 },
|
|
{ "txpt", 1, 0, 0 },
|
|
{ "txht", 1, 0, 0 },
|
|
{ "txwt", 1, 0, 0 },
|
|
{ "txfreet", 1, 0, 0 },
|
|
{ "txrst", 1, 0, 0 },
|
|
{ "rxpt", 1, 0, 0 },
|
|
{ "rxht", 1, 0, 0 },
|
|
{ "rxwt", 1, 0, 0 },
|
|
{ "rxfreet", 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 },
|
|
{ "no-rmv-interrupt", 0, 0, 0 },
|
|
{ "print-event", 1, 0, 0 },
|
|
{ "mask-event", 1, 0, 0 },
|
|
{ "tx-offloads", 1, 0, 0 },
|
|
{ "rx-offloads", 1, 0, 0 },
|
|
{ "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 },
|
|
{ "noisy-tx-sw-buffer-size", 1, 0, 0 },
|
|
{ "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
|
|
{ "noisy-lkup-memory", 1, 0, 0 },
|
|
{ "noisy-lkup-num-writes", 1, 0, 0 },
|
|
{ "noisy-lkup-num-reads", 1, 0, 0 },
|
|
{ "noisy-lkup-num-reads-writes", 1, 0, 0 },
|
|
{ "no-iova-contig", 0, 0, 0 },
|
|
{ "rx-mq-mode", 1, 0, 0 },
|
|
{ "record-core-cycles", 0, 0, 0 },
|
|
{ "record-burst-stats", 0, 0, 0 },
|
|
{ 0, 0, 0, 0 },
|
|
};
|
|
|
|
argvopt = argv;
|
|
|
|
#ifdef RTE_LIB_CMDLINE
|
|
#define SHORTOPTS "i"
|
|
#else
|
|
#define SHORTOPTS ""
|
|
#endif
|
|
while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
|
|
lgopts, &opt_idx)) != EOF) {
|
|
switch (opt) {
|
|
#ifdef RTE_LIB_CMDLINE
|
|
case 'i':
|
|
printf("Interactive-mode selected\n");
|
|
interactive = 1;
|
|
break;
|
|
#endif
|
|
case 'a':
|
|
printf("Auto-start selected\n");
|
|
auto_start = 1;
|
|
break;
|
|
|
|
case 0: /*long options */
|
|
if (!strcmp(lgopts[opt_idx].name, "help")) {
|
|
usage(argv[0]);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
#ifdef RTE_LIB_CMDLINE
|
|
if (!strcmp(lgopts[opt_idx].name, "interactive")) {
|
|
printf("Interactive-mode selected\n");
|
|
interactive = 1;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "cmdline-file")) {
|
|
printf("CLI commands to be read from %s\n",
|
|
optarg);
|
|
strlcpy(cmdline_filename, optarg,
|
|
sizeof(cmdline_filename));
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "auto-start")) {
|
|
printf("Auto-start selected\n");
|
|
auto_start = 1;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "tx-first")) {
|
|
printf("Ports to start sending a burst of "
|
|
"packets first\n");
|
|
tx_first = 1;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "stats-period")) {
|
|
char *end = NULL;
|
|
unsigned int n;
|
|
|
|
n = strtoul(optarg, &end, 10);
|
|
if ((optarg[0] == '\0') || (end == NULL) ||
|
|
(*end != '\0'))
|
|
break;
|
|
|
|
stats_period = n;
|
|
break;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"eth-peers-configfile")) {
|
|
if (init_peer_eth_addrs(optarg) != 0)
|
|
rte_exit(EXIT_FAILURE,
|
|
"Cannot open logfile\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "eth-peer")) {
|
|
char *port_end;
|
|
|
|
errno = 0;
|
|
n = strtoul(optarg, &port_end, 10);
|
|
if (errno != 0 || port_end == optarg || *port_end++ != ',')
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid eth-peer: %s", optarg);
|
|
if (n >= RTE_MAX_ETHPORTS)
|
|
rte_exit(EXIT_FAILURE,
|
|
"eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
|
|
n, RTE_MAX_ETHPORTS);
|
|
|
|
if (rte_ether_unformat_addr(port_end,
|
|
&peer_eth_addrs[n]) < 0)
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid ethernet address: %s\n",
|
|
port_end);
|
|
nb_peer_eth_addrs++;
|
|
}
|
|
#endif
|
|
if (!strcmp(lgopts[opt_idx].name, "tx-ip")) {
|
|
struct in_addr in;
|
|
char *end;
|
|
|
|
end = strchr(optarg, ',');
|
|
if (end == optarg || !end)
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid tx-ip: %s", optarg);
|
|
|
|
*end++ = 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_pton(AF_INET, end, &in) == 0)
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid destination IP address: %s\n",
|
|
optarg);
|
|
tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "tx-udp")) {
|
|
char *end = NULL;
|
|
|
|
errno = 0;
|
|
n = strtoul(optarg, &end, 10);
|
|
if (errno != 0 || end == optarg ||
|
|
n > UINT16_MAX ||
|
|
!(*end == '\0' || *end == ','))
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid UDP port: %s\n",
|
|
optarg);
|
|
tx_udp_src_port = n;
|
|
if (*end == ',') {
|
|
char *dst = end + 1;
|
|
|
|
n = strtoul(dst, &end, 10);
|
|
if (errno != 0 || end == dst ||
|
|
n > UINT16_MAX || *end)
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid destination UDP port: %s\n",
|
|
dst);
|
|
tx_udp_dst_port = n;
|
|
} else {
|
|
tx_udp_dst_port = n;
|
|
}
|
|
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
|
|
n = atoi(optarg);
|
|
if (n > 0 && n <= nb_ports)
|
|
nb_fwd_ports = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid port %d\n", n);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
|
|
n = atoi(optarg);
|
|
if (n > 0 && n <= nb_lcores)
|
|
nb_fwd_lcores = (uint8_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"nb-cores should be > 0 and <= %d\n",
|
|
nb_lcores);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "coremask"))
|
|
parse_fwd_coremask(optarg);
|
|
if (!strcmp(lgopts[opt_idx].name, "portmask"))
|
|
parse_fwd_portmask(optarg);
|
|
if (!strcmp(lgopts[opt_idx].name, "portlist"))
|
|
parse_fwd_portlist(optarg);
|
|
if (!strcmp(lgopts[opt_idx].name, "no-numa"))
|
|
numa_support = 0;
|
|
if (!strcmp(lgopts[opt_idx].name, "numa"))
|
|
numa_support = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "mp-anon")) {
|
|
mp_alloc_type = MP_ALLOC_ANON;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "mp-alloc")) {
|
|
if (!strcmp(optarg, "native"))
|
|
mp_alloc_type = MP_ALLOC_NATIVE;
|
|
else if (!strcmp(optarg, "anon"))
|
|
mp_alloc_type = MP_ALLOC_ANON;
|
|
else if (!strcmp(optarg, "xmem"))
|
|
mp_alloc_type = MP_ALLOC_XMEM;
|
|
else if (!strcmp(optarg, "xmemhuge"))
|
|
mp_alloc_type = MP_ALLOC_XMEM_HUGE;
|
|
else if (!strcmp(optarg, "xbuf"))
|
|
mp_alloc_type = MP_ALLOC_XBUF;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"mp-alloc %s invalid - must be: "
|
|
"native, anon, xmem or xmemhuge\n",
|
|
optarg);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) {
|
|
if (parse_portnuma_config(optarg))
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid port-numa configuration\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "ring-numa-config"))
|
|
if (parse_ringnuma_config(optarg))
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid ring-numa configuration\n");
|
|
if (!strcmp(lgopts[opt_idx].name, "socket-num")) {
|
|
n = atoi(optarg);
|
|
if (!new_socket_id((uint8_t)n)) {
|
|
socket_num = (uint8_t)n;
|
|
} else {
|
|
print_invalid_socket_id_error();
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid socket id");
|
|
}
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) {
|
|
unsigned int mb_sz[MAX_SEGS_BUFFER_SPLIT];
|
|
unsigned int nb_segs, i;
|
|
|
|
nb_segs = parse_item_list(optarg, "mbuf-size",
|
|
MAX_SEGS_BUFFER_SPLIT, mb_sz, 0);
|
|
if (nb_segs <= 0)
|
|
rte_exit(EXIT_FAILURE,
|
|
"bad mbuf-size\n");
|
|
for (i = 0; i < nb_segs; i++) {
|
|
if (mb_sz[i] <= 0 || mb_sz[i] > 0xFFFF)
|
|
rte_exit(EXIT_FAILURE,
|
|
"mbuf-size should be "
|
|
"> 0 and < 65536\n");
|
|
mbuf_data_size[i] = (uint16_t) mb_sz[i];
|
|
}
|
|
mbuf_data_size_n = nb_segs;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) {
|
|
n = atoi(optarg);
|
|
if (n > 1024)
|
|
param_total_num_mbufs = (unsigned)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"total-num-mbufs should be > 1024\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
|
|
n = atoi(optarg);
|
|
if (n >= RTE_ETHER_MIN_LEN)
|
|
rx_mode.max_rx_pkt_len = (uint32_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"Invalid max-pkt-len=%d - should be > %d\n",
|
|
n, RTE_ETHER_MIN_LEN);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "max-lro-pkt-size")) {
|
|
n = atoi(optarg);
|
|
rx_mode.max_lro_pkt_size = (uint32_t) n;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "pkt-filter-mode")) {
|
|
if (!strcmp(optarg, "signature"))
|
|
fdir_conf.mode =
|
|
RTE_FDIR_MODE_SIGNATURE;
|
|
else if (!strcmp(optarg, "perfect"))
|
|
fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
|
|
else if (!strcmp(optarg, "perfect-mac-vlan"))
|
|
fdir_conf.mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN;
|
|
else if (!strcmp(optarg, "perfect-tunnel"))
|
|
fdir_conf.mode = RTE_FDIR_MODE_PERFECT_TUNNEL;
|
|
else if (!strcmp(optarg, "none"))
|
|
fdir_conf.mode = RTE_FDIR_MODE_NONE;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"pkt-mode-invalid %s invalid - must be: "
|
|
"none, signature, perfect, perfect-mac-vlan"
|
|
" or perfect-tunnel\n",
|
|
optarg);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"pkt-filter-report-hash")) {
|
|
if (!strcmp(optarg, "none"))
|
|
fdir_conf.status =
|
|
RTE_FDIR_NO_REPORT_STATUS;
|
|
else if (!strcmp(optarg, "match"))
|
|
fdir_conf.status =
|
|
RTE_FDIR_REPORT_STATUS;
|
|
else if (!strcmp(optarg, "always"))
|
|
fdir_conf.status =
|
|
RTE_FDIR_REPORT_STATUS_ALWAYS;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"pkt-filter-report-hash %s invalid "
|
|
"- must be: none or match or always\n",
|
|
optarg);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "pkt-filter-size")) {
|
|
if (!strcmp(optarg, "64K"))
|
|
fdir_conf.pballoc =
|
|
RTE_FDIR_PBALLOC_64K;
|
|
else if (!strcmp(optarg, "128K"))
|
|
fdir_conf.pballoc =
|
|
RTE_FDIR_PBALLOC_128K;
|
|
else if (!strcmp(optarg, "256K"))
|
|
fdir_conf.pballoc =
|
|
RTE_FDIR_PBALLOC_256K;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "pkt-filter-size %s invalid -"
|
|
" must be: 64K or 128K or 256K\n",
|
|
optarg);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"pkt-filter-drop-queue")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
fdir_conf.drop_queue = (uint8_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"drop queue %d invalid - must"
|
|
"be >= 0 \n", n);
|
|
}
|
|
#ifdef RTE_LIB_LATENCYSTATS
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"latencystats")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0) {
|
|
latencystats_lcore_id = (lcoreid_t) n;
|
|
latencystats_enabled = 1;
|
|
} else
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid lcore id %d for latencystats"
|
|
" must be >= 0\n", n);
|
|
}
|
|
#endif
|
|
#ifdef RTE_LIB_BITRATESTATS
|
|
if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0) {
|
|
bitrate_lcore_id = (lcoreid_t) n;
|
|
bitrate_enabled = 1;
|
|
} else
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid lcore id %d for bitrate stats"
|
|
" must be >= 0\n", n);
|
|
}
|
|
#endif
|
|
if (!strcmp(lgopts[opt_idx].name, "disable-crc-strip"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_KEEP_CRC;
|
|
if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_TCP_LRO;
|
|
if (!strcmp(lgopts[opt_idx].name, "enable-scatter"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_SCATTER;
|
|
if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_CHECKSUM;
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"enable-rx-timestamp"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
|
|
if (!strcmp(lgopts[opt_idx].name, "enable-hw-vlan"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_VLAN;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"enable-hw-vlan-filter"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"enable-hw-vlan-strip"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"enable-hw-vlan-extend"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"enable-hw-qinq-strip"))
|
|
rx_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name, "enable-drop-en"))
|
|
rx_drop_en = 1;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name, "disable-rss"))
|
|
rss_hf = 0;
|
|
if (!strcmp(lgopts[opt_idx].name, "port-topology")) {
|
|
if (!strcmp(optarg, "paired"))
|
|
port_topology = PORT_TOPOLOGY_PAIRED;
|
|
else if (!strcmp(optarg, "chained"))
|
|
port_topology = PORT_TOPOLOGY_CHAINED;
|
|
else if (!strcmp(optarg, "loop"))
|
|
port_topology = PORT_TOPOLOGY_LOOP;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
|
|
" must be: paired, chained or loop\n",
|
|
optarg);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "forward-mode"))
|
|
set_pkt_forwarding_mode(optarg);
|
|
if (!strcmp(lgopts[opt_idx].name, "rss-ip"))
|
|
rss_hf = ETH_RSS_IP;
|
|
if (!strcmp(lgopts[opt_idx].name, "rss-udp"))
|
|
rss_hf = ETH_RSS_UDP;
|
|
if (!strcmp(lgopts[opt_idx].name, "rss-level-inner"))
|
|
rss_hf |= ETH_RSS_LEVEL_INNERMOST;
|
|
if (!strcmp(lgopts[opt_idx].name, "rss-level-outer"))
|
|
rss_hf |= ETH_RSS_LEVEL_OUTERMOST;
|
|
if (!strcmp(lgopts[opt_idx].name, "rxq")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
|
|
nb_rxq = (queueid_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
|
|
" >= 0 && <= %u\n", n,
|
|
get_allowed_max_nb_rxq(&pid));
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txq")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
|
|
nb_txq = (queueid_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
|
|
" >= 0 && <= %u\n", n,
|
|
get_allowed_max_nb_txq(&pid));
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0 &&
|
|
check_nb_hairpinq((queueid_t)n) == 0)
|
|
nb_hairpinq = (queueid_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
|
|
" >= 0 && <= %u\n", n,
|
|
get_allowed_max_nb_hairpinq
|
|
(&pid));
|
|
if ((n + nb_txq) < 0 ||
|
|
check_nb_txq((queueid_t)(n + nb_txq)) != 0)
|
|
rte_exit(EXIT_FAILURE, "txq + hairpinq "
|
|
"%d invalid - must be"
|
|
" >= 0 && <= %u\n",
|
|
n + nb_txq,
|
|
get_allowed_max_nb_txq(&pid));
|
|
if ((n + nb_rxq) < 0 ||
|
|
check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
|
|
rte_exit(EXIT_FAILURE, "rxq + hairpinq "
|
|
"%d invalid - must be"
|
|
" >= 0 && <= %u\n",
|
|
n + nb_rxq,
|
|
get_allowed_max_nb_rxq(&pid));
|
|
}
|
|
if (!nb_rxq && !nb_txq) {
|
|
rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
|
|
"be non-zero\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "hairpin-mode")) {
|
|
char *end = NULL;
|
|
unsigned int n;
|
|
|
|
errno = 0;
|
|
n = strtoul(optarg, &end, 0);
|
|
if (errno != 0 || end == optarg)
|
|
rte_exit(EXIT_FAILURE, "hairpin mode invalid\n");
|
|
else
|
|
hairpin_mode = (uint16_t)n;
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "burst")) {
|
|
n = atoi(optarg);
|
|
if (n == 0) {
|
|
/* A burst size of zero means that the
|
|
* PMD should be queried for
|
|
* recommended Rx burst size. Since
|
|
* testpmd uses a single size for all
|
|
* ports, port 0 is queried for the
|
|
* value, on the assumption that all
|
|
* ports are of the same NIC model.
|
|
*/
|
|
ret = eth_dev_info_get_print_err(
|
|
0,
|
|
&dev_info);
|
|
if (ret != 0)
|
|
return;
|
|
|
|
rec_nb_pkts = dev_info
|
|
.default_rxportconf.burst_size;
|
|
|
|
if (rec_nb_pkts == 0)
|
|
rte_exit(EXIT_FAILURE,
|
|
"PMD does not recommend a burst size. "
|
|
"Provided value must be between "
|
|
"1 and %d\n", MAX_PKT_BURST);
|
|
else if (rec_nb_pkts > MAX_PKT_BURST)
|
|
rte_exit(EXIT_FAILURE,
|
|
"PMD recommended burst size of %d"
|
|
" exceeds maximum value of %d\n",
|
|
rec_nb_pkts, MAX_PKT_BURST);
|
|
printf("Using PMD-provided burst value of %d\n",
|
|
rec_nb_pkts);
|
|
nb_pkt_per_burst = rec_nb_pkts;
|
|
} else if (n > MAX_PKT_BURST)
|
|
rte_exit(EXIT_FAILURE,
|
|
"burst must be between1 and %d\n",
|
|
MAX_PKT_BURST);
|
|
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, "mbcache")) {
|
|
n = atoi(optarg);
|
|
if ((n >= 0) &&
|
|
(n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
|
|
mb_mempool_cache = (uint16_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"mbcache must be >= 0 and <= %d\n",
|
|
RTE_MEMPOOL_CACHE_MAX_SIZE);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txfreet")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
tx_free_thresh = (int16_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txrst")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
tx_rs_thresh = (int16_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "rxd")) {
|
|
n = atoi(optarg);
|
|
if (n > 0) {
|
|
if (rx_free_thresh >= n)
|
|
rte_exit(EXIT_FAILURE,
|
|
"rxd must be > "
|
|
"rx_free_thresh(%d)\n",
|
|
(int)rx_free_thresh);
|
|
else
|
|
nb_rxd = (uint16_t) n;
|
|
} else
|
|
rte_exit(EXIT_FAILURE,
|
|
"rxd(%d) invalid - must be > 0\n",
|
|
n);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txd")) {
|
|
n = atoi(optarg);
|
|
if (n > 0)
|
|
nb_txd = (uint16_t) n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txpt")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
tx_pthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txht")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
tx_hthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txwt")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
tx_wthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "rxpt")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
rx_pthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "rxht")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
rx_hthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "rxwt")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
rx_wthresh = (int8_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "rxfreet")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
rx_free_thresh = (int16_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\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, "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];
|
|
unsigned int nb_segs;
|
|
|
|
nb_segs = parse_item_list(optarg, "txpkt segments",
|
|
RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
|
|
if (nb_segs > 0)
|
|
set_tx_pkt_segments(seg_lengths, nb_segs);
|
|
else
|
|
rte_exit(EXIT_FAILURE, "bad txpkts\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "txonly-multi-flow"))
|
|
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"))
|
|
no_device_start = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "no-lsc-interrupt"))
|
|
lsc_interrupt = 0;
|
|
if (!strcmp(lgopts[opt_idx].name, "no-rmv-interrupt"))
|
|
rmv_interrupt = 0;
|
|
if (!strcmp(lgopts[opt_idx].name, "flow-isolate-all"))
|
|
flow_isolate_all = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "tx-offloads")) {
|
|
char *end = NULL;
|
|
n = strtoull(optarg, &end, 16);
|
|
if (n >= 0)
|
|
tx_offloads = (uint64_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"tx-offloads must be >= 0\n");
|
|
}
|
|
|
|
if (!strcmp(lgopts[opt_idx].name, "rx-offloads")) {
|
|
char *end = NULL;
|
|
n = strtoull(optarg, &end, 16);
|
|
if (n >= 0)
|
|
rx_offloads = (uint64_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"rx-offloads must be >= 0\n");
|
|
}
|
|
|
|
if (!strcmp(lgopts[opt_idx].name, "vxlan-gpe-port")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
vxlan_gpe_udp_port = (uint16_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"vxlan-gpe-port must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"geneve-parsed-port")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
geneve_udp_port = (uint16_t)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"geneve-parsed-port must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "print-event"))
|
|
if (parse_event_printing_config(optarg, 1)) {
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid print-event argument\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "mask-event"))
|
|
if (parse_event_printing_config(optarg, 0)) {
|
|
rte_exit(EXIT_FAILURE,
|
|
"invalid mask-event argument\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "hot-plug"))
|
|
hot_plug = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "mlockall"))
|
|
do_mlockall = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "no-mlockall"))
|
|
do_mlockall = 0;
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-tx-sw-buffer-size")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_tx_sw_bufsz = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-tx-sw-buffer-size must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-tx-sw-buffer-flushtime")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_tx_sw_buf_flush_time = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-tx-sw-buffer-flushtime must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-lkup-memory")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_lkup_mem_sz = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-lkup-memory must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-lkup-num-writes")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_lkup_num_writes = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-lkup-num-writes must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-lkup-num-reads")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_lkup_num_reads = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-lkup-num-reads must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name,
|
|
"noisy-lkup-num-reads-writes")) {
|
|
n = atoi(optarg);
|
|
if (n >= 0)
|
|
noisy_lkup_num_reads_writes = n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"noisy-lkup-num-reads-writes must be >= 0\n");
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
|
|
mempool_flags = MEMPOOL_F_NO_IOVA_CONTIG;
|
|
|
|
if (!strcmp(lgopts[opt_idx].name, "rx-mq-mode")) {
|
|
char *end = NULL;
|
|
n = strtoul(optarg, &end, 16);
|
|
if (n >= 0 && n <= ETH_MQ_RX_VMDQ_DCB_RSS)
|
|
rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
|
|
else
|
|
rte_exit(EXIT_FAILURE,
|
|
"rx-mq-mode must be >= 0 and <= %d\n",
|
|
ETH_MQ_RX_VMDQ_DCB_RSS);
|
|
}
|
|
if (!strcmp(lgopts[opt_idx].name, "record-core-cycles"))
|
|
record_core_cycles = 1;
|
|
if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
|
|
record_burst_stats = 1;
|
|
break;
|
|
case 'h':
|
|
usage(argv[0]);
|
|
exit(EXIT_SUCCESS);
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
fprintf(stderr, "Invalid option: %s\n", argv[optind]);
|
|
rte_exit(EXIT_FAILURE,
|
|
"Command line is incomplete or incorrect\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (optind != argc) {
|
|
usage(argv[0]);
|
|
fprintf(stderr, "Invalid parameter: %s\n", argv[optind]);
|
|
rte_exit(EXIT_FAILURE, "Command line is incorrect\n");
|
|
}
|
|
|
|
/* Set offload configuration from command line parameters. */
|
|
rx_mode.offloads = rx_offloads;
|
|
tx_mode.offloads = tx_offloads;
|
|
|
|
if (mempool_flags & MEMPOOL_F_NO_IOVA_CONTIG &&
|
|
mp_alloc_type != MP_ALLOC_ANON) {
|
|
TESTPMD_LOG(WARNING, "cannot use no-iova-contig without "
|
|
"mp-alloc=anon. mempool no-iova-contig is "
|
|
"ignored\n");
|
|
mempool_flags = 0;
|
|
}
|
|
}
|