app/testpmd: support hairpin
This commit introduce the hairpin queues to the testpmd. the hairpin queue is configured using --hairpinq=<n> the hairpin queue adds n queue objects for both the total number of TX queues and RX queues. The connection between the queues are 1 to 1, first Rx hairpin queue will be connected to the first Tx hairpin queue Signed-off-by: Ori Kam <orika@mellanox.com> Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
653b285ff1
commit
1c69df45f8
@ -149,6 +149,8 @@ usage(char* progname)
|
||||
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(" --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");
|
||||
@ -622,6 +624,7 @@ launch_args_parse(int argc, char** argv)
|
||||
{ "txq", 1, 0, 0 },
|
||||
{ "rxd", 1, 0, 0 },
|
||||
{ "txd", 1, 0, 0 },
|
||||
{ "hairpinq", 1, 0, 0 },
|
||||
{ "burst", 1, 0, 0 },
|
||||
{ "mbcache", 1, 0, 0 },
|
||||
{ "txpt", 1, 0, 0 },
|
||||
@ -1045,6 +1048,31 @@ launch_args_parse(int argc, char** argv)
|
||||
" >= 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");
|
||||
|
@ -234,6 +234,7 @@ uint8_t dcb_test = 0;
|
||||
/*
|
||||
* Configurable number of RX/TX queues.
|
||||
*/
|
||||
queueid_t nb_hairpinq; /**< Number of hairpin queues per port. */
|
||||
queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
|
||||
queueid_t nb_txq = 1; /**< Number of TX queues per port. */
|
||||
|
||||
@ -1067,6 +1068,53 @@ check_nb_txq(queueid_t txq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the allowed maximum number of hairpin queues.
|
||||
* *pid return the port id which has minimal value of
|
||||
* max_hairpin_queues in all ports.
|
||||
*/
|
||||
queueid_t
|
||||
get_allowed_max_nb_hairpinq(portid_t *pid)
|
||||
{
|
||||
queueid_t allowed_max_hairpinq = MAX_QUEUE_ID;
|
||||
portid_t pi;
|
||||
struct rte_eth_hairpin_cap cap;
|
||||
|
||||
RTE_ETH_FOREACH_DEV(pi) {
|
||||
if (rte_eth_dev_hairpin_capability_get(pi, &cap) != 0) {
|
||||
*pid = pi;
|
||||
return 0;
|
||||
}
|
||||
if (cap.max_nb_queues < allowed_max_hairpinq) {
|
||||
allowed_max_hairpinq = cap.max_nb_queues;
|
||||
*pid = pi;
|
||||
}
|
||||
}
|
||||
return allowed_max_hairpinq;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check input hairpin is valid or not.
|
||||
* If input hairpin is not greater than any of maximum number
|
||||
* of hairpin queues of all ports, it is valid.
|
||||
* if valid, return 0, else return -1
|
||||
*/
|
||||
int
|
||||
check_nb_hairpinq(queueid_t hairpinq)
|
||||
{
|
||||
queueid_t allowed_max_hairpinq;
|
||||
portid_t pid = 0;
|
||||
|
||||
allowed_max_hairpinq = get_allowed_max_nb_hairpinq(&pid);
|
||||
if (hairpinq > allowed_max_hairpinq) {
|
||||
printf("Fail: input hairpin (%u) can't be greater "
|
||||
"than max_hairpin_queues (%u) of port %u\n",
|
||||
hairpinq, allowed_max_hairpinq, pid);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_config(void)
|
||||
{
|
||||
@ -2016,6 +2064,63 @@ port_is_started(portid_t port_id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Configure the Rx and Tx hairpin queues for the selected port. */
|
||||
static int
|
||||
setup_hairpin_queues(portid_t pi)
|
||||
{
|
||||
queueid_t qi;
|
||||
struct rte_eth_hairpin_conf hairpin_conf = {
|
||||
.peer_count = 1,
|
||||
};
|
||||
int i;
|
||||
int diag;
|
||||
struct rte_port *port = &ports[pi];
|
||||
|
||||
for (qi = nb_txq, i = 0; qi < nb_hairpinq + nb_txq; qi++) {
|
||||
hairpin_conf.peers[0].port = pi;
|
||||
hairpin_conf.peers[0].queue = i + nb_rxq;
|
||||
diag = rte_eth_tx_hairpin_queue_setup
|
||||
(pi, qi, nb_txd, &hairpin_conf);
|
||||
i++;
|
||||
if (diag == 0)
|
||||
continue;
|
||||
|
||||
/* Fail to setup rx queue, return */
|
||||
if (rte_atomic16_cmpset(&(port->port_status),
|
||||
RTE_PORT_HANDLING,
|
||||
RTE_PORT_STOPPED) == 0)
|
||||
printf("Port %d can not be set back "
|
||||
"to stopped\n", pi);
|
||||
printf("Fail to configure port %d hairpin "
|
||||
"queues\n", pi);
|
||||
/* try to reconfigure queues next time */
|
||||
port->need_reconfig_queues = 1;
|
||||
return -1;
|
||||
}
|
||||
for (qi = nb_rxq, i = 0; qi < nb_hairpinq + nb_rxq; qi++) {
|
||||
hairpin_conf.peers[0].port = pi;
|
||||
hairpin_conf.peers[0].queue = i + nb_txq;
|
||||
diag = rte_eth_rx_hairpin_queue_setup
|
||||
(pi, qi, nb_rxd, &hairpin_conf);
|
||||
i++;
|
||||
if (diag == 0)
|
||||
continue;
|
||||
|
||||
/* Fail to setup rx queue, return */
|
||||
if (rte_atomic16_cmpset(&(port->port_status),
|
||||
RTE_PORT_HANDLING,
|
||||
RTE_PORT_STOPPED) == 0)
|
||||
printf("Port %d can not be set back "
|
||||
"to stopped\n", pi);
|
||||
printf("Fail to configure port %d hairpin "
|
||||
"queues\n", pi);
|
||||
/* try to reconfigure queues next time */
|
||||
port->need_reconfig_queues = 1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
start_port(portid_t pid)
|
||||
{
|
||||
@ -2024,6 +2129,7 @@ start_port(portid_t pid)
|
||||
queueid_t qi;
|
||||
struct rte_port *port;
|
||||
struct rte_ether_addr mac_addr;
|
||||
struct rte_eth_hairpin_cap cap;
|
||||
|
||||
if (port_id_is_invalid(pid, ENABLED_WARN))
|
||||
return 0;
|
||||
@ -2056,9 +2162,16 @@ start_port(portid_t pid)
|
||||
configure_rxtx_dump_callbacks(0);
|
||||
printf("Configuring Port %d (socket %u)\n", pi,
|
||||
port->socket_id);
|
||||
if (nb_hairpinq > 0 &&
|
||||
rte_eth_dev_hairpin_capability_get(pi, &cap)) {
|
||||
printf("Port %d doesn't support hairpin "
|
||||
"queues\n", pi);
|
||||
return -1;
|
||||
}
|
||||
/* configure port */
|
||||
diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq,
|
||||
&(port->dev_conf));
|
||||
diag = rte_eth_dev_configure(pi, nb_rxq + nb_hairpinq,
|
||||
nb_txq + nb_hairpinq,
|
||||
&(port->dev_conf));
|
||||
if (diag != 0) {
|
||||
if (rte_atomic16_cmpset(&(port->port_status),
|
||||
RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
|
||||
@ -2151,6 +2264,9 @@ start_port(portid_t pid)
|
||||
port->need_reconfig_queues = 1;
|
||||
return -1;
|
||||
}
|
||||
/* setup hairpin queues */
|
||||
if (setup_hairpin_queues(pi) != 0)
|
||||
return -1;
|
||||
}
|
||||
configure_rxtx_dump_callbacks(verbose_level);
|
||||
/* start port */
|
||||
|
@ -385,6 +385,7 @@ extern struct rte_eth_txmode tx_mode;
|
||||
|
||||
extern uint64_t rss_hf;
|
||||
|
||||
extern queueid_t nb_hairpinq;
|
||||
extern queueid_t nb_rxq;
|
||||
extern queueid_t nb_txq;
|
||||
|
||||
@ -859,6 +860,8 @@ queueid_t get_allowed_max_nb_rxq(portid_t *pid);
|
||||
int check_nb_rxq(queueid_t rxq);
|
||||
queueid_t get_allowed_max_nb_txq(portid_t *pid);
|
||||
int check_nb_txq(queueid_t txq);
|
||||
queueid_t get_allowed_max_nb_hairpinq(portid_t *pid);
|
||||
int check_nb_hairpinq(queueid_t hairpinq);
|
||||
|
||||
uint16_t dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
|
||||
uint16_t nb_pkts, __rte_unused uint16_t max_pkts,
|
||||
|
@ -266,6 +266,17 @@ The command line options are:
|
||||
Set the number of descriptors in the TX rings to N, where N > 0.
|
||||
The default value is 512.
|
||||
|
||||
* ``--hairpinq=N``
|
||||
|
||||
Set the number of hairpin queues per port to N, where 1 <= N <= 65535.
|
||||
The default value is 0. The number of hairpin queues are added to the
|
||||
number of TX queues and to the number of RX queues. then the first
|
||||
RX hairpin is binded to the first TX hairpin, the second RX hairpin is
|
||||
binded to the second TX hairpin and so on. The index of the first
|
||||
RX hairpin queue is the number of RX queues as configured using --rxq.
|
||||
The index of the first TX hairpin queue is the number of TX queues
|
||||
as configured using --txq.
|
||||
|
||||
* ``--burst=N``
|
||||
|
||||
Set the number of packets per burst to N, where 1 <= N <= 512.
|
||||
|
Loading…
x
Reference in New Issue
Block a user