From: Dariusz Sosnowski <dsosnow...@nvidia.com>

This patch adds validation of direction attributes of pattern templates
and template tables.

In case of pattern templates the following configurations are allowed
(and if this configuration requires addition of implicit pattern items):

1. If E-Switch is enabled (i.e. dv_esw_en devarg is set to 1):
    1. If a port is a VF/SF representor:
        1. Ingress only - implicit pattern items are added.
        2. Egress only - implicit pattern items are added.
    2. If a port is a transfer proxy port (E-Switch Manager/PF
       representor):
        1. Ingress, egress and transfer - no implicit items are added.
           This setting is useful for applications which require to
           receive traffic from devices connected to the E-Switch and
           did not hit any transfer flow rules.
        2. Ingress only - implicit pattern items are added.
        3. Egress only - implicit pattern items are added.
        4. Transfer only - no implicit pattern items are added.
2. If E-Switch is disabled (i.e. dv_esw_en devarg is set to 0):
    1. Ingress only - no implicit pattern items are added.
    2. Egress only - no implicit pattern items are added.
    3. Ingress and egress - no implicit pattern items are added.
    4. Transfer is not allowed.

In case of template tables, the table attributes must be consistent
with attributes associated with pattern template attributes.

Signed-off-by: Dariusz Sosnowski <dsosnow...@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c | 80 +++++++++++++++++++++++++--------
 1 file changed, 62 insertions(+), 18 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 92b61b63d1..dfbc434d54 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2379,6 +2379,13 @@ flow_hw_table_create(struct rte_eth_dev *dev,
        for (i = 0; i < nb_item_templates; i++) {
                uint32_t ret;
 
+               if ((flow_attr.ingress && !item_templates[i]->attr.ingress) ||
+                   (flow_attr.egress && !item_templates[i]->attr.egress) ||
+                   (flow_attr.transfer && !item_templates[i]->attr.transfer)) {
+                       DRV_LOG(ERR, "pattern template and template table 
attribute mismatch");
+                       rte_errno = EINVAL;
+                       goto it_error;
+               }
                ret = __atomic_add_fetch(&item_templates[i]->refcnt, 1,
                                         __ATOMIC_RELAXED);
                if (ret <= 1) {
@@ -2557,6 +2564,7 @@ flow_hw_template_table_create(struct rte_eth_dev *dev,
                              uint8_t nb_action_templates,
                              struct rte_flow_error *error)
 {
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_template_table_cfg cfg = {
                .attr = *attr,
                .external = true,
@@ -2565,6 +2573,12 @@ flow_hw_template_table_create(struct rte_eth_dev *dev,
 
        if (flow_hw_translate_group(dev, &cfg, group, 
&cfg.attr.flow_attr.group, error))
                return NULL;
+       if (priv->sh->config.dv_esw_en && cfg.attr.flow_attr.egress) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, 
NULL,
+                                 "egress flows are not supported with HW 
Steering"
+                                 " when E-Switch is enabled");
+               return NULL;
+       }
        return flow_hw_table_create(dev, &cfg, item_templates, 
nb_item_templates,
                                    action_templates, nb_action_templates, 
error);
 }
@@ -3254,11 +3268,48 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
                         const struct rte_flow_item items[],
                         struct rte_flow_error *error)
 {
+       struct mlx5_priv *priv = dev->data->dev_private;
        int i;
        bool items_end = false;
-       RTE_SET_USED(dev);
-       RTE_SET_USED(attr);
 
+       if (!attr->ingress && !attr->egress && !attr->transfer)
+               return rte_flow_error_set(error, EINVAL, 
RTE_FLOW_ERROR_TYPE_ATTR, NULL,
+                                         "at least one of the direction 
attributes"
+                                         " must be specified");
+       if (priv->sh->config.dv_esw_en) {
+               MLX5_ASSERT(priv->master || priv->representor);
+               if (priv->master) {
+                       /*
+                        * It is allowed to specify ingress, egress and 
transfer attributes
+                        * at the same time, in order to construct flows 
catching all missed
+                        * FDB traffic and forwarding it to the master port.
+                        */
+                       if (!(attr->ingress ^ attr->egress ^ attr->transfer))
+                               return rte_flow_error_set(error, EINVAL,
+                                                         
RTE_FLOW_ERROR_TYPE_ATTR, NULL,
+                                                         "only one or all 
direction attributes"
+                                                         " at once can be used 
on transfer proxy"
+                                                         " port");
+               } else {
+                       if (attr->transfer)
+                               return rte_flow_error_set(error, EINVAL,
+                                                         
RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
+                                                         "transfer attribute 
cannot be used with"
+                                                         " port representors");
+                       if (attr->ingress && attr->egress)
+                               return rte_flow_error_set(error, EINVAL,
+                                                         
RTE_FLOW_ERROR_TYPE_ATTR, NULL,
+                                                         "ingress and egress 
direction attributes"
+                                                         " cannot be used at 
the same time on"
+                                                         " port representors");
+               }
+       } else {
+               if (attr->transfer)
+                       return rte_flow_error_set(error, EINVAL,
+                                                 
RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
+                                                 "transfer attribute cannot be 
used when"
+                                                 " E-Switch is disabled");
+       }
        for (i = 0; !items_end; i++) {
                int type = items[i].type;
 
@@ -3289,7 +3340,15 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
                                                          
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
                                                          NULL,
                                                          "Unsupported internal 
tag index");
+                       break;
                }
+               case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
+                       if (attr->ingress || attr->egress)
+                               return rte_flow_error_set(error, EINVAL,
+                                                 RTE_FLOW_ERROR_TYPE_ITEM, 
NULL,
+                                                 "represented port item cannot 
be used"
+                                                 " when transfer attribute is 
set");
+                       break;
                case RTE_FLOW_ITEM_TYPE_VOID:
                case RTE_FLOW_ITEM_TYPE_ETH:
                case RTE_FLOW_ITEM_TYPE_VLAN:
@@ -3299,7 +3358,6 @@ flow_hw_pattern_validate(struct rte_eth_dev *dev,
                case RTE_FLOW_ITEM_TYPE_TCP:
                case RTE_FLOW_ITEM_TYPE_GTP:
                case RTE_FLOW_ITEM_TYPE_GTP_PSC:
-               case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
                case RTE_FLOW_ITEM_TYPE_VXLAN:
                case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE:
                case RTE_FLOW_ITEM_TYPE_META:
@@ -3350,21 +3408,7 @@ flow_hw_pattern_template_create(struct rte_eth_dev *dev,
 
        if (flow_hw_pattern_validate(dev, attr, items, error))
                return NULL;
-       if (priv->sh->config.dv_esw_en && attr->ingress) {
-               /*
-                * Disallow pattern template with ingress and egress/transfer
-                * attributes in order to forbid implicit port matching
-                * on egress and transfer traffic.
-                */
-               if (attr->egress || attr->transfer) {
-                       rte_flow_error_set(error, EINVAL,
-                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                          NULL,
-                                          "item template for ingress traffic"
-                                          " cannot be used for egress/transfer"
-                                          " traffic when E-Switch is enabled");
-                       return NULL;
-               }
+       if (priv->sh->config.dv_esw_en && attr->ingress && !attr->egress && 
!attr->transfer) {
                copied_items = flow_hw_copy_prepend_port_item(items, error);
                if (!copied_items)
                        return NULL;
-- 
2.25.1

Reply via email to