]> git.droids-corp.org - dpdk.git/commitdiff
app/testpmd: add flow engine configuration
authorAlexander Kozyrev <akozyrev@nvidia.com>
Wed, 23 Feb 2022 03:02:34 +0000 (05:02 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 24 Feb 2022 13:04:48 +0000 (14:04 +0100)
Add testpmd support for the rte_flow_configure API.
Provide the command line interface for the Flow management.
Usage example: flow configure 0 queues_number 8 queues_size 256

Implement rte_flow_info_get API to get available resources:
Usage example: flow info 0

Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
app/test-pmd/cmdline_flow.c
app/test-pmd/config.c
app/test-pmd/testpmd.h
doc/guides/testpmd_app_ug/testpmd_funcs.rst

index c0644d678c632cff0893dd9f8a87bfa62f662f75..0533a33ca22ec8dddd430b5299c59ebb5ad084fd 100644 (file)
@@ -72,6 +72,8 @@ enum index {
        /* Top-level command. */
        FLOW,
        /* Sub-level commands. */
+       INFO,
+       CONFIGURE,
        INDIRECT_ACTION,
        VALIDATE,
        CREATE,
@@ -122,6 +124,13 @@ enum index {
        DUMP_ALL,
        DUMP_ONE,
 
+       /* Configure arguments */
+       CONFIG_QUEUES_NUMBER,
+       CONFIG_QUEUES_SIZE,
+       CONFIG_COUNTERS_NUMBER,
+       CONFIG_AGING_OBJECTS_NUMBER,
+       CONFIG_METERS_NUMBER,
+
        /* Indirect action arguments */
        INDIRECT_ACTION_CREATE,
        INDIRECT_ACTION_UPDATE,
@@ -868,6 +877,11 @@ struct buffer {
        enum index command; /**< Flow command. */
        portid_t port; /**< Affected port ID. */
        union {
+               struct {
+                       struct rte_flow_port_attr port_attr;
+                       uint32_t nb_queue;
+                       struct rte_flow_queue_attr queue_attr;
+               } configure; /**< Configuration arguments. */
                struct {
                        uint32_t *action_id;
                        uint32_t action_id_n;
@@ -949,6 +963,16 @@ static const enum index next_flex_item[] = {
        ZERO,
 };
 
+static const enum index next_config_attr[] = {
+       CONFIG_QUEUES_NUMBER,
+       CONFIG_QUEUES_SIZE,
+       CONFIG_COUNTERS_NUMBER,
+       CONFIG_AGING_OBJECTS_NUMBER,
+       CONFIG_METERS_NUMBER,
+       END,
+       ZERO,
+};
+
 static const enum index next_ia_create_attr[] = {
        INDIRECT_ACTION_CREATE_ID,
        INDIRECT_ACTION_INGRESS,
@@ -2045,6 +2069,9 @@ static int parse_aged(struct context *, const struct token *,
 static int parse_isolate(struct context *, const struct token *,
                         const char *, unsigned int,
                         void *, unsigned int);
+static int parse_configure(struct context *, const struct token *,
+                          const char *, unsigned int,
+                          void *, unsigned int);
 static int parse_tunnel(struct context *, const struct token *,
                        const char *, unsigned int,
                        void *, unsigned int);
@@ -2270,7 +2297,9 @@ static const struct token token_list[] = {
                .type = "{command} {port_id} [{arg} [...]]",
                .help = "manage ingress/egress flow rules",
                .next = NEXT(NEXT_ENTRY
-                            (INDIRECT_ACTION,
+                            (INFO,
+                             CONFIGURE,
+                             INDIRECT_ACTION,
                              VALIDATE,
                              CREATE,
                              DESTROY,
@@ -2285,6 +2314,65 @@ static const struct token token_list[] = {
                .call = parse_init,
        },
        /* Top-level command. */
+       [INFO] = {
+               .name = "info",
+               .help = "get information about flow engine",
+               .next = NEXT(NEXT_ENTRY(END),
+                            NEXT_ENTRY(COMMON_PORT_ID)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+               .call = parse_configure,
+       },
+       /* Top-level command. */
+       [CONFIGURE] = {
+               .name = "configure",
+               .help = "configure flow engine",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_PORT_ID)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+               .call = parse_configure,
+       },
+       /* Configure arguments. */
+       [CONFIG_QUEUES_NUMBER] = {
+               .name = "queues_number",
+               .help = "number of queues",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer,
+                                       args.configure.nb_queue)),
+       },
+       [CONFIG_QUEUES_SIZE] = {
+               .name = "queues_size",
+               .help = "number of elements in queues",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer,
+                                       args.configure.queue_attr.size)),
+       },
+       [CONFIG_COUNTERS_NUMBER] = {
+               .name = "counters_number",
+               .help = "number of counters",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer,
+                                       args.configure.port_attr.nb_counters)),
+       },
+       [CONFIG_AGING_OBJECTS_NUMBER] = {
+               .name = "aging_counters_number",
+               .help = "number of aging objects",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer,
+                                       args.configure.port_attr.nb_aging_objects)),
+       },
+       [CONFIG_METERS_NUMBER] = {
+               .name = "meters_number",
+               .help = "number of meters",
+               .next = NEXT(next_config_attr,
+                            NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer,
+                                       args.configure.port_attr.nb_meters)),
+       },
+       /* Top-level command. */
        [INDIRECT_ACTION] = {
                .name = "indirect_action",
                .type = "{command} {port_id} [{arg} [...]]",
@@ -7736,6 +7824,33 @@ parse_isolate(struct context *ctx, const struct token *token,
        return len;
 }
 
+/** Parse tokens for info/configure command. */
+static int
+parse_configure(struct context *ctx, const struct token *token,
+               const char *str, unsigned int len,
+               void *buf, unsigned int size)
+{
+       struct buffer *out = buf;
+
+       /* Token name must match. */
+       if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+               return -1;
+       /* Nothing else to do if there is no buffer. */
+       if (!out)
+               return len;
+       if (!out->command) {
+               if (ctx->curr != INFO && ctx->curr != CONFIGURE)
+                       return -1;
+               if (sizeof(*out) > size)
+                       return -1;
+               out->command = ctx->curr;
+               ctx->objdata = 0;
+               ctx->object = out;
+               ctx->objmask = NULL;
+       }
+       return len;
+}
+
 static int
 parse_flex(struct context *ctx, const struct token *token,
             const char *str, unsigned int len,
@@ -8964,6 +9079,15 @@ static void
 cmd_flow_parsed(const struct buffer *in)
 {
        switch (in->command) {
+       case INFO:
+               port_flow_get_info(in->port);
+               break;
+       case CONFIGURE:
+               port_flow_configure(in->port,
+                                   &in->args.configure.port_attr,
+                                   in->args.configure.nb_queue,
+                                   &in->args.configure.queue_attr);
+               break;
        case INDIRECT_ACTION_CREATE:
                port_action_handle_create(
                                in->port, in->args.vc.attr.group,
index de1ec14bc75b5aa6468e2f4825a1cb5f04a74345..33a85cd7ca247dd58ee78e61bd2cb78fe40f8f6d 100644 (file)
@@ -1610,6 +1610,67 @@ action_alloc(portid_t port_id, uint32_t id,
        return 0;
 }
 
+/** Get info about flow management resources. */
+int
+port_flow_get_info(portid_t port_id)
+{
+       struct rte_flow_port_info port_info;
+       struct rte_flow_queue_info queue_info;
+       struct rte_flow_error error;
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+           port_id == (portid_t)RTE_PORT_ALL)
+               return -EINVAL;
+       /* Poisoning to make sure PMDs update it in case of error. */
+       memset(&error, 0x99, sizeof(error));
+       memset(&port_info, 0, sizeof(port_info));
+       memset(&queue_info, 0, sizeof(queue_info));
+       if (rte_flow_info_get(port_id, &port_info, &queue_info, &error))
+               return port_flow_complain(&error);
+       printf("Flow engine resources on port %u:\n"
+              "Number of queues: %d\n"
+                  "Size of queues: %d\n"
+              "Number of counters: %d\n"
+              "Number of aging objects: %d\n"
+              "Number of meter actions: %d\n",
+              port_id, port_info.max_nb_queues,
+                  queue_info.max_size,
+              port_info.max_nb_counters,
+              port_info.max_nb_aging_objects,
+              port_info.max_nb_meters);
+       return 0;
+}
+
+/** Configure flow management resources. */
+int
+port_flow_configure(portid_t port_id,
+       const struct rte_flow_port_attr *port_attr,
+       uint16_t nb_queue,
+       const struct rte_flow_queue_attr *queue_attr)
+{
+       struct rte_port *port;
+       struct rte_flow_error error;
+       const struct rte_flow_queue_attr *attr_list[nb_queue];
+       int std_queue;
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+           port_id == (portid_t)RTE_PORT_ALL)
+               return -EINVAL;
+       port = &ports[port_id];
+       port->queue_nb = nb_queue;
+       port->queue_sz = queue_attr->size;
+       for (std_queue = 0; std_queue < nb_queue; std_queue++)
+               attr_list[std_queue] = queue_attr;
+       /* Poisoning to make sure PMDs update it in case of error. */
+       memset(&error, 0x66, sizeof(error));
+       if (rte_flow_configure(port_id, port_attr, nb_queue, attr_list, &error))
+               return port_flow_complain(&error);
+       printf("Configure flows on port %u: "
+              "number of queues %d with %d elements\n",
+              port_id, nb_queue, queue_attr->size);
+       return 0;
+}
+
 /** Create indirect action */
 int
 port_action_handle_create(portid_t port_id, uint32_t id,
index 996782504465465d5cd258c5c3b2a5ad5a8feef1..096b6825ebae4443d40c568d076a04d2437a622e 100644 (file)
@@ -243,6 +243,8 @@ struct rte_port {
        struct rte_eth_txconf   tx_conf[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue tx configuration */
        struct rte_ether_addr   *mc_addr_pool; /**< pool of multicast addrs */
        uint32_t                mc_addr_nb; /**< nb. of addr. in mc_addr_pool */
+       queueid_t               queue_nb; /**< nb. of queues for flow rules */
+       uint32_t                queue_sz; /**< size of a queue for flow rules */
        uint8_t                 slave_flag; /**< bonding slave port */
        struct port_flow        *flow_list; /**< Associated flows. */
        struct port_indirect_action *actions_list;
@@ -885,6 +887,11 @@ struct rte_flow_action_handle *port_action_handle_get_by_id(portid_t port_id,
                                                            uint32_t id);
 int port_action_handle_update(portid_t port_id, uint32_t id,
                              const struct rte_flow_action *action);
+int port_flow_get_info(portid_t port_id);
+int port_flow_configure(portid_t port_id,
+                       const struct rte_flow_port_attr *port_attr,
+                       uint16_t nb_queue,
+                       const struct rte_flow_queue_attr *queue_attr);
 int port_flow_validate(portid_t port_id,
                       const struct rte_flow_attr *attr,
                       const struct rte_flow_item *pattern,
index 9cc248084f360208af68a838177444c4d9691d3d..c8f048aeef316bde11e5a1f91b9660fe1a6c7d24 100644 (file)
@@ -3308,8 +3308,8 @@ Flow rules management
 ---------------------
 
 Control of the generic flow API (*rte_flow*) is fully exposed through the
-``flow`` command (validation, creation, destruction, queries and operation
-modes).
+``flow`` command (configuration, validation, creation, destruction, queries
+and operation modes).
 
 Considering *rte_flow* overlaps with all `Filter Functions`_, using both
 features simultaneously may cause undefined side-effects and is therefore
@@ -3332,6 +3332,18 @@ The first parameter stands for the operation mode. Possible operations and
 their general syntax are described below. They are covered in detail in the
 following sections.
 
+- Get info about flow engine::
+
+   flow info {port_id}
+
+- Configure flow engine::
+
+   flow configure {port_id}
+       [queues_number {number}] [queues_size {size}]
+       [counters_number {number}]
+       [aging_counters_number {number}]
+       [meters_number {number}]
+
 - Check whether a flow rule can be created::
 
    flow validate {port_id}
@@ -3391,6 +3403,51 @@ following sections.
 
    flow tunnel list {port_id}
 
+Retrieving info about flow management engine
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow info`` retrieves info on pre-configurable resources in the underlying
+device to give a hint of possible values for flow engine configuration.
+
+``rte_flow_info_get()``::
+
+   flow info {port_id}
+
+If successful, it will show::
+
+   Flow engine resources on port #[...]:
+   Number of queues: #[...]
+   Size of queues: #[...]
+   Number of counters: #[...]
+   Number of aging objects: #[...]
+   Number of meters: #[...]
+
+Otherwise it will show an error message of the form::
+
+   Caught error type [...] ([...]): [...]
+
+Configuring flow management engine
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow configure`` pre-allocates all the needed resources in the underlying
+device to be used later at the flow creation. Flow queues are allocated as well
+for asynchronous flow creation/destruction operations. It is bound to
+``rte_flow_configure()``::
+
+   flow configure {port_id}
+       [queues_number {number}] [queues_size {size}]
+       [counters_number {number}]
+       [aging_counters_number {number}]
+       [meters_number {number}]
+
+If successful, it will show::
+
+   Configure flows on port #[...]: number of queues #[...] with #[...] elements
+
+Otherwise it will show an error message of the form::
+
+   Caught error type [...] ([...]): [...]
+
 Creating a tunnel stub for offload
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~