* [dpdk-dev] [PATCH] app/testpmd: add hairpin support
@ 2019-11-03 16:00 Ori Kam
2019-11-05 15:37 ` [dpdk-dev] [PATCH v2] " Ori Kam
2019-11-05 19:05 ` [dpdk-dev] [PATCH v3] " Ori Kam
0 siblings, 2 replies; 4+ messages in thread
From: Ori Kam @ 2019-11-03 16:00 UTC (permalink / raw)
To: Wenzhuo Lu, Jingjing Wu, Bernard Iremonger; +Cc: dev, orika, ferruh.yigit
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>
---
This patch was part of the hairpin series. [1]
in this version, the configuration of the hairpin was moved to external function,
and the documentation was updated.
[1] https://mails.dpdk.org/archives/dev/2019-October/149590.html
---
app/test-pmd/parameters.c | 28 ++++++++++++
app/test-pmd/testpmd.c | 109 +++++++++++++++++++++++++++++++++++++++++++++-
app/test-pmd/testpmd.h | 3 ++
3 files changed, 138 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 9ea87c1..9b6e35b 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -149,6 +149,8 @@
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 @@
{ "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 @@
" >= 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");
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 38acbc5..0fc5b45 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -234,6 +234,7 @@ struct fwd_engine * fwd_engines[] = {
/*
* 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 @@ struct extmem_param {
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)
{
@@ -2028,6 +2076,11 @@ struct extmem_param {
queueid_t qi;
struct rte_port *port;
struct rte_ether_addr mac_addr;
+ struct rte_eth_hairpin_conf hairpin_conf = {
+ .peer_count = 1,
+ };
+ int i;
+ struct rte_eth_hairpin_cap cap;
if (port_id_is_invalid(pid, ENABLED_WARN))
return 0;
@@ -2060,9 +2113,16 @@ struct extmem_param {
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)
@@ -2155,6 +2215,51 @@ struct extmem_param {
port->need_reconfig_queues = 1;
return -1;
}
+ /* setup hairpin queues */
+ i = 0;
+ for (qi = nb_txq; 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;
+ }
+ i = 0;
+ for (qi = nb_rxq; 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;
+ }
}
configure_rxtx_dump_callbacks(verbose_level);
/* start port */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ec10a1a..8da1e8e 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -385,6 +385,7 @@ struct queue_stats_mappings {
extern uint64_t rss_hf;
+extern queueid_t nb_hairpinq;
extern queueid_t nb_rxq;
extern queueid_t nb_txq;
@@ -859,6 +860,8 @@ enum print_warning {
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,
--
1.8.3.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [dpdk-dev] [PATCH v2] app/testpmd: add hairpin support
2019-11-03 16:00 [dpdk-dev] [PATCH] app/testpmd: add hairpin support Ori Kam
@ 2019-11-05 15:37 ` Ori Kam
2019-11-05 19:05 ` [dpdk-dev] [PATCH v3] " Ori Kam
1 sibling, 0 replies; 4+ messages in thread
From: Ori Kam @ 2019-11-05 15:37 UTC (permalink / raw)
To: Wenzhuo Lu, Jingjing Wu, Bernard Iremonger, John McNamara,
Marko Kovacevic
Cc: dev, orika, ferruh.yigit
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>
---
v2: send the updated patch.
This patch was part of the hairpin series. [1]
in this version, the configuration of the hairpin was moved to external function,
and the documentation was updated.
[1] https://mails.dpdk.org/archives/dev/2019-October/149590.html
---
app/test-pmd/parameters.c | 28 ++++++++
app/test-pmd/testpmd.c | 120 +++++++++++++++++++++++++++++++++-
app/test-pmd/testpmd.h | 3 +
doc/guides/testpmd_app_ug/run_app.rst | 11 ++++
4 files changed, 160 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 9ea87c1..9b6e35b 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -149,6 +149,8 @@
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 @@
{ "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 @@
" >= 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");
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 38acbc5..d5e57ff 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -234,6 +234,7 @@ struct fwd_engine * fwd_engines[] = {
/*
* 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 @@ struct extmem_param {
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)
{
@@ -2020,6 +2068,63 @@ struct extmem_param {
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)
{
@@ -2028,6 +2133,7 @@ struct extmem_param {
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;
@@ -2060,9 +2166,16 @@ struct extmem_param {
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)
@@ -2155,6 +2268,9 @@ struct extmem_param {
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 */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ec10a1a..8da1e8e 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -385,6 +385,7 @@ struct queue_stats_mappings {
extern uint64_t rss_hf;
+extern queueid_t nb_hairpinq;
extern queueid_t nb_rxq;
extern queueid_t nb_txq;
@@ -859,6 +860,8 @@ enum print_warning {
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,
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index ef677ba..7535ed7 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -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.
--
1.8.3.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [dpdk-dev] [PATCH v3] app/testpmd: add hairpin support
2019-11-03 16:00 [dpdk-dev] [PATCH] app/testpmd: add hairpin support Ori Kam
2019-11-05 15:37 ` [dpdk-dev] [PATCH v2] " Ori Kam
@ 2019-11-05 19:05 ` Ori Kam
2019-11-08 13:43 ` Ferruh Yigit
1 sibling, 1 reply; 4+ messages in thread
From: Ori Kam @ 2019-11-05 19:05 UTC (permalink / raw)
To: Wenzhuo Lu, Jingjing Wu, Bernard Iremonger, John McNamara,
Marko Kovacevic
Cc: dev, orika, ferruh.yigit
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>
---
v3: fix checkpatch warnings.
v2: send the updated patch.
This patch was part of the hairpin series. [1]
in this version, the configuration of the hairpin was moved to external function,
and the documentation was updated.
[1] https://mails.dpdk.org/archives/dev/2019-October/149590.html
---
app/test-pmd/parameters.c | 28 ++++++++
app/test-pmd/testpmd.c | 120 +++++++++++++++++++++++++++++++++-
app/test-pmd/testpmd.h | 3 +
doc/guides/testpmd_app_ug/run_app.rst | 11 ++++
4 files changed, 160 insertions(+), 2 deletions(-)
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 9ea87c1..9b6e35b 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -149,6 +149,8 @@
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 @@
{ "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 @@
" >= 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");
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 38acbc5..890e326 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -234,6 +234,7 @@ struct fwd_engine * fwd_engines[] = {
/*
* 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 @@ struct extmem_param {
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)
{
@@ -2020,6 +2068,63 @@ struct extmem_param {
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)
{
@@ -2028,6 +2133,7 @@ struct extmem_param {
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;
@@ -2060,9 +2166,16 @@ struct extmem_param {
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)
@@ -2155,6 +2268,9 @@ struct extmem_param {
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 */
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ec10a1a..8da1e8e 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -385,6 +385,7 @@ struct queue_stats_mappings {
extern uint64_t rss_hf;
+extern queueid_t nb_hairpinq;
extern queueid_t nb_rxq;
extern queueid_t nb_txq;
@@ -859,6 +860,8 @@ enum print_warning {
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,
diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
index ef677ba..d09c2c3 100644
--- a/doc/guides/testpmd_app_ug/run_app.rst
+++ b/doc/guides/testpmd_app_ug/run_app.rst
@@ -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.
--
1.8.3.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [dpdk-dev] [PATCH v3] app/testpmd: add hairpin support
2019-11-05 19:05 ` [dpdk-dev] [PATCH v3] " Ori Kam
@ 2019-11-08 13:43 ` Ferruh Yigit
0 siblings, 0 replies; 4+ messages in thread
From: Ferruh Yigit @ 2019-11-08 13:43 UTC (permalink / raw)
To: Ori Kam, Wenzhuo Lu, Jingjing Wu, Bernard Iremonger,
John McNamara, Marko Kovacevic
Cc: dev
On 11/5/2019 7:05 PM, Ori Kam wrote:
> 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>
Applied to dpdk-next-net/master, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-11-08 13:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-03 16:00 [dpdk-dev] [PATCH] app/testpmd: add hairpin support Ori Kam
2019-11-05 15:37 ` [dpdk-dev] [PATCH v2] " Ori Kam
2019-11-05 19:05 ` [dpdk-dev] [PATCH v3] " Ori Kam
2019-11-08 13:43 ` Ferruh Yigit
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).