[v5,1/5] app/flow-perf: add flow performance skeleton
Checks
Commit Message
Add flow performance application skeleton.
Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
---
MAINTAINERS | 5 +
app/Makefile | 1 +
app/meson.build | 1 +
app/test-flow-perf/Makefile | 23 +++
app/test-flow-perf/config.h | 14 ++
app/test-flow-perf/main.c | 200 +++++++++++++++++++++++++
app/test-flow-perf/meson.build | 8 +
config/common_base | 5 +
doc/guides/rel_notes/release_20_05.rst | 10 ++
doc/guides/tools/flow-perf.rst | 44 ++++++
doc/guides/tools/index.rst | 1 +
11 files changed, 312 insertions(+)
create mode 100644 app/test-flow-perf/Makefile
create mode 100644 app/test-flow-perf/config.h
create mode 100644 app/test-flow-perf/main.c
create mode 100644 app/test-flow-perf/meson.build
create mode 100644 doc/guides/tools/flow-perf.rst
Comments
On 5/6/20 3:36 PM, Wisam Jaddo wrote:
> Add flow performance application skeleton.
>
> Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
> ---
[snip]
> diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
> new file mode 100644
> index 000000000..7a924cdb7
> --- /dev/null
> +++ b/app/test-flow-perf/main.c
> @@ -0,0 +1,200 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright 2020 Mellanox Technologies, Ltd
> + *
> + * This file contain the application main file
> + * This application provides the user the ability to test the
> + * insertion rate for specific rte_flow rule under stress state ~4M rule/
> + *
> + * Then it will also provide packet per second measurement after installing
> + * all rules, the user may send traffic to test the PPS that match the rules
> + * after all rules are installed, to check performance or functionality after
> + * the stress.
> + *
> + * The flows insertion will go for all ports first, then it will print the
> + * results, after that the application will go into forwarding packets mode
> + * it will start receiving traffic if any and then forwarding it back and
> + * gives packet per second measurement.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <stdarg.h>
> +#include <errno.h>
> +#include <getopt.h>
> +#include <signal.h>
> +#include <stdbool.h>
> +#include <sys/time.h>
> +
> +#include <rte_malloc.h>
> +#include <rte_mempool.h>
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_flow.h>
> +
> +#include "config.h"
> +
> +static uint32_t nb_lcores;
> +static struct rte_mempool *mbuf_mp;
> +
> +static void
> +usage(char *progname)
> +{
> + printf("\nusage: %s\n", progname);
> +}
> +
> +static void
> +args_parse(int argc, char **argv)
> +{
> + char **argvopt;
> + int opt;
> + int opt_idx;
> + static struct option lgopts[] = {
> + /* Control */
> + { "help", 0, 0, 0 },
> + };
> +
> + argvopt = argv;
> +
> + while ((opt = getopt_long(argc, argvopt, "",
> + lgopts, &opt_idx)) != EOF) {
> + switch (opt) {
> + case 0:
> + if (!strcmp(lgopts[opt_idx].name, "help")) {
DPDK coding style recommends to compare vs 0 instead of logical
not.
> + usage(argv[0]);
> + rte_exit(EXIT_SUCCESS, "Displayed help\n");
> + }
> + break;
> + default:
> + printf("Invalid option: %s\n", argv[optind]);
Again, sorry if I missed reply: Why error is not logged to
stderr?
> + usage(argv[0]);
> + rte_exit(EXIT_SUCCESS, "Invalid option\n");
> + break;
> + }
> + }
> +}
> +
> +static void
> +init_port(void)
> +{
> + int ret;
> + uint16_t i;
> + uint16_t port_id;
> + uint16_t nr_ports;
> + struct rte_eth_conf port_conf = {
> + .rx_adv_conf = {
> + .rss_conf.rss_hf =
> + ETH_RSS_IP |
> + ETH_RSS_TCP,
> + }
> + };
> + struct rte_eth_txconf txq_conf;
> + struct rte_eth_rxconf rxq_conf;
> + struct rte_eth_dev_info dev_info;
> +
> + nr_ports = rte_eth_dev_count_avail();
> + if (nr_ports == 0)
> + rte_exit(EXIT_FAILURE, "Error: no port detected\n");
> +
> + mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool",
> + TOTAL_MBUF_NUM, MBUF_CACHE_SIZE,
> + 0, MBUF_SIZE,
> + rte_socket_id());
> + if (mbuf_mp == NULL)
> + rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n");
> +
> + for (port_id = 0; port_id < nr_ports; port_id++) {
> + ret = rte_eth_dev_info_get(port_id, &dev_info);
> + if (ret != 0)
> + rte_exit(EXIT_FAILURE,
> + "Error during getting device"
> + " (port %u) info: %s\n",
> + port_id, strerror(-ret));
> +
> + port_conf.txmode.offloads &= dev_info.tx_offload_capa;
> + port_conf.rxmode.offloads &= dev_info.rx_offload_capa;
> +
> + printf(":: initializing port: %d\n", port_id);
> +
> + ret = rte_eth_dev_configure(port_id, RXQ_NUM,
> + TXQ_NUM, &port_conf);
> + if (ret < 0)
> + rte_exit(EXIT_FAILURE,
> + ":: cannot configure device: err=%d, port=%u\n",
> + ret, port_id);
> +
> + rxq_conf = dev_info.default_rxconf;
> + rxq_conf.offloads = port_conf.rxmode.offloads;
As far as I know there is no necessity to repeat port offlaod
on queue level. So, the line is not necesary.
> +
> + for (i = 0; i < RXQ_NUM; i++) {
> + ret = rte_eth_rx_queue_setup(port_id, i, NR_RXD,
> + rte_eth_dev_socket_id(port_id),
> + &rxq_conf,
> + mbuf_mp);
> + if (ret < 0)
> + rte_exit(EXIT_FAILURE,
> + ":: Rx queue setup failed: err=%d, port=%u\n",
> + ret, port_id);
> + }
> +
> + txq_conf = dev_info.default_txconf;
> + txq_conf.offloads = port_conf.txmode.offloads;
As far as I know there is no necessity to repeat port offlaod
on queue level. So, the line is not necesary.
> +
> + for (i = 0; i < TXQ_NUM; i++) {
> + ret = rte_eth_tx_queue_setup(port_id, i, NR_TXD,
> + rte_eth_dev_socket_id(port_id),
> + &txq_conf);
> + if (ret < 0)
> + rte_exit(EXIT_FAILURE,
> + ":: Tx queue setup failed: err=%d, port=%u\n",
> + ret, port_id);
> + }
> +
> + /* Catch all packets from traffic generator. */
> + ret = rte_eth_promiscuous_enable(port_id);
> + if (ret != 0)
> + rte_exit(EXIT_FAILURE,
> + ":: promiscuous mode enable failed: err=%s, port=%u\n",
> + rte_strerror(-ret), port_id);
> +
> + ret = rte_eth_dev_start(port_id);
> + if (ret < 0)
> + rte_exit(EXIT_FAILURE,
> + "rte_eth_dev_start:err=%d, port=%u\n",
> + ret, port_id);
> +
> + printf(":: initializing port: %d done\n", port_id);
> + }
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> + int ret;
> + uint16_t port;
> + struct rte_flow_error error;
> +
> + ret = rte_eal_init(argc, argv);
> + if (ret < 0)
> + rte_exit(EXIT_FAILURE, "EAL init failed\n");
> +
> + argc -= ret;
> + argv += ret;
> + if (argc > 1)
> + args_parse(argc, argv);
> +
> + init_port();
> +
> + nb_lcores = rte_lcore_count();
> + if (nb_lcores <= 1)
> + rte_exit(EXIT_FAILURE, "This app needs at least two cores\n");
> +
> + RTE_ETH_FOREACH_DEV(port) {
> + rte_flow_flush(port, &error);
> + rte_eth_dev_stop(port);
> + rte_eth_dev_close(port);
> + }
> + return 0;
> +}
[snip]
> diff --git a/config/common_base b/config/common_base
> index 14000ba07..b2edd5267 100644
> diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
> index b124c3f28..258b1e03e 100644
> --- a/doc/guides/rel_notes/release_20_05.rst
> +++ b/doc/guides/rel_notes/release_20_05.rst
> @@ -212,6 +212,16 @@ New Features
> * Added IPsec inbound load-distribution support for ipsec-secgw application
> using NIC load distribution feature(Flow Director).
>
> +* **Added flow performance application.**
> +
> + Add new application to test rte_flow performance.
> +
> + Application features:
> + * Measure rte_flow insertion rate.
> + * Measure rte_flow deletion rate.
> + * Dump rte_flow memory consumption.
> + * Measure packet per second forwarding.
I think above lines should be added in appropriate patches
which really do it.
> +
>
> Removed Items
> -------------
[snip]
>-----Original Message-----
>From: Andrew Rybchenko <arybchenko@solarflare.com>
>Sent: Wednesday, May 6, 2020 5:26 PM
>To: Wisam Monther <wisamm@mellanox.com>; dev@dpdk.org; Jack Min
><jackmin@mellanox.com>; Thomas Monjalon <thomas@monjalon.net>;
>jerinjacobk@gmail.com; gerlitz.or@gmail.com; l.yan@epfl.ch;
>ajit.khaparde@broadcom.com
>Subject: Re: [dpdk-dev] [PATCH v5 1/5] app/flow-perf: add flow performance
>skeleton
>
>On 5/6/20 3:36 PM, Wisam Jaddo wrote:
>> Add flow performance application skeleton.
>>
>> Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
>> ---
>
>[snip]
>
>> diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c new
>> file mode 100644 index 000000000..7a924cdb7
>> --- /dev/null
>> +++ b/app/test-flow-perf/main.c
>> @@ -0,0 +1,200 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright 2020 Mellanox Technologies, Ltd
>> + *
>> + * This file contain the application main file
>> + * This application provides the user the ability to test the
>> + * insertion rate for specific rte_flow rule under stress state ~4M
>> +rule/
>> + *
>> + * Then it will also provide packet per second measurement after
>> +installing
>> + * all rules, the user may send traffic to test the PPS that match
>> +the rules
>> + * after all rules are installed, to check performance or
>> +functionality after
>> + * the stress.
>> + *
>> + * The flows insertion will go for all ports first, then it will
>> +print the
>> + * results, after that the application will go into forwarding
>> +packets mode
>> + * it will start receiving traffic if any and then forwarding it back
>> +and
>> + * gives packet per second measurement.
>> + */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <stdint.h>
>> +#include <inttypes.h>
>> +#include <stdarg.h>
>> +#include <errno.h>
>> +#include <getopt.h>
>> +#include <signal.h>
>> +#include <stdbool.h>
>> +#include <sys/time.h>
>> +
>> +#include <rte_malloc.h>
>> +#include <rte_mempool.h>
>> +#include <rte_mbuf.h>
>> +#include <rte_ethdev.h>
>> +#include <rte_flow.h>
>> +
>> +#include "config.h"
>> +
>> +static uint32_t nb_lcores;
>> +static struct rte_mempool *mbuf_mp;
>> +
>> +static void
>> +usage(char *progname)
>> +{
>> + printf("\nusage: %s\n", progname);
>> +}
>> +
>> +static void
>> +args_parse(int argc, char **argv)
>> +{
>> + char **argvopt;
>> + int opt;
>> + int opt_idx;
>> + static struct option lgopts[] = {
>> + /* Control */
>> + { "help", 0, 0, 0 },
>> + };
>> +
>> + argvopt = argv;
>> +
>> + while ((opt = getopt_long(argc, argvopt, "",
>> + lgopts, &opt_idx)) != EOF) {
>> + switch (opt) {
>> + case 0:
>> + if (!strcmp(lgopts[opt_idx].name, "help")) {
>
>DPDK coding style recommends to compare vs 0 instead of logical not.
Ok, will move it
>
>> + usage(argv[0]);
>> + rte_exit(EXIT_SUCCESS, "Displayed help\n");
>> + }
>> + break;
>> + default:
>> + printf("Invalid option: %s\n", argv[optind]);
>
>Again, sorry if I missed reply: Why error is not logged to stderr?
No, I missed it, will move it to stderr
>
>> + usage(argv[0]);
>> + rte_exit(EXIT_SUCCESS, "Invalid option\n");
>> + break;
>> + }
>> + }
>> +}
>> +
>> +static void
>> +init_port(void)
>> +{
>> + int ret;
>> + uint16_t i;
>> + uint16_t port_id;
>> + uint16_t nr_ports;
>> + struct rte_eth_conf port_conf = {
>> + .rx_adv_conf = {
>> + .rss_conf.rss_hf =
>> + ETH_RSS_IP |
>> + ETH_RSS_TCP,
>> + }
>> + };
>> + struct rte_eth_txconf txq_conf;
>> + struct rte_eth_rxconf rxq_conf;
>> + struct rte_eth_dev_info dev_info;
>> +
>> + nr_ports = rte_eth_dev_count_avail();
>> + if (nr_ports == 0)
>> + rte_exit(EXIT_FAILURE, "Error: no port detected\n");
>> +
>> + mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool",
>> + TOTAL_MBUF_NUM,
>MBUF_CACHE_SIZE,
>> + 0, MBUF_SIZE,
>> + rte_socket_id());
>> + if (mbuf_mp == NULL)
>> + rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n");
>> +
>> + for (port_id = 0; port_id < nr_ports; port_id++) {
>> + ret = rte_eth_dev_info_get(port_id, &dev_info);
>> + if (ret != 0)
>> + rte_exit(EXIT_FAILURE,
>> + "Error during getting device"
>> + " (port %u) info: %s\n",
>> + port_id, strerror(-ret));
>> +
>> + port_conf.txmode.offloads &= dev_info.tx_offload_capa;
>> + port_conf.rxmode.offloads &= dev_info.rx_offload_capa;
>> +
>> + printf(":: initializing port: %d\n", port_id);
>> +
>> + ret = rte_eth_dev_configure(port_id, RXQ_NUM,
>> + TXQ_NUM, &port_conf);
>> + if (ret < 0)
>> + rte_exit(EXIT_FAILURE,
>> + ":: cannot configure device: err=%d,
>port=%u\n",
>> + ret, port_id);
>> +
>> + rxq_conf = dev_info.default_rxconf;
>> + rxq_conf.offloads = port_conf.rxmode.offloads;
>
>
>As far as I know there is no necessity to repeat port offlaod on queue level.
>So, the line is not necesary.
Yes you are right, just checked the code, it takes the offloads from the port it self.
Will remove it.
>
>> +
>> + for (i = 0; i < RXQ_NUM; i++) {
>> + ret = rte_eth_rx_queue_setup(port_id, i, NR_RXD,
>> + rte_eth_dev_socket_id(port_id),
>> + &rxq_conf,
>> + mbuf_mp);
>> + if (ret < 0)
>> + rte_exit(EXIT_FAILURE,
>> + ":: Rx queue setup failed: err=%d,
>port=%u\n",
>> + ret, port_id);
>> + }
>> +
>> + txq_conf = dev_info.default_txconf;
>> + txq_conf.offloads = port_conf.txmode.offloads;
>
>As far as I know there is no necessity to repeat port offlaod on queue level.
>So, the line is not necesary.
Will remove it
>
>> +
>> + for (i = 0; i < TXQ_NUM; i++) {
>> + ret = rte_eth_tx_queue_setup(port_id, i, NR_TXD,
>> + rte_eth_dev_socket_id(port_id),
>> + &txq_conf);
>> + if (ret < 0)
>> + rte_exit(EXIT_FAILURE,
>> + ":: Tx queue setup failed: err=%d,
>port=%u\n",
>> + ret, port_id);
>> + }
>> +
>> + /* Catch all packets from traffic generator. */
>> + ret = rte_eth_promiscuous_enable(port_id);
>> + if (ret != 0)
>> + rte_exit(EXIT_FAILURE,
>> + ":: promiscuous mode enable failed: err=%s,
>port=%u\n",
>> + rte_strerror(-ret), port_id);
>> +
>> + ret = rte_eth_dev_start(port_id);
>> + if (ret < 0)
>> + rte_exit(EXIT_FAILURE,
>> + "rte_eth_dev_start:err=%d, port=%u\n",
>> + ret, port_id);
>> +
>> + printf(":: initializing port: %d done\n", port_id);
>> + }
>> +}
>> +
>> +int
>> +main(int argc, char **argv)
>> +{
>> + int ret;
>> + uint16_t port;
>> + struct rte_flow_error error;
>> +
>> + ret = rte_eal_init(argc, argv);
>> + if (ret < 0)
>> + rte_exit(EXIT_FAILURE, "EAL init failed\n");
>> +
>> + argc -= ret;
>> + argv += ret;
>> + if (argc > 1)
>> + args_parse(argc, argv);
>> +
>> + init_port();
>> +
>> + nb_lcores = rte_lcore_count();
>> + if (nb_lcores <= 1)
>> + rte_exit(EXIT_FAILURE, "This app needs at least two
>cores\n");
>> +
>> + RTE_ETH_FOREACH_DEV(port) {
>> + rte_flow_flush(port, &error);
>> + rte_eth_dev_stop(port);
>> + rte_eth_dev_close(port);
>> + }
>> + return 0;
>> +}
>
>[snip]
>
>> diff --git a/config/common_base b/config/common_base index
>> 14000ba07..b2edd5267 100644 diff --git
>> a/doc/guides/rel_notes/release_20_05.rst
>> b/doc/guides/rel_notes/release_20_05.rst
>> index b124c3f28..258b1e03e 100644
>> --- a/doc/guides/rel_notes/release_20_05.rst
>> +++ b/doc/guides/rel_notes/release_20_05.rst
>> @@ -212,6 +212,16 @@ New Features
>> * Added IPsec inbound load-distribution support for ipsec-secgw
>application
>> using NIC load distribution feature(Flow Director).
>>
>> +* **Added flow performance application.**
>> +
>> + Add new application to test rte_flow performance.
>> +
>> + Application features:
>> + * Measure rte_flow insertion rate.
>> + * Measure rte_flow deletion rate.
>> + * Dump rte_flow memory consumption.
>> + * Measure packet per second forwarding.
>
>I think above lines should be added in appropriate patches which really do it.
What do you mean?
each feature should add it's own line in the same commit?
>
>> +
>>
>> Removed Items
>> -------------
>
>[snip]
On 5/6/20 8:07 PM, Wisam Monther wrote:
>> -----Original Message-----
>> From: Andrew Rybchenko <arybchenko@solarflare.com>
>> Sent: Wednesday, May 6, 2020 5:26 PM
>> To: Wisam Monther <wisamm@mellanox.com>; dev@dpdk.org; Jack Min
>> <jackmin@mellanox.com>; Thomas Monjalon <thomas@monjalon.net>;
>> jerinjacobk@gmail.com; gerlitz.or@gmail.com; l.yan@epfl.ch;
>> ajit.khaparde@broadcom.com
>> Subject: Re: [dpdk-dev] [PATCH v5 1/5] app/flow-perf: add flow performance
>> skeleton
>>
>> On 5/6/20 3:36 PM, Wisam Jaddo wrote:
>>> Add flow performance application skeleton.
>>>
>>> Signed-off-by: Wisam Jaddo <wisamm@mellanox.com>
>>> ---
[snip]
>>> diff --git a/config/common_base b/config/common_base index
>>> 14000ba07..b2edd5267 100644 diff --git
>>> a/doc/guides/rel_notes/release_20_05.rst
>>> b/doc/guides/rel_notes/release_20_05.rst
>>> index b124c3f28..258b1e03e 100644
>>> --- a/doc/guides/rel_notes/release_20_05.rst
>>> +++ b/doc/guides/rel_notes/release_20_05.rst
>>> @@ -212,6 +212,16 @@ New Features
>>> * Added IPsec inbound load-distribution support for ipsec-secgw
>> application
>>> using NIC load distribution feature(Flow Director).
>>>
>>> +* **Added flow performance application.**
>>> +
>>> + Add new application to test rte_flow performance.
>>> +
>>> + Application features:
>>> + * Measure rte_flow insertion rate.
>>> + * Measure rte_flow deletion rate.
>>> + * Dump rte_flow memory consumption.
>>> + * Measure packet per second forwarding.
>> I think above lines should be added in appropriate patches which really do it.
> What do you mean?
> each feature should add it's own line in the same commit?
As I understand there features are not available if the first patch
only is applied. I.e. ideally features should be mentioned when
they are actually added (the second patch if I understand correctly).
Add new application to test rte flow performance from:
- Insertion rate.
- Deletion rate.
- Memory consumption.
- PPS forward measurement.
---
v6:
* Move compare vs 0 logic instead of logical not.
* Logged errors into stderr.
* Remove offload parse on queue level.
* Fix documentation and limitations.
* Added macro for rss hash value, used in port and rss action configuration.
* Remove all design global variable, only control left.
* Remove items/action defines for bit map and use rte_types instead.
* Addressing comments regard args_parse()
v5:
* Add app to 20.05 release notes.
* Addressing comments.
* Fix compilation issue for gcc >= 10.
* Fix documentation.
* Remove unneeded CFLAGS.
* Remove unused includes.
* Addressing format comments.
* Move hairpin to be option use only.
* Use RSS hash IP + TCP in ports and rss action.
* Introduce and use new macro for bit flags.
v4:
* Fix compilation error due to variable set but not used.
v3:
* Fix passing hairpin queues to hairpin rss action.
v2:
* reset cpu_time_used every port.
* generate different RSS action every flow with different RETA.
* Fix in commit log message
Wisam Jaddo (5):
app/flow-perf: add flow performance skeleton
app/flow-perf: add insertion rate calculation
app/flow-perf: add deletion rate calculation
app/flow-perf: add memory dump to app
app/flow-perf: add packet forwarding support
MAINTAINERS | 5 +
app/Makefile | 1 +
app/meson.build | 1 +
app/test-flow-perf/Makefile | 26 +
app/test-flow-perf/actions_gen.c | 164 ++++
app/test-flow-perf/actions_gen.h | 29 +
app/test-flow-perf/config.h | 30 +
app/test-flow-perf/flow_gen.c | 145 +++
app/test-flow-perf/flow_gen.h | 37 +
app/test-flow-perf/items_gen.c | 277 ++++++
app/test-flow-perf/items_gen.h | 31 +
app/test-flow-perf/main.c | 1116 ++++++++++++++++++++++++
app/test-flow-perf/meson.build | 11 +
config/common_base | 5 +
doc/guides/rel_notes/release_20_05.rst | 10 +
doc/guides/tools/flow-perf.rst | 247 ++++++
doc/guides/tools/index.rst | 1 +
17 files changed, 2136 insertions(+)
create mode 100644 app/test-flow-perf/Makefile
create mode 100644 app/test-flow-perf/actions_gen.c
create mode 100644 app/test-flow-perf/actions_gen.h
create mode 100644 app/test-flow-perf/config.h
create mode 100644 app/test-flow-perf/flow_gen.c
create mode 100644 app/test-flow-perf/flow_gen.h
create mode 100644 app/test-flow-perf/items_gen.c
create mode 100644 app/test-flow-perf/items_gen.h
create mode 100644 app/test-flow-perf/main.c
create mode 100644 app/test-flow-perf/meson.build
create mode 100644 doc/guides/tools/flow-perf.rst
@@ -1506,6 +1506,11 @@ T: git://dpdk.org/next/dpdk-next-net
F: app/test-pmd/
F: doc/guides/testpmd_app_ug/
+Flow performance tool
+M: Wisam Jaddo <wisamm@mellanox.com>
+F: app/test-flow-perf
+F: doc/guides/flow-perf.rst
+
Compression performance test application
T: git://dpdk.org/next/dpdk-next-crypto
F: app/test-compress-perf/
@@ -10,6 +10,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump
DIRS-$(CONFIG_RTE_LIBRTE_ACL) += test-acl
DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test-cmdline
DIRS-$(CONFIG_RTE_LIBRTE_FIB) += test-fib
+DIRS-$(CONFIG_RTE_TEST_FLOW_PERF) += test-flow-perf
DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test-pipeline
DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += test-sad
@@ -15,6 +15,7 @@ apps = [
'test-crypto-perf',
'test-eventdev',
'test-fib',
+ 'test-flow-perf',
'test-pipeline',
'test-pmd',
'test-sad']
new file mode 100644
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020 Mellanox Technologies, Ltd
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_TEST_FLOW_PERF),y)
+
+#
+# library name
+#
+APP = dpdk-test-flow-perf
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y += main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Claus
+ * Copyright 2020 Mellanox Technologies, Ltd
+ *
+ * This file will hold the user parameters values
+ */
+
+/* Configuration */
+#define RXQ_NUM 4
+#define TXQ_NUM 4
+#define TOTAL_MBUF_NUM 32000
+#define MBUF_SIZE 2048
+#define MBUF_CACHE_SIZE 512
+#define NR_RXD 256
+#define NR_TXD 256
new file mode 100644
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 Mellanox Technologies, Ltd
+ *
+ * This file contain the application main file
+ * This application provides the user the ability to test the
+ * insertion rate for specific rte_flow rule under stress state ~4M rule/
+ *
+ * Then it will also provide packet per second measurement after installing
+ * all rules, the user may send traffic to test the PPS that match the rules
+ * after all rules are installed, to check performance or functionality after
+ * the stress.
+ *
+ * The flows insertion will go for all ports first, then it will print the
+ * results, after that the application will go into forwarding packets mode
+ * it will start receiving traffic if any and then forwarding it back and
+ * gives packet per second measurement.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <sys/time.h>
+
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+
+#include "config.h"
+
+static uint32_t nb_lcores;
+static struct rte_mempool *mbuf_mp;
+
+static void
+usage(char *progname)
+{
+ printf("\nusage: %s\n", progname);
+}
+
+static void
+args_parse(int argc, char **argv)
+{
+ char **argvopt;
+ int opt;
+ int opt_idx;
+ static struct option lgopts[] = {
+ /* Control */
+ { "help", 0, 0, 0 },
+ };
+
+ argvopt = argv;
+
+ while ((opt = getopt_long(argc, argvopt, "",
+ lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+ case 0:
+ if (!strcmp(lgopts[opt_idx].name, "help")) {
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ }
+ break;
+ default:
+ printf("Invalid option: %s\n", argv[optind]);
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Invalid option\n");
+ break;
+ }
+ }
+}
+
+static void
+init_port(void)
+{
+ int ret;
+ uint16_t i;
+ uint16_t port_id;
+ uint16_t nr_ports;
+ struct rte_eth_conf port_conf = {
+ .rx_adv_conf = {
+ .rss_conf.rss_hf =
+ ETH_RSS_IP |
+ ETH_RSS_TCP,
+ }
+ };
+ struct rte_eth_txconf txq_conf;
+ struct rte_eth_rxconf rxq_conf;
+ struct rte_eth_dev_info dev_info;
+
+ nr_ports = rte_eth_dev_count_avail();
+ if (nr_ports == 0)
+ rte_exit(EXIT_FAILURE, "Error: no port detected\n");
+
+ mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool",
+ TOTAL_MBUF_NUM, MBUF_CACHE_SIZE,
+ 0, MBUF_SIZE,
+ rte_socket_id());
+ if (mbuf_mp == NULL)
+ rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n");
+
+ for (port_id = 0; port_id < nr_ports; port_id++) {
+ ret = rte_eth_dev_info_get(port_id, &dev_info);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ "Error during getting device"
+ " (port %u) info: %s\n",
+ port_id, strerror(-ret));
+
+ port_conf.txmode.offloads &= dev_info.tx_offload_capa;
+ port_conf.rxmode.offloads &= dev_info.rx_offload_capa;
+
+ printf(":: initializing port: %d\n", port_id);
+
+ ret = rte_eth_dev_configure(port_id, RXQ_NUM,
+ TXQ_NUM, &port_conf);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ ":: cannot configure device: err=%d, port=%u\n",
+ ret, port_id);
+
+ rxq_conf = dev_info.default_rxconf;
+ rxq_conf.offloads = port_conf.rxmode.offloads;
+
+ for (i = 0; i < RXQ_NUM; i++) {
+ ret = rte_eth_rx_queue_setup(port_id, i, NR_RXD,
+ rte_eth_dev_socket_id(port_id),
+ &rxq_conf,
+ mbuf_mp);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ ":: Rx queue setup failed: err=%d, port=%u\n",
+ ret, port_id);
+ }
+
+ txq_conf = dev_info.default_txconf;
+ txq_conf.offloads = port_conf.txmode.offloads;
+
+ for (i = 0; i < TXQ_NUM; i++) {
+ ret = rte_eth_tx_queue_setup(port_id, i, NR_TXD,
+ rte_eth_dev_socket_id(port_id),
+ &txq_conf);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ ":: Tx queue setup failed: err=%d, port=%u\n",
+ ret, port_id);
+ }
+
+ /* Catch all packets from traffic generator. */
+ ret = rte_eth_promiscuous_enable(port_id);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ ":: promiscuous mode enable failed: err=%s, port=%u\n",
+ rte_strerror(-ret), port_id);
+
+ ret = rte_eth_dev_start(port_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_dev_start:err=%d, port=%u\n",
+ ret, port_id);
+
+ printf(":: initializing port: %d done\n", port_id);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ uint16_t port;
+ struct rte_flow_error error;
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "EAL init failed\n");
+
+ argc -= ret;
+ argv += ret;
+ if (argc > 1)
+ args_parse(argc, argv);
+
+ init_port();
+
+ nb_lcores = rte_lcore_count();
+ if (nb_lcores <= 1)
+ rte_exit(EXIT_FAILURE, "This app needs at least two cores\n");
+
+ RTE_ETH_FOREACH_DEV(port) {
+ rte_flow_flush(port, &error);
+ rte_eth_dev_stop(port);
+ rte_eth_dev_close(port);
+ }
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Mellanox Technologies, Ltd
+
+sources = files(
+ 'main.c',
+)
+
+deps += ['ethdev']
@@ -1105,6 +1105,11 @@ CONFIG_RTE_TEST_PMD=y
CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
+#
+# Compile the rte flow perf application
+#
+CONFIG_RTE_TEST_FLOW_PERF=y
+
#
# Compile the bbdev test application
#
@@ -212,6 +212,16 @@ New Features
* Added IPsec inbound load-distribution support for ipsec-secgw application
using NIC load distribution feature(Flow Director).
+* **Added flow performance application.**
+
+ Add new application to test rte_flow performance.
+
+ Application features:
+ * Measure rte_flow insertion rate.
+ * Measure rte_flow deletion rate.
+ * Dump rte_flow memory consumption.
+ * Measure packet per second forwarding.
+
Removed Items
-------------
new file mode 100644
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2020 Mellanox Technologies, Ltd
+
+Flow performance tool
+=====================
+
+Application for rte_flow performance testing.
+
+
+Compiling the Application
+=========================
+
+The ``test-flow-perf`` application is compiled as part of the main compilation
+of the DPDK libraries and tools.
+
+Refer to the DPDK Getting Started Guides for details.
+
+
+Running the Application
+=======================
+
+EAL Command-line Options
+------------------------
+
+Please refer to :doc:`EAL parameters (Linux) <../linux_gsg/linux_eal_parameters>`
+or :doc:`EAL parameters (FreeBSD) <../freebsd_gsg/freebsd_eal_parameters>` for
+a list of available EAL command-line options.
+
+
+Flow performance Options
+------------------------
+
+The following are the command-line options for the flow performance application.
+They must be separated from the EAL options, shown in the previous section,
+with a ``--`` separator:
+
+.. code-block:: console
+
+ sudo ./dpdk-test-flow-perf -n 4 -w 08:00.0 --
+
+The command line options are:
+
+* ``--help``
+ Display a help message and quit.
@@ -16,3 +16,4 @@ DPDK Tools User Guides
cryptoperf
comp_perf
testeventdev
+ flow-perf